利用OpenCV实现图像的仿射变换
仿射变换可以形象的表示成如下形式:一个平面内任意的平行四边形ABCD可以被仿射变换映射为另一个平行四边形A'B'C'D',如果四边形的面积不等于0,仿射变换就被这两个平行四边形(其中的三个顶点)唯一的定义,这里注意确定一个平行四边形只需要三个顶点。我们可以把仿射变换想象成把一幅图像画到一个胶板上,在胶板的角上推或拉以得到不同的平行四边形。
下面的程序实现了对图像的仿射变换,还包括图像旋转、缩放这两个重要的子集。
#include
#include
#include
#include
int main( int argc, char** argv )
{
CvPoint2D32f srcTri[3],dstTri[3];
CvMat* rot_mat = cvCreateMat( 2, 3, CV_32FC1 );
CvMat* warp_mat = cvCreateMat( 2, 3, CV_32FC1 );
IplImage *src, *dst, *srcBak, *dstBak;
int TLx = 0, TLy = 0, TRx = 0, TRy = 0, DLx = 0, DLy = 0;
double angle = 40, scale = 0.8;
float delta = 0.01;
int PressKey;
char name[1][80];
if(!(src=cvLoadImage("C:/Users/jinxing/Desktop/Tests/test/Debug/lena.bmp",1)) )
{
printf("Input Error
");
return -1;
}
srcTri[0].x = 0;// Top left
srcTri[0].y = 0;
srcTri[1].x = src->width-1;//Top right
srcTri[1].y = 0;
srcTri[2].x = 0;//Down left
srcTri[2].y = src->height-1;
dst = cvCloneImage(src);
srcBak = cvCloneImage(src);
cvCopy(src,srcBak);
dst->origin = src->origin;
cvZero(dst);
cvNamedWindow( "AffineTransform", 1 );
CvFont font = cvFont( 1, 1 );
while(1)
{
dstTri[0].x = srcBak->width*delta*(TLx%101);
dstTri[0].y = srcBak->height*delta*(TLy%101);
dstTri[1].x = srcBak->width-1 - srcBak->width*delta*(TRx%101);
dstTri[1].y = srcBak->height*delta*(TRy%101);
dstTri[2].x = srcBak->width*delta*(DLx%101);
dstTri[2].y = srcBak->height-1 - srcBak->height*delta*(DLy%101);
cvGetAffineTransform(srcTri,dstTri,warp_mat);
cvWarpAffine(srcBak,dst,warp_mat);
cvCopy(dst,src);
CvPoint2D32f center = cvPoint2D32f(src->width/2,src->height/2);
cv2DRotationMatrix(center,angle,scale,rot_mat);
cvWarpAffine(src,dst,rot_mat);
dstBak = cvCloneImage(dst);
cvCopy(dst,dstBak);
//--------------------------字符显示--------------------------------//
char buf[8];
char dspStr1[32] = {'|'};
char dspStr2[32] = {'|'};
char dspStr3[32] = {'|'};
char dspStr4[32] = {'|'};
memset(buf,'/0',sizeof(buf));
strcat(dspStr1,itoa(TLx%101,buf,10));
strcat(dspStr1,",");
strcat(dspStr1,itoa(TLy%101,buf,10));
strcat(dspStr1,"|TL");
strcat(dspStr2,"angle=");
strcat(dspStr2,itoa(int(angle),buf,10));
strcat(dspStr2,",scale=");
strcat(dspStr2,itoa(int(scale*100),buf,10));
strcat(dspStr2,"%|");
strcat(dspStr3,itoa(TRx%101,buf,10));
strcat(dspStr3,",");
strcat(dspStr3,itoa(TRy%101,buf,10));
strcat(dspStr3,"|TR");
strcat(dspStr4,itoa(DLx%101,buf,10));
strcat(dspStr4,",");
strcat(dspStr4,itoa(DLy%101,buf,10));
strcat(dspStr4,"|DL");
cvPutText(dst,dspStr1,cvPoint(dst->width-120,20),&font,cvScalar(0,0xff));
cvPutText(dst,dspStr2,cvPoint(dst->width-180,80),&font,cvScalar(0,0xff));
cvPutText(dst,dspStr3,cvPoint(dst->width-120,40),&font,cvScalar(0,0xff));
cvPutText(dst,dspStr4,cvPoint(dst->width-120,60),&font,cvScalar(0,0xff));
//---------------------------------------------------------------------//
cvShowImage( "AffineTransform", dst );
PressKey = cvWaitKey();
printf("%c is pressed
",PressKey);
switch(PressKey)
{
case '1':
TLx++;
break;
case 'q':
TLx--;
break;
case '2':
TLy++;
break;
case 'w':
TLy--;
break;
case '3':
TRx++;
break;
case 'e':
TRx--;
break;
case '4':
TRy++;
break;
case 'r':
TRy--;
break;
case '5':
DLx++;
break;
case 't':
DLx--;
break;
case '6':
DLy++;
break;
case 'y':
DLy--;
break;
case '7':
angle++;
break;
case 'u':
angle--;
break;
case '8':
scale+=0.01;
break;
case 'i':
scale-=0.01;
break;
case 27:
cvReleaseImage(&dst);
cvDestroyWindow("AffineTransform");
cvReleaseMat(&rot_mat);
cvReleaseMat(&warp_mat);
return 0;
case 's':
cout<<"Input the filename:"<
cin>>name[0];
cvSaveImage( name[0], dstBak );
cout<
break;
default:
cout<<"Input Error."<
cout<<"Input 1 2 3 4 5 6 7 8 q w e r t y to change the coordinate."<
"Input u and i to change the angle and scale."<
<<"Input the esc to quit."<
break;
}
}
cvDestroyWindow("AffineTransform");
cvReleaseImage(&dst);
cvReleaseMat(&rot_mat);
cvReleaseMat(&warp_mat);
return 0;
}
程序执行结果: