首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

opencv进阶学习笔记6:使用鼠标在图像上绘制矩形框或者多边形框

  • 23-09-22 21:02
  • 4174
  • 5740
blog.csdn.net

基础版笔记传送门:
python3+opencv学习笔记汇总目录(适合基础入门学习)
进阶版笔记目录:
python+opencv进阶版学习笔记目录(适合有一定基础)

感兴趣区域传统绘制:
opencv学习笔记5:感兴趣区域ROI

opencv 鼠标事件

1.opencv 鼠标事件类型

import cv2

d=[i for i in dir(cv2) if 'EVENT' in i]
print(d)
  • 1
  • 2
  • 3
  • 4
'EVENT_FLAG_ALTKEY':代表拖拽事件。按住alt键不放
'EVENT_FLAG_CTRLKEY'按住ctrl键不放
'EVENT_FLAG_LBUTTON'按住左键拖拽
'EVENT_FLAG_MBUTTON'中键拖拽
'EVENT_FLAG_RBUTTON'右键拖拽
'EVENT_FLAG_SHIFTKEY'按住shift不放
'EVENT_LBUTTONDBLCLK'event鼠标事件。左键双击
'EVENT_LBUTTONDOWN'按下左键
'EVENT_LBUTTONUP'释放左键
 'EVENT_MBUTTONDBLCLK' 中键双击
 'EVENT_MBUTTONDOWN'中键点击
 'EVENT_MBUTTONUP'中键放开
 'EVENT_MOUSEHWHEEL'
 'EVENT_MOUSEMOVE'滑动
 'EVENT_MOUSEWHEEL',
 'EVENT_RBUTTONDBLCLK',右键双击
 'EVENT_RBUTTONDOWN',右键点击
 'EVENT_RBUTTONUP'右键释放
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

2.opencv回调函数

cv2.setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0)

winname:窗口的名字 
onMouse:鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 这个函数的原型应该为void on_Mouse(int event, int x, int y, int flags, void* param);
userdate:传给回调函数的参数 
  • 1
  • 2
  • 3
  • 4
  • 5

响应函数

void on_Mouse(int event, int x, int y, int flags, void* param);
event是 CV_EVENT_*变量之一
x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系) 
flags是CV_EVENT_FLAG的组合, param是用户定义的传递到setMouseCallback函数调用的参数。

  • 1
  • 2
  • 3
  • 4
  • 5

opencv 绘图函数

1绘制直线
cv2.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
参数:图像名,起点,终点,颜色,笔宽/px

import numpy as np
import cv2
# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
# Draw a diagonal blue line with thickness of 5 px
cv2.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2绘制矩形
cv2.rectangle(img,(104,50),(300,128),(0,255,0),5)
参数:图像名,左上角,右下角,颜色,笔粗细

import numpy as np
import cv2
# Create a black image
img = np.zeros((400, 400, 3), np.uint8)
cv2.rectangle(img,(104,50),(300,128),(0,255,0),5)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3绘制圆形
cv2.circle(img,中心点(x,y), 半径, 颜色(0,255,255), -1或1)
参数:图像名,中心点,半径,颜色。-1是绘制真个圆,1边框。

import numpy as np
import cv2
# Create a black image
img = np.zeros((400, 400, 3), np.uint8)
cv2.circle(img,(100,63), 63, (0,255,255), -1)
cv2.circle(img,(300,63), 63, (0,0,255), 1)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4绘制椭圆

cv2.ellipse(img,(256,256),(100,50),0,0,120,(0,0,255),-1)
参数:
中心点坐标:如(256,256)
长轴和短轴长度:如(100,50)
夹角椭圆在逆时针方向旋转的角度:如0
起始角和端角表示从主轴顺时针方向测量的椭圆弧的开始和结束:如 0,120
颜色:如(0,0,255)
整个还是轮廓:-1表示整个椭圆,1表示轮廓

import numpy as np
import cv2
# Create a black image
img = np.zeros((400, 400, 3), np.uint8)
cv2.ellipse(img,(256,256),(100,50),0,0,120,(0,0,255),-1)
cv2.ellipse(img,(120,120),(100,50),0,0,360,(0,255,255),1)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

5绘制多边形
pts = np.array([[50,30],[150,30],[200,80],[40,90]], np.int32)
传入的是几个点的坐标,可以有很多点。

import numpy as np
import cv2
# Create a black image
img = np.zeros((400, 400, 3), np.uint8)
pts = np.array([[50,30],[150,30],[200,80],[40,90]], np.int32)
pts = pts.reshape((-1,1,2))
cv2.polylines(img,[pts],True,(0,0,255))
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

使用鼠标在图片上绘制矩形框

绘制一个矩形框 方法1
这段代码有借鉴其他博客

import cv2

global img
global point1, point2

