您的位置:首页 > 其它

【练习4.7】使用键盘控制透视变换和仿射变换的变换矩阵:实现拉伸、收缩、扭曲、旋转

2014-08-03 18:03 477 查看
《学习OpenCV》中文版第4章第7题

注意:操作的使用将输入法状态切换到“英文”状态

提纲

题目要求
程序代码
结果图片
题目要求:

a、使用数字键1~9以及数字键与Shift的组合,实现透视变换变换矩阵中对应元素的增大和缩小

b、使用上下方向键实现仿射变换变换矩阵中对应元素的增大和缩小,以实现对图片的缩放。

c、使用左右方向键实现仿射变换变换矩阵中对应元素的增大和缩小,以实现对图片的旋转。

程序代码:

#include "stdafx.h"
#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace cv;
using namespace std;
//函数声明-->--->-->--->-->--->-->--->//

int shiftKeyHandler(int key);

//<--<--<--<--<--<--<--<--<--函数声明//

int _tmain(int argc, _TCHAR* argv[])
{
const char * fileName = "D:\\Work\\Work_Programming\\Source\\Image\\lena.jpg";
IplImage * img = cvLoadImage(fileName, CV_LOAD_IMAGE_UNCHANGED);
assert(img);

IplImage * dst = cvCloneImage(img);
dst->origin = img->origin;
cvZero(dst);

IplImage * affinedImage = NULL;
CvPoint2D32f center = cvPoint2D32f(img->width / 2, img->height/2);
double angle = -20.0;
double scale = 1.0;

cvNamedWindow("ExerciseWindow", CV_WINDOW_AUTOSIZE);
cvNamedWindow("透视变换", CV_WINDOW_AUTOSIZE);
cvNamedWindow("图片缩放旋转", CV_WINDOW_AUTOSIZE);

cvShowImage("ExerciseWindow", img);

CvMat * warp_matrix = cvCreateMatHeader(3, 3, CV_32FC1);
float matDataSource[9] = { 0.372190326f, 0.216031685f, 25.6000004f,
-0.213343531f, 0.600807548f, 168.960007f,
-0.00104052317f, 0.000641974097f, 1.00000000f };
warp_matrix->data.fl = matDataSource;

CvMat *rot_mat = cvCreateMat(2, 3, CV_32FC1);

while (true)
{
int key = cvWaitKey(0);

//---------------------------透视变换:开始--------------------------------//
//使用1~9键盘数字或与Shift的结合控制透视变换矩阵的9个元素

//当没有按下Shift键的时候
if (key >= 49 && key <= 57)    //按键1~9的ASCII码是49~57
{
matDataSource[key % 49] += matDataSource[key % 49] / 10.0f;    //这种方式可以省掉使用switch的大段代码
}
else//当按下Shift键的时候
{
if (key == 27)
{
break;
}

int subscript = shiftKeyHandler(key);
if (subscript != -1)
{
//题目要求是对应数据最小值是0,但实际操作中发现,有负值的情况比较理想
/*float temp = matDataSource[subscript] / 10.0f;
if ((matDataSource[subscript] -= matDataSource[subscript] / 10.0f) < 0.000001f)
{
matDataSource[subscript] += temp;
}*/

matDataSource[subscript] -= matDataSource[subscript] / 10.0f;
}
else
{
cout << "请在程序获取输入焦点的情况下将输入法切换到英文状态再试!" << endl;
}
}

cvWarpPerspective(img, dst, warp_matrix);
cvShowImage("透视变换", dst);

//---------------------------透视变换:结束--------------------------------//

//---------------------------图片缩放与旋转:开始(仿射变换方法)----------------//
//使用上下箭头即“↑”“↓”控制图片放大缩小
//使用上下箭头即“←”“→”控制图片旋转

if (key == 2490368 || key == 2621440 || key == 2424832 || key == 2555904)
{
affinedImage = cvCloneImage(img);
affinedImage->origin = img->origin;
cvZero(affinedImage);

if (key == 2490368)//方向键“↑”
{
scale += scale*0.2;
}

if (key == 2621440)
{
scale -= scale*0.2;
}

if (key == 2424832)//方向键“←”
{
angle -= 10.0;
}

if (key == 2555904)
{
angle += 10.0;
}

cv2DRotationMatrix(center, angle, scale, rot_mat);
cvWarpAffine(img, affinedImage, rot_mat);
cvShowImage("图片缩放旋转", affinedImage);
}
else if (key == 27)
{
break;
}

//---------------------------图片缩放与旋转:结束--------------------------------//
}

//cvWaitKey(0);

cvReleaseImage(&img);
cvReleaseImage(&dst);
cvReleaseImage(&affinedImage);
cvDestroyWindow("ExerciseWindow");
cvDestroyWindow("透视变换");
cvDestroyWindow("图片缩放旋转");

return 0;
}

//当同时按下Shift键时,处理key的值,使其结果方便使用
int shiftKeyHandler(int key)
{
//输入法分为英文和中文两种输入状态,本程序只开了英文状态,当然,实际开发中也可在使用代码控制输入法状态
switch (key)
{
case '!':return 0;
case '@':return 1;
case '#':return 2;
case '$':return 3;
case '%':return 4;
case '^':return 5;
case '&':return 6;
case '*':return 7;
case '(':return 8;
default:
return -1;
}
}


结果图片

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