我正在进行一个OpenCV项目,正在进行校准。我相信我已经正确地实现了代码;然而,我得到了不同的相机矩阵值,有时变化很大。在重复6次显示校准模式10次后,我得到(为清晰起见,小数被截断):
[573, 0, 386;
0, 573, 312;
0, 0, 1]
[642, 0, 404;
0, 644, 288;
0, 0, 1]
[664, 0, 395;
0, 665, 272;
0, 0, 1]
[629, 0, 403;
0, 630, 288;
0, 0, 1]
[484, 0, 377;
0, 486, 307;
0, 0, 1]
[644, 0, 393;
0, 643, 289;
0, 0, 1]
这些数值相差不可接受的程度。我需要准确地知道给定的参数是什么。这些大的不准确度的典型原因是什么?我如何评估给定矩阵的正确性?这似乎取决于我展示图案的距离和方向的变化,但我无法理解图案。
代码:
using namespace cv;
using namespace std;
int main(int, char**)
{
VideoCapture cap(1);
if(!cap.isOpened())
return -1;
cap.set(CV_CAP_PROP_FRAME_WIDTH,800);
cap.set(CV_CAP_PROP_FRAME_HEIGHT,600);
Mat edges;
Size size(9,17);
int counter = 10;
vector<Point2f> corners;
bool found;
vector<Point3f> chess = fr::ChessGen::getBoard(size,1,true);
vector<vector<Point3f> > objectPoints;
vector<vector<Point2f> > imagePoints;
Mat camera = Mat::eye(3,3,CV_64F);
Mat distortion = Mat::zeros(8, 1, CV_64F);
vector<Mat > rvecs;
vector<Mat > tvecs;
namedWindow("edges",1);
for(;;)
{
Mat frame;
cap >> frame;
cvtColor(frame, edges, CV_BGR2GRAY);
found = findCirclesGrid(edges,size,corners
,CALIB_CB_ASYMMETRIC_GRID
);
if(found) frame.convertTo(edges,-1,0.2);
drawChessboardCorners(edges,size,corners,found);
imshow("edges", edges);
if(found){
if(waitKey(200)>=0){
objectPoints.push_back(chess);
imagePoints.push_back(corners);
if(--counter<= 0)
break;
}
}
else waitKey(30);
}
calibrateCamera(objectPoints,imagePoints,Size(800,600),camera,distortion,rvecs,tvecs,0);
if(found) imwrite("/home/ryan/snapshot.png",edges);
cout << camera << endl;
return 0;
}
取决于相机/镜头和所需的精度,但您可能需要10个以上的位置,并且需要覆盖更大范围的视角。
我从800x600假设这是一个带有简单广角镜头的网络摄像头,有很多失真。我想说,你需要6-8个位置/旋转的目标,每3-4个不同的角度到相机。你还需要确保目标和相机是固定的,在拍摄过程中不会移动。再次假设相机有简单的自动增益,你应该确保目标照明良好,这样它就会使用快速快门速度和低增益。
openCV使用的技术的一个问题是,它需要看到目标上的所有角落/点,才能识别并在解决方案中使用帧,因此很难在图像的角落附近找到点。你应该检查数据中实际用于校准的图像数量——可能只是在10张图像中的少数图像上找到所有点,并基于该子集制定解决方案。
同样重要的是,不要只拍摄垂直于相机的图案,而是旋转它们。为了提高结果质量,您还可以仔细检查检测到的角点的位置,删除未正确检测到某些角点的图片,然后再次运行算法。
我不知道你用的是哪台相机,但由于相机失真严重,不够清晰,所以很难正确检测到角落。OpenCV校准也可以用圆形图案来实现,在这种情况下可以获得更好的结果。
根据我的经验,您应该使用OpenCV提供的函数undistortion(),使用未失真的图像进行校准。
这意味着你要进行两次校准,第一次是确定透镜系数。然后在第二轮比赛中不干扰每个棋盘框。使用无失真校准帧,焦距fx和fy变得更加精确。
根据张正友的论文,合适的角度在45度以下,而且必须有6张以上的照片,最好拍20张。此外,你需要注意光的平衡和强度。