#鼠标响应函数
def Rectangular_box(event, x, y, flags, param):
    global img, point1, point2
    img2 = img.copy()
    if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击
        point1 = (x, y)
        cv2.circle(img2, point1, 10, (0, 255, 0), 5)
        cv2.imshow('img', img2)
    elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON):  # 按住左键拖曳
        cv2.rectangle(img2, point1, (x, y), (255, 0, 0), 5)
        cv2.imshow('img', img2)
    elif event == cv2.EVENT_LBUTTONUP:  # 左键释放
        point2 = (x, y)
        cv2.rectangle(img2, point1, point2, (0, 255, 255), 4)
        cv2.imshow('img', img2)
        min_x = min(point1[0], point2[0])
        min_y = min(point1[1], point2[1])
        width = abs(point1[0] - point2[0])
        height = abs(point1[1] - point2[1])
        cut_img = img[min_y:min_y + height, min_x:min_x + width]
        #cv2.imwrite('baocun.jpg', cut_img)
        cv2.imshow('result',cut_img
def main():
    global img
    img = cv2.imread('yangmi.jpg')
    img=cv2.resize(img,None,fx=0.4,fy=0.4)
    cv2.namedWindow('image')
    cv2.setMouseCallback('image', Rectangular_box)
    cv2.imshow('image', img)
    cv2.waitKey(0)
if __name__ == '__main__':
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

绘制一个矩形框 方法2
使用函数cv2.selectROI(windowName, img, showCrosshair=None, fromCenter=None)
windowName:选择的区域被显示在的窗口的名字
img:要在什么图片上选择ROI
showCrosshair:是否在矩形框里画十字线.
fromCenter:是否是从矩形框的中心开始画

import cv2
img=cv2.imread('fangye.jpg')

r= cv2.selectROI('ROI',img,False,False)
#x,y,w,h=r
print(r)
imCrop = img[int(r[1]):int(r[1] + r[3]), int(r[0]):int(r[0] + r[2])]
cv2.imshow("cut_image", imCrop)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

结果r=(109, 44, 243, 153)

框选后 一点要点击 Enter 键才显示框选图像。

绘制多边形框
cv2.polylines:绘制多边形框
cv2.fillPoly:填充多边形框。把框内填满,使其是多边形。
这下面这段代码借鉴博客
OpenCV-Python选择ROI(矩形和多边形)

import cv2

import numpy as np


pts = []  # 用于存放点
# 统一的:mouse callback function
def on_mouse(event, x, y, flags, param):
    img2 = img.copy()

    if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击,选择点
        pts.append((x, y))

    if event == cv2.EVENT_RBUTTONDOWN:  # 右键点击,取消最近一次选择的点
        pts.pop()

    if event == cv2.EVENT_RBUTTONDBLCLK:  # 右键双击绘制轮廓
        mask = np.zeros(img.shape, np.uint8)#掩膜
        points = np.array(pts, np.int32)
        points = points.reshape((-1, 1, 2))
        # 画多边形
        mask = cv2.polylines(mask, [points], True, (255, 255, 255), 2)
        mask2 = cv2.fillPoly(mask.copy(), [points], (255, 255, 255))  # 用于求 ROI
        mask3 = cv2.fillPoly(mask.copy(), [points], (0, 255, 0))  # 用于 显示在桌面的图像

        show_image = cv2.addWeighted(src1=img, alpha=0.8, src2=mask3, beta=0.2, gamma=0)

        #cv2.imshow("mask", mask2)
        cv2.imshow("show_img", show_image)

        ROI = cv2.bitwise_and(mask2, img)
        cv2.imshow("ROI", ROI)
        cv2.waitKey(0)

    if len(pts) > 0:
        # 将pts中的最后一点画出来
        cv2.circle(img2, pts[-1], 3, (0, 0, 255), -1)

    if len(pts) > 1:
        # 画线
        for i in range(len(pts) - 1):
            cv2.circle(img2, pts[i], 5, (0, 0, 255), -1)  # x ,y 为鼠标点击地方的坐标
            cv2.line(img=img2, pt1=pts[i], pt2=pts[i + 1], color=(255, 0, 0), thickness=2)

    cv2.imshow('image', img2)


# 创建图像与窗口并将窗口与回调函数绑定
img = cv2.imread("fangye.jpg")
cv2.namedWindow('image')
cv2.setMouseCallback('image', on_mouse)
print("[INFO] 单击左键:选择点,单击右键:删除上一次选择的点,双击右键:确定ROI区域")
print("[INFO] 按 ESC 退出")
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

用下 范爷的美图吧。来源于网络。
这方法速度太慢。

电气专业的计算机萌新。写博文不容易。如果你觉得本文不错,请点个赞支持下,谢谢。

文章知识点与官方知识档案匹配,可进一步学习相关知识
OpenCV技能树进阶任务OpenCV问答20473 人正在系统学习中
注:本文转载自blog.csdn.net的总裁余(余登武)的文章"https://blog.csdn.net/kobeyu652453/article/details/107309456"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top