opencv可以利用selectROI在图像上选择矩形框,并返回相应的的坐标,其源码在https://github.com/opencv/opencv/blob/17234f82d025e3bbfbf611089637e5aa2038e7b8/modules/highgui/src/roiSelector.cpp
这里我们依葫芦画瓢,搞个在图像中实时绘制直线的版本
import cv2
class LineSelector:
"""
在图像上实时绘制线段(类似selectROIs),并返回起始和终点坐标
"""
def __init__(self):
self.lines = []
self.image = None
self.start_pos = None
self.end_pos = None
self.is_drawing = None
def draw_lines(self, img_bgr, window_name='roi'):
cv2.imshow(window_name, img_bgr)
self.image = img_bgr.copy()
cv2.setMouseCallback(window_name, self.mouse_handler)
while cv2.waitKey(50) & 0xFF != ord('q'):
if self.start_pos is not None and self.end_pos is not None:
x, y = self.start_pos
cv2.putText(self.image, f'{x},{y}', (x, y), cv2.FONT_HERSHEY_PLAIN, 1, (0, 255, 255))
# cv2.line(self.image, self.start_pos, self.end_pos, (0, 0, 255))
cv2.arrowedLine(self.image, self.start_pos, self.end_pos, (0, 0, 255))
x, y = self.end_pos
cv2.putText(self.image, f'{x},{y}', (x, y), cv2.FONT_HERSHEY_PLAIN, 1, (0, 255, 255))
cv2.imshow(window_name, self.image)
self.image = img_bgr.copy()
cv2.waitKey(30)
cv2.setMouseCallback(window_name, self.empty_handler)
cv2.destroyWindow(window_name)
return self.lines
def empty_handler(self, event, x, y, flags, params):
pass
def mouse_handler(self, event, x, y, flags, params):
self.mouse_callback(event, x, y, flags, params)
def mouse_callback(self, event, x, y, flags, params):
if event == cv2.EVENT_MOUSEMOVE:
if self.is_drawing:
self.end_pos = (x, y)
if event == cv2.EVENT_LBUTTONDOWN:
self.is_drawing = True
self.start_pos = (x, y)
if event == cv2.EVENT_LBUTTONUP:
self.is_drawing = False
if self.start_pos is not None and self.end_pos is not None:
self.lines.append([self.start_pos, self.end_pos])
self.start_pos = None
self.end_pos = None
img = cv2.imread('data/1.png')
ls = LineSelector()
lines = ls.draw_lines(img)
print(lines) # 返回起始坐标和终点坐标 [[(202, 502), (441, 288)]]
(注:画完按 q 结束)
import cv2
import numpy as np
from draw_api import LineSelector
ls = LineSelector()
def draw_region(img_bgr):
h, w, _ = img_bgr.shape
region = np.zeros((h, w))
lines = ls.draw_lines(img_bgr)
area = np.array([p for line in lines for p in line])
img_region = cv2.fillPoly(region, [area], (1, 0, 0))
return img_region
if __name__ == '__main__':
img = cv2.imread('data/1.png')
img_region = draw_region(img)
cv2.imshow('windows', img_region)
cv2.waitKey(0)
结束。