121 lines
3.8 KiB
Python
121 lines
3.8 KiB
Python
import cv2
|
|
import json
|
|
import numpy as np
|
|
|
|
CAM_INDEX = 1
|
|
OUTPUT_FILE = "calibration.json"
|
|
|
|
# Reihenfolge: P1=oben links, P2=oben rechts, P3=unten rechts, P4=unten links
|
|
POINT_NAMES = ["P1 (oben links)", "P2 (oben rechts)", "P3 (unten rechts)", "P4 (unten links)"]
|
|
|
|
|
|
def dist(a, b):
|
|
return np.linalg.norm(np.array(a) - np.array(b))
|
|
|
|
|
|
def main():
|
|
cap = cv2.VideoCapture(CAM_INDEX)
|
|
if not cap.isOpened():
|
|
print("❌ Kamera konnte nicht geöffnet werden!")
|
|
return
|
|
|
|
print("📸 Kalibrierung gestartet (nur Maus)")
|
|
print("----------------------------------")
|
|
print("🖱 Linksklick = Punkt setzen")
|
|
print("🖱 Ziehen = Punkt verschieben")
|
|
print("🖱 Rechtsklick = Punkt löschen")
|
|
print("💾 S / Enter = Speichern")
|
|
print("❌ ESC = Abbrechen")
|
|
print("----------------------------------")
|
|
print("Bitte Punkte in dieser Reihenfolge setzen:")
|
|
for i, name in enumerate(POINT_NAMES):
|
|
print(f" {i+1}. {name}")
|
|
|
|
points = [None, None, None, None]
|
|
dragging_index = None
|
|
|
|
def mouse_callback(event, mx, my, flags, param):
|
|
nonlocal dragging_index, points
|
|
|
|
# Linksklick → Punkt setzen oder ziehen
|
|
if event == cv2.EVENT_LBUTTONDOWN:
|
|
# Prüfen ob Klick auf existierenden Punkt
|
|
for i, p in enumerate(points):
|
|
if p is not None and dist(p, (mx, my)) < 20:
|
|
dragging_index = i
|
|
return
|
|
|
|
# Neuen Punkt setzen
|
|
for i in range(4):
|
|
if points[i] is None:
|
|
points[i] = (mx, my)
|
|
print(f"✔ {POINT_NAMES[i]} gesetzt bei {points[i]}")
|
|
return
|
|
|
|
# Dragging
|
|
elif event == cv2.EVENT_MOUSEMOVE and dragging_index is not None:
|
|
points[dragging_index] = (mx, my)
|
|
|
|
# Loslassen
|
|
elif event == cv2.EVENT_LBUTTONUP:
|
|
dragging_index = None
|
|
|
|
# Rechtsklick → Punkt löschen
|
|
elif event == cv2.EVENT_RBUTTONDOWN:
|
|
for i, p in enumerate(points):
|
|
if p is not None and dist(p, (mx, my)) < 20:
|
|
print(f"🗑 {POINT_NAMES[i]} gelöscht")
|
|
points[i] = None
|
|
return
|
|
|
|
cv2.namedWindow("Calibration")
|
|
cv2.setMouseCallback("Calibration", mouse_callback)
|
|
|
|
while True:
|
|
ok, frame = cap.read()
|
|
if not ok:
|
|
break
|
|
frame = cv2.flip(frame, -1)#<----------------------------------------------------------------Flip old:frame = cv2.flip(frame, 1)
|
|
|
|
h, w, _ = frame.shape
|
|
|
|
# Punkte zeichnen
|
|
for i, p in enumerate(points):
|
|
if p is not None:
|
|
cv2.circle(frame, p, 10, (0, 255, 255), -1)
|
|
cv2.putText(frame, f"P{i+1}", (p[0] + 10, p[1] - 10),
|
|
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,255), 2)
|
|
|
|
# Polygon zeichnen wenn alle Punkte vorhanden
|
|
if all(points):
|
|
cv2.polylines(frame, [np.array(points, np.int32)], True, (0, 255, 0), 2)
|
|
|
|
# Hinweise
|
|
cv2.putText(frame, "Setze P1,P2,P3,P4 mit der Maus | S=Speichern | ESC=Abbruch",
|
|
(10, h - 20),
|
|
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,255,255), 1)
|
|
|
|
cv2.imshow("Calibration", frame)
|
|
key = cv2.waitKey(10) & 0xFF
|
|
|
|
# Speichern
|
|
if key in [ord('s'), 13]: # 's' oder Enter
|
|
if None in points:
|
|
print("⚠️ Nicht alle 4 Punkte wurden gesetzt!")
|
|
else:
|
|
with open(OUTPUT_FILE, "w") as f:
|
|
json.dump(points, f)
|
|
print("💾 Kalibrierung gespeichert:", points)
|
|
break
|
|
|
|
if key == 27: # ESC
|
|
print("❌ Kalibrierung abgebrochen")
|
|
break
|
|
|
|
cap.release()
|
|
cv2.destroyAllWindows()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|