题目说明:透视变换
a.写一个程序读入一幅图像,并使用数字键1~9控制变换矩阵(参考cvWarpPerspective()函数)。按住任意1~9中的任意一个按键,透视变换矩阵中对应数据会变大。同时按下Shift键时,对应数据会减小(最小为0)。每次改变一个数据,在两个窗口中显示图像:原始图像和变换后的图像。
b.添加放大、缩小功能。
c.添加旋转图像功能。
代码使用说明:由于opencv中没有找到实现键盘‘组合键’的功能,所以代码使用方式有些改变
程序运行后:
Step1:有三种按键方式z—缩放、r—旋转、p—透视变换
Step2(1):然后接着对于z—缩放、r—旋转可以有-和+两种方式(与主键盘数字键共行的按键,直接按不用按Shift)进行操作。
Step2(2):对于p—透视变换,先选择H矩阵要增减的位置,即1~9(H矩阵按行优先排列),然后再按-和+两种方式(与主键盘数字键共行的按键,直接按不用按Shift)进行操作
注:退出z—缩放、r—旋转、p—透视变换操作按ESE键
#include <opencv/highgui.h>
#include <opencv/cv.h>
#define WARPSTEPSIZE 0.2 // 透视变换矩阵每次的变化率
#define RESIZESTEPSIZE 0.1 // 放大、缩小每次的变化率
#define ROTATESTEPSIZE 10 // 旋转图像时每次旋转的角度(逆时针)
//变化数值
float g_H_value = 0;
float g_resize_value = 0;
int g_RotateDegree = 0;
//图像缩放定义
void zoom_OUTorIN(IplImage *dst_imresize,float g_resize_value);
//图像旋转定义
void rotateImage_CWorCCW(IplImage* dst_rotate,float g_RotateDegree);
//图像透视投影
void changeg_H_Plus(CvMat *H,char d,float g_H_value );
void WarpPerspective(IplImage *src,IplImage *dst,const CvMat warp_matrix,char d);
void WarpPerspective_PLUSorSUB(IplImage *src,IplImage *dst,CvMat *H,char d,float g_H_value);
//主函数
int main()
{
const char * FILEPATH = "F:/试验数据/du.jpg";
IplImage * src = cvLoadImage(FILEPATH, CV_LOAD_IMAGE_UNCHANGED);
if(!src)
{
printf("load image error.\texit\n");
return -1;
}
//初始化H矩阵
float a[9]={1,0,0,0,1,0,0,0,1};
const CvMat warp_matrix = cvMat(3, 3, CV_32FC1,a);
//初始化缩放、旋转、透视投影原始矩阵
IplImage *dst_rotate,*dst_imresize,*dst_Perspective;
dst_rotate = cvCloneImage(src);
dst_imresize = cvCloneImage(src);
dst_Perspective = cvCloneImage(src);
printf("input z means zoom in or zoom out\n");
printf("input r means rotate\n");
printf("input p means perspective\n");
cvNamedWindow("Source_Image", 1);
while(1)
{
cvShowImage("Source_Image", src);
char c = cvWaitKey(10);
switch(c)
{
// ESC
case 27:
break;
// 122 -- 放大缩小图像
case 122:
{
cvNamedWindow("Resize_Image",1);
while (1)
{
cvShowImage("Resize_Image", dst_imresize);
char d = cvWaitKey(10);
switch(d)
{
case 61:
g_resize_value = RESIZESTEPSIZE;
zoom_OUTorIN(dst_imresize,g_resize_value);
break;
case 45:
g_resize_value = -RESIZESTEPSIZE;
zoom_OUTorIN(dst_imresize,g_resize_value);
break;
case 27:
break;
}
if (d == 27) break;
}
cvDestroyWindow("Resize_Image");
g_resize_value = 0;
cvReleaseImage(&dst_imresize);
dst_imresize = cvCloneImage(src);
break;
}
//114 -- 旋转图像
case 114:
{
cvNamedWindow("Rotate_Image", 1);
while (1)
{
cvShowImage("Rotate_Image", dst_rotate);
char d = cvWaitKey(10);
switch(d)
{
case 61:
g_RotateDegree += ROTATESTEPSIZE;
rotateImage_CWorCCW(dst_rotate,g_RotateDegree);
break;
case 45:
g_RotateDegree -= ROTATESTEPSIZE;
rotateImage_CWorCCW(dst_rotate,g_RotateDegree);
break;
case 27:
break;
}
if (d == 27) break;
}
cvDestroyWindow("Rotate_Image");
g_RotateDegree = 0;
cvReleaseImage(&dst_rotate);
dst_rotate = cvCloneImage(src);
break;
}
//112 -- 透射变换
case 112:
{
cvNamedWindow("Perspective_Image", 1);
cvShowImage("Perspective_Image",dst_Perspective);
while (1)
{
char d = cvWaitKey(10);
switch(d)
{
case 49:
WarpPerspective(src,dst_Perspective,warp_matrix,d);
break;
case 50:
WarpPerspective(src,dst_Perspective,warp_matrix,d);
break;
case 51:
WarpPerspective(src,dst_Perspective,warp_matrix,d);
break;
case 52:
WarpPerspective(src,dst_Perspective,warp_matrix,d);
break;
case 53:
WarpPerspective(src,dst_Perspective,warp_matrix,d);
break;
case 54:
WarpPerspective(src,dst_Perspective,warp_matrix,d);
break;
case 55:
WarpPerspective(src,dst_Perspective,warp_matrix,d);
break;
case 56:
WarpPerspective(src,dst_Perspective,warp_matrix,d);
break;
case 57:
WarpPerspective(src,dst_Perspective,warp_matrix,d);
break;
case 27:
break;
}
if(d == 27) break;
}
cvDestroyWindow("Perspective_Image");
break;
}
}
if (c == 27) break;
}
cvReleaseImage(&src);
cvReleaseImage(&dst_rotate);
cvReleaseImage(&dst_imresize);
cvReleaseImage(&dst_Perspective);
cvDestroyAllWindows();
return 0;
}
//图像缩放
void zoom_OUTorIN(IplImage *dst_imresize,float g_resize_value)
{
CvSize dstSize = cvSize(dst_imresize->width * (1 + g_resize_value), dst_imresize->height * (1 + g_resize_value));
IplImage* imageresize = cvCreateImage(dstSize, dst_imresize->depth, dst_imresize->nChannels);
cvResize(dst_imresize, imageresize, CV_INTER_LINEAR);
cvReleaseImage(&dst_imresize);
dst_imresize = cvCloneImage(imageresize);
cvReleaseImage(&imageresize);
}
//图像旋转
void rotateImage_CWorCCW(IplImage* dst_rotate,float g_RotateDegree)
{
IplImage* imagerotate = cvCreateImage(cvGetSize(dst_rotate), dst_rotate->depth, dst_rotate->nChannels);
// 旋转中心
CvPoint2D32f center;
center.x=float (dst_rotate->width/2.0+0.5);
center.y=float (dst_rotate->height/2.0+0.5);
// 计算二维旋转的仿射变换矩阵
float m[6];
CvMat M = cvMat( 2, 3, CV_32F, m );
cv2DRotationMatrix( center, g_RotateDegree,1, &M);
// 变换图像,并用黑色填充其余值
cvWarpAffine(dst_rotate,imagerotate, &M,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,cvScalarAll(0) );
cvReleaseImage(&dst_rotate);
dst_rotate = cvCloneImage(imagerotate);
cvReleaseImage(&imagerotate);
}
//图像透视投影
void changeg_H_Plus(CvMat *H,char d,float g_H_value )
{
if (d == 49) cvSetReal2D(H,0,0,cvGetReal2D(H,0,0)+g_H_value);
if (d == 50) cvSetReal2D(H,0,1,cvGetReal2D(H,0,1)+g_H_value);
if (d == 51) cvSetReal2D(H,0,2,cvGetReal2D(H,0,2)+g_H_value);
if (d == 52) cvSetReal2D(H,1,0,cvGetReal2D(H,1,0)+g_H_value);
if (d == 53) cvSetReal2D(H,1,1,cvGetReal2D(H,1,1)+g_H_value);
if (d == 54) cvSetReal2D(H,1,2,cvGetReal2D(H,1,2)+g_H_value);
if (d == 55) cvSetReal2D(H,2,0,cvGetReal2D(H,2,0)+g_H_value);
if (d == 56) cvSetReal2D(H,2,1,cvGetReal2D(H,2,1)+g_H_value);
if (d == 57) cvSetReal2D(H,2,2,cvGetReal2D(H,2,2)+g_H_value);
}
void WarpPerspective_PLUSorSUB(IplImage *src,IplImage *dst,CvMat *H,char d,float g_H_value)
{
changeg_H_Plus(H,d,g_H_value);
IplImage *dst_Perspective = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
cvWarpPerspective( src, dst_Perspective, H, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0));
cvReleaseImage(&dst);
dst = cvCloneImage(dst_Perspective);
}
void WarpPerspective(IplImage *src,IplImage *dst,const CvMat warp_matrix,char d)
{
CvMat *H = cvCloneMat(&warp_matrix);
cvNamedWindow("Perspective_H_Chagne", 1);
while (1)
{
cvShowImage("Perspective_H_Chagne", dst);
char e = cvWaitKey(10);
switch(e)
{
case 61:
g_H_value = WARPSTEPSIZE;
WarpPerspective_PLUSorSUB(src,dst,H,d,g_H_value);
break;
case 45:
g_H_value = -WARPSTEPSIZE;
WarpPerspective_PLUSorSUB(src,dst,H,d,g_H_value);
break;
case 27:
break;
}
if (e == 27) break;
}
cvDestroyWindow("Perspective_H_Chagne");
g_H_value = 0;
cvReleaseImage(&dst);
dst = cvCloneImage(src);
}
旋转图片:
注:透视变化结果可以运行代码尝试,本程序对于理解透视‘变换矩阵H’很有帮助。
部分引用:qdsclove的专栏
http://blog.csdn.net/stk_overflow/article/details/12263783