如何在Android上使用OpenCV进行摄像头标定,我们这里使用官方一个例程,其实并不难,只是网上的资料少了而已。
相机标定是计算机视觉工作的前提,为了确定相机矩阵和畸变参数。
标定的方法:线性标定法、非线性优化标定法、两步标定法。线性标定法:运算速度快但是标定的精度不高,因为相机畸变都是非线性的。
非线性优化标定法:标定精度高,但模型复杂。
两步标定法有:Tsai的经典两步法和张正友的标定方法。
本OpenCV官方的标定demo使用的标定方式是张正友标定法。
首先我们下载android相关代码:OpenCV的android Demo下载地址:
https://opencv.org/releases/
下载后解压,用android Studio打开AndroidStudioProjects\opencv-4.6.0-android-sdk\OpenCV-android-sdk\samples,
配置好版本和ndk版本,以下是我使用的版本:
samples\gradle\wrapper\gradle-wrapper.properties
distributionUrl=https://services.gradle.org/distributions/gradle-6.1.1-all.zip
samples\build.gradle
classpath ‘com.android.tools.build:gradle:4.0.0’
samples\local.properties
sdk.dir=D:\xx\xx\sdk-windows
ndk.dir=D:\xx\xx\sdk-windows\ndk\25.0.8528842
gradle版本一般都会配置,那就说一下怎么配置ndk版本:
首先打开Settings-Android SDK,
选择SDK Tools,选中NDK和CMake,
点击右下角的Show Package Details ,
就可以选择NDK和CMake的对于的版本下载。
点击图中大象图标Sync一下,即可看到正常加载项目了。
选择使用camera-calibration,这个就是相机标定的例程,
这里使用的是外接一个摄像头的安卓板子,烧录apk到板子上。
samples\camera-calibration\src\org\opencv\samples\cameracalibration\CameraCalibrationActivity.java
上面的注释说原理在网站:https://docs.opencv.org/4.x/d4/d94/tutorial_camera_calibration.html
标定的图片在https://github.com/opencv/opencv/blob/4.x/doc/acircles_pattern.png
设置的圆点大小:
samples\camera-calibration\src\org\opencv\samples\cameracalibration\CameraCalibrator.java
private final Size mPatternSize = new Size(4, 11);
打开APP,可以看到Captured 0 ;
手举着那张纸,不同角度,识别出彩色点后就点击一下屏幕,Captured 加1 ,
差不多到20时,点击CALIBRATE,开始对摄像头标定,
标定后会打印标定后的内参矩阵和畸变系数的log,
代码实现在
samples\camera-calibration\src\org\opencv\samples\cameracalibration\CalibrationResult.java
Log.i(TAG, "Saved camera matrix: " + cameraMatrix.dump());//内参矩阵
Log.i(TAG, "Saved distortion coefficients: " + distortionCoefficients.dump());//畸变系数
内参矩阵和畸变系数保存在data/data/org.opencv.samples.cameracalibration/shared_prefs/CameraCalibrationActivity.xml
就这样标定完成。这里说说代码的常用配置:
samples\camera-calibration\src\org\opencv\samples\cameracalibration\CameraCalibrationActivity.java
// Camera.getNumberOfCameras() 获取摄像头数量
mOpenCvCameraView.setCameraIndex(0);//设置摄像头id
samples\camera-calibration\src\org\opencv\samples\cameracalibration\CameraCalibrator.java
private void findPattern(Mat grayFrame) {
mPatternWasFound = Calib3d.findCirclesGrid(grayFrame, mPatternSize,
mCorners, Calib3d.CALIB_CB_ASYMMETRIC_GRID);//使用的图片是圆点,还可以设置成棋盘等方式
//mPatternWasFound = Calib3d.findChessboardCorners(grayFrame, mPatternSize,
//mCorners, Calib3d.CALIB_CB_ADAPTIVE_THRESH|Calib3d.CALIB_CB_NORMALIZE_IMAGE);//检测方点,不能用,摄像头卡住,原因未查
}
是否为鱼眼摄像头:
samples\camera-calibration\src\org\opencv\samples\cameracalibration\CameraCalibrator.java
第一部分: public CameraCalibrator(int width, int height) {…
mFlags = Calib3d.CALIB_FIX_PRINCIPAL_POINT +
Calib3d.CALIB_ZERO_TANGENT_DIST +
Calib3d.CALIB_FIX_ASPECT_RATIO +
Calib3d.CALIB_FIX_K4 +
Calib3d.CALIB_FIX_K5;
摄像头是鱼眼的,配置改成
mFlags = Calib3d.fisheye_CALIB_RECOMPUTE_EXTRINSIC +
Calib3d.fisheye_CALIB_CHECK_COND +
Calib3d.fisheye_CALIB_FIX_SKEW;
第二部分: public void calibrate() {…
Calib3d.calibrateCamera(objectPoints, mCornersBuffer, mImageSize,mCameraMatrix, mDistortionCoefficients, rvecs, tvecs, mFlags);
摄像头是鱼眼的,改成
Calib3d.fisheye_calibrate(objectPoints, mCornersBuffer, mImageSize,
mCameraMatrix, mDistortionCoefficients, rvecs, tvecs, mFlags);
第三部分:
Mat.zeros(5, 1, CvType.CV_64FC1).copyTo(mDistortionCoefficients);
//Mat.zeros(4, 1, CvType.CV_64FC1).copyTo(mDistortionCoefficients);//鱼眼
就这样,可以使用OpenCVj简单地对摄像头进行标定。
欢迎留言交流。
参考:https://blog.csdn.net/weixin_42145554/article/details/112700441
————————————————
版权声明:本文为CSDN博主「花草123」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_27512319/article/details/125640255