《learning opencv》书上的例子
opencv2.2版本,vc9.0
个人仿真了下,觉得这个例子欠妥,仿真的结果也和书上不一样
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
int main(int argc , char * argv[])
{
if (argc!=6)
{
printf("there is something wrong");
return -1;
}
int board_w=atoi(argv[1]);
int board_h=atoi(argv[2]);
int board_n=board_h*board_w;
CvSize board_sz=cvSize(board_w,board_h);
CvMat * intrisic=(CvMat *)cvLoad(argv[3]);
CvMat * distortion=(CvMat *)cvLoad(argv[4]);
IplImage * image=NULL;
IplImage * gray_image=NULL;
if ((image=cvLoadImage(argv[5]))==0)
{
printf("there is something error !",argv[5]);
return -1;
}
gray_image=cvCreateImage(cvGetSize(image),8,1);
// cvCvtColor(image,gray_image,CV_BGR2GRAY);
//矫正图像
IplImage * mapx=cvCreateImage(cvGetSize(image),IPL_DEPTH_32F,1);
IplImage * mapy=cvCreateImage(cvGetSize(image),IPL_DEPTH_32F,1);
cvInitUndistortMap(intrisic,distortion,mapx,mapy);
IplImage * t=cvCloneImage(image);//分配了新的存储空间
cvRemap(t,image,mapx,mapy);
//得到棋盘上的角点
cvCvtColor(image,gray_image,CV_BGR2GRAY);//自己添加
cvNamedWindow("chessboard",0);
CvPoint2D32f * corners=new CvPoint2D32f[board_n];
int corner_count=0;
// int found=cvFindChessboardCorners(image,board_sz,corners,&corner_count,
// CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS);//cvFindChessboardCorners 中的图像应该是单通道的
//《learning opencv》p417,书上程序却用了image,image为3个通道的。但如果运行程序,还是能通过,不知原因,可能2.2版本没问题
int found=cvFindChessboardCorners(gray_image,board_sz,corners,&corner_count, CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS);
//在原程序中gray_image为未校正的原图的灰度图,所以在自己的程序中把gray_image改为矫正后图像的灰度图。
if (!found)
{
printf("fail finding the corner !");
return -1;
}
cvFindCornerSubPix(gray_image,corners,corner_count,cvSize(11,11),cvSize(-1,-1),cvTermCriteria(
CV_TERMCRIT_EPS|CV_TERMCRIT_ITER,30,0.1));
CvPoint2D32f objPts[4], imgPts[4];
objPts[0].x = 0; objPts[0].y = 0;
objPts[1].x = board_w-1; objPts[1].y = 0;
objPts[2].x = 0; objPts[2].y = board_h-1;
objPts[3].x = board_w-1; objPts[3].y = board_h-1;
imgPts[0] = corners[0];
imgPts[1] = corners[board_w-1];
imgPts[2] = corners[(board_h-1)*board_w];
imgPts[3] = corners[(board_h-1)*board_w + board_w-1];
//画图
cvCircle(image,cvPointFrom32f(imgPts[0]),9,CV_RGB(0,0,255),3);
cvCircle(image,cvPointFrom32f(imgPts[1]),9,CV_RGB(0,255,0),3);
cvCircle(image,cvPointFrom32f(imgPts[2]),9,CV_RGB(255,0,0),3);
cvCircle(image,cvPointFrom32f(imgPts[3]),9,CV_RGB(255,255,0),3);//cvPointFrom32f from f to int
//DRAW THE FOUND CHECKERBOARD
cvDrawChessboardCorners(image, board_sz, corners, corner_count, found);
cvShowImage( "chessboard", image );
//求解单应矩阵H
CvMat * H =cvCreateMat(3,3,CV_32F);
cvGetPerspectiveTransform(objPts,imgPts,H);
//这样求解出来的H,感觉有点忽悠人。上一语句的意思为,objPts为一长方形,imgPts为一梯形,所以以后再用H对整幅图像中进行变换显
//然能把原本为长方形的图像透视变换为一梯形,但是也不能成为俯视图么~而且对对objPts的边长放大10,效果又会变化很大。
float aa=CV_MAT_ELEM(*H,float,2,2);
printf("%f\n",aa);
//用户操作
float z=25;//预设高度
int key=0;
IplImage *birds_image=cvCloneImage(image);
cvNamedWindow("Birds_Eye",0);
while (key!=27)
{
CV_MAT_ELEM(*H,float,2,2)=z;//改变z的大小可以使得图像放大缩小,但不影响图像的透视变化后的形状。不明白其中的道理
cvWarpPerspective(image,birds_image,H,CV_INTER_LINEAR|CV_WARP_INVERSE_MAP|CV_WARP_FILL_OUTLIERS);
cvShowImage("Birds_Eye", birds_image);
key = cvWaitKey();
if(key == 'u') z += 0.5;
if(key == 'd') z -= 0.5;
}
cvSave("H.xml",H);
return 0;
}
程序上的问题已经在程序中用备注的方式说明