opencv对相机进行畸变校正,及校正前后的坐标对应

您所在的位置:网站首页 相机畸变系数 opencv对相机进行畸变校正,及校正前后的坐标对应

opencv对相机进行畸变校正,及校正前后的坐标对应

2024-07-15 06:41| 来源: 网络整理| 查看: 265

文章目录 1.背景2.需求分析3.解决方案3.1.镜头畸变校正3.2.知道校正后的画面坐标(x, y),求其在原画面的坐标(x', y')3.2.知道原画面坐标(x1, y1),求其在校正后的画面坐标(x2, y2) 4.效果5.代码

1.背景

目前有个项目,需要用到热成像相机。但是这个热成像相机它的畸变比较厉害,因此需要用标定板进行标定,从而消除镜头畸变。 同时需要实现用户用鼠标点击校正后的画面后,显示用户点击位置的像素所代表的温度。 另外热成像sdk中还有个功能:选定一个rect,可以返回这个rect中的最高最低温度以及其各自的位置。假如我们需要这个功能,那么又需要知道从src到dst的关系了。

2.需求分析

消除镜头畸变后,就不能直接使用热成像sdk提供的函数来查询像素对应的温度。 因为在查询函数中,有个像素坐标的形参,要求传入原来的热成像图像A的像素坐标,函数返回此像素位置的温度。 而我们经过畸变消除后,得到画面B。B上面的特定像素所处的坐标和原图不一定一样。 因此,假如用户想查询画面B上的某个像素点的有效温度,就必须要取得此像素点在原图A上的位置坐标。 而在知道原图的最高最低温度点的位置后,需要知道其在校正后的画面中的位置,才能准确绘制出来。 总结一下,需要实现以下功能: a、镜头畸变校正 b、知道校正后的画面坐标(x,y),求其在原画面的坐标(x’,y’) c、知道原画面坐标(x1,y1),求其在校正后的画面坐标(x2,y2)

3.解决方案

其实很简单,opencv本身就提供了。

3.1.镜头畸变校正

在经过 findChessboardCorners、calibrateCamera之后,我们就已经获得了相机矩阵cameraMatrix、畸变矩阵distCoeffs。 然后,我们利用getOptimalNewCameraMatrix,获得了一个相对容易控制画面取舍的新相机矩阵newCamMatrix。 接下来,就有两种方式对画面进行校正: a、直接undistort。 b、先利用initUndistortRectifyMap得到map1、map2,然后再利用remap进行画面校正。 后面的代码把两种都演示了。

3.2.知道校正后的画面坐标(x, y),求其在原画面的坐标(x’, y’)

其实,我们真正需要的是第二种。 关键就在于map1、map2。 这两个矩阵是什么玩意呢? 其实你先看看他们的尺寸、通道数,再查阅一下资料就知道了: map1、map2的尺寸与目标图像(校正后的图像)的尺寸一致,而通道数为1(这个其实不一定,与其他参数有关,暂时先这样认为)。我们假设,最终图像(x,y)处的像素来源于源图像(x’,y’)处,那么,map1中存储了坐标(x’,y’)中的x’,而map2中存储了y’。 虽然我描述得很混乱,但是你配合代码应该明白我在说什么。😁 所以,我们直接利用这个map1、map2就可以实现从消除畸变后的画面坐标转换到原画面的坐标了。

initUndistortRectifyMap(cameraMatrix, distCoeffs, cv::Mat(), newCamMatrix, imageSize, CV_32FC1, map1, map2); ...... Point dstPt(400, 109); double pt_x = map1.at(dstPt); double pt_y = map2.at(dstPt); 3.2.知道原画面坐标(x1, y1),求其在校正后的画面坐标(x2, y2)

这个可以利用opencv的undistortPoints函数进行求解。 假如你是单目相机标定,需要注意第三个参数使用相机矩阵、第五个参数使用空矩阵、第六个参数使用新相机矩阵。这些参数需要和initUndistortRectifyMap的相对应起来。

vector srcPts; srcPts.push_back(Point2f(300, 145)); vector dstPts; undistortPoints(srcPts, dstPts, cameraMatrix, distCoeffs, Mat(), newCamMatrix);

假如你用的是立体相机标定的话【opencv/samples/cpp/stereo_calib.cpp】,可以直接把得到的R、P填上去:

stereoRectify(cameraMatrix[0], distCoeffs[0], cameraMatrix[1], distCoeffs[1], imageSize, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, 1, imageSize, &validRoi[0], &validRoi[1]); ...... vector srcPts; srcPts.push_back(Point2f(110, 205)); vector dstPts; undistortPoints(srcPts, dstPts, cameraMatrix[0], distCoeffs[0], R1, P1); 4.效果

由于一些原因,我不能直接展示我的效果图。这里用opencv自带的图像来演示吧。 在这里插入图片描述

5.代码 int cameraCalibration() { Size boardSize = {9, 6}; float squareSize = 0.05; bool displayCorners = false; vector imageList; for(int i = 0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3