视频流画线 视频流画多边形
目录
四边形:
视频流画多边形:
四边形:
import cv2
import json
import av# 全局变量
polygon_points = [] # 四边形点
current_pos = None # 鼠标当前位置
finished = False # 是否完成绘制# ------------------------------------------
# 鼠标绘制四边形回调函数
# ------------------------------------------
def mouse_draw_quad(event, x, y, flags, param):global polygon_points, current_pos, finishedif finished:returnif event == cv2.EVENT_LBUTTONDOWN:# 点击添加一个点if len(polygon_points) < 4:polygon_points.append((x, y))print(f"添加点: {polygon_points[-1]}")# 4 个点完成 → 自动闭合if len(polygon_points) == 4:polygon_points.append(polygon_points[0])print("✅ 四边形完成:", polygon_points)finished = Trueelif event == cv2.EVENT_MOUSEMOVE:current_pos = (x, y)# ------------------------------------------
# 保存四边形到 JSON
# ------------------------------------------
def save_quad_json(points, filename="roi.json"):if len(points) < 4:print("⚠️ 点不足 4 个,不保存")returndata = {"polygon": [{"x": p[0], "y": p[1]} for p in points]}with open(filename, "w", encoding="utf-8") as f:json.dump(data, f, indent=4, ensure_ascii=False)print("✅ ROI 已保存到:", filename)# ------------------------------------------
# RTSP 绘制四边形主函数
# ------------------------------------------
def draw_quad_rtsp(rtsp_url, filename="roi.json"):global polygon_points, current_pos, finished# 打开 RTSP 视频container = av.open(rtsp_url, timeout=8)stream = next(s for s in container.streams if s.type == 'video')window = "Draw Quad ROI"cv2.namedWindow(window)cv2.setMouseCallback(window, mouse_draw_quad)print("🎬 进入四边形绘制模式:")print("✅ 左键点击 4 次画四边形")print("✅ 第 4 个点自动闭合并保存")print("✅ 按 Q 退出")for packet in container.demux(stream):if finished:breakfor frame in packet.decode():img = frame.to_ndarray(format='bgr24')img = cv2.resize(img, (960, 544))# 绘制已有点for p in polygon_points:cv2.circle(img, p, 4, (0, 255, 0), -1)# 绘制线段if len(polygon_points) > 1:for i in range(len(polygon_points) - 1):cv2.line(img, polygon_points[i], polygon_points[i + 1], (0, 255, 0), 2)# 鼠标预览线if current_pos and 0 < len(polygon_points) < 4:cv2.line(img, polygon_points[-1], current_pos, (0, 255, 255), 1)cv2.imshow(window, img)if cv2.waitKey(1) == ord("q"):finished = Truebreakcv2.destroyAllWindows()# 保存结果if len(polygon_points) >= 4:save_quad_json(polygon_points, filename)return polygon_pointsdef save_quad_json(points, filename="roi.json"):# points 形式为:p1, p2, p3, p4, p1(最后一个是闭合点)if len(points) < 4:print("⚠️ 点不足 4 个,不保存")return# ✅ 去掉重复的闭合点if len(points) == 5 and points[0] == points[-1]:points = points[:-1] # 去掉最后一个data = {"polygon": [{"x": p[0], "y": p[1]} for p in points]}with open(filename, "w", encoding="utf-8") as f:json.dump(data, f, indent=4, ensure_ascii=False)print("✅ ROI 已保存到:", filename)if __name__ == "__main__":rtsp = "rtsp://admin:Zenking306$@192.168.8.240:554/unicast/c5/s0/live"points = draw_quad_rtsp(rtsp)print("绘制结果:", points)save_quad_json(points,filename="roi.json")
视频流画多边形:
import cv2
import json
import av
import time# -----------------------------
# 全局变量(鼠标交互)
# -----------------------------
polygon_points = [] # 保存多边形顶点
current_pos = None # 鼠标当前坐标(用于预览)
finished = False # 是否完成绘制def mouse_draw_polygon(event, x, y, flags, param):global polygon_points, current_pos, finishedif finished:returnif event == cv2.EVENT_LBUTTONDOWN:# 添加一个多边形点polygon_points.append((x, y))print("添加点:", (x, y))elif event == cv2.EVENT_RBUTTONDOWN:# 删除最近一个点if polygon_points:removed = polygon_points.pop()print("删除点:", removed)elif event == cv2.EVENT_MOUSEMOVE:current_pos = (x, y)def save_polygon_json(points, filename="polygon.json"):data = {"polygon": [{"x": p[0], "y": p[1]} for p in points]}with open(filename, "w", encoding="utf-8") as f:json.dump(data, f, indent=4, ensure_ascii=False)print("✅ 已保存多边形 ROI 为:", filename)# ----------------------------------------
# RTSP 视频读取 + 多边形绘制主函数
# ----------------------------------------
def draw_polygon_roi_rtsp(rtsp_url, window_name="RTSP Polygon ROI"):global polygon_points, current_pos, finishedcontainer = av.open(rtsp_url, timeout=10)video_stream = next(s for s in container.streams if s.type == 'video')cv2.namedWindow(window_name)cv2.setMouseCallback(window_name, mouse_draw_polygon)print("🎥 开始显示 RTSP 视频,左键添加点,右键删除点,按 Enter 完成多边形。")for packet in container.demux(video_stream):if finished:breakfor frame in packet.decode():img = frame.to_ndarray(format='bgr24')img = cv2.resize(img, (960, 544))# 显示多边形点for p in polygon_points:cv2.circle(img, p, 4, (0, 255, 0), -1)# 展示动态连线if len(polygon_points) > 0:for i in range(len(polygon_points) - 1):cv2.line(img, polygon_points[i], polygon_points[i+1], (0, 255, 0), 2)# 鼠标移动预览if current_pos is not None:cv2.line(img, polygon_points[-1], current_pos, (0, 255, 255), 1)cv2.imshow(window_name, img)key = cv2.waitKey(1)if key == 13: # Enter 键if len(polygon_points) >= 3:finished = Trueprint("✅ 绘制完成")else:print("⚠️ 至少需要 3 个点")breakelif key == ord('q'):print("退出")finished = Truebreakcv2.destroyAllWindows()if finished and len(polygon_points) >= 3:# 闭合多边形(可选)polygon_points.append(polygon_points[0])save_polygon_json(polygon_points)return polygon_pointsreturn None
if __name__ == "__main__":rtsp = "rtsp://admin:Zenking306$@192.168.8.240:554/unicast/c5/s0/live"polygon = draw_polygon_roi_rtsp(rtsp)if polygon:print("最终多边形 ROI 点:", polygon)
