cv 畸变图像校正(使用openCV)
获取镜头的畸变参数
- 1 基于平面标定版的畸变参数计算。使用既定的标定版,从多个角度进行拍照,如下:
- 2 使用openCV中的标定板角点检测函数,检测出角点。
int cvFindChessboardCorners(const void* image, CvSize patternSize, CvPoint2D32f* corners, int* cornerCount=NULL, int flags=CV_CALIB_CB_ADAPTIVE_THRESHParameters:
-
- image – Source chessboard view; it must be an 8-bit grayscale or color image
- patternSize – The number of inner corners per chessboard row and column ( patternSize = cvSize(points_per_row,points_per_colum) = cvSize(columns,rows) )
- corners – The output array of corners detected
- cornerCount – The output corner counter. If it is not NULL, it stores the number of corners found
- flags – Various operation flags, can be 0 or a combination of the following values:
- CV_CALIB_CB_ADAPTIVE_THRESH - use adaptive thresholding to convert the image to black and white, rather than a fixed threshold level (computed from the average image brightness).
- CV_CALIB_CB_NORMALIZE_IMAGE - normalize the image gamma with EqualizeHist before applying fixed or adaptive thresholding.
- CV_CALIB_CB_FILTER_QUADS - use additional criteria (like contour area, perimeter, square-like shape) to filter out false quads that are extracted at the contour retrieval stage.
- 3 找到亚像素角度位置,函数:cvFindCornerSubPix
- 4 赋值给像点坐标和对应地面点坐标
size.height = img_->height; size.width = img_->width;float dImage[CornerNumbers*2]; float dObject[CornerNumbers*3]; int dCount[NumberImages]; float dIntrin[9];// float dDistor[4];// float dRot[NumberImages*3]; float dTrans[NumberImages*3]; CvMat object_points, image_points, point_counts; CvMat intrinsic, distortion, rot, trans; cvInitMatHeader(&object_points,CornerNumbers ,3, CV_32FC1, dObject); cvInitMatHeader(&image_points, CornerNumbers, 2, CV_32FC1, dImage); cvInitMatHeader(&point_counts, NumberImages, 1, CV_32SC1, dCount); cvInitMatHeader(&intrinsic, 3, 3, CV_32FC1, dIntrin); cvInitMatHeader(&distortion, 1, 4, CV_32FC1, dDistor); cvInitMatHeader(&rot, NumberImages, 3, CV_32FC1, dRot); cvInitMatHeader(&trans, NumberImages, 3, CV_32FC1, dTrans); for (int i = 0; i < NumberImages; i++) { dCount[i] = ROWS*COLS;// *****每一行角点数(ROWS),每一列角点数(COLS) for (int j = 0; j < COLS; j++) for (int k = 0; k < ROWS; k++) { dImage[i*COLS*ROWS*2 + 2*ROWS*j + 2*k + 0] = p[i*COLS*ROWS+j*ROWS+k].x; dImage[i*COLS*ROWS*2 + 2*ROWS*j + 2*k + 1] = p[i*COLS*ROWS+j*ROWS+k].y; dObject[i*COLS*ROWS*3 + 3*ROWS*j + 3*k + 0] = k*10; dObject[i*COLS*ROWS*3 + 3*ROWS*j + 3*k + 1] = j*10; dObject[i*COLS*ROWS*3 + 3*ROWS*j + 3*k + 2] = 0; } }
- 5 计算内外方位元素
cvCalibrateCamera2(&object_points, &image_points, &point_counts, size, &intrinsic, &distortion, &rot, &trans, CV_CALIB_FIX_PRINCIPAL_POINT);
根据畸变参数纠正影像
int width=image->width; int high=image->height; CvSize sz= buildSize(width,high); IplImage* dst = cvCreateImage( sz, IPL_DEPTH_8U, 1); //转换为灰度图 cvCvtColor( image, ImageGry, CV_RGB2GRAY); //cvFlip( ImageGry, NULL, 0);// 有时候需要翻转 double *mi= new double[3*3]; double *md = new double[4]; CvMat intrinsic_matrix,distortion_coeffs; //摄像机内参数 cvInitMatHeader(&intrinsic_matrix,3,3,CV_64FC1,mi); //镜头畸变参数 cvInitMatHeader(&distortion_coeffs,1,4,CV_64FC1,md); //****** 畸变参数 赋值 ******* double fc1,fc2,cc1,cc2,kc1,kc2,kc3,kc4; fc1 = 533.817749; fc2 = 534.484619 ; cc1 = 319.5; cc2 = 239.5; kc1 = -0.302179; kc2 = 0.148561; kc3 = 0.001140 ; kc4 = -0.000979; cvmSet(&intrinsic_matrix, 0, 0, fc1); cvmSet(&intrinsic_matrix, 0, 1, 0); cvmSet(&intrinsic_matrix, 0, 2, cc1); cvmSet(&intrinsic_matrix, 1, 0, 0); cvmSet(&intrinsic_matrix, 1, 1, fc2); cvmSet(&intrinsic_matrix, 1, 2, cc2); cvmSet(&intrinsic_matrix, 2, 0, 0); cvmSet(&intrinsic_matrix, 2, 1, 0); cvmSet(&intrinsic_matrix, 2, 2, 1); cvmSet(&distortion_coeffs, 0, 0, kc1); cvmSet(&distortion_coeffs, 0, 1, kc2); cvmSet(&distortion_coeffs, 0, 2, kc3); cvmSet(&distortion_coeffs, 0, 3, kc4); //******** 矫正畸变(opencv)*********** cvUndistort2( ImageGry, dst, &intrinsic_matrix, &distortion_coeffs);
//******** 显示结果 (opencv)***********
cvNamedWindow( "矫正", 1 );//创建窗口
cvShowImage("矫正", dst);
cvWaitKey(1);
cvReleaseImage( &dst );
原图和纠正的图