张正友相机标定Opencv实现以及标定流程&&标定结果评价&&图像矫正流程解析(附标定程序和棋盘图)...

本文介绍了使用Opencv进行张正友相机标定的详细步骤,包括准备标定图片、提取角点信息、亚像素角点定位、相机标定、结果评价和图像矫正。通过标定,可以获得相机的内参和外参矩阵,用于减少图像畸变。文章还展示了不同方法的矫正效果对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用Opencv实现张正友法相机标定之前,有几个问题事先要确认一下,那就是相机为什么需要标定,标定需要的输入和输出分别是哪些?


相机标定的目的:获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的选择和平移矩阵),内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像。

相机标定的输入:标定图像上所有内角点的图像坐标,标定板图像上所有内角点的空间三维坐标(一般情况下假定图像位于Z=0平面上)。

相机标定的输出:摄像机的内参、外参系数。


这三个基础的问题就决定了使用Opencv实现张正友法标定相机的标定流程、标定结果评价以及使用标定结果矫正原始图像的完整流程:


1. 准备标定图片

2. 对每一张标定图片,提取角点信息

3. 对每一张标定图片,进一步提取亚像素角点信息

4. 在棋盘标定图上绘制找到的内角点(非必须,仅为了显示)

5. 相机标定

6. 对标定结果进行评价

7. 查看标定效果——利用标定结果对棋盘图进行矫正


1. 准备标定图片


标定图片需要使用标定板在不同位置、不同角度、不同姿态下拍摄,最少需要3张,以10~20张为宜。标定板需要是黑白相间的矩形构成的棋盘图,制作精度要求较高,如下图所示:





2.对每一张标定图片,提取角点信息


需要使用findChessboardCorners函数提取角点,这里的角点专指的是标定板上的内角点,这些角点与标定板的边缘不接触。

 findChessboardCorners函数原型:

//! finds checkerboard pattern of the specified size in the image
CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize,
                                         OutputArray corners,
                                         int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE );


第一个参数Image,传入拍摄的棋盘图Mat图像,必须是8位的灰度或者彩色图像;

第二个参数patternSize,每个棋盘图上内角点的行列数,一般情况下,行列数不要相同,便于后续标定程序识别标定板的方向;

第三个参数corners,用于存储检测到的内角点图像坐标位置,一般用元素是Point2f的向量来表示:vector<Point2f> image_points_buf;

第四个参数flage:用于定义棋盘图上内角点查找的不同处理方式,有默认值。



3. 对每一张标定图片,进一步提取亚像素角点信息


为了提高标定精度,需要在初步提取的角点信息上进一步提取亚像素信息,降低相机标定偏差,常用的方法是cornerSubPix,另一个方法是使用find4QuadCornerSubpix函数,这个方法是专门用来获取棋盘图上内角点的精确位置的,或许在相机标定的这个特殊场合下它的检测精度会比cornerSubPix更高?

cornerSubPix函数原型:

//! adjusts the corner locations with sub-pixel accuracy to maximize the certain cornerness criteria
CV_EXPORTS_W void cornerSubPix( InputArray image, InputOutputArray corners,
                                Size winSize, Size zeroZone,
                                TermCriteria criteria );

第一个参数image,输入的Mat矩阵,最好是8位灰度图像,检测效率更高;

第二个参数corners,初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据,一般用元素是Pointf2f/Point2d的向量来表示:vector<Point2f/Point2d> iamgePointsBuf;

第三个参数winSize,大小为搜索窗口的一半;

第四个参数zeroZone,死区的一半尺寸,死区为不对搜索区的中央位置做求和运算的区域。它是用来避免自相关矩阵出现某些可能的奇异性。当值为(-1,-1)时表示没有死区;

第五个参数criteria,定义求角点的迭代过程的终止条件,可以为迭代次数和角点精度两者的组合;

find4QuadCornerSubpix函数原型:

//! finds subpixel-accurate positions of the chessboard corners
CV_EXPORTS bool find4QuadCornerSubpix(InputArray img, InputOutputArray corners, Size region_size);

第一个参数img,输入的Mat矩阵,最好是8位灰度图像,检测效率更高;

第二个参数corners,初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据,一般用元素是Pointf2f/Point2d的向量来表示:vector<Point2f/Point2d> iamgePointsBuf;

第三个参数region_size,角点搜索窗口的尺寸;

在其中一个标定的棋盘图上分别运行cornerSubPix和find4QuadCornerSubpix寻找亚像素角点,两者定位到的亚像素角点坐标分别为:


   cornerSubPix:                                                 find4QuadCornerSubpix:

在C++中使用OpenCV进行相机标定矫正是一个常见的计算机视觉任务。相机标定的主要目的是确定相机的内参和外参,从而矫正由于镜头畸变导致的图像失真。以下是一个基本的步骤和代码示例,帮助你理解如何使用OpenCV进行相机标定矫正。 ### 步骤: 1. **准备标定板**:通常使用棋盘格作为标定板。确保标定板在不同的位置和角度下被拍摄多张片。 2. **检测棋盘格角点**:使用OpenCV提供的函数检测棋盘格的角点。 3. **相机标定**:使用检测到的角点进行相机标定,计算相机的内参和畸变系数。 4. **矫正**:使用标定结果片进行矫正,去除畸变。 ### 代码示例: ```cpp #include <opencv2/opencv.hpp> #include <vector> #include <string> int main() { // 1. 读取标定片 std::vector<std::string> imageFiles; // 假设标定片存放在calib_images文件夹下 cv::glob("calib_images/*.jpg", imageFiles); // 2. 检测棋盘格角点 cv::Size patternSize(9, 6); // 棋盘格内角点的行数和列数 std::vector<std::vector<cv::Point2f>> imagePoints; std::vector<cv::Point3f> objectPoint; for (int i = 0; i < patternSize.height; ++i) { for (int j = 0; j < patternSize.width; ++j) { objectPoint.push_back(cv::Point3f(j, i, 0)); } } for (const auto& file : imageFiles) { cv::Mat image = cv::imread(file); cv::Mat gray; cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY); std::vector<cv::Point2f> corners; bool found = cv::findChessboardCorners(gray, patternSize, corners); if (found) { imagePoints.push_back(corners); cv::drawChessboardCorners(image, patternSize, corners, found); cv::imshow("Chessboard", image); cv::waitKey(100); } } // 3. 相机标定 std::vector<std::vector<cv::Point3f>> objectPoints(imagePoints.size(), objectPoint); cv::Mat cameraMatrix, distCoeffs; std::vector<cv::Mat> rvecs, tvecs; cv::calibrateCamera(objectPoints, imagePoints, gray.size(), cameraMatrix, distCoeffs, rvecs, tvecs); // 4. 矫正 for (const auto& file : imageFiles) { cv::Mat image = cv::imread(file); cv::Mat undistorted; cv::undistort(image, undistorted, cameraMatrix, distCoeffs); cv::imshow("Original", image); cv::imshow("Undistorted", undistorted); cv::waitKey(0); } return 0; } ``` ### 代码说明: 1. **读取标定片**:使用`cv::glob`函数读取所有标定片。 2. **检测棋盘格角点**:使用`cv::findChessboardCorners`函数检测棋盘格的角点。 3. **相机标定**:使用`cv::calibrateCamera`函数进行相机标定,计算相机的内参和畸变系数。 4. **矫正**:使用`cv::undistort`函数对片进行矫正
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值