一、前言
因为项目采用PNP测距,需要知道工业相机的内参矩阵和畸变矩阵,所以采用MATLAB自带的标定应用CameraCalibrator进行标定工业相机(以迈德威视相机为例)。
原理及操作可结合以下博客:
二、准备
1、电脑上装好matlab。
2、普通无驱USB相机直接用,工业相机需要装SDK驱动,因为标定的时候需要拍照。
3、标准标定板-棋盘格图片,标定的时候保证平整,
请下载正规标定板PDF,以下仅为演示图片:
三、拍标定图
以下两点非常重要!!!!!!
1、标定拍的照片尺寸一定要与实际工程处理图像尺寸一样,不然利用参数矩阵进行测距会完全错误,具体方法是在图像采集前resize一下。
2、标定格最好占整个画面的三分之二,而且视角多元化。
采集镜头各个角度大概 15~20 张图片,我一般是上下左右左上左下右上右下各两张一共16张-20张。
采集图像代码如下:以迈德威视SDK为例,拍照前把鼠标指针对着视频流点一下,按Z进行拍照:
cv::Mat matImage(
cvSize(sFrameInfo.iWidth,sFrameInfo.iHeight),
sFrameInfo.uiMediaType == CAMERA_MEDIA_TYPE_MONO8 ? CV_8UC1 : CV_8UC3,
m_pFrameBuffer
);
resize(matImage, matImage, Size(640, 512));
imshow(g_CameraName, matImage);
int a = waitKey(2);
if (a == 'z' || a == 'Z')
{
sprintf(cstr, "%d%s", num++, ".jpg");
imwrite(cstr, matImage);
printf("已保存图片!\n");
}
四、标定
1、点击CameraCalibrator或者在MATLAB的命令行窗口输入 cameraCalibrator 打开标定工具。
2、点击Add Images选择拍棋盘格的路径,把拍的都包含进去,点打开。
3、填写方格纸中黑色小格的边长,我的标定纸格子边长不到25mm,大概是24.5mm,点击确定。
4、此时会出现处理好的图片如下
5、上面的Options里设置如下(使用两参数,选择错切和桶形畸变),设置好后点击Calibrate
6、标定完成,右边总平均误差小于0.5即可,右下方显示拍摄视角和距离。点击Export Camera Parameters导出标定结果。
五、数据处理并应用于PNP测距
数据导出后,双击工作区的值,只需要注意这四行结果。
第一行ImageSize是图像大小。
第二行RadialDistortion是径向畸变k1,k2,k3=0。
第三行TangentialDistortion是切向畸变p1,p2。
第四行IntrinsicMatrix为相机内参的3×3转置矩阵
应用于PNP测距中相机参数设定:
cameraMatrix = Mat::eye(3, 3, CV_64F); //相机内参
cameraMatrix.at<double>(0, 0) = 3.020093800002726e+03;
cameraMatrix.at<double>(0, 1) = 3.908106555724952;
cameraMatrix.at<double>(0, 2) = 6.251778697785120e+02;
cameraMatrix.at<double>(1, 1) = 3.028534518793932e+03;
cameraMatrix.at<double>(1, 2) = 5.777494389750183e+02;
distCoeffs = Mat::zeros(5, 1, CV_64F); //相机畸变
distCoeffs.at<double>(0, 0) = 0.106919541349743; //k1
distCoeffs.at<double>(1, 0) = 2.058323550640524; //k2
distCoeffs.at<double>(2, 0) = 0.008357212337159; //p1
distCoeffs.at<double>(3, 0) = 0.004352178235639; //p2
distCoeffs.at<double>(4, 0) = 0; //k3
solvePnP函数:
注意!!!!!!!
世界坐标选取要与目标点选取顺序一 一对应,不然测距错误。
关于测距方面,后续会另出博客讲述如何应用于实际工程。
六、总结
关于PNP具体原理:
3D-2D:PnP算法原理
具体书籍:《视觉SLAM十四讲》