Android通过OpenCV实现相机标定

在 Android 中使用 OpenCV 实现相机标定,你可以按照以下步骤进行操作:

  1. 首先,确保你已经在项目中引入了 OpenCV 库的依赖。

  2. 创建一个 CameraCalibrator 类,用于执行相机标定。

     import org.opencv.calib3d.Calib3d
     import org.opencv.core.CvType.CV_32F
     import org.opencv.core.CvType.CV_64F
     import org.opencv.core.Mat
     import org.opencv.core.MatOfPoint2f
     import org.opencv.core.MatOfPoint3f
     import org.opencv.core.Size
     
    
     class CameraCalibrator {
         private val objectPoints = ArrayList<Mat>()
         private val imagePoints = ArrayList<Mat>()
         private var imageSize = Size()
         var cameraMatrix = Mat(3, 3, CV_64F)
         private var distortionCoefficients = Mat(5, 1, CV_64F)
         // 添加一组图像点和对应的物理世界点
         fun addObjectPoint(objectPoint: Mat) {
             objectPoints.add(objectPoint)
         }
     
         fun addImagePoint(imagePoint: Mat) {
             imagePoints.add(imagePoint)
         }
          执行相机标定
         fun calibrate(): Mat? {
             val rotationVectors = ArrayList<Mat>()
             val translationVectors = ArrayList<Mat>()
             val rms = Calib3d.calibrateCamera(
                 objectPoints,
                 imagePoints,
                 imageSize,
                 cameraMatrix,
                 distortionCoefficients,
                 rotationVectors,
                 translationVectors
             )
     
             if (rms < 1.0) {
                 return cameraMatrix
             }
     
             return null
         }
          // 获取相机矩阵
         fun getCameraMatrix(): Mat {
             return cameraMatrix
         }
    
     	 // 获取畸变系数
         fun getDistortionCoefficients(): Mat {
             return distortionCoefficients
         }
     
         fun setImageSize(width: Int, height: Int) {
             imageSize = Size(width.toDouble(), height.toDouble())
         }
     }
    
  3. 通过Camera2获取到帧数据后转成灰度图Mat,创建一个 CameraCalibrator 对象,添加物理世界点和图像点

     fun startCalib(){
     	calibrator = CameraCalibrator()
         GlobalScope.launch(Dispatchers.IO) {
                 var grayMat = Mat(CameraUtil.cameraH, CameraUtil.cameraW, CvType.CV_8UC1);
                 grayMat.put(0,0,data)
                 addPoint(grayMat)
         }
     }
    
     fun addPoint(grayImage:Mat){
         Log.i(TAG,"addPointstart")
         val corners = MatOfPoint2f()
         val patternSize = Size(11.0, 8.0) // 棋盘格的内角点数目
         val found = Calib3d.findChessboardCorners(
             grayImage, patternSize, corners,
             Calib3d.CALIB_CB_ADAPTIVE_THRESH or Calib3d.CALIB_CB_NORMALIZE_IMAGE
         )
         if (found) {
             Log.i(TAG,"addPointend found")
             // 添加图像点和物理世界点
             val objectPoints = MatOfPoint3f()
             for (i in 0 until patternSize.height.toInt()) {
                 for (j in 0 until patternSize.width.toInt()) {
                     objectPoints.push_back(MatOfPoint3f(Point3(j.toDouble(), i.toDouble(), 0.0)))
                 }
             }
             calibrator?.addObjectPoint(objectPoints)
             calibrator?.addImagePoint(corners)
         }
         Log.i(TAG,"addPointend")
         stopCabin()
     }
    
  4. 执行相机标定,并获取相机矩阵和畸变系数

     fun stopCabin(){
             Log.i(TAG,"stopCabin")
             calibrator?.setImageSize(1920, 1080)
             val cameraMatrix = calibrator?.calibrate()
             val distortionCoefficients = calibrator?.getDistortionCoefficients()
             if (cameraMatrix != null) {
                 // 标定成功,可以使用相机矩阵进行后续处理
                 //查看相机的内参(相机矩阵),你可以获取 cameraMatrix 输出的 Mat 对象,并使用 OpenCV 提供的函数来解析和显示其内容
                 //将 cameraMatrix 转换为双精度数组
                 val cameraMatrixArray = DoubleArray(9)
                 cameraMatrix.get(0, 0, cameraMatrixArray)
                 Log.i(TAG,"相机内参 = "+cameraMatrixArray.contentToString())
             } else {
                 // 标定失败,请检查标定图像和参数设置
             }
         }
    
  5. Calib3d.calibrateCamera() 方法用于相机标定,它接受多个参数来执行标定过程。下面是各个参数的含义:

    objectPoints:一个 ArrayList 对象,存储了多个棋盘格的物理世界坐标点。每个 Mat 对象表示一个图像对应的物理世界坐标点。该参数用于指定棋盘格的内角点在物理世界中的坐标。

    imagePoints:一个 ArrayList 对象,存储了多个棋盘格的图像坐标点。每个 Mat 对象表示一个图像中检测到的棋盘格的内角点坐标。该参数用于指定棋盘格的内角点在图像中的坐标。

    imageSize:一个 Size 对象,指定图像的大小(宽度和高度)。该参数用于指定输入图像的尺寸。

    cameraMatrix:一个 Mat 对象,用于存储输出的相机矩阵。相机矩阵包含了相机的内参,如焦距和光心坐标等信息。

    distortionCoefficients:一个 Mat 对象,用于存储输出的畸变系数。畸变系数描述了相机的畸变情况,包括径向畸变和切向畸变等。

    rotationVectors:一个 ArrayList 对象,用于存储输出的旋转向量。每个旋转向量表示了相机在捕获每张图像时的姿态信息。

    translationVectors:一个 ArrayList 对象,用于存储输出的平移向量。每个平移向量表示了相机在捕获每张图像时的位置信息。

    返回值是一个浮点数,表示标定的均方根误差(RMSE),用于评估标定结果的准确度。

    请注意,为了将参数传递到 Calib3d.calibrateCamera() 方法中,你需要正确地创建和填充这些参数。特别是 objectPoints 和 imagePoints,它们应该包含正确的物理世界坐标和图像坐标。

相关推荐
无极程序员1 小时前
PHP常量
android·ide·android studio
萌面小侠Plus2 小时前
Android笔记(三十三):封装设备性能级别判断工具——低端机还是高端机
android·性能优化·kotlin·工具类·低端机
慢慢成长的码农2 小时前
Android Profiler 内存分析
android
大风起兮云飞扬丶2 小时前
Android——多线程、线程通信、handler机制
android
L72562 小时前
Android的Handler
android
清风徐来辽2 小时前
Android HandlerThread 基础
android
凤枭香3 小时前
Python OpenCV 傅里叶变换
开发语言·图像处理·python·opencv
HerayChen3 小时前
HbuildderX运行到手机或模拟器的Android App基座识别不到设备 mac
android·macos·智能手机
顾北川_野3 小时前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java
hairenjing11233 小时前
在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序
android·人工智能·windows·macos·智能手机