Qt+OpenCV缩放图像至格子级别以及跟踪鼠标位置

最近需要做一个将图像放大至格子级别以及随着鼠标移动(不需要按下鼠标),实时显示鼠标位置以及对应的RGB的值。因此结合了opencv以及Qt做了一个这样的东西

实现的主要的主要思路是,通过OpenCV进行图像的处理和放大,然后转换为QImage在Qt中显示出来。

  •    opencv缩放图像

首先是利用opencv进行图像的放大,利用的函数是resize函数。

      需要更进一步了解opencv图像的缩放,可以了解一下博客内容:【OpenCV入门教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放。以下是resize函数的相关内容:

resize( )为OpenCV中专职调整图像大小的函数。
此函数将源图像精确地转换为指定尺寸的目标图像。如果源图像中设置了ROI(Region Of Interest ,感兴趣区域),那么resize( )函数会对源图像的ROI区域进行调整图像尺寸的操作,来输出到目标图像中。若目标图像中已经设置ROI区域,不难理解resize( )将会对源图像进行尺寸调整并填充到目标图像的ROI中。
很多时候,我们并不用考虑第二个参数dst的初始图像尺寸和类型(即直接定义一个Mat类型,不用对其初始化),因为其尺寸和类型可以由src,dsize,fx和fy这其他的几个参数来确定。

函数原型为:

C++: void resize(InputArray src,OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )  

  • 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。
  • 第二个参数,OutputArray类型的dst,输出图像,当其非零时,有着dsize(第三个参数)的尺寸,或者由src.size()计算出来。
  • 第三个参数,Size类型的dsize,输出图像的大小;如果它等于零,自动通过fx和fy计算大小。
  • 第四个参数,double类型的fx,沿水平轴的缩放系数,有默认值0,且当其等于0时,自动匹配目标图像大小计算缩放系数:
  • 第五个参数,double类型的fy,沿垂直轴的缩放系数,有默认值0,且当其等于0时,自动匹配目标图像大小计算缩放系数:
  • 第六个参数,int类型的interpolation,用于指定插值方式,默认为INTER_LINEAR(线性插值)。
可选的插值方式如下:
  1. INTER_NEAREST - 最近邻插值
  2. INTER_LINEAR - 线性插值(默认值)
  3. INTER_AREA - 区域插值(利用像素区域关系的重采样插值)
  4. INTER_CUBIC –三次样条插值(超过4×4像素邻域内的双三次插值)
  5. INTER_LANCZOS4 -Lanczos插值(超过8×8像素邻域的Lanczos插值)
如果需要放大图像至格子形状,尽量保持不失真,可采用区域插值。

  • Qt跟踪鼠标以及获取鼠标坐标

接着就是跟踪鼠标位置,如何在不点击鼠标的情况下,移动鼠标就可以得到鼠标的位置呢,在qt的官网文档中,给出了关于mouseMoveEvent的解释:

Qt+OpenCV缩放图像至格子级别以及跟踪鼠标位置_第1张图片

所以为了在不按下鼠标就能获取到鼠标移动的事先,需要对setMouseTracking()进行设置,默认是false,因此我们需要在代码中显示的设置为true。另外,需要注意到的是,我们是对对指定的控件类型进行鼠标移动的进行跟踪,几乎所有的控件如QLabel,都是继承自QWidget,因此我们需要针对我们的控件进行设置鼠标跟踪,如接下来我是在我的对象ui.display(class为QLabel)进行鼠标跟踪,因此我需要进行ui.display->setMouseTracking(true)的设置。

此外,我的目的是为了判断进行到ui.display的区域类之后,才会进行鼠标跟踪以及对鼠标样式的修改,如进入到区域内,会变成cross样式,离开后又会重新变成Arrow样式。因此QLabel需要进行事件监听,对此,我的博文有详细的介绍: Qt(四)--- 事件处理机制以及QLabel的交互实现

现将部分的关键代码贴出来:

      类中的定义:

proctected:
virtual bool eventFilter(QObject *, QEvent *);
proctected slots:
void onScaleUp();
void onScaleDown();
private:
double m_scale_factor;

构造函数的定义:

m_scale_factor=1.0;
//这里是在display设置mouseTracking,而不是直接setMouseTracking,不然display没有办法跟踪鼠标移动
ui.display->setMouseTracking(true);
ui.display->installEventFilter(this);
connect(ui.scaleUpBtn,SIGNAL(clicked()),this,SLOT(onScaleUp()));
connect(ui.scaleDownBtn,SIGNAL(clicked()),this,SLOT(onScaleDown()));


函数实现:

