Python opencv 调用摄像头,并允许鼠标绘制两个框

发布时间 2023-11-27 14:17:47作者: 可乐芬达
import cv2

# 定义框的类
class BoundingBox:
    def __init__(self, label, x, y):
        self.label = label
        self.x_initial = x
        self.y_initial = y
        self.x = x
        self.y = y
        self.width = 0
        self.height = 0
        self.selected = False
        self.finished = False

    def draw(self, frame):
        cv2.rectangle(frame, (self.x, self.y), (self.x + self.width, self.y + self.height), (0, 255, 0), 2)
        cv2.putText(frame, self.label, (self.x, self.y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

    def contains_point(self, x, y):
        if self.x < self.x + self.width:
            return self.x < x < self.x + self.width and self.y < y < self.y + self.height
        else:
            return self.x + self.width < x < self.x and self.y + self.height < y < self.y

# 定义全局变量来存储框的信息
boxes = []
max_box_count = 2
selected_box = None

# opncv mouse callback
def on_mouse(event, x, y, flags, params):
    global boxes, selected_box

    if event == cv2.EVENT_LBUTTONDOWN:
        if len(boxes) < max_box_count:
            found_selected = False
            for box in boxes:
                if box.contains_point(x, y):
                    box.selected = True
                    selected_box = box
                    found_selected = True
                else:
                    box.selected = False
            
            # if no select box, create new box and select
            if not found_selected:
                new_box = BoundingBox(f'Box {x}', x, y)
                boxes.append(new_box)
                selected_box = new_box
                selected_box.selected = True

        else:
            for box in boxes:
                if box.contains_point(x, y):
                    box.selected = True
                    selected_box = box

    elif event == cv2.EVENT_LBUTTONUP:
        if selected_box:
            selected_box.finished = True

    elif event == cv2.EVENT_RBUTTONDOWN:
        if selected_box:
            boxes.remove(selected_box)
            selected_box = None

    elif event == cv2.EVENT_MOUSEMOVE:
        # if have select box and mouse left button is pressed
        if selected_box and flags & cv2.EVENT_FLAG_LBUTTON and not selected_box.finished: 
            selected_box.width = x - selected_box.x_initial
            selected_box.height = y - selected_box.y_initial
            selected_box.x = selected_box.x_initial
            selected_box.y = selected_box.y_initial

# 打开外置摄像头
cap = cv2.VideoCapture(0)  # 如果有多个摄像头,可能需要尝试不同的索引

# 创建窗口并绑定鼠标事件
cv2.namedWindow('Video')
cv2.setMouseCallback('Video', on_mouse)

while True:
    ret, frame = cap.read()

    # 画出框并显示标签
    for box in boxes:
        box.draw(frame)

    # 显示实时视频
    cv2.imshow('Video', frame)

    # 按下 'q' 键退出循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放摄像头并关闭窗口
cap.release()
cv2.destroyAllWindows()