《学习OpenCV》第四章课后题7

题目说明:透视变换
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

发布了19 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/windxf/article/details/48297695