959 def draw_overlay(self, canvas: np.ndarray):
960 if not self.editor_mode:
961 return
962
963 num_panels = len(DISPLAY_ORDER)
964 panel_w = DISP_W
965 col_start = self.cam_panel_idx * panel_w
966
967
968 overlay = canvas.copy()
969 cv2.rectangle(overlay, (col_start, 0), (col_start + panel_w, DISP_H),
970 (0, 60, 100), -1)
971 cv2.addWeighted(overlay, 0.15, canvas, 0.85, 0, canvas)
972
973 mx, my = self.mouse_pos
974 cv2.line(canvas, (mx, 0), (mx, DISP_H), self.CURSOR_COLOR, 1, cv2.LINE_AA)
975 cv2.line(canvas, (0, my), (canvas.shape[1], my), self.CURSOR_COLOR, 1, cv2.LINE_AA)
976
977 canvas_pts = [(col_start + px, py) for (px, py) in self.points]
978
979 if len(canvas_pts) >= 3:
980 fill_overlay = canvas.copy()
981 cv2.fillPoly(fill_overlay,
982 [np.array(canvas_pts, dtype=np.int32)],
983 self.FILL_COLOR)
984 cv2.addWeighted(fill_overlay, 0.25, canvas, 0.75, 0, canvas)
985
986 for i in range(1, len(canvas_pts)):
987 cv2.line(canvas, canvas_pts[i - 1], canvas_pts[i],
988 self.LINE_COLOR, 2, cv2.LINE_AA)
989
990 if len(canvas_pts) >= 3:
991 p0, pn = canvas_pts[0], canvas_pts[-1]
992
993 dx = p0[0] - pn[0];
994 dy = p0[1] - pn[1]
995 dist = max(1, int((dx ** 2 + dy ** 2) ** 0.5))
996 segs = max(4, dist // 10)
997 for s in range(segs):
998 if s % 2 == 0:
999 t0 = s / segs
1000 t1 = (s + 1) / segs
1001 pt0 = (int(pn[0] + dx * t0), int(pn[1] + dy * t0))
1002 pt1 = (int(pn[0] + dx * t1), int(pn[1] + dy * t1))
1003 cv2.line(canvas, pt0, pt1, self.CLOSE_COLOR, 2, cv2.LINE_AA)
1004
1005 for idx, (cx, cy) in enumerate(canvas_pts):
1006 cv2.circle(canvas, (cx, cy), 5, self.POINT_COLOR, -1, cv2.LINE_AA)
1007 cv2.circle(canvas, (cx, cy), 5, (0, 0, 0), 1, cv2.LINE_AA)
1008 lbl = str(idx)
1009 (tw, th), _ = cv2.getTextSize(lbl, cv2.FONT_HERSHEY_SIMPLEX, 0.4, 1)
1010 cv2.putText(canvas, lbl, (cx + 7, cy + 4),
1011 cv2.FONT_HERSHEY_SIMPLEX, 0.4, self.SHADOW_COLOR, 2, cv2.LINE_AA)
1012 cv2.putText(canvas, lbl, (cx + 7, cy + 4),
1013 cv2.FONT_HERSHEY_SIMPLEX, 0.4, self.POINT_COLOR, 1, cv2.LINE_AA)
1014
1015 hud_lines = [
1016 f"ROI EDITOR | cam: {self.active_cam} | pts: {len(self.points)}",
1017 "LClick=add RClick=undo Enter=done Bksp=clear Tab=cam I=exit",
1018 ]
1019 for li, line in enumerate(hud_lines):
1020 yy = DISP_H - 12 - (len(hud_lines) - 1 - li) * 18
1021 (tw, th), _ = cv2.getTextSize(line, cv2.FONT_HERSHEY_SIMPLEX, 0.45, 1)
1022 cv2.rectangle(canvas,
1023 (col_start + 4, yy - th - 4),
1024 (col_start + tw + 10, yy + 4),
1025 (10, 10, 10), -1)
1026 cv2.putText(canvas, line,
1027 (col_start + 7, yy),
1028 cv2.FONT_HERSHEY_SIMPLEX, 0.45, self.TEXT_COLOR, 1, cv2.LINE_AA)
1029
1030 if col_start <= mx < col_start + panel_w:
1031 lx = mx - col_start
1032 tip = f"({lx}, {my})"
1033 (tw, th), _ = cv2.getTextSize(tip, cv2.FONT_HERSHEY_SIMPLEX, 0.4, 1)
1034 tx = min(mx + 10, canvas.shape[1] - tw - 6)
1035 ty = max(my - 10, th + 4)
1036 cv2.rectangle(canvas, (tx - 2, ty - th - 2), (tx + tw + 2, ty + 2),
1037 (20, 20, 20), -1)
1038 cv2.putText(canvas, tip, (tx, ty),
1039 cv2.FONT_HERSHEY_SIMPLEX, 0.4, self.TEXT_COLOR, 1, cv2.LINE_AA)
1040
1041