OpenCV 利用滚动条在不缩小的情况下显示大型图片

叁歲伎倆 2022-09-28 11:40 223阅读 0赞

最近由于项目需要,要在不缩小的情况下显示一张2500*2000大小的图片,找到了一篇博客写的非常好,是邹老师写于2011年的:
http://blog.csdn.net/chenyusiyuan/article/details/6565424

我正在试着把它翻译成C++风格,用Mat类型,实现后会再发出来

原贴代码,简单修改并加上了一些注释,在VS2010上运行成功:

  1. // Image_ScrollBar.cpp : Defines the entry point for the console application.
  2. //
  3. #include <opencv2/highgui/highgui.hpp>
  4. #include <opencv2/imgproc/imgproc_c.h>
  5. #include <iostream>
  6. #include <vector>
  7. using namespace std;
  8. double mx = 0, my = 0;
  9. int dx = 0, dy = 0, horizBar_x = 0, vertiBar_y = 0;
  10. bool clickVertiBar = false, clickHorizBar = false, needScroll = false;
  11. CvRect rect_bar_horiz, rect_bar_verti;
  12. void help()
  13. {
  14. printf(
  15. "/n"
  16. "This program demonstrated the use of the cvSetMouseCallback /n"
  17. "for viewing large image with scroll bar in a small window/n"
  18. "created by OpenCV highgui model. (chenyusiyuan, 2011-06-24)/n"
  19. "Call:/n"
  20. "./Image_ScrollBar [<img_filename default im.jpg> <window_width default 1400> <window_height default 700>]/n/n"
  21. );
  22. }
  23. void mouse_callback( int event, int x, int y, int flags, void* param )
  24. {
  25. if (needScroll)
  26. {
  27. switch( event )
  28. {
  29. case CV_EVENT_LBUTTONDOWN:
  30. mx = x, my = y;
  31. dx = 0, dy = 0;
  32. // 按下左键时光标定位在水平滚动条区域内
  33. if (x >= rect_bar_horiz.x && x <= rect_bar_horiz.x+rect_bar_horiz.width
  34. && y >= rect_bar_horiz.y && y<= rect_bar_horiz.y+rect_bar_horiz.height)
  35. {
  36. clickHorizBar = true;
  37. }
  38. // 按下左键时光标定位在垂直滚动条区域内
  39. if (x >= rect_bar_verti.x && x <= rect_bar_verti.x+rect_bar_verti.width
  40. && y >= rect_bar_verti.y && y<= rect_bar_verti.y+rect_bar_verti.height)
  41. {
  42. clickVertiBar = true;
  43. }
  44. break;
  45. case CV_EVENT_MOUSEMOVE:
  46. if (clickHorizBar)
  47. {
  48. dx = fabs(x-mx) > 1 ? (int)(x-mx) : 0;
  49. dy = 0;
  50. }
  51. if (clickVertiBar)
  52. {
  53. dx = 0;
  54. dy = fabs(y-my) > 1 ? (int)(y-my) : 0;
  55. }
  56. mx = x, my = y;
  57. break;
  58. case CV_EVENT_LBUTTONUP:
  59. mx = x, my = y;
  60. dx = 0, dy = 0;
  61. clickHorizBar = false;
  62. clickVertiBar = false;
  63. break;
  64. default:
  65. dx = 0, dy = 0;
  66. break;
  67. }
  68. }
  69. }
  70. void myShowImageScroll(char* title, IplImage* src_img,
  71. int winWidth = 1400, int winHeight = 700) // 显示窗口大小默认为 1400×700
  72. {
  73. IplImage* dst_img;
  74. CvRect rect_dst, // 窗口中有效的图像显示区域
  75. rect_src; // 窗口图像对应于源图像中的区域
  76. int imgWidth = src_img->width,
  77. imgHeight = src_img->height,
  78. barWidth = 25; // 滚动条的宽度(像素)
  79. double scale_w = (double)imgWidth/(double)winWidth, // 源图像与窗口的宽度比值 用以判断是否超出显示范围
  80. scale_h = (double)imgHeight/(double)winHeight; // 源图像与窗口的高度比值 用以判断是否超出显示范围
  81. if(scale_w<1) //如果小于1 说明原图比窗口小,窗口的宽度将重新赋值
  82. winWidth = imgWidth+barWidth;
  83. if(scale_h<1) //如果小于1 说明原图比窗口小,窗口的高度将重新赋值
  84. winHeight = imgHeight+barWidth;
  85. int showWidth = winWidth, showHeight = winHeight; // 窗口中有效的图像显示区域的宽和高
  86. int src_x = 0, src_y = 0; // 源图像中 rect_src 的左上角位置
  87. int horizBar_width = 0, horizBar_height = 0, //定义并初始化垂直于水平滑块的宽高
  88. vertiBar_width = 0, vertiBar_height = 0;
  89. needScroll = scale_w>1.0 || scale_h>1.0 ? true : false;
  90. // 若图像大于设定的窗口大小,则显示滚动条
  91. if(needScroll)
  92. {
  93. dst_img = cvCreateImage(cvSize(winWidth, winHeight),src_img->depth, src_img->nChannels);
  94. cvZero(dst_img);
  95. // 源图像宽度大于窗口宽度,则显示水平滚动条
  96. if(scale_w > 1.0) //宽度超出了
  97. {
  98. showHeight = winHeight - barWidth;
  99. horizBar_width = (int)((double)winWidth/scale_w);
  100. horizBar_height = winHeight-showHeight;
  101. horizBar_x = min(
  102. max(0,horizBar_x+dx),
  103. winWidth-horizBar_width);
  104. rect_bar_horiz = cvRect(
  105. horizBar_x,
  106. showHeight+1,
  107. horizBar_width,
  108. horizBar_height);
  109. // 显示水平滚动条
  110. cvRectangleR(dst_img, rect_bar_horiz, cvScalarAll(255), -1);
  111. }
  112. // 源图像高度大于窗口高度,则显示垂直滚动条
  113. if(scale_h > 1.0) //高度超出了
  114. {
  115. showWidth = winWidth - barWidth;
  116. vertiBar_width = winWidth-showWidth;
  117. vertiBar_height = (int)((double)winHeight/scale_h);
  118. vertiBar_y = min(
  119. max(0,vertiBar_y+dy),
  120. winHeight-vertiBar_height);
  121. rect_bar_verti = cvRect(
  122. showWidth+1,
  123. vertiBar_y,
  124. vertiBar_width,
  125. vertiBar_height); //确定垂直滚动条的白色部分的大小
  126. // 显示垂直滚动条
  127. cvRectangleR(dst_img, rect_bar_verti, cvScalarAll(255), -1);
  128. }
  129. showWidth = min(showWidth,imgWidth);
  130. showHeight = min(showHeight,imgHeight);
  131. // 设置窗口显示区的 ROI
  132. rect_dst = cvRect(0, 0, showWidth, showHeight);
  133. cvSetImageROI(dst_img, rect_dst);
  134. // 设置源图像的 ROI
  135. src_x = (int)((double)horizBar_x*scale_w);
  136. src_y = (int)((double)vertiBar_y*scale_h);
  137. src_x = min(src_x, imgWidth-showWidth);
  138. src_y = min(src_y, imgHeight-showHeight);
  139. rect_src = cvRect(src_x, src_y, showWidth, showHeight);
  140. cvSetImageROI(src_img, rect_src);
  141. // 将源图像内容复制到窗口显示区
  142. cvCopy(src_img, dst_img);
  143. cvResetImageROI(dst_img);
  144. cvResetImageROI(src_img);
  145. // 显示图像和滚动条
  146. cvShowImage(title,dst_img);
  147. cvReleaseImage(&dst_img);
  148. }
  149. // 源图像小于设定窗口,则直接显示图像,无滚动条
  150. else
  151. {
  152. cvShowImage(title, src_img);
  153. }
  154. }
  155. int main(int argc, char** argv)
  156. {
  157. help();
  158. const char* filename = argc > 1 ? argv[1] : "1.bmp";
  159. int width = 1200, height = 800;
  160. if (4==argc)
  161. {
  162. sscanf( argv[2], "%u", &width );
  163. sscanf( argv[3], "%u", &height );
  164. }
  165. cvNamedWindow("Image Scroll Bar", 1);
  166. cvSetMouseCallback("Image Scroll Bar", mouse_callback);
  167. IplImage* image = cvLoadImage( filename, CV_LOAD_IMAGE_COLOR );
  168. if( !image )
  169. {
  170. fprintf( stderr, "Can not load %s and/or %s/n"
  171. "Usage: Image_ScrollBar [<img_filename default im.jpg>]/n",
  172. filename );
  173. exit(-1);
  174. }
  175. while(1)
  176. {
  177. myShowImageScroll("Image Scroll Bar", image, width, height);
  178. int KEY = cvWaitKey(10);
  179. if( (char) KEY == 27 )
  180. break;
  181. }
  182. cvDestroyWindow("Image Scroll Bar");
  183. return 0;
  184. }

这里写图片描述

发表评论

表情:
评论列表 (有 0 条评论,223人围观)

还没有评论,来说两句吧...

相关阅读