网站制作网站建设,个人可以做导航网站吗,管理咨询和战略咨询,做企业网站服务器在国外一、单目相机模型 上图为针孔相机成像原理#xff0c;蓝色坐标中的O即为镜头光心。成像原理与小孔成像相同。 单目相机映射关系如下#xff1a; 将上式进行变换#xff0c;就可以从三位空间映射到2维平面的公式。 相机的畸变公式如下#xff1a;
二、模型投影函数
vo…一、单目相机模型 上图为针孔相机成像原理蓝色坐标中的O即为镜头光心。成像原理与小孔成像相同。 单目相机映射关系如下 将上式进行变换就可以从三位空间映射到2维平面的公式。 相机的畸变公式如下
二、模型投影函数
void cv:projectPoints ( InputArray objectPoints, InputArray rvec, InputArray tvec, InputArray cameraMatrix,InputArray distCoeffs,outputArray imagePolints, jacobian , OutputArray naArray(), double aspectRatio 0)objectPoints:世界坐标系中3D点的三维坐标。 rvec:世界坐标系变换到相机坐标系的旋转向量。 tvec:世界坐标系变换到相机坐标系的平移向量。 cameraMatrix:相机的内参矩阵。 distCoeffs:相机的畸变系数矩阵。 imagcPoints:三维坐标点在像素坐标系中估计的坐标。 jacobian:可选输出的雅可比矩阵。 aspectRatio:是否固定“宽高比”参数标志。 本节应用案例如下
int main() {//输入计算的内参矩阵和畸变矩阵(在相机厂家说明或者标定获得)Mat cameraMatrix (Mat_float(3, 3) 532.016297, 0, 332.172519,0, 531.565159, 233.388075,0, 0, 1);Mat distCoeffs (Mat_float(1, 5) -0.285188, 0.080097, 0.001274,0.002415, 0.106579);//图像相机坐标系与世界坐标系之间的关系Mat rvec (Mat_float(1, 3) -1.977853, -2.002220, 0.130029);Mat tvec (Mat_float(1, 3) -26.88155, -42.79936, 159.19703);//生成第一张图像中内角点的三位世界坐标Size boardSize Size(9,6);//棋盘格每个方格的真实尺寸Size squareSize Size(10, 10);vectorPoint3f PointSets;for (int j 0; j boardSize.height; j){for (int k 0; k boardSize.width; k){Point3f realPoint;//假设标定板为世界坐标系的Z平面及z0realPoint.x j * squareSize.width;realPoint.y k * squareSize.height;realPoint.z 0;PointSets.push_back(realPoint);}}//根据三维坐标和相机与世界坐标系时间的关系估计内角点像素坐标vectorPoint2f imagePoints;projectPoints(PointSets, rvec, tvec, cameraMatrix, distCoeffs, imagePoints);for (int i 0; i imagePoints.size(); i){cout imagePoints[i] endl;}waitKey(0);return 0;}三、单目相机标定
标定原理 从上图中可以看出相机坐标系可以通过世界坐标系进行平移变换来得到。具体的变换矩阵如相机坐标系右侧的公式。 标定板的图例如下 上图中为两种类型的标定板左侧为常用标定板在提取的时候是内角点。而右侧标定板中不存在内角点所以我们提取的是每个圆的中心点。 内角点提取函数如下
bool cv:.findChessboardCorners ( InputArray image, Size patternSize, OutputArray corners, int flags CALIB_CB_ADAPTIVE_THRESHCALIB_CB_NORNALIZE_IPAGE)image:含有棋盘标定板的图像图像必须是CV_8U的灰度图像或者彩色图像。 patternSize:图像中棋盘内角点行数和列数 corners:检测到的角点坐标 flags:检测角点方式的标志 圆形标定板中心提取
bool cv::findCirclesGrid ( InputArray image, Size patternSize, OutputArray centers, int flags, const Ptr FeatureDetector blolbDetector, const CirclesGridFinderParameters parameters)image:输入含有圆形网格的图像图像必须是CV_8U的灰度图像或者彩色图像。 patternSize:图像中每行和每列圆形的数目。 corners:输出的圆形中心坐标。 flags:检测圆心的操作标志。 blobDetector:在浅色背景中寻找黑色圆形斑点的特征探测器。 角点位置优化函数
bool cv.find4QuadCornerSubpix ( InputArray img, InputOutputArray corners, size region_size)img:计算出内角点的图像。 patternSize:内角点坐标。 corners:优化坐标时考虑的邻域范围。
绘制内角点提取的结果
void cv::drawChessboardCorners ( InputOutputArray image, size patternSize, InputArray corners, bool patternWasFound)image:需要绘制角点的目标图像必须是CU_8U的彩色图像。patternSize:标定板每行和每列角点的数目。 corners:检测到的角点坐标数组。 pattern WasFound:是否显示找到完成的标定板标志。
相机标定函数
double cv::calibrateCamera ( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints,Size imageSize, InputOutputArray cameraMatrix, InputoutputArray distCoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,int flags 0, TermCriteria criteria TermCriteria(TermCriteria::COUNTTermCriteria::EPS,30,DBL_EPSILON)objectPoints:棋盘格内角点的三维坐标。 imagePoints:棋盘格内角点在图像中的二维坐标。 imageSize:图像的像素尺寸大小。 cameraMatrix:相机的内参矩阵。 distCoeffs:相机的畸变系数矩阵。 rvecs:相机坐标系与世界坐标系之间的旋转向量。 tvecs:相机坐标系与世界坐标系之间的平移向量。 flags:选择标定算法的标志。 本节应用案例如下 本案例中采用了两张标定板的提取图像 并将两个图片的路径存放到ca.txt文件中
int main() {//读取图像vectorMatimgs;string imgName;//读取存放图片路径的txt文件ifstream fin(ca.txt);//挨个读取图片while(getline(fin, imgName)){Mat img imread(imgName);imgs.push_back(img);}//方格标定板内角点的数目行列Size board_size Size(9, 6);//存放内角点坐标vectorvectorPoint2f imgsPoints;//开始内角点提取for (int i 0; i imgs.size(); i){Mat img1 imgs[i];Mat gray1;cvtColor(img1, gray1, COLOR_BGR2GRAY);vectorPoint2f img1_points;//计算标定板的角点findChessboardCorners(gray1, board_size, img1_points);//细化方格标定板角点坐标find4QuadCornerSubpix(gray1, img1_points, Size(5, 5));bool pattern true;drawChessboardCorners(img1, board_size, img1_points, pattern);namedWindow(img1, WINDOW_NORMAL);imshow(img1, img1);waitKey(0);imgsPoints.push_back(img1_points);}//生成每个内角点的空间坐标Size squareSize Size(10, 10);vectorvectorPoint3f objectPoints;for (int i 0; i imgsPoints.size(); i){vectorPoint3f tempPointSet;for (int j 0; j board_size.height; j){for (int k 0; k board_size.width; k){Point3f realPoint;//设标定板为世界坐标系的z平面即z0realPoint.x j * squareSize.width;realPoint.y k * squareSize.height;realPoint.z 0;tempPointSet.push_back(realPoint);}}objectPoints.push_back(tempPointSet);}//图像尺寸Size imageSize;imageSize.width imgs[0].cols;imageSize.height imgs[0].rows;//摄像机内参数矩阵Mat cameraMatrix Mat(3, 3, CV_32FC1, Scalar::all(0));//摄像机的5个畸变系数k1,k2,p1,p2,k3Mat distCoeffs Mat(1, 5, CV_32FC1, Scalar::all(0));//每幅图像的旋转向量、平移量vectorMat rvecs, tvecs;calibrateCamera(objectPoints, imgsPoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, 0);cout 相机的内参矩阵 cameraMatrix endl;cout 相机畸变系数 distCoeffs endl;waitKey(0);return 0;
}
最终的运行结果如下图 这里只放一张图像。最终的输出结果为
相机的内参矩阵[120.8643306554273, 0, 94.55565247064737;0, 119.979406894919, 55.48571212317609;0, 0, 1]
相机畸变系数[-0.5559208449775317, 3.15840209023594, -0.001816753642197531, -0.01817901488786, -7.629569308066959]四、图像矫正 如上图左可以看出相机采集的数据造成了一定的畸变尤其是在边缘部分。
去畸变函数
void cv::undistort ( InputArray src, OutputArray dst, InputArray cameraMatrix, InputArray distCoeffs, InputArray newCameraMatrix noArray())src:含有畸变的输入图像。 dst:去畸变后的输出图像与输入图像具有相同的尺寸和数据类型。 cameraMatrix:相机内参矩阵上节中相机标定获得。 distCoeffis:相机的畸变矩阵根据近似模型不同参数数量可以为4、5、8、12或者14如果是空矩阵表示没有畸变。 newCameraMatrix:畸变图像的相机内参矩阵一般情况下与第三个参数相同或者使用默认值。 本节应用案例如下
//用undiststort()函数直接计算校正图像
void undist(vectorMat imgs, //原有图像向量Mat cameraMatrix, //计算得到的相机内存Mat distCoeffs, //计算得到的相机畸变系数vectorMat undistImgs //校正后的输出图像
)
{for (int i 0; i imgs.size(); i){Mat undisImg;undistort(imgs[i], undistImgs, cameraMatrix, distCoeffs);undistImgs.push_back(undisImg);}
}int main() {//读取图像vectorMatimgs;string imgName;//读取存放图片路径的txt文件ifstream fin(ca.txt);//挨个读取图片while (getline(fin, imgName)){Mat img imread(imgName);imgs.push_back(img);}//输入计算的内参矩阵和畸变矩阵(在相机厂家说明或者标定获得)Mat cameraMatrix (Mat_float(3, 3) 120.8643306554273, 0, 94.55565247064737,0, 119.979406894919, 55.48571212317609,0, 0, 1);Mat distCoeffs (Mat_float(1, 5) -0.5559208449775317, 3.15840209023594, -0.001816753642197531, -0.01817901488786, -7.629569308066959);//去畸变图像存放变量vectorMat undistImags;Size imageSize;imageSize.width imgs[0].cols;imageSize.height imgs[0].rows;undist(imgs, cameraMatrix, distCoeffs, undistImags);//显示校正后的图像for (int i 0; i imgs.size(); i){string windowNumber to_string(i);imshow(矫正后的图像 windowNumber, undistImags[i]);waitKey(0);destroyWindow(矫正后的图像 windowNumber);}waitKey(0);return 0;
}