import cv2 import os import json import numpy as np # State constants STATE_TRUCK = 0 STATE_DETECTION = 1 STATE_LINE = 2 STATE_DONE = 3 state = STATE_TRUCK points_truck = [] points_detection = [] points_line = [] def click_event(event, x, y, flags, params): global state if event == cv2.EVENT_LBUTTONDOWN: if state == STATE_TRUCK: points_truck.append([x, y]) print(f"Truck Area - Point {len(points_truck)}: [{x}, {y}]") if len(points_truck) == 4: state = STATE_DETECTION print("\n-> Area Truk Berhasil Dipilih (4 titik).") print("-> SILAHKAN PILIH AREA DETEKSI (Klik Kiri 4 Titik secara berurutan: Top-Left, Top-Right, Bottom-Right, Bottom-Left).") elif state == STATE_DETECTION: points_detection.append([x, y]) print(f"Detection Area - Point {len(points_detection)}: [{x}, {y}]") if len(points_detection) == 4: state = STATE_LINE print("\n-> Area Deteksi Berhasil Dipilih (4 titik).") print("-> SILAHKAN PILIH COUNT LINE (Klik Kiri Titik Mulai dan Titik Selesai).") elif state == STATE_LINE: points_line.append([x, y]) print(f"Count Line - Point {len(points_line)}: [{x}, {y}]") if len(points_line) == 2: state = STATE_DONE print("\n-> Count Line Berhasil Dipilih.") print("-> Semua koordinat telah lengkap! Tekan 's' untuk mencetak & menyimpan koordinat.") draw_frame() def draw_frame(): img_copy = img.copy() h, w, _ = img_copy.shape # 1. Draw Area Truk (Orange Polygon) for pt in points_truck: cv2.circle(img_copy, tuple(pt), 5, (0, 165, 255), -1) if len(points_truck) == 4: pts = np.array(points_truck, np.int32) cv2.polylines(img_copy, [pts], True, (0, 165, 255), 2) cv2.putText(img_copy, "TRUCK AREA", tuple(points_truck[0]), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 165, 255), 1) # 2. Draw Area Deteksi (Cyan Polygon) for pt in points_detection: cv2.circle(img_copy, tuple(pt), 5, (255, 255, 0), -1) if len(points_detection) == 4: pts = np.array(points_detection, np.int32) cv2.polylines(img_copy, [pts], True, (255, 255, 0), 2) cv2.putText(img_copy, "DETECTION AREA", tuple(points_detection[0]), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1) # 3. Draw Count Line (Magenta Line) if len(points_line) > 0: cv2.circle(img_copy, tuple(points_line[0]), 5, (255, 0, 255), -1) if len(points_line) == 2: cv2.line(img_copy, tuple(points_line[0]), tuple(points_line[1]), (255, 0, 255), 3) # Draw midpoint circle mid_x = int((points_line[0][0] + points_line[1][0]) / 2) mid_y = int((points_line[0][1] + points_line[1][1]) / 2) cv2.circle(img_copy, (mid_x, mid_y), 6, (0, 255, 0), -1) cv2.putText(img_copy, f"LINE (y={mid_y})", (mid_x + 10, mid_y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 1) # Draw Instruction Overlay on Top overlay_y = 35 if state == STATE_TRUCK: txt = f"1. PILIH AREA TRUK (Klik Kiri 4 Titik, saat ini: {len(points_truck)}/4)" color = (0, 165, 255) elif state == STATE_DETECTION: txt = f"2. PILIH AREA DETEKSI (Klik Kiri 4 Titik, saat ini: {len(points_detection)}/4)" color = (255, 255, 0) elif state == STATE_LINE: txt = f"3. PILIH COUNT LINE (Klik Kiri Titik Awal lalu Titik Akhir, saat ini: {len(points_line)}/2)" color = (255, 0, 255) else: txt = "SELESAI! Tekan 's' untuk simpan atau 'c' untuk ulang." color = (0, 255, 0) # Draw background panel for text cv2.rectangle(img_copy, (10, 10), (w - 10, 50), (0, 0, 0), -1) cv2.putText(img_copy, txt, (20, overlay_y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.imshow('Interactive 4-Point Zone Selector', img_copy) if __name__ == "__main__": source_img = "gambar_terbaru.jpg" if os.path.exists("gambar_terbaru.jpg") else "calib_frame.jpg" video_source = "0727.mp4" if os.path.exists(source_img): img = cv2.imread(source_img) print(f"Loaded image: {source_img}") elif os.path.exists(video_source): print(f"Grabbing frame from video: {video_source}") cap = cv2.VideoCapture(video_source) for _ in range(10): ret, img = cap.read() cap.release() if not ret: print("Error: Could not grab frame from video.") exit(1) else: print("Error: Neither calib_frame.jpg nor the video file exists.") exit(1) cv2.namedWindow('Interactive 4-Point Zone Selector') cv2.setMouseCallback('Interactive 4-Point Zone Selector', click_event) print("\n=== OpenCV 4-Point Zone Coordinate Selector ===") print("Instructions:") print("1. Left-click to select coordinates for each step.") print("2. Press 'c' at any time to clear selection and restart.") print("3. Press 's' when done to print python snippets and save to zones_output.json.") print("4. Press 'q' or 'ESC' to quit.") print("========================================\n") print("-> SILAHKAN PILIH AREA TRUK (Klik Kiri 4 Titik secara berurutan: Top-Left, Top-Right, Bottom-Right, Bottom-Left).") draw_frame() while True: key = cv2.waitKey(1) & 0xFF if key == ord('c') or key == ord('C'): state = STATE_TRUCK points_truck = [] points_detection = [] points_line = [] print("\nCleared selection. Restarting from Step 1 (Area Truk)...") draw_frame() elif key == ord('s') or key == ord('S'): if state != STATE_DONE: print(f"Warning: Harap selesaikan semua langkah terlebih dahulu. State saat ini: {state}") continue lx1, ly1 = points_line[0] lx2, ly2 = points_line[1] line_y_avg = int((ly1 + ly2) / 2) output_data = { "truck_poly": points_truck, "detection_poly": points_detection, "count_line": { "x_start": lx1, "x_end": lx2, "y": line_y_avg } } # Print configuration code snippets print("\n" + "="*50) print("KOORDINAT BERHASIL DI-GENERATE!") print("="*50) print("\n--- SALIN KODE DI BAWAH INI KE predict.py ---\n") print(f" # 1. Detection Area (4-point Polygon)") print(f" detection_poly_pts = [") for pt in points_detection: print(f" [int({pt[0]} * scale_x), int({pt[1]} * scale_y)],") print(f" ]") print(f" detection_polygon = Polygon(detection_poly_pts)") print() print(f" # 2. Count Line coordinates") print(f" static_line_y = int({line_y_avg} * scale_y)") print(f" static_line_x_start = int({lx1} * scale_x)") print(f" static_line_x_end = int({lx2} * scale_x)") print() print(f" # 3. Truck Area (4-point Polygon for presence check)") print(f" truck_poly_pts = [") for pt in points_truck: print(f" [int({pt[0]} * scale_x), int({pt[1]} * scale_y)],") print(f" ]") print(f" truck_polygon = Polygon(truck_poly_pts)") print() # Calculate bounding box of truck_polygon to maintain backward compatibility with static_roi tx_coords = [p[0] for p in points_truck] ty_coords = [p[1] for p in points_truck] min_tx, max_tx = min(tx_coords), max(tx_coords) min_ty, max_ty = min(ty_coords), max(ty_coords) print(f" static_roi = TruckROI(") print(f" x1=int({min_tx} * scale_x),") print(f" y1=int({min_ty} * scale_y),") print(f" x2=int({max_tx} * scale_x),") print(f" y2=int({max_ty} * scale_y),") print(f" line_y=static_line_y,") print(f" confidence=1.0") print(f" )") print("\n" + "="*50) # Save to json file with open("zones_output.json", "w") as f: json.dump(output_data, f, indent=4) print("Koordinat juga telah disimpan ke 'zones_output.json'\n") elif key == ord('q') or key == 27: break cv2.destroyAllWindows()