开发者

python opencv鼠标画点之cv2.drawMarker()函数

目录
  • 前言
  • cv2.drawMarker()函数说明

    • 参数说明

  • 利用鼠标回调函数交互式画点

    • 例1,简单的例子

    • 例2,删除功能

  • 总结

    前言

    这里所谓画点的意思是指在单一像素点上画一个标记符,而不是画小圆点。使用的函数是cv2.drawMarker(img, position, color, ...)

    关于鼠标回调函数的说明可以参考:opencv-python的鼠标交互操作

    cv2.drawMarker()函数说明

    参数说明

    导入cv2后,通过help(cv2.drawMarker)可以看到函数的帮助文档如下:

    drawMarker(...)
        drawMarker(img, position, color[, markerType[, markerSize[, thickness[, line_type]]]]) -> img
        .   @brief Draws a marker on a predefined position in an image.
        .   
        .   The function cv::drawMarker draws a marker on a given position in the image. For the moment several
        .   marker types are supported, see #MarkerTypes for more information.
        .   
        .   @param img Image.
        .   @param position The point where the crosshair is positioned.
        .   @param color Line color.
        .   @param markerType The specific type of marker you want to use, see #MarkerTypes
        .   @param thickness Line thickness.
        .   @param line_type Type of the line, See #LineTypes
        .   @param markerSize The length of the marker axis [default = 20 pixels]
    

    其中三个必选参数:img, position, color,其他参数是可选。三个必选参数说明如下:

    • img:底图,uint8类型的ndarray,
    • position:坐标,是一个包含两个数字的tuple(必需是tuple),表示(x, y)
    • color:颜色,是一个包含三个数字的tuple或list,表示(b, g, r)

    其他参数说明如下:

    • markerType:点的类型。取值0-6,有相应的宏定义与之对应,具体的可参考下面的一个表。
    • markerSize:点的大小。大于0的整数,必需是整数。实际输入<=0的数字也可,但是估计程序里有判断,<=0等同于1。默认值是20。
    • thickness:点的线宽。必需是大于0的整数,必需是整数,不能小于0,默认值是1。
    • line_type:线的类型。可以取的值有cv2.LINE_4,cv2.LINE_8,cv2.LINE_AA。其中cv2.LINE_AA的AA表示抗锯齿,线会更平滑。

    markerType取值说明

    数值 宏定义 说明
    0 cv2.MARKER_CROSS 十字线(横竖两根线)
    1 cv2.MARKER_TILTED_CROSS 交叉线(斜着两根线)
    2 cv2.MARKER_STAR 米字线(横竖加斜着共四根线)
    3 cv2.MARKER_DIAMOND 旋转45度的正方形
    4 cv2.MARKER_SQUARE 正方形
    5 cv2.MARKER_TRIANGLE_UP 尖角向上的三角形
    6 cv2.MARKER_TRIANGLE_DOWN 尖角向下的三角形

    markerType示例

    下面是一个简单的画点程序

    # -*- coding: utf-8 -*-
    
    import cv2
    import numpy as np
    
    if __name__ == '__main__':
        image = np.zeros((256, 256, 3), np.uint8)
        color = (0, 255, 0)
        cv2.drawMarker(image, (50, 50), color, markerType=0)
        cv2.drawMarker(image, (100, 50), color, markerType=1)
        cv2.drawMarker(image, (150, 50), color, markerType=2)
        cv2.drawMarker(image, (200, 50), color, markerType=3)
        cv2.drawMarker(image, (50, 100), color, markerType=4)
        cv2.drawMarker(image, (100, 100), color, markerType=5)
        cv2.drawMarker(image, (150, 100), color, markerType=6)
        cv2.namedWindow('marker_type', 1)
        cv2.imshow('marker_type', image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    

    请特别注意,opencv在调用这些画图函数后,image的内容会被这些画图函数改变,也就是说,函数调用之后,我们就拿不回原始的image了,除非另外保存一份原始image的副本。在写一些交互画图函数时,这个特性需要格外注意。

    程序执行结果如下。

    python opencv鼠标画点之cv2.drawMarker()函数

    利用鼠标回调函数交互式画点

    例1,简单的例子

    该例子与 中的例子相同

    # -*- coding: utf-8 -*-
    
    import cv2
    import numpy as np
    
    WIN_NAME = 'pick_points'
    
    
    def onmouse_pick_points(event, x, y, flags, param):
        if event == cv2.EVENT_LBUTTONDOWN:
            print('x = %d, y = %d' % (x, y))
            cv2.drawMarker(param, (x, y), (0, 255, 0))
    
    
    if __name__ == '__main__':
        image = np.zeros((256, 256, 3), np.uint8)
        cv2.namedWindow(WIN_NAME, 0)
        cv2.setMouseCallback(WIN_NAME, onmouse_pick_points, image)
        while True:
            cv2.imshow(WIN_NAME, image)
            key = cv2.waitKey(30)
            ifwww.cppcns.com key == 27:  # ESC
                break
        cv2.destroyAllWindows()
    

    上面程序中有几个注意点:

    • setMouseCallback()中的param参数我们传递了image进去,也就是说鼠标回调函数onmouse_pick_points()中的param就是image,画点的操作在鼠标回调函数中,该参数在onmouse_pick_points中的变化可以保留到函数外,可以理解为C++的引用传递,或C语言的指针传递。
    • 需要一个无限循环来刷新图像。
    • 无限循环的退出条件由键盘获取,cv2.waitKey()用来获取键盘的按键,当我们点ESC后就可以退出。

    这里点了三次左键,终端输出以下内容:

    x = 60, y = 55
    x = 206, y = 113
    x = 114, y = 192
    

    并得到这样一张图像:

    python opencv鼠标画点之cv2.drawMarker()函数

    例2,删除功能

    如果需要删除已经画了的点的功能,那么问题就变得略有些复杂了。

    我们之前讲过,opencv在画了这些点之后,图像的像素已经事实上被改变了,想要紧紧通过当前图像将其恢复原状是不行的。所以为了实现删除功能,我们需要备份一张原始图像,一张用来对外显示的图像,以及一个由点坐标组成的list。

    每次做删除点的操作后,我们都使用原始图像重置对外显示的图像,然后再把list中所有的点都重新画在对外显示的图像上,就可以实现删除点的效果。如果是增加点的操作,则不用重置图像。

    实现代码如下:

    下面代码中,左键实现增加一个点的操作,右键依次删除后面画上的点。

    # -*- coding:FPHhRR utf-8 -*-
    
    import cv2
    import numpy as np
    
    WIN_NAME = 'pick_points'
    
    
    class DrawPoints(object):
        def __init__(self, image, color,
                     marker_type=cv2.MARKER_CROSS,
                     marker_size=20,
                     thickness=1):
            """
            Initialization of class DrawPoints编程客栈
    
            Parameters
            ----------
            image: ndarray
                source image. shape is [height, width, channels]
            color: tuple
                a tuple containing uint8 integers, designating B, G, R values,
                separately
            marker_type: int
                marker type, between [0, 6]
            marker_size: int
                marker size, >=1
            thickness: int
                line thickness, >=1
            """
            self.original_image = image
            self.image_for_show = image.copy()
            self.color = color
            self.marker_type = marker_type
            self.marker_size = marker_size
            self.thickness = thickness
            self.pts = []
    
        def append(self, x, y):
            """
            add a point to points list
    
            Parameters
            ----------
            x, y: int, int
                coordinate of a point
            """
            self.pts.append((x, y))
    
        def pop(self):
            """
            pop a point from points list
            """
            pt = ()
            if self.pts:
                pt = self.pts.pop()
            return pt
    
        def reset_image(self):
            """
            reset image_for_show using original image
            """
            self.image_for_show = self.original_image.copy()
    
        def draw(self):
            """
       www.cppcns.com     draw points on image_for_show
            """
            for pt in self.pts:
                cv2.drawMarker(self.image_for_show, pt, color=self.color,
                               markerType=self.marker_type,
                               markerSize=self.marker_size,
                               thickness=self.thickness)
    
    
    def onmouse_pick_points(event, x, y, flags, draw_pts):
        if event == cv2.EVENT_LBUTTONDOWN:
            print('add: x = %d, y = %d' % (x, y))
            draw_pts.append(x, y)
            draw_pts.draw()
        elif event == cv2.EVENT_FPHhRRRBUTTONDOWN:
            pt = draw_pts.pop()
            if pt:
                print('delete: x = %d, y = %d' % (pt[0], pt[1]))
                draw_pts.reset_image()
                draw_pts.draw()
    
    
    if __name__ == '__main__':
        image = np.zeros((256, 256, 3), np.uint8)
        draw_pts = DrawPoints(image, (0, 255, 0))
        cv2.namedWindow(WIN_NAME, 0)
        cv2.setMouseCallback(WIN_NAME, onmouse_pick_points, draw_pts)
        while True:
            cv2.imshow(WIN_NAME, draw_pts.image_for_show)
            key = cv2.waitKey(30)
            if key == 27:  # ESC
                break
        cv2.destroyAllWindows()
    

    终端输出如下:

    add: x = 54, y = 51

    add: x = 215, y = 81

    add: x = 123, y = 121

    add: x = 57, y = 197

    add: x = 168, y = 210

    delete: x = 168, y = 210

    delete: x = 57, y = 197

    得到的结果如下:

    python opencv鼠标画点之cv2.drawMarker()函数

    总结

    到此这篇关于python opencv鼠标画点之cv2.drawMarker()函数的文章就介绍到这了,更多相关opencv鼠标画点cv2.drawMarker()内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