python opencv鼠标画点之cv2.drawMarker()函数
作者:拜阳 发布时间:2021-11-28 18:34:40
目录
前言
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的副本。在写一些交互画图函数时,这个特性需要格外注意。
程序执行结果如下。
利用鼠标回调函数交互式画点
例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)
if 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
并得到这样一张图像:
例2,删除功能
如果需要删除已经画了的点的功能,那么问题就变得略有些复杂了。
我们之前讲过,opencv在画了这些点之后,图像的像素已经事实上被改变了,想要紧紧通过当前图像将其恢复原状是不行的。所以为了实现删除功能,我们需要备份一张原始图像,一张用来对外显示的图像,以及一个由点坐标组成的list。
每次做删除点的操作后,我们都使用原始图像重置对外显示的图像,然后再把list中所有的点都重新画在对外显示的图像上,就可以实现删除点的效果。如果是增加点的操作,则不用重置图像。
实现代码如下:
下面代码中,左键实现增加一个点的操作,右键依次删除后面画上的点。
# -*- coding: 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):
"""
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_RBUTTONDOWN:
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
得到的结果如下:
来源:https://blog.csdn.net/bby1987/article/details/107302373


猜你喜欢
- 这篇文章主要介绍了如何使用Python发送HTML格式的邮件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需
- 前言 网传的七天学Python的路线如下,我觉得可以在学过此表中前几天的内容后,就可以回头来学习一下列表推导式:它综合了列表、fo
- 本文实例讲述了php基于curl实现随机ip地址抓取内容的方法。分享给大家供大家参考,具体如下:使用php curl 我们可以模仿用户行为,
- 如下所示:# the basic ways = 0for x in range(10): s += x# the right ways =
- 本文实例为大家分享了python开发飞机大战游戏的具体代码,供大家参考,具体内容如下import pygameimport randomim
- 本文实例讲述了php自定义函数实现二维数组按指定key排序的方法。分享给大家供大家参考,具体如下:二维数组官方的排序方法并不好,该函数可以进
- 内容摘要:在像网站首页这样的资源比较集中的页面中,那些栏目最经常被用户点击?居左居右对广告的点击率的影响是什么?“一切用数字说话”:以上问题
- 什么是 docopt?1、docopt 是一种 Python 编写的命令行执行脚本的交互语言。它是一种语言!它是一种语言!它是一种语言!2、
- 1、File > Setting > Project:xxx > Project Interpreter 选择或添加环境2
- 上一文,介绍了vue.js动态添加、删除绑定的radio选项,本文介绍如何选中radio的某一项绑定的数据和上文的model是一致的,选中r
- 1.闭包的定义和使用当返回的内部函数使用了外部函数的变量就形成了闭包闭包可以对外部函数的变量进行保存,还可以提高代码的可重用性实现闭包的标准
- 本文实例讲述了Python实用库 PrettyTable。分享给大家供大家参考,具体如下:PrettyTable安装使用pip即可十分方便的
- 上个月就打算开发个还算好玩的项目,但是一直没时间。这篇是此项目用到的一部分,处理好此部分基本还差通信等方面的了。首先模拟鼠标键盘按下释放的动
- 1.在本地建立项目 可使用Eclipse,Idea等开发工具创建项目 打开根目录到所在在工程名的下一级2.使用git 客户端 进
- 添加用户(随着用户的创建,自动产生与用户同名的schema) CREATE USER "TESTER" PROFILE
- functools模块提供了一些常用的高阶函数(处理其他可调用对象/函数的特殊函数;以函数作为输入参数,返回也是函数)。functools模
- 本文实例讲述了Python数据分析之获取双色球历史信息的方法。分享给大家供大家参考,具体如下:每个人都有一颗中双色球大奖的心,对于技术人员来
- I. 简介MoviePy 是什么?MoviePy 是一个使用 Python 编写的开源库,用于在视频编辑中创建、编辑和操作视频文件。它是一款
- 最近在看廖老师的python教程,在看到关于文件的操作时,廖老师的其中一段关于查找电脑里的python文件,突然想把之前写的python代码
- 前言 Tensorflow中可以使用tensorboard这个强大的工具对计算图、loss、网络参数等进行可视化。本文并不涉及对tensor