Python 调用 OpenCV 库实现鼠标框选感兴趣区域
小伙伴们在日常工作中,肯定会经常用鼠标框选自己所需要的截图区域,那么在Python编程中,如何调用摄像头并框选自己感兴趣的区域(ROI)呢,本文将为你详细介绍并提供示例代码!
老规矩,先看效果图:
示例代码:
import cv2
from tkinter import messagebox
import threading
class CameraApp:
def __init__(self):
self.cap = None
self.roi_display = False
self.selecting_roi = False
self.top_left_pt, self.bottom_right_pt = (-1, -1), (-1, -1) # ROI的左上角和右下角坐标
def open_camera(self, camera_index):
"""
创建子线程来打开摄像头。
参数:
camera_index (int): 摄像头索引号
"""
if not self.cap or not self.cap.isOpened():
thread = threading.Thread(target=self.camera, args=(camera_index,))
thread.start()
else:
messagebox.showwarning("警告", "摄像头已打开,避免重复操作.")
def start_camera_capture(self, camera_index):
"""
初始化并开始从指定的摄像头索引捕获视频流。
参数:
camera_index (int): 摄像头索引号
返回:
bool: 如果成功打开摄像头返回True,否则返回False
"""
if self.cap is None:
self.cap = cv2.VideoCapture(camera_index, cv2.CAP_DSHOW)
return self.cap.isOpened()
def stop_camera_capture(self):
"""停止视频捕捉并释放资源"""
if self.cap and self.cap.isOpened():
self.cap.release()
self.cap = None
cv2.destroyAllWindows()
def get_frame(self):
"""从摄像头获取单帧图像"""
ret, frame = self.cap.read()
return frame if ret else None
def set_roi_callback(self, event, x, y, flags, param):
"""
鼠标回调函数用于设置ROI。
参数:
event (int): 鼠标事件类型
x, y (int): 鼠标的x,y坐标
flags (int): 任何附加状态信息
param: 用户定义的数据
"""
if not self.roi_display:
if event == cv2.EVENT_LBUTTONDOWN:
self.top_left_pt = (x, y)
self.selecting_roi = True
elif event == cv2.EVENT_MOUSEMOVE and self.selecting_roi:
self.bottom_right_pt = (x, y)
elif event == cv2.EVENT_LBUTTONUP:
self.finish_roi_selection()
def finish_roi_selection(self):
"""完成ROI的选择并询问用户确认"""
if not self.selecting_roi:
return
self.selecting_roi = False
x1, y1 = self.top_left_pt
x2, y2 = self.bottom_right_pt
self.top_left_pt = (min(x1, x2), min(y1, y2))
self.bottom_right_pt = (max(x1, x2), max(y1, y2))
frame = self.get_frame()
if frame is not None:
cv2.rectangle(frame, self.top_left_pt, self.bottom_right_pt, (255, 0, 0), 2)
cv2.imshow("Camera", frame)
answer = messagebox.askyesno("提示", "是否选择此 ROI ?")
if answer:
self.roi_display = True
frame = self.get_frame()
cropped = frame[self.top_left_pt[1]:self.bottom_right_pt[1], self.top_left_pt[0]:self.bottom_right_pt[0]]
cv2.imwrite('ROI.jpg', cropped)
'''其他调用方法'''
else:
self.reset_roi()
def reset_roi(self):
"""重置ROI选择"""
self.top_left_pt, self.bottom_right_pt = (-1, -1), (-1, -1)
frame = self.get_frame()
if frame is not None:
cv2.imshow("Camera", frame)
def camera(self, camera_index):
"""
开始监控摄像头,允许用户选择ROI。
参数:
camera_index (int): 摄像头索引号
"""
if not self.start_camera_capture(camera_index):
messagebox.showerror("错误", f"打开摄像头索引-{camera_index}失败!")
return
try:
cv2.namedWindow("Camera")
cv2.setMouseCallback("Camera", self.set_roi_callback)
while self.cap.isOpened():
frame = self.get_frame()
if frame is None:
break
if all(p != -1 for p in self.top_left_pt + self.bottom_right_pt):
cv2.rectangle(frame, self.top_left_pt, self.bottom_right_pt, (255, 0, 0), 2)
cv2.imshow("Camera", frame)
key = cv2.waitKey(1) & 0xFF
if key == 27 or cv2.getWindowProperty("Camera", cv2.WND_PROP_VISIBLE) < 1:
break
finally:
self.stop_camera_capture()
camera = CameraApp()
# 一般0是内置摄像头,1是外接摄像头
camera.open_camera(1)
以上就是Python 调用Opencv 库实现鼠标框选感兴趣区域的详细示例代码了,有任何疑问欢迎随时咨询沟通,谢谢!