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

基础版笔记传送门:
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)
'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'右键释放

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:传给回调函数的参数 

响应函数

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

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()

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()

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()

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()

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
这段代码有借鉴其他博客

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()

绘制一个矩形框 方法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()

结果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()

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

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

猜你喜欢

转载自blog.csdn.net/kobeyu652453/article/details/107309456