bool FrameGrabber::eventFilter(QObject *obj, QEvent *event)
{
	if(obj==ui.display && (event->type()==QMouseEvent::MouseMove))
	{
		if(!displayImage.isNull())
		{
			ui.textBrowser->clear();
			QMouseEvent *mouseEvent=static_cast(event);
			setCursor(Qt::CrossCursor);
			QPoint qPos=mouseEvent->globalPos();
			QPoint qPos1=ui.display->mapFromGlobal(qPos);
			QRect rect=ui.display->contentsRect();
			QPoint qPos2 = qPos1 + rect.topLeft();
			QString posInfo;
			int x, y;
			if(m_scale_factor> 1.0 || m_scale_factor<1.0)
			{
				x=(int)(qPos2.x()*(1/m_scale_factor));
				y=(int)(qPos2.y()*(1/m_scale_factor));
			}
			else
			{
				x=qPos2.x();
				y=qPos2.y();
			}
			
			posInfo="(x,y) = ";
			posInfo+="(";
			posInfo+=QString::number(x);
			posInfo+=",";
			posInfo+=QString::number(y);
			posInfo+=")";
			ui.textBrowser->append(posInfo);

			QImage infoImage=QImage(image.data,width,height,QImage::Format_Grayscale8);
			QString rgbInfo;
			QRgb qRgb=infoImage.pixel(x,y);
			rgbInfo="(r,g,b) = ";
			rgbInfo+="(";
			rgbInfo+=QString::number(qRed(qRgb));
			rgbInfo+=",";
			rgbInfo+=QString::number(qGreen(qRgb));
			rgbInfo+=",";
			rgbInfo+=QString::number(qBlue(qRgb));
			rgbInfo+=")";
			ui.textBrowser->append(rgbInfo);
		}
	}
	else if(obj==ui.display && (event->type()==QEvent::Leave))
	{
		setCursor(Qt::ArrowCursor);
	}
	return QWidget::eventFilter(obj,event);
}
oid FrameGrabber::onScaleUp()
{
	if(timer->isActive())
	{
		QMessageBox qb;qb.setIcon(QMessageBox::Information);qb.setWindowFlags(Qt::FramelessWindowHint);
		qb.setText(QString::fromLocal8Bit("连续帧显示中,请先暂停图像抓取,然后进行图像缩放查看"));
		qb.exec();
		return;
	}
	if(m_scale_factor<16.0)
	{
		if(image.empty())
			return;
		m_scale_factor*=2.0;

		QString factorStr;
		if(m_scale_factor*1.0==1.0f)
			factorStr="1/1";
		else if(m_scale_factor*2.0==1.0f)
			factorStr="1/2";
		else if(m_scale_factor*4.0==1.0f)
			factorStr="1/4";
		else if(m_scale_factor*8.0==1.0f)
			factorStr="1/8";
		else if(m_scale_factor*16.0==1.0f)
			factorStr="1/16";
		else if(m_scale_factor*32.0==1.0f)
			factorStr="1/32";
		else if(m_scale_factor/2.0==1.0f)
			factorStr="2/1";
		else if(m_scale_factor/4.0==1.0f)
			factorStr="4/1";
		else if(m_scale_factor/8.0==1.0f)
			factorStr="8/1";
		else if(m_scale_factor/16.0==1.0f)
			factorStr="16/1";
		else if(m_scale_factor/32.0==1.0f)
			factorStr="32/1";
		ui.label_factor->setText(factorStr);
		Mat scaleMat;
		cv::resize(image,scaleMat,Size(0,0),m_scale_factor,m_scale_factor,INTER_AREA);
		displayImage=QImage(scaleMat.data,scaleMat.cols,scaleMat.rows,QImage::Format_Grayscale8);
		ui.display->setPixmap(QPixmap::fromImage(displayImage));
	}
	else
		return;
	
}

void FrameGrabber::onScaleDown()
{
	if(timer->isActive())
	{
		QMessageBox qb;qb.setIcon(QMessageBox::Information);qb.setWindowFlags(Qt::FramelessWindowHint);
		qb.setText(QString::fromLocal8Bit("连续帧显示中,请先暂停图像抓取,然后进行图像缩放查看"));
		qb.exec();
		return;
	}
	if(m_scale_factor*16>1.0)
	{
		if(image.empty())
			return;
		m_scale_factor=m_scale_factor/2.0;
		QString factorStr;
		if(m_scale_factor*1.0==1.0f)
			factorStr="1/1";
		else if(m_scale_factor*2.0==1.0f)
			factorStr="1/2";
		else if(m_scale_factor*4.0==1.0f)
			factorStr="1/4";
		else if(m_scale_factor*8.0==1.0f)
			factorStr="1/8";
		else if(m_scale_factor*16.0==1.0f)
			factorStr="1/16";
		else if(m_scale_factor*32.0==1.0f)
			factorStr="1/32";
		else if(m_scale_factor/2.0==1.0f)
			factorStr="2/1";
		else if(m_scale_factor/4.0==1.0f)
			factorStr="4/1";
		else if(m_scale_factor/8.0==1.0f)
			factorStr="8/1";
		else if(m_scale_factor/16.0==1.0f)
			factorStr="16/1";
		else if(m_scale_factor/32.0==1.0f)
			factorStr="32/1";

		ui.label_factor->setText(factorStr);
		Mat scaleMat;
		cv::resize(image,scaleMat,Size(0,0),m_scale_factor,m_scale_factor,INTER_AREA);
		displayImage=QImage(scaleMat.data,scaleMat.cols,scaleMat.rows,QImage::Format_Grayscale8);
		ui.display->setPixmap(QPixmap::fromImage(displayImage));
	}
	
}

最后的结果如图:

Qt+OpenCV缩放图像至格子级别以及跟踪鼠标位置_第2张图片

你可能感兴趣的:(图像处理,OpenCV,Qt,Qt学习与实践,opencv实践)