Files

208 lines
8.6 KiB
Python

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()