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 小时前
[Android] APK提取器(1.3.7)版本
android
m0_748232641 小时前
mysql的主从配置
android·mysql·adb
秋长愁2 小时前
Android监听应用前台的实现方案解析
android
高力士等十万人2 小时前
OpenCV二值化处理
python·opencv·计算机视觉
默凉2 小时前
Ubuntu 20.04源码安装opencv 4.5.0
opencv·ubuntu
胖虎12 小时前
2025 新版Android Studio创建Java语言项目
android·java·android studio·创建java项目
视觉人机器视觉3 小时前
3D与2D机器视觉机械臂引导的区别
人工智能·数码相机·计算机视觉·3d·视觉检测
JabamiLight4 小时前
Lineageos 22.1(Android 15)Launcer简单调整初始化配置
android·android 15·lineageos 22.1·launcer
敲代码的鱼哇5 小时前
设备唯一ID获取,支持安卓/iOS/鸿蒙Next(uni-device-id)UTS插件
android·ios·uniapp·harmonyos
时光旅人01号6 小时前
深度学习工厂的蓝图:拆解CUDA驱动、PyTorch与OpenCV的依赖关系
pytorch·深度学习·opencv