【练习4.7】使用键盘控制透视变换和仿射变换的变换矩阵:实现拉伸、收缩、扭曲、旋转
《学习OpenCV》中文版第4章第7题
注意:操作的使用将输入法状态切换到“英文”状态
题目要求 |
程序代码 |
结果图片 |
a、使用数字键1~9以及数字键与Shift的组合,实现透视变换变换矩阵中对应元素的增大和缩小
b、使用上下方向键实现仿射变换变换矩阵中对应元素的增大和缩小,以实现对图片的缩放。
c、使用左右方向键实现仿射变换变换矩阵中对应元素的增大和缩小,以实现对图片的旋转。
1 #include "stdafx.h" 2 #include <cv.h> 3 #include <highgui.h> 4 #include <iostream> 5 using namespace cv; 6 using namespace std; 7 //函数声明-->--->-->--->-->--->-->--->// 8 9 int shiftKeyHandler(int key); 10 11 //<--<--<--<--<--<--<--<--<--函数声明// 12 13 int _tmain(int argc, _TCHAR* argv[]) 14 { 15 const char * fileName = "D:\\Work\\Work_Programming\\Source\\Image\\lena.jpg"; 16 IplImage * img = cvLoadImage(fileName, CV_LOAD_IMAGE_UNCHANGED); 17 assert(img); 18 19 IplImage * dst = cvCloneImage(img); 20 dst->origin = img->origin; 21 cvZero(dst); 22 23 IplImage * affinedImage = NULL; 24 CvPoint2D32f center = cvPoint2D32f(img->width / 2, img->height/2); 25 double angle = -20.0; 26 double scale = 1.0; 27 28 cvNamedWindow("ExerciseWindow", CV_WINDOW_AUTOSIZE); 29 cvNamedWindow("透视变换", CV_WINDOW_AUTOSIZE); 30 cvNamedWindow("图片缩放旋转", CV_WINDOW_AUTOSIZE); 31 32 cvShowImage("ExerciseWindow", img); 33 34 CvMat * warp_matrix = cvCreateMatHeader(3, 3, CV_32FC1); 35 float matDataSource[9] = { 0.372190326f, 0.216031685f, 25.6000004f, 36 -0.213343531f, 0.600807548f, 168.960007f, 37 -0.00104052317f, 0.000641974097f, 1.00000000f }; 38 warp_matrix->data.fl = matDataSource; 39 40 CvMat *rot_mat = cvCreateMat(2, 3, CV_32FC1); 41 42 while (true) 43 { 44 int key = cvWaitKey(0); 45 46 //---------------------------透视变换:开始--------------------------------// 47 //使用1~9键盘数字或与Shift的结合控制透视变换矩阵的9个元素 48 49 //当没有按下Shift键的时候 50 if (key >= 49 && key <= 57) //按键1~9的ASCII码是49~57 51 { 52 matDataSource[key % 49] += matDataSource[key % 49] / 10.0f; //这种方式可以省掉使用switch的大段代码 53 } 54 else//当按下Shift键的时候 55 { 56 if (key == 27) 57 { 58 break; 59 } 60 61 int subscript = shiftKeyHandler(key); 62 if (subscript != -1) 63 { 64 //题目要求是对应数据最小值是0,但实际操作中发现,有负值的情况比较理想 65 /*float temp = matDataSource[subscript] / 10.0f; 66 if ((matDataSource[subscript] -= matDataSource[subscript] / 10.0f) < 0.000001f) 67 { 68 matDataSource[subscript] += temp; 69 }*/ 70 71 matDataSource[subscript] -= matDataSource[subscript] / 10.0f; 72 } 73 else 74 { 75 cout << "请在程序获取输入焦点的情况下将输入法切换到英文状态再试!" << endl; 76 } 77 } 78 79 cvWarpPerspective(img, dst, warp_matrix); 80 cvShowImage("透视变换", dst); 81 82 //---------------------------透视变换:结束--------------------------------// 83 84 //---------------------------图片缩放与旋转:开始(仿射变换方法)----------------// 85 //使用上下箭头即“↑”“↓”控制图片放大缩小 86 //使用上下箭头即“←”“→”控制图片旋转 87 88 if (key == 2490368 || key == 2621440 || key == 2424832 || key == 2555904) 89 { 90 affinedImage = cvCloneImage(img); 91 affinedImage->origin = img->origin; 92 cvZero(affinedImage); 93 94 if (key == 2490368)//方向键“↑” 95 { 96 scale += scale*0.2; 97 } 98 99 if (key == 2621440) 100 { 101 scale -= scale*0.2; 102 } 103 104 if (key == 2424832)//方向键“←” 105 { 106 angle -= 10.0; 107 } 108 109 if (key == 2555904) 110 { 111 angle += 10.0; 112 } 113 114 cv2DRotationMatrix(center, angle, scale, rot_mat); 115 cvWarpAffine(img, affinedImage, rot_mat); 116 cvShowImage("图片缩放旋转", affinedImage); 117 } 118 else if (key == 27) 119 { 120 break; 121 } 122 123 //---------------------------图片缩放与旋转:结束--------------------------------// 124 } 125 126 //cvWaitKey(0); 127 128 cvReleaseImage(&img); 129 cvReleaseImage(&dst); 130 cvReleaseImage(&affinedImage); 131 cvDestroyWindow("ExerciseWindow"); 132 cvDestroyWindow("透视变换"); 133 cvDestroyWindow("图片缩放旋转"); 134 135 return 0; 136 } 137 138 //当同时按下Shift键时,处理key的值,使其结果方便使用 139 int shiftKeyHandler(int key) 140 { 141 //输入法分为英文和中文两种输入状态,本程序只开了英文状态,当然,实际开发中也可在使用代码控制输入法状态 142 switch (key) 143 { 144 case '!':return 0; 145 case '@':return 1; 146 case '#':return 2; 147 case '$':return 3; 148 case '%':return 4; 149 case '^':return 5; 150 case '&':return 6; 151 case '*':return 7; 152 case '(':return 8; 153 default: 154 return -1; 155 } 156 }
‖==========钟于原创 乐于分享 宁静致远 毋忆典藏==========‖