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,它们应该包含正确的物理世界坐标和图像坐标。

相关推荐
多巴胺与内啡肽.27 分钟前
OpenCV进阶操作:光流估计
人工智能·opencv·计算机视觉
alpszero2 小时前
YOLO11解决方案之物体模糊探索
人工智能·python·opencv·计算机视觉·yolo11
多巴胺与内啡肽.2 小时前
OpenCV进阶操作:风格迁移以及DNN模块解析
人工智能·opencv·dnn
zm-v-159304339863 小时前
解锁遥感数据密码:DeepSeek、Python 与 OpenCV 的协同之力
开发语言·python·opencv
沙振宇3 小时前
【HarmonyOS】ArkTS开发应用的横竖屏切换
android·华为·harmonyos
jndingxin3 小时前
OpenCV CUDA 模块中在 GPU 上对图像或矩阵进行 翻转(镜像)操作的一个函数 flip()
人工智能·opencv
橙子199110165 小时前
Kotlin 中的作用域函数
android·开发语言·kotlin
zimoyin5 小时前
Kotlin 懒初始化值
android·开发语言·kotlin
码农新猿类5 小时前
初入OpenCV
qt·opencv·计算机视觉
枣伊吕波6 小时前
第六节第二部分:抽象类的应用-模板方法设计模式
android·java·设计模式