《OpenCV 4计算机视觉项目实战 》 —3.3 OpenCV的基本图形用户界面

举报
华章计算机 发表于 2019/11/10 12:02:03 2019/11/10
【摘要】 本节书摘来自华章计算机《OpenCV 4计算机视觉项目实战》 一书中第三章,第3.3节,作者[西班牙]大卫·米兰·埃斯克里瓦(David Millán Escrivá)[西班牙]维尼休斯·G.门东萨(Vinícius G. Mendon)。

3.3 OpenCV的基本图形用户界面

我们将使用OpenCV创建一个基本用户界面。OpenCV用户界面使我们能够创建窗口,然后在里面添加图像,并移动、调整大小和销毁所添加的图像。用户界面位于OpenCV的highui模块中。在下面的代码中,我们将学习如何创建和显示两个图像,具体来说,可以在桌面上通过按键来显示多个窗口,并使图像移入这些窗口中。

不要担心阅读完整的代码,我们会用小代码块来逐个解释它:

 image.png

image.png

我们来理解这段代码:

1. 为了便于使用图形用户界面,第一项必须完成的任务是导入OpenCV的highui模块:

 image.png

2. 完成创建新窗口的准备工作之后,我们必须加载一些图像:

 image.png

3. 要创建窗口,我们使用namedWindow函数。该函数有两个参数。第一个参数是带有窗口名称的常量字符串,第二个参数是我们需要的标志,第二个参数是可选的:

 image.png

4. 在这个例子中,我们创建了两个窗口:第一个叫作Lena,第二个叫作Photo。

对于Qt和原生界面,默认有三个标志:

WINDOW_NORMAL:此标志允许用户调整窗口的大小

WINDOW_AUTOSIZE:如果设置了此标志,则窗口大小为自动调整以适应显示图像,但不能调整窗口的大小

WINDOW_OPENGL:此标志启用OpenGL支持

Qt有许多额外的标志:

WINDOW_FREERATIO或WINDOW_KEEPRATIO:如果设置了WINDOW_FREERATIO,则调整图像时不考虑其比例。如果设置了WINDOW_KEEPRATIO,则根据其比例调整图像。

WINDOW_GUI_NORMAL或WINDOW_GUI_EXPANDED:第一个标志提供没有状态栏和工具栏的基本界面。第二个标志使用状态栏和工具栏来支持最高级的图形用户界面。

如果使用Qt编译OpenCV,默认情况下,我们创建的所有窗口都在展开的界面中,但我们可以添加CV_GUI_NORMAL标志使用原生界面和更基本的界面。默认情况下,标志为WINDOW_AUTOSIZE、WINDOW_KEEPRATIO和WINDOW_GUI_EXPANDED。

5. 当创建多个窗口时,它们是叠加的,但我们可以使用moveWindow函数将窗口移动到桌面的任何区域,如下所示:

 image.png

6. 在这段代码中,我们将Lena窗口向左移动了10个像素,向上移动了10个像素,将Photo窗口向左移动了520个像素,向上移动了10个像素。

在使用imshow函数显示此前加载的图像之后,我们通过调用resizeWindow函数将Lena窗口的大小调整为512像素,该函数有三个参数:window name、width和height。

 image.png

具体的窗口大小是指图像区域,工具栏不计算在内,只有未启用WINDOW_AUTOSIZE标志的窗口才能调整大小。

7. 在利用waitKey函数等待按键按下之后,我们用destroyWindow函数删除这个窗口,其中,窗口的名称是唯一需要的参数:

 image.png

8. OpenCV可以通过一次调用删除所创建的所有窗口,该函数称为destroyAllWindows。为了演示它是如何工作的,我们在样本中创建10个窗口,然后等待按键按下。当用户按下任意键时,它就会销毁所有得窗口:

 image.png

在任何情况下,OpenCV都会在应用程序终止时自动销毁所有窗口,因此在我们的应用程序结束时不必调用此函数。

所有这些代码的结果可以在以下图像中看到。首先,它显示两个窗口,如图3-2所示。

按下任意键之后,应用程序继续运行,并在不同的位置绘制出几个窗口,如图3-3所示。

只需几行代码,我们就可以创建和操作窗口并显示图像。我们现在已经准备好进行用户与图像的交互,并添加用户界面控件。

 image.png

图 3-2

 image.png

图 3-3

将滑块和鼠标事件添加到界面

鼠标事件和滑块控件在计算机视觉和OpenCV中非常有用。使用这些控件,可以直接与界面交互,并改变输入图像或变量的属性。在本节中,我们将介绍用于基本交互的鼠标事件和滑块控件。为了便于正确理解,我们创建了以下代码,通过这些代码,我们将使用鼠标事件在图像中绘制绿色圆圈,并使用滑块对图像进行模糊处理:

 image.png

我们来理解这段代码。

首先,创建一个变量来保存滑块位置。我们需要保存滑块位置,以便从其他函数访问它:

 image.png

现在,为滑块和鼠标事件定义回调函数,这是OpenCV的setMouseCallback函数和createTrackbar函数必需的:

 image.png

在main函数中,加载一个图像并创建一个名为Lena的新窗口:

 image.png

image.png

现在创建滑块。OpenCV的createTrackbar函数用于生成滑块,其参数按顺序如下所示:

1. 跟踪条名称。

2. 窗口名称。

3. 将作为值使用的整数指针。该参数是可选的,如果被设置,则滑块会在创建时获得该位置。

4. 滑块上的最大位置。

5. 滑块位置变化时的回调函数。

6. 要发送到回调函数的用户数据。它可用于在不使用全局变量的情况下将数据发送到回调函数。

对于这段代码,我们为Lena窗口添加了trackbar,然后调用Lena跟踪条对图像进行模糊处理。跟踪条的值存储在将会作为指针传递的blurAmount整数中,并将跟踪条的最大值设置为30。把onChange设置为回调函数,并将lena mat图像作为用户数据发送:

 image.png

滑块创建好以后,当用户单击鼠标左键时,我们添加鼠标事件来绘制圆形。这需要使用OpenCV的setMouseCallback函数,该函数有三个参数:

获取鼠标事件的窗口名称。

当有任何鼠标交互时调用的回调函数。

用户数据:这是在触发时将要发送给回调函数的任意数据。在这个例子中,我们将会发送整个Lena图像。

使用以下代码,可以向Lena窗口添加鼠标回调,并将onMouse设置为回调函数,从而将lena mat图像作为用户数据进行传递:

 image.png

为了完成主函数,需要使用与滑块相同的参数来初始化图像。要执行初始化,只需调用onChange回调函数,并在使用destroyWindow关闭窗口之前等待事件,如下面的代码所示:

 image.png

滑块回调函数使用滑块值作为模糊量,将基本的模糊滤镜应用于图像:

 

 image.png

该函数使用变量pos来检查滑块值是否为0。在这种情况下,我们不使用过滤器,因为它会生成执行错误,也不能用0像素模糊。检查滑块值后,我们创建一个名为imgBlur的空矩阵来存储模糊结果。要检索通过回调函数中的用户数据发送的图像,必须把void * userData转换为正确的图像类型指针Mat*。

现在我们有了正确的变量来应用模糊滤镜。模糊函数将基本的中值滤波器应用于输入图像,在这个例子中是* img。对于输出图像,最后需要的参数是想要应用的模糊内核的大小(内核是用于计算内核和图像之间卷积平均值的小矩阵)。在这个例子中使用的是pos大小的平方内核。最后,只需用imshow函数更新图像界面。

鼠标事件的回调函数有五个输入参数:第一个参数定义事件类型,第二个和第三个定义鼠标位置,第四个参数定义滚轮动作,第五个参数定义用户输入数据。

鼠标事件类型如下:

image.png

 

在这个例子中,我们只处理单击鼠标左键所产生的事件,并且丢弃除EVENT_LBUTTONDOWN之外的任何事件。丢弃其他事件后,用滑块回调获取输入图像,并用OpenCV的circle函数获取图像中的圆:

 

image.png

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。