OpenCV 相机标定
语音余音玉印 人气:0环境准备
vs2015+opencv4.10安装与配置
相机标定
棋盘格图片
可以自己生成,然后打印到A4纸上。(也可以去TB买一块,平价买亚克力板的,不反光买氧化铝材质,高精度买陶瓷的)
/** * 生成棋盘格图片 **/ int generateCalibrationPicture() { //Mat frame = imread("3A4.bmp"); // cols*rows = 630*891 Mat frame(1600, 2580, CV_8UC3, Scalar(0, 0, 0)); int nc = frame.channels(); int nWidthOfROI = 320; for (int j = 10; j<frame.rows - 10; j++) { uchar* data = frame.ptr<uchar>(j); for (int i = 10; i<(frame.cols - 10)*nc; i += nc) { if ((i / nc / nWidthOfROI + j / nWidthOfROI) % 2) { // bgr data[i / nc*nc + 0] = 255; data[i / nc*nc + 1] = 255; data[i / nc*nc + 2] = 255; } } } imshow("test", frame); //imwrite("3.bmp", frame); waitKey(0); return 0; }
实时显示相机的画面
准备一个相机,我的是usb相机(罗技100多的)。
int displayCameraRealTime() { //1.从摄像头读入视频 VideoCapture capture(0); if (!capture.isOpened()) { std::cout << "无法开启摄像头!" << std::endl; return -1; } //2.循环显示每一帧 while (1) { Mat cam; capture >> cam;//获取当前帧图像 namedWindow("实时相机画面", WINDOW_AUTOSIZE); imshow("实时相机画面", cam);//显示当前帧图像 //imwrite(to_string(i) + ".png", cam); waitKey(20);//延时20ms } }
效果如下图:
在线标定
把打印的棋盘格固定在板子上
/** * 实时检测角点,按键保存角点参数,达到数量执行标定并保存标定结果 * @param numBoards 需要几张标定图片,即获取几组角点参数 * @param boardSize 格子尺寸Size 7*4 * @param squareSize 格子尺寸 mm * @param flipHorizontal 是否翻转 */ int calibrateCameraRealTime(int numBoards, cv::Size boardSize, float squareSize = 1, int delay = 50, bool flipHorizontal = false);
实时显示相机画面,按键保存能检测到角点的 棋盘格图片
int saveChessboardImages(cv::Size boardSize, string savePath) { //1.从摄像头读入视频 VideoCapture capture(0); if (!capture.isOpened()) { std::cout << "无法开启摄像头!" << std::endl; return -1; } if (savePath != "./") { myMkdir(savePath); } //2.循环显示每一帧 while (1) { Mat image0, image; capture >> image0; // 将图像复制到image image0.copyTo(image); // 查找标定板(不对称圆网格板) vector<Point2f> corners; //bool found = findCirclesGrid(image, boardSize, corners, CALIB_CB_ASYMMETRIC_GRID); bool found = findChessboardCorners(image, boardSize, corners, CALIB_CB_FAST_CHECK); // 画上去 drawChessboardCorners(image, boardSize, corners, found); int action = waitKey(30) & 255; // 判断动作 if (action == ACTION_SPACE) { // 用户按下了空格 if (found) { // 保存图片 string imgFileName = savePath + getCurrentTime() + ".png"; imwrite(imgFileName, image0); cout << imgFileName << " saved" << endl; } else { printf("%s\n", "未检测到角点"); } } else if (action == ACTION_ESC) { // 用户按下了ESC break; } cv::imshow("Calibration", image); } cv::destroyAllWindows(); return 1; }
离线标定
/** * 离线相机标定 * @param imagePath 标定图片存放路径 * @param boardSize 格子尺寸Size 7*4 * @param squareSize 格子尺寸 mm */ int calibrateCameraOffLine(string imagePath, const Size boardSize, float squareSize = 1);
畸变矫正
/** * 去畸变 1、本地图片 2、实时相机图像 * @param path 标定参数存放路径 * @param imagePath 需要矫正的图片 存放路径 */ int undistortRectifyImage(string paraPath, string imagePath = " ");
矫正效果貌似不明显
加载全部内容