前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV 利用滚动条在不缩小的情况下显示大型图片

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

作者头像
chaibubble
发布2022-05-07 09:26:12
6660
发布2022-05-07 09:26:12
举报
文章被收录于专栏:深度学习与计算机视觉

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

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

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

代码语言:javascript
复制
// Image_ScrollBar.cpp : Defines the entry point for the console application.  
//  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc_c.h>  

#include <iostream>  
#include <vector>  

using namespace std;  


double mx = 0, my = 0;  
int dx = 0, dy = 0, horizBar_x = 0, vertiBar_y = 0;  
bool clickVertiBar = false, clickHorizBar = false, needScroll = false;  
CvRect rect_bar_horiz, rect_bar_verti;  

void help()  
{  
	printf(  
		"/n"  
		"This program demonstrated the use of the cvSetMouseCallback /n"  
		"for viewing large image with scroll bar in a small window/n"  
		"created by OpenCV highgui model. (chenyusiyuan, 2011-06-24)/n"  
		"Call:/n"  
		"./Image_ScrollBar [<img_filename default im.jpg> <window_width default 1400> <window_height default 700>]/n/n"  
		);  
}  


void mouse_callback( int event, int x, int y, int flags, void* param )  
{  
	if (needScroll)  
	{  
		switch( event )   
		{  
		case CV_EVENT_LBUTTONDOWN:  
			mx = x, my = y;  
			dx = 0, dy = 0;  
			// 按下左键时光标定位在水平滚动条区域内  
			if (x >= rect_bar_horiz.x && x <= rect_bar_horiz.x+rect_bar_horiz.width  
				&& y >= rect_bar_horiz.y && y<= rect_bar_horiz.y+rect_bar_horiz.height)  
			{  
				clickHorizBar = true;  
			}  
			// 按下左键时光标定位在垂直滚动条区域内  
			if (x >= rect_bar_verti.x && x <= rect_bar_verti.x+rect_bar_verti.width  
				&& y >= rect_bar_verti.y && y<= rect_bar_verti.y+rect_bar_verti.height)  
			{  
				clickVertiBar = true;  
			}  
			break;   
		case CV_EVENT_MOUSEMOVE:   
			if (clickHorizBar)  
			{  
				dx = fabs(x-mx) > 1 ? (int)(x-mx) : 0;  
				dy = 0;  
			}  
			if (clickVertiBar)  
			{  
				dx = 0;  
				dy = fabs(y-my) > 1 ? (int)(y-my) : 0;  
			}  
			mx = x, my = y;  
			break;    
		case CV_EVENT_LBUTTONUP:   
			mx = x, my = y;  
			dx = 0, dy = 0;  
			clickHorizBar = false;  
			clickVertiBar = false;  
			break;    
		default:  
			dx = 0, dy = 0;  
			break;  
		}  
	}  
}  

void myShowImageScroll(char* title, IplImage* src_img,   
	int winWidth = 1400, int winHeight = 700) // 显示窗口大小默认为 1400×700  
{  
	IplImage* dst_img;  
	CvRect  rect_dst,   // 窗口中有效的图像显示区域  
		rect_src;   // 窗口图像对应于源图像中的区域  
	int imgWidth = src_img->width,   
		imgHeight = src_img->height,  
		barWidth = 25;  // 滚动条的宽度(像素)  
	double  scale_w = (double)imgWidth/(double)winWidth,    // 源图像与窗口的宽度比值  用以判断是否超出显示范围
		scale_h = (double)imgHeight/(double)winHeight;            // 源图像与窗口的高度比值  用以判断是否超出显示范围

	if(scale_w<1)                                                                     //如果小于1 说明原图比窗口小,窗口的宽度将重新赋值
		winWidth = imgWidth+barWidth;  
	if(scale_h<1)                                                                     //如果小于1 说明原图比窗口小,窗口的高度将重新赋值
		winHeight = imgHeight+barWidth;  

	int showWidth = winWidth, showHeight = winHeight; // 窗口中有效的图像显示区域的宽和高  
	int src_x = 0, src_y = 0;                                                      // 源图像中 rect_src 的左上角位置  
	int horizBar_width = 0, horizBar_height = 0,                   //定义并初始化垂直于水平滑块的宽高
		vertiBar_width = 0, vertiBar_height = 0;  

	needScroll = scale_w>1.0 || scale_h>1.0 ? true : false;  
	// 若图像大于设定的窗口大小,则显示滚动条  
	if(needScroll)  
	{  
		dst_img = cvCreateImage(cvSize(winWidth, winHeight),src_img->depth, src_img->nChannels);  
		cvZero(dst_img);  
		// 源图像宽度大于窗口宽度,则显示水平滚动条  
		if(scale_w > 1.0)  //宽度超出了
		{  
			showHeight = winHeight - barWidth;  
			horizBar_width = (int)((double)winWidth/scale_w);  
			horizBar_height = winHeight-showHeight;  
			horizBar_x = min(  
				max(0,horizBar_x+dx),  
				winWidth-horizBar_width);  
			rect_bar_horiz = cvRect(  
				horizBar_x,   
				showHeight+1,   
				horizBar_width,   
				horizBar_height);  
			// 显示水平滚动条  
			cvRectangleR(dst_img, rect_bar_horiz, cvScalarAll(255), -1);  
		}   
		// 源图像高度大于窗口高度,则显示垂直滚动条  
		if(scale_h > 1.0)  //高度超出了
		{  
			showWidth = winWidth - barWidth;  
			vertiBar_width = winWidth-showWidth;  
			vertiBar_height = (int)((double)winHeight/scale_h);  
			vertiBar_y = min(  
				max(0,vertiBar_y+dy),   
				winHeight-vertiBar_height);  
			rect_bar_verti = cvRect(  
				showWidth+1,   
				vertiBar_y,   
				vertiBar_width,   
				vertiBar_height);   //确定垂直滚动条的白色部分的大小
			// 显示垂直滚动条  
			cvRectangleR(dst_img, rect_bar_verti, cvScalarAll(255), -1);  
		}  

		showWidth = min(showWidth,imgWidth);  
		showHeight = min(showHeight,imgHeight);  
		// 设置窗口显示区的 ROI  
		rect_dst = cvRect(0, 0, showWidth, showHeight);  
		cvSetImageROI(dst_img, rect_dst);  
		// 设置源图像的 ROI  
		src_x = (int)((double)horizBar_x*scale_w);  
		src_y = (int)((double)vertiBar_y*scale_h);  
		src_x = min(src_x, imgWidth-showWidth);  
		src_y = min(src_y, imgHeight-showHeight);  
		rect_src = cvRect(src_x, src_y, showWidth, showHeight);  
		cvSetImageROI(src_img, rect_src);  
		// 将源图像内容复制到窗口显示区  
		cvCopy(src_img, dst_img);  

		cvResetImageROI(dst_img);  
		cvResetImageROI(src_img);  
		// 显示图像和滚动条  
		cvShowImage(title,dst_img);  

		cvReleaseImage(&dst_img);  
	}  
	// 源图像小于设定窗口,则直接显示图像,无滚动条  
	else  
	{  
		cvShowImage(title, src_img);  
	}     
}  

int main(int argc, char** argv)  
{  
	help();  
	const char* filename = argc > 1 ? argv[1] : "1.bmp";  
	int width = 1200, height = 800;  
	if (4==argc)  
	{  
		sscanf( argv[2], "%u", &width );  
		sscanf( argv[3], "%u", &height );  
	}  

	cvNamedWindow("Image Scroll Bar", 1);  
	cvSetMouseCallback("Image Scroll Bar", mouse_callback);  

	IplImage* image = cvLoadImage( filename, CV_LOAD_IMAGE_COLOR );  
	if( !image )  
	{  
		fprintf( stderr, "Can not load %s and/or %s/n"  
			"Usage: Image_ScrollBar [<img_filename default im.jpg>]/n",  
			filename );  
		exit(-1);  
	}  

	while(1)  
	{  
		myShowImageScroll("Image Scroll Bar", image, width, height);  

		int KEY = cvWaitKey(10);  
		if( (char) KEY == 27 )  
			break;  

	}  
	cvDestroyWindow("Image Scroll Bar");  

	return 0;  
}  
这里写图片描述
这里写图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-03-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档