这里介绍了一个使用directshow标定与Matlab的示例,写的很详细。
http://w3.impa.br/~pcezar/3dp/original/CVL_html/appPage/doc_calib.html#Tutorial
OPENCV没有提供完整的示例,自己整理了一下,贴出来记录。
步骤如下:
首先自制一张标定图片,用A4纸打印出来,设定距离,再设定标定棋盘的格子数目,如8×6,以下是我做的图片8×8
然后利用cvFindChessboardCorners找到棋盘在摄像头中的2D位置,这里cvFindChessboardCorners不太稳定,有时不能工作。
计算实际的距离,应该是3D的距离。我设定为21.6毫米,既在A4纸上为两厘米。
再用cvCalibrateCamera2计算内参,
最后用cvUndistort2纠正图像的变形。
结果如下:
源代码如下:
- #include "stdafx.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <cxcore.h>
- #include <cv.h>
- #include <highgui.h>
- #include <cvaux.h>
-
-
- void InitCorners3D(CvMat *Corners3D, CvSize ChessBoardSize,
- int Nimages, float SquareSize);
- void makeChessBoard();
- int myFindChessboardCorners( const void* image, CvSize pattern_size,
- CvPoint2D32f* corners, int* corner_count=NULL,
- int flags=CV_CALIB_CB_ADAPTIVE_THRESH );
-
-
- inline int drawCorssMark(IplImage *dst,CvPoint pt)
-
-
-
-
-
-
-
-
-
-
- {
-
- const int cross_len = 4;
- CvPoint pt1,pt2,pt3,pt4;
- pt1.x = pt.x;
- pt1.y = pt.y - cross_len;
- pt2.x = pt.x;
- pt2.y = pt.y + cross_len;
- pt3.x = pt.x - cross_len;
- pt3.y = pt.y;
- pt4.x = pt.x + cross_len;
- pt4.y = pt.y;
-
- cvLine(dst,pt1,pt2,CV_RGB(0,255,0),2,CV_AA, 0 );
- cvLine(dst,pt3,pt4,CV_RGB(0,255,0),2,CV_AA, 0 );
-
- return 0;
- }
-
-
- IplImage *current_frame_rgb,grid;
- IplImage *current_frame_gray;
- IplImage *chessBoard_Img;
-
- int Thresholdness = 120;
-
- int image_width = 320;
- int image_height = 240;
-
- bool verbose = false;
-
- const int ChessBoardSize_w = 7;
- const int ChessBoardSize_h = 7;
-
- bool calibration_done = false;
- const CvSize ChessBoardSize = cvSize(ChessBoardSize_w,ChessBoardSize_h);
-
- float SquareWidth = 17;
-
- const int NPoints = ChessBoardSize_w*ChessBoardSize_h;
- const int NImages = 20;
-
- CvPoint2D32f corners[NPoints*NImages];
- int corner_count[NImages] = {0};
- int captured_frames = 0;
-
- CvMat *intrinsics;
- CvMat *distortion_coeff;
- CvMat *rotation_vectors;
- CvMat *translation_vectors;
- CvMat *object_points;
- CvMat *point_counts;
- CvMat *image_points;
- int find_corners_result =0 ;
-
-
- void on_mouse( int event, int x, int y, int flags, void* param )
- {
-
- if( event == CV_EVENT_LBUTTONDOWN )
- {
-
- }
- }
-
-
- int main(int argc, char *argv[])
- {
-
-
- CvFont font;
- cvInitFont( &font, CV_FONT_VECTOR0,5, 5, 0, 7, 8);
-
- intrinsics = cvCreateMat(3,3,CV_32FC1);
- distortion_coeff = cvCreateMat(1,4,CV_32FC1);
- rotation_vectors = cvCreateMat(NImages,3,CV_32FC1);
- translation_vectors = cvCreateMat(NImages,3,CV_32FC1);
-
- point_counts = cvCreateMat(NImages,1,CV_32SC1);
-
- object_points = cvCreateMat(NImages*NPoints,3,CV_32FC1);
- image_points = cvCreateMat(NImages*NPoints,2,CV_32FC1);
-
-
-
- InitCorners3D(object_points, ChessBoardSize, NImages, SquareWidth);
-
-
- CvCapture* capture = 0;
-
-
- if( argc == 1 || (argc==2 && strlen(argv[1])==1 && isdigit(argv[1][0])))
- capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
- else if( argc == 2 )
- capture = cvCaptureFromAVI( argv[1] );
-
- if( !capture )
- {
- fprintf(stderr,"Could not initialize capturing ");
- return -1;
- }
-
-
-
- current_frame_rgb =
- cvCreateImage(cvSize(image_width, image_height), IPL_DEPTH_8U, 3);
-
- IplImage *current_frame_rgb2 =
- cvCreateImage(cvSize(image_width, image_height), IPL_DEPTH_8U, 3);
- current_frame_gray =
- cvCreateImage(cvSize(image_width, image_height), IPL_DEPTH_8U, 1);
-
- chessBoard_Img =
- cvCreateImage(cvSize(image_width, image_height), IPL_DEPTH_8U, 3);
- current_frame_rgb2->origin = chessBoard_Img->origin =
- current_frame_gray->origin = current_frame_rgb->origin = 1;
-
- makeChessBoard();
-
- cvNamedWindow( "result", 0);
- cvNamedWindow( "Window 0", 0);
- cvNamedWindow( "grid", 0);
- cvMoveWindow( "grid", 100,100);
- cvSetMouseCallback( "Window 0", on_mouse, 0 );
- cvCreateTrackbar("Thresholdness","Window 0",&Thresholdness, 255,0);
-
- while (!calibration_done)
- {
-
- while (captured_frames < NImages)
- {
- current_frame_rgb = cvQueryFrame( capture );
-
-
-
- if( !current_frame_rgb )
- break;
-
- cvCopy(current_frame_rgb,current_frame_rgb2);
- cvCvtColor(current_frame_rgb, current_frame_gray, CV_BGR2GRAY);
-
- Thresholdness,255,CV_THRESH_BINARY);
-
- 150,255,CV_THRESH_BINARY_INV);
-
-
-
-
-
-
-
-
-
-
-
-
- find_corners_result = cvFindChessboardCorners(current_frame_gray,
- ChessBoardSize,
- &corners[captured_frames*NPoints],
- &corner_count[captured_frames],
- 0);
-
-
-
- cvDrawChessboardCorners(current_frame_rgb2, ChessBoardSize,
- &corners[captured_frames*NPoints], NPoints, find_corners_result);
-
-
- cvShowImage("Window 0",current_frame_rgb2);
- cvShowImage("grid",chessBoard_Img);
-
- if(find_corners_result==1)
- {
- cvWaitKey(2000);
- cvSaveImage("c:\hardyinCV.jpg",current_frame_rgb2);
- captured_frames++;
- }
-
-
- intrinsics->data.fl[0] = 256.8093262;
- intrinsics->data.fl[2] = 160.2826538;
- intrinsics->data.fl[4] = 254.7511139;
- intrinsics->data.fl[5] = 127.6264572;
-
- intrinsics->data.fl[1] = 0;
- intrinsics->data.fl[3] = 0;
- intrinsics->data.fl[6] = 0;
- intrinsics->data.fl[7] = 0;
- intrinsics->data.fl[8] = 1;
-
- distortion_coeff->data.fl[0] = -0.193740;
- distortion_coeff->data.fl[1] = -0.378588;
- distortion_coeff->data.fl[2] = 0.028980;
- distortion_coeff->data.fl[3] = 0.008136;
-
- cvWaitKey(40);
- find_corners_result = 0;
- }
-
- {
-
- printf(" ");
-
- cvSetData( image_points, corners, sizeof(CvPoint2D32f));
- cvSetData( point_counts, &corner_count, sizeof(int));
-
-
- cvCalibrateCamera2( object_points,
- image_points,
- point_counts,
- cvSize(image_width,image_height),
- intrinsics,
- distortion_coeff,
- rotation_vectors,
- translation_vectors,
- 0);
-
-
-
- cvUndistort2(current_frame_rgb,current_frame_rgb,intrinsics,distortion_coeff);
- cvShowImage("result",current_frame_rgb);
-
-
- float intr[3][3] = {0.0};
- float dist[4] = {0.0};
- float tranv[3] = {0.0};
- float rotv[3] = {0.0};
-
- for ( int i = 0; i < 3; i++)
- {
- for ( int j = 0; j < 3; j++)
- {
- intr[i][j] = ((float*)(intrinsics->data.ptr + intrinsics->step*i))[j];
- }
- dist[i] = ((float*)(distortion_coeff->data.ptr))[i];
- tranv[i] = ((float*)(translation_vectors->data.ptr))[i];
- rotv[i] = ((float*)(rotation_vectors->data.ptr))[i];
- }
- dist[3] = ((float*)(distortion_coeff->data.ptr))[3];
-
- printf("----------------------------------------- ");
- printf("INTRINSIC MATRIX: ");
- printf("[ %6.4f %6.4f %6.4f ] ", intr[0][0], intr[0][1], intr[0][2]);
- printf("[ %6.4f %6.4f %6.4f ] ", intr[1][0], intr[1][1], intr[1][2]);
- printf("[ %6.4f %6.4f %6.4f ] ", intr[2][0], intr[2][1], intr[2][2]);
- printf("----------------------------------------- ");
- printf("DISTORTION VECTOR: ");
- printf("[ %6.4f %6.4f %6.4f %6.4f ] ", dist[0], dist[1], dist[2], dist[3]);
- printf("----------------------------------------- ");
- printf("ROTATION VECTOR: ");
- printf("[ %6.4f %6.4f %6.4f ] ", rotv[0], rotv[1], rotv[2]);
- printf("TRANSLATION VECTOR: ");
- printf("[ %6.4f %6.4f %6.4f ] ", tranv[0], tranv[1], tranv[2]);
- printf("----------------------------------------- ");
-
- cvWaitKey(0);
-
- calibration_done = true;
- }
-
- }
-
- exit(0);
- cvDestroyAllWindows();
- }
-
- void InitCorners3D(CvMat *Corners3D,CvSize ChessBoardSize,int NImages,float SquareSize)
- {
- int CurrentImage = 0;
- int CurrentRow = 0;
- int CurrentColumn = 0;
- int NPoints = ChessBoardSize.height*ChessBoardSize.width;
- float * temppoints = new float[NImages*NPoints*3];
-
-
- for (CurrentImage = 0 ; CurrentImage < NImages ; CurrentImage++)
- {
- for (CurrentRow = 0; CurrentRow < ChessBoardSize.height; CurrentRow++)
- {
- for (CurrentColumn=0;CurrentColumn<ChessBoardSize.width;CurrentColumn++)
- {
- temppoints[(CurrentImage*NPoints*3)+(CurrentRow*ChessBoardSize.width +
- CurrentColumn)*3]=(float)CurrentRow*SquareSize;
- temppoints[(CurrentImage*NPoints*3)+(CurrentRow*ChessBoardSize.width +
- CurrentColumn)*3+1]=(float)CurrentColumn*SquareSize;
- temppoints[(CurrentImage*NPoints*3)+(CurrentRow*ChessBoardSize.width +
- CurrentColumn)*3+2]=0.f;
- }
- }
- }
- (*Corners3D) = cvMat(NImages*NPoints,3,CV_32FC1, temppoints);
- }
-
- int myFindChessboardCorners( const void* image, CvSize pattern_size,
- CvPoint2D32f* corners, int* corner_count,
- int flags )
-
- {
-
-
- IplImage* eig = cvCreateImage( cvGetSize(image), 32, 1 );
- IplImage* temp = cvCreateImage( cvGetSize(image), 32, 1 );
- double quality = 0.01;
- double min_distance = 5;
- int win_size =10;
-
- int count = pattern_size.width * pattern_size.height;
- cvGoodFeaturesToTrack( image, eig, temp, corners, &count,
- quality, min_distance, 0, 3, 0, 0.04 );
- cvFindCornerSubPix( image, corners, count,
- cvSize(win_size,win_size), cvSize(-1,-1),
- cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03));
-
- cvReleaseImage( &eig );
- cvReleaseImage( &temp );
-
- return 1;
- }
-
- void makeChessBoard()
- {
-
- CvScalar e;
- e.val[0] =255;
- e.val[1] =255;
- e.val[2] =255;
- cvSet(chessBoard_Img,e,0);
- for(int i = 0;i<ChessBoardSize.width+1;i++)
- for(int j = 0;j<ChessBoardSize.height+1;j++)
- {
- int w =(image_width)/2/(ChessBoardSize.width);
- int h = w;
-
- int ii = i+1;
- int iii = ii+1;
- int jj =j+1;
- int jjj =jj+1;
- int s_x = image_width/6;
-
- if((i+j)%2==1)
- cvRectangle( chessBoard_Img, cvPoint(w*i+s_x,h*j+s_x),
- cvPoint(w*ii-1+s_x,h*jj-1+s_x), CV_RGB(0,0,0),CV_FILLED, 8, 0 );
- }
- }
(pcezar) |