OpenCV的图形用户界面(Graphical User Interface, GUI)和绘图等相关功能也是很有用的功能,无论是可视化,图像调试还是我们这节要实现的标注任务,都可以有所帮助。

窗口循环

OpenCV显示一幅图片的函数是cv2.imshow(),第一个参数是显示图片的窗口名称,第二个参数是图片的array。不过如果直接执行这个函数的话,什么都不会发生,因为这个函数得配合cv2.waitKey()一起使用。cv2.waitKey()指定当前的窗口显示要持续的毫秒数,比如cv2.waitKey(1000)就是显示一秒,然后窗口就关闭了。比较特殊的是cv2.waitKey(0),并不是显示0毫秒的意思,而是一直显示,直到有键盘上的按键被按下,或者鼠标点击了窗口的小叉子才关闭。cv2.waitKey()的默认参数就是0,所以对于图像展示的场景,cv2.waitKey()或者cv2.waitKey(0)是最常用的。

cv2.waitKey()参数不为零的时候则可以和循环结合产生动态画面。Python的itertools模块中的cycle函数可以把一个可遍历结构编程一个无限循环的迭代器。cv2.waitKey()返回的就是键盘上出发的按键。对于字母就是ascii码,特殊按键比如上下左右等,则对应特殊的值,其实这就是键盘事件的最基本用法。

鼠标和键盘事件

cv2.waitKey()就是获取键盘消息的最基本方法。下面这段循环代码就能够获取键盘上按下的按键,并在终端输出:

while key != 27:
cv2.imshow('Honeymoon Island', img)
key = cv2.waitKey()
# 如果获取的键值小于256则作为ascii码输出对应字符,否则直接输出值
msg = '{} is pressed'.format(chr(key) if key < 256 else key)
print(msg)

通过这个程序我们能获取一些常用特殊按键的值。

需要注意的是在不同的操作系统里这些值可能是不一样的。鼠标事件比起键盘事件稍微复杂一点点,需要定义一个回调函数,然后把回调函数和一个指定名称的窗口绑定,这样只要鼠标位于画面区域内的事件就都能捕捉到。把下面这段代码插入到上段代码的while之前,就能获取当前鼠标的位置和动作并输出:

# 定义鼠标事件回调函数
def on_mouse(event, x, y, flags, param): # 鼠标左键按下,抬起,双击
if event == cv2.EVENT_LBUTTONDOWN:
print('Left button down at ({}, {})'.format(x, y))
elif event == cv2.EVENT_LBUTTONUP:
print('Left button up at ({}, {})'.format(x, y))
elif event == cv2.EVENT_LBUTTONDBLCLK:
print('Left button double clicked at ({}, {})'.format(x, y)) # 鼠标右键按下,抬起,双击
elif event == cv2.EVENT_RBUTTONDOWN:
print('Right button down at ({}, {})'.format(x, y))
elif event == cv2.EVENT_RBUTTONUP:
print('Right button up at ({}, {})'.format(x, y))
elif event == cv2.EVENT_RBUTTONDBLCLK:
print('Right button double clicked at ({}, {})'.format(x, y)) # 鼠标中/滚轮键(如果有的话)按下,抬起,双击
elif event == cv2.EVENT_MBUTTONDOWN:
print('Middle button down at ({}, {})'.format(x, y))
elif event == cv2.EVENT_MBUTTONUP:
print('Middle button up at ({}, {})'.format(x, y))
elif event == cv2.EVENT_MBUTTONDBLCLK:
print('Middle button double clicked at ({}, {})'.format(x, y)) # 鼠标移动
elif event == cv2.EVENT_MOUSEMOVE:
print('Moving at ({}, {})'.format(x, y)) # 为指定的窗口绑定自定义的回调函数
cv2.namedWindow('Honeymoon Island')
cv2.setMouseCallback('Honeymoon Island', on_mouse)

标注小工具

基本思路是对要标注的图像建立一个窗口循环,然后每次循环的时候对图像进行一次拷贝。鼠标在画面上画框的操作,以及已经画好的框的相关信息在全局变量中保存,并且在每个循环中根据这些信息,在拷贝的图像上再画一遍,然后显示这份拷贝的图像。

基于这种实现思路,使用上我们采用一个尽量简化的设计:

- 输入是一个文件夹,下面包含了所有要标注物体框的图片。如果图片中标注了物体,则生成一个相同名称加额外后缀名的文件保存标注信息。

- 标注的方式是按下鼠标左键选择物体框的左上角,松开鼠标左键选择物体框的右下角,鼠标右键删除上一个标注好的物体框。所有待标注物体的类别,和标注框颜色由用户自定义,如果没有定义则默认只标注一种物体,定义该物体名称叫“Object”。

- 方向键的←和→用来遍历图片,↑和↓用来选择当前要标注的物体,Delete键删除一张图片和对应的标注信息。

每张图片的标注信息,以及自定义标注物体和颜色的信息,用一个元组表示,第一个元素是物体名字,第二个元素是代表BGR颜色的tuple或者是代表标注框坐标的元组。对于这种并不复杂复杂的数据结构,我们直接利用Python的repr()函数,把数据结构保存成机器可读的字符串放到文件里,读取的时候用eval()函数就能直接获得数据。这样的方便之处在于不需要单独写个格式解析器。如果需要可以在此基础上再编写一个转换工具就能够转换成常见的Pascal VOC的标注格式或是其他的自定义格式。

在这些思路和设计下,我们定义标注信息文件的格式的例子如下:

('Hill', ((221, 163), (741, 291)))
('Horse', ((465, 430), (613, 570)))

元组中第一项是物体名称,第二项是标注框左上角和右下角的坐标。这里之所以不把标注信息的数据直接用pickle保存,是因为数据本身不会很复杂,直接保存还有更好的可读性。自定义标注物体和对应标注框颜色的格式也类似,不过更简单些,因为括号可以不写,具体如下:

'Horse', (255, 255, 0)
'Hill', (0, 255, 255)
'DiaoSi', (0, 0, 255)

第一项是物体名称,第二项是物体框的颜色。使用的时候把自己定义好的内容放到一个文本里,然后保存成和待标注文件夹同名,后缀名为labels的文件。比如我们在一个叫samples的文件夹下放上一些草原的照片,然后自定义一个samples.labels的文本文件。把上段代码的内容放进去,就定义了小山头的框为黄色,骏马的框为青色,以及红色的屌丝。

opencv(5)GUI的更多相关文章

  1. 使用Qt创建第一个OpenCV的Gui应用

    写在前面 学习OpenCV有一些小日子了,发现群里还有很多初学OpenCV的人像我当初一样跌跌撞撞到处找资料,所以在这里把学习笔记分享给大家,希望有志学习OpenCV进行计算机视觉活动的小伙伴们能少走 ...

  2. EmguCV学习 与opencv的区别和联系

    openCV是因特尔的一个开源的视觉库,里面几乎包含了所有的图像处理的经典算法,并且采用C和少量的C++编写,运行效率很高,对于做图像处理这方面工作的,认识opencv是必须的工作.不过opencv有 ...

  3. opencv 61篇

    (一)--安装配置.第一个程序 标签: imagebuildincludeinputpathcmd 2011-10-21 16:16 41132人阅读 评论(50) 收藏 举报  分类: OpenCV ...

  4. 图像显示与加载——opencv(转)

    cvLoadImage() 函数:IplImage* cvLoadImage("图像名称",参数): 函数作用:加载图片: 函数返回值:为IplImage结构体: 参数说明:参数值 ...

  5. opencv在arm和x86在移植

    一个.开发环境 操作系统:fedora14 Opencv版本号:2.0 Qt版本号:4.7 arm:mini6410 交叉编译工具:arm-linux-gcc-4.5.1 二.安装与配置 Linux系 ...

  6. OpenCV学习笔记:opencv_highgui模块

    一,简介 本模块为跨平台的gui/IO组件,支持平台包括windows,linux,mac,IOS,android,可支持图像/视频/摄像头的读取显示以及转码. 二,分析 本模块为跨平台的gui/IO ...

  7. OpenCV学习笔记(六十二)——《OpenCV Computer Version with Python》阅读摘要

    如今python火啊.每次OpenCV自带的ml模块都让我直呼坑爹,索性准备用python来做OpenCV后期的机器学习算法的处理.于是赶紧拿起这本书读读. 适合OpenCV和python都有一定基础 ...

  8. Qt QImage与OpenCV Mat转换

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/51029382 应一个朋友的要求,整理总 ...

  9. opencv数据结构与基本绘图

    #include <opencv2\core\core.hpp>//核心组件 #include <opencv2\opencv.hpp>//GUI,包含媒体输入输出,视频捕捉. ...

随机推荐

  1. Android 通知之 Notification

    Notifications | Android Developershttp://developer.android.com/guide/topics/ui/notifiers/notificatio ...

  2. Sentence-seven basic patterns 英语句子结构

    Meaning of some words subject 主语 verb  动词 object 宾语 adverbial 状语 complement 补语 imperative sentence 祈 ...

  3. windows安装filebeat服务报错

    cmd进入filebeat目录下   用以下命令执行: PowerShell.exe -ExecutionPolicy UnRestricted -File .\install-service-fil ...

  4. 2015/11/5用Python写游戏,pygame入门(5):面向对象的游戏设计

    昨天的内容里有了运动的子弹,虽然我们只添加了一个子弹,但你可以看到我们需要记录子弹的x,y坐标,每次要更新它的坐标.如果我们想要有多颗子弹,就需要存储多个坐标.那时候处理起来就不显得那么简单,也许我们 ...

  5. 如何写一个好bug

      自己的总结,和大家分享~

  6. [转载]Getting Started with ASP.NET vNext and Visual Studio 14

    说在转载之前的话:ASP.NET框架之前不断做大,而vNext则是从头开始,对ASP.NET框架进行拆分并瘦身,面对不同的需求而更加灵活,各个拆分出来的模块更加轻量.vNext的出现,对ASP.NET ...

  7. 实验九 Web安全基础

  8. 20155306 2016-2017-2 《Java程序设计》第6周学习总结

    20155306 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 第十章 输入/输出 10.1 InputStream与OutputStream 如果要将数据 ...

  9. Hadoop/Spark环境运行过程中可能遇到的问题或注意事项

    1.集群启动的时候,从节点的datanode没有启动 问题原因:从节点的tmp/data下的配置文件中的clusterID与主节点的tmp/data下的配置文件中的clusterID不一致,导致集群启 ...

  10. SQL Server DB Link相关

    若想通过DBlink 清空表或执行存储过程,可以通过这种方式 Insert into table select * from table时,Pull 方式比Push方式快很多