/u010128736/article/details/52875137
/h532600610/article/details/51800488
python 角点检测+相机标定+去畸变+重投影误差计算:
#coding:utf-8
importcv2importnumpy as npimportglob#找棋盘格角点#阈值
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)#棋盘格模板规格
w = 9h= 6
#世界坐标系中的棋盘格点,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z坐标,记为二维矩阵
objp = np.zeros((w*h,3), np.float32)
objp[:,:2] = np.mgrid[0:w,0:h].T.reshape(-1,2)#储存棋盘格角点的世界坐标和图像坐标对
objpoints = [] #在世界坐标系中的三维点
imgpoints = [] #在图像平面的二维点
images= glob.glob('calib/*.png')for fname inimages:
img=cv2.imread(fname)
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#找到棋盘格角点
ret, corners =cv2.findChessboardCorners(gray, (w,h),None)#如果找到足够点对,将其存储起来
if ret ==True:
cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
objpoints.append(objp)
imgpoints.append(corners)#将角点在图像上显示
cv2.drawChessboardCorners(img, (w,h), corners, ret)
cv2.imshow('findCorners',img)
cv2.waitKey(1)
cv2.destroyAllWindows()#标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)#去畸变
img2 = cv2.imread('calib/00169.png')
h, w= img2.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),0,(w,h)) #自由比例参数
dst =cv2.undistort(img2, mtx, dist, None, newcameramtx)#根据前面ROI区域裁剪图片#x,y,w,h = roi#dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)#反投影误差
total_error =0for i inxrange(len(objpoints)):
imgpoints2, _=cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
error= cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
total_error+=errorprint "total error:", total_error/len(objpoints)
标定 cv2.calibrateCamera函数文档:/2.4.1/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html
c++ 角点检测+角点绘制:
#include #include#include#include
using namespacestd;intmain( )
{
cout<
IplImage* imgRGB =cvLoadImage(filename);
IplImage* imgGrey =cvLoadImage(filename,CV_LOAD_IMAGE_GRAYSCALE);if (imgGrey==NULL){//image validation
cout<< "No valid image input."<
}//-------find chessboard corners--------------
int corner_row=7;//interior number of row corners.(this can be countered by fingers.)
int corner_col=7;//interior number of column corners.
int corner_n=corner_row*corner_col;
CvSize pattern_size=cvSize(corner_row,corner_col);//CvPoint2D32f* corners=new CvPoint2D32f[corner_n];
CvPoint2D32f corners[49];intcorner_count;int found=cvFindChessboardCorners(//returning non-zero means sucess.
imgGrey,//8-bit single channel greyscale image.
pattern_size,//how many INTERIOR corners in each row and column of the chessboard.
corners,//an array where the corner locations can be recorded.
&corner_count,//optional, if non-NULL, its a point to an integer where the nuber of corners found can be recorded.//CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS//check page 382-383.
0);
cout<
cvDrawChessboardCorners(
imgRGB,
pattern_size,
corners,
corner_count,
found
);
cvSaveImage(filename2,imgRGB);//to summary a bit of findings.
cout<
cout<
cout<
cvNamedWindow("Find and Draw ChessBoard", 0);
cvShowImage("Find and Draw ChessBoard", imgRGB );
cvWaitKey(0);
cvReleaseImage(&imgGrey);
cvReleaseImage(&imgRGB);
cvDestroyWindow("Find and Draw ChessBoard");return 0;
}
注意事项:
pattern_size参数传递内点数,8*8的棋盘只有7*7内点。
图像选取应注意减少干扰,例如光照与背景等。
Corners中的角点坐标顺序排列规律不一定是以行从左上到右下。使用坐标计算映射关系时应提高警惕,对坐标进行重新排列。
关键函数参数说明:
int cvFindChessboardCorners( const void* image, CvSize pattern_size, CvPoint2D32f* corners, int* corner_count=NULL, int flags=CV_CALIB_CB_ADAPTIVE_THRESH );
Image:
输入的棋盘图,必须是8位的灰度或者彩色图像。
pattern_size:
棋盘图中每行和每列角点的个数。
Corners:
检测到的角点
corner_count:
输出,角点的个数。如果不是NULL,函数将检测到的角点的个数存储于此变量。
Flags:
各种操作标志,可以是0或者下面值的组合:
CV_CALIB_CB_ADAPTIVE_THRESH -使用自适应阈值(通过平均图像亮度计算得到)将图像转换为黑白图,而不是一个固定的阈值。
CV_CALIB_CB_NORMALIZE_IMAGE -在利用固定阈值或者自适应的阈值进行二值化之前,先使用cvNormalizeHist来均衡化图像亮度。
CV_CALIB_CB_FILTER_QUADS -使用其他的准则(如轮廓面积,周长,方形形状)来去除在轮廓检测阶段检测到的错误方块。