zoukankan      html  css  js  c++  java
  • opencv(5)GUI

    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的文本文件。把上段代码的内容放进去,就定义了小山头的框为黄色,骏马的框为青色,以及红色的屌丝。

  • 相关阅读:
    1024X768大图 (Wallpaper)
    (Mike Lynch)Application of linear weight neural networks to recognition of hand print characters
    瞬间模糊搜索1000万基本句型的语言算法
    单核与双核的竞争 INTEL P4 670对抗820
    FlashFTP工具的自动缓存服务器目录的功能
    LDAP over SSL (LDAPS) Certificate
    Restart the domain controller in Directory Services Restore Mode Remotely
    How do I install Active Directory on my Windows Server 2003 server?
    指针与指针变量(转)
    How to enable LDAP over SSL with a thirdparty certification authority
  • 原文地址:https://www.cnblogs.com/qjoanven/p/7680330.html
Copyright © 2011-2022 走看看