题外话:一直是打算把这本书的全部课后编程题写完的,中间断了几个月,一直忙于其他事。现在开始补上。

这道题我不清楚我理解的题意是不是正确的,这道题可以练习用OpenCV实现透视变换(可以用于矫正在3维环境下的图像失真),b&c部分则是实现图像放大缩小插值,旋转图像。所有的功能都和键盘事件处理联系起来,纯OpenCV实现,和OS无关。不过,在处理SHIFT键时,我取得是其在键盘上对应字符的ASCII码,好像OpenCV对键盘事件的支持不如对鼠标事件的支持。所以SHIFT键+小键盘上的数字键是不行的。

代码:

  1. #include <opencv/highgui.h>
  2. #include <opencv/cv.h>
  3. #include <opencv_libs.h>
  4.  
  5. /*
  6. *《学习OpenCV》第四章第七题
  7. * 完成时间:0:23 10/4 星期五 2013
  8. */
  9.  
  10. #define WARPSTEPSIZE 0.01 // 透视变换矩阵每次的变化率
  11.  
  12. #define RESIZESTEPSIZE 0.1 // 放大、缩小每次的变化率
  13.  
  14. #define ROTATESTEPSIZE 10 // 旋转图像时每次旋转的角度(逆时针)
  15.  
  16. // 透视变换目标变换矩阵
  17. CvPoint2D32f g_dstQuad[];
  18.  
  19. // image width & height
  20. int g_width = ;
  21. int g_height = ;
  22.  
  23. // rotate degree
  24. int g_RotateDegree = ;
  25.  
  26. /*
  27. * function: Zoom in or zoom out an image.
  28. * param: inorout -- indicate in or out(0 means zoom in; 1 means zoom out)
  29. * param: the destination size.
  30. */
  31. CvSize getZoomDstSize(int inorout)
  32. {
  33. if(inorout != && inorout != )
  34. {
  35. return cvSize(-, -);
  36. }
  37. if(g_height == || g_width == )
  38. {
  39. return cvSize(-, -);
  40. }
  41.  
  42. // Zoom in
  43. if(inorout == )
  44. {
  45. g_width += g_width * RESIZESTEPSIZE;
  46. g_height += g_height * RESIZESTEPSIZE;
  47. }
  48. else if(inorout == )
  49. {
  50. g_width -= g_width * RESIZESTEPSIZE;
  51. g_height -= g_height * RESIZESTEPSIZE;
  52.  
  53. if(g_height < )
  54. {
  55. g_height = ;
  56. }
  57. else if(g_width < )
  58. {
  59. g_width = ;
  60. }
  61. }
  62.  
  63. return cvSize(g_width, g_height);
  64. }
  65.  
  66. void rotateImage(IplImage* img, IplImage *img_rotate,float degree)
  67. {
  68. // 旋转中心
  69. CvPoint2D32f center;
  70. center.x=float (img->width/2.0+0.5);
  71. center.y=float (img->height/2.0+0.5);
  72. // 计算二维旋转的仿射变换矩阵
  73. float m[];
  74. CvMat M = cvMat( , , CV_32F, m );
  75. cv2DRotationMatrix( center, degree,, &M);
  76. // 变换图像,并用黑色填充其余值
  77. cvWarpAffine(img,img_rotate, &M,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,cvScalarAll() );
  78. }
  79.  
  80. /*
  81. * function: change the g_dstQuad(minus or plus one of the element)
  82. * param: index -- which element(0 -- 4)
  83. * param: xory -- indicate x or y to change(0 means x; 1 means y)
  84. * param: operation -- indicate which operation(0 means plus; 1 means minus)
  85. * return: 0 means success. -1 means failed.
  86. */
  87. int changeg_dstQuad(int index, int xory, int operation)
  88. {
  89. // param check
  90. if( index > || index < ||
  91. (xory != && xory != ) ||
  92. (operation != && operation != ) ||
  93. g_width == || g_height == )
  94. {
  95. return -;
  96. }
  97.  
  98. // plus
  99. if(operation == )
  100. {
  101. if(xory == ) // x
  102. {
  103. g_dstQuad[index].x += WARPSTEPSIZE * g_width;
  104. if(g_dstQuad[index].x > g_width - )
  105. {
  106. g_dstQuad[index].x = g_width - ;
  107. }
  108. }
  109. else if(xory == ) // y
  110. {
  111. g_dstQuad[index].y += WARPSTEPSIZE * g_height;
  112. if(g_dstQuad[index].y > g_height - )
  113. {
  114. g_dstQuad[index].y = g_height -;
  115. }
  116. }
  117. }
  118.  
  119. // minus
  120. else if (operation == )
  121. {
  122. if(xory == ) // x
  123. {
  124. g_dstQuad[index].x -= WARPSTEPSIZE * g_width;
  125. if(g_dstQuad[index].x < )
  126. {
  127. g_dstQuad[index].x = ;
  128. }
  129. }
  130. else if(xory == ) // y
  131. {
  132. g_dstQuad[index].y -= WARPSTEPSIZE * g_height;
  133. if(g_dstQuad[index].y < )
  134. {
  135. g_dstQuad[index].y = ;
  136. }
  137. }
  138. }
  139.  
  140. return ;
  141. }
  142.  
  143. int main()
  144. {
  145. const char * FILEPATH = "lena.bmp";
  146. IplImage * src = cvLoadImage(FILEPATH, CV_LOAD_IMAGE_UNCHANGED);
  147.  
  148. if(!src)
  149. {
  150. printf("load image error.\texit\n");
  151. return -;
  152. }
  153.  
  154. CvPoint2D32f srcQuad[];
  155. CvMat* warp_matrix = cvCreateMat(, , CV_32FC1);
  156. IplImage *dst;
  157.  
  158. cvNamedWindow("Source_Image", );
  159. cvNamedWindow("Perspective_Warp", );
  160.  
  161. dst = cvCloneImage(src);
  162. dst->origin = dst->origin;
  163. cvZero(dst);
  164.  
  165. // image width & height
  166. g_width = src->width;
  167. g_height = src->height;
  168.  
  169. srcQuad[].x = ; // src Top left
  170. srcQuad[].y = ;
  171. srcQuad[].x = g_width - ; // src Top right
  172. srcQuad[].y = ;
  173. srcQuad[].x = ; // src Bottom left
  174. srcQuad[].y = g_height - ;
  175. srcQuad[].x = g_width - ; // src Bottom right
  176. srcQuad[].y = g_height - ;
  177.  
  178. g_dstQuad[].x = ; // dst Top left
  179. g_dstQuad[].y = ;
  180. g_dstQuad[].x = g_width - ; // dst Top right
  181. g_dstQuad[].y = ;
  182. g_dstQuad[].x = ; // dst Bottom left
  183. g_dstQuad[].y = g_height - ;
  184. g_dstQuad[].x = g_width - ; // dst Bottom right
  185. g_dstQuad[].y = g_height - ;
  186.  
  187. while()
  188. {
  189. cvShowImage("Source_Image", src);
  190. char c = cvWaitKey();
  191.  
  192. int ret = ;
  193. switch(c)
  194. {
  195. // ESC
  196. case :
  197. goto end;
  198. break;
  199. // 0 -- 放大图像
  200. case :
  201. {
  202. cvNamedWindow("Resize", );
  203. CvSize dstSize = getZoomDstSize();
  204. if(dstSize.height == - || dstSize.width == -)
  205. {
  206. goto end;
  207. }
  208.  
  209. IplImage* imageresize = cvCreateImage(dstSize, src->depth, src->nChannels);
  210. if(!imageresize)
  211. {
  212. goto end;
  213. }
  214. cvResize(src, imageresize, CV_INTER_LINEAR);
  215. cvShowImage("Resize", imageresize);
  216. cvReleaseImage(&imageresize);
  217. }
  218. break;
  219. // SHIFT + 0 ')' -- 缩小图像
  220. case :
  221. {
  222. cvNamedWindow("Resize", );
  223. CvSize dstSize = getZoomDstSize();
  224. if(dstSize.height == - || dstSize.width == -)
  225. {
  226. goto end;
  227. }
  228.  
  229. IplImage* imageresize = cvCreateImage(dstSize, src->depth, src->nChannels);
  230. if(!imageresize)
  231. {
  232. goto end;
  233. }
  234. cvResize(src, imageresize, CV_INTER_LINEAR);
  235. cvShowImage("Resize", imageresize);
  236. cvReleaseImage(&imageresize);
  237. }
  238. break;
  239. // 9 -- 旋转图像(逆时针)
  240. case :
  241. {
  242. cvNamedWindow("Rotate", );
  243.  
  244. IplImage* imagerotate = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
  245. if(!imagerotate)
  246. {
  247. goto end;
  248. }
  249. g_RotateDegree += ROTATESTEPSIZE;
  250. rotateImage(src, imagerotate, g_RotateDegree);
  251. cvShowImage("Rotate", imagerotate);
  252. cvReleaseImage(&imagerotate);
  253. }
  254. break;
  255. // SHIFT + 9 '(' -- 旋转图像(顺时针)
  256. case :
  257. {
  258. cvNamedWindow("Rotate", );
  259.  
  260. IplImage* imagerotate = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
  261. if(!imagerotate)
  262. {
  263. goto end;
  264. }
  265. g_RotateDegree -= ROTATESTEPSIZE;
  266. rotateImage(src, imagerotate, g_RotateDegree);
  267. cvShowImage("Rotate", imagerotate);
  268. cvReleaseImage(&imagerotate);
  269. }
  270. break;
  271. //
  272. case :
  273. ret = changeg_dstQuad(, , );
  274. break;
  275. //
  276. case :
  277. ret = changeg_dstQuad(, , );
  278. break;
  279. //
  280. case :
  281. ret = changeg_dstQuad(, , );
  282. break;
  283. //
  284. case :
  285. ret = changeg_dstQuad(, , );
  286. break;
  287. //
  288. case :
  289. ret = changeg_dstQuad(, , );
  290. break;
  291. //
  292. case :
  293. ret = changeg_dstQuad(, , );
  294. break;
  295. //
  296. case :
  297. ret = changeg_dstQuad(, , );
  298. break;
  299. //
  300. case :
  301. ret = changeg_dstQuad(, , );
  302. break;
  303. // SHIFT + 1 '!'
  304. case :
  305. ret = changeg_dstQuad(, , );
  306. break;
  307. // SHIFT + 2 '@'
  308. case :
  309. ret = changeg_dstQuad(, , );
  310. break;
  311. // SHIFT + 3 '#'
  312. case :
  313. ret = changeg_dstQuad(, , );
  314. break;
  315. // SHIFT + 4 '$'
  316. case :
  317. ret = changeg_dstQuad(, , );
  318. break;
  319. // SHIFT + 5 '%'
  320. case :
  321. ret = changeg_dstQuad(, , );
  322. break;
  323. // SHIFT + 6 '^'
  324. case :
  325. ret = changeg_dstQuad(, , );
  326. break;
  327. // SHIFT + 7 '&'
  328. case :
  329. ret = changeg_dstQuad(, , );
  330. break;
  331. // SHIFT + 8 '*'
  332. case :
  333. ret = changeg_dstQuad(, , );
  334. break;
  335.  
  336. default:
  337. break;
  338. }
  339.  
  340. // Error
  341. if(ret != )
  342. {
  343. goto end;
  344. }
  345. cvGetPerspectiveTransform(srcQuad, g_dstQuad, warp_matrix);
  346. cvWarpPerspective( src, dst, warp_matrix,
  347. CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll());
  348.  
  349. cvShowImage("Source_Image", src);
  350. cvShowImage("Perspective_Warp", dst);
  351. }
  352.  
  353. end:
  354. cvReleaseImage(&src);
  355. cvReleaseImage(&dst);
  356. cvReleaseMat(&warp_matrix);
  357. cvDestroyAllWindows();
  358.  
  359. return ;
  360. }

程序运行截图:

首先是透视变换:

图像放大缩小(b部分):

图像旋转(c部分):

《学习OpenCV》练习题第四章第七题abc的更多相关文章

  1. 《学习OpenCV》练习题第四章第八题ab

    这道题是利用OpenCV例子程序里自带的人脸检测程序,做点图像的复制操作以及alpha融合. 说明:人脸检测的程序我参照了网上现有的例子程序,没有用我用的OpenCV版本(2.4.5)的facedet ...

  2. 《学习OpenCV》练习题第四章第三题b

    #include <highgui.h> #include <cv.h> #include "opencv_libs.h" /* *<学习OpenCV ...

  3. 《学习OpenCV》练习题第四章第三题a

    #include <highgui.h> #include <cv.h> #include "opencv_libs.h" #pragma comment ...

  4. 《学习OpenCV》 第四章 习题六

    实现的是一个图像标签编辑器,其间遇到了些问题还未解决或者可能解决方法上不是最优,若你有更好的思路可以提供给我,大恩不言谢啦!!☆⌒(*^-゜)v. #include "stdafx.h&qu ...

  5. 《学习OpenCV》练习题第四章第二题

    #include <highgui.h> #include <cv.h> #pragma comment (lib,"opencv_calib3d231d.lib&q ...

  6. 《学习OpenCV》练习题第四章第一题b&c

    #include <highgui.h> #include <cv.h> #pragma comment (lib,"opencv_calib3d231d.lib&q ...

  7. 《学习OpenCV》练习题第四章第一题a

    #include <highgui.h> #include <cv.h> #pragma comment (lib,"opencv_calib3d231d.lib&q ...

  8. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化 学习目标 对Direct 3D编程在 ...

  9. 学习opencv中文版教程——第二章

    学习opencv中文版教程——第二章 所有案例,跑起来~~~然而并没有都跑起来...我只把我能跑的都尽量跑了,毕竟看书还是很生硬,能运行能出结果,才比较好. 越着急,心越慌,越是着急,越要慢,越是陌生 ...

随机推荐

  1. [原]Water Water Search Problems&#39; Set~Orz【updating...】

    [HDU] [POJ] 作者:u011652573 发表于2014-4-30 10:39:04 原文链接 阅读:30 评论:0 查看评论

  2. H5移动前端完美布局之padding

    序上次的提到了H5移动前端完美布局之-margin百分比的使用margin-top(left,right,bottom)的百分比在移动页面布局中对上下左右距离的处理,攻下城外再攘城内,今天看看padd ...

  3. 爬虫技术(四)-- 简单爬虫抓取示例(附c#代码)

    这是我的第一个爬虫代码...算是一份测试版的代码.大牛大神别喷... 通过给定一个初始的地址startPiont然后对网页进行捕捉,然后通过正则表达式对网址进行匹配. List<string&g ...

  4. 安装cloudera

    1. 查看selinux状态 $ /usr/sbin/getenforce Enforcing $ /usr/sbin/sestatus SELinux status: enabled SELinux ...

  5. JSON 之 SuperObject(5): Format 与转义字符

    unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For ...

  6. 在HibernateTemplate里执行Sql语句

    如下所示只能执行非Select语句: public static void executeSQL(HibernateTemplate hibernateTemplate, String sql) { ...

  7. table注意事项

    注意事项:1.不要给table,th,td以外的表格标签加样式:2.单元格默认平分table 的宽度3.th里面的内容默认加粗并且左右上下居中显示4.td里面的内容默认上下居中左右居左显示5. tab ...

  8. IE6,7下li标签的间隙

    1.在IE6,7下li本身没浮动,但是li内容有浮动的时候,li下边就会产生3px的间隙. 解决办法: 1.给li加浮动 2.给li加vertical-align:top; eg: <!DOCT ...

  9. org.apache.jasper.JasperException: /WEB-INF/jsp/add.jsp(40,24) quote symbol expected

    add.jsp 的40行24列少了一个 引号

  10. Ant编译环境

    使用ant编译有关于C compiler(cc task)的时候,需要确认vs的环境有无配置, 否则会遇到形形色色的问题,比如各种 vs编译工具找不到的错误, 一个比较简单的解决方案,就是在执行ant ...