traptools/02-testcalibration-and-draw-points.py
2025-05-09 21:44:58 +02:00

113 lines
No EOL
3.6 KiB
Python

"""
After obtaining the calibration.json (camera P and distortion matrixes)
using 01-calibrate.py, this script previews the calibration. Using the cursor
on the original (not-yet-undistorted) image you can add points, which can be
used for the homography later.
1. Set dataset variable to point to the folder with calibration.json and a preview image
2. Set a snapshot image. Note that this image _can_ be higher resolution than the video that is used
this allows for more precise point placement, but might need some conversion in the next step
3. Points are read and saved from points.json in the dataset folder
"""
import cv2
import json
import os
import numpy as np
from load_calibration import load_calibration
dataset = 'hof3-cam-baumer'
snapshot_img = 'snapshot.png'
points_fname = dataset + '/points.json'
w, h, undistorted_img, undistort_points = load_calibration(dataset + "/fisheye_calibration_data.json")
# with open(dataset + '/calibration-chessboard4.json', 'r') as fp:
# with open(dataset + '/calibration-chessboard4.json', 'r') as fp:
if os.path.exists(points_fname):
with open(points_fname, 'r') as fp:
points = json.load(fp)
else:
points = [[500,500],[1000,1000]]
def add_point(event,x,y,flags,param):
global points
if event == cv2.EVENT_LBUTTONUP:
selected = None
for i, p in enumerate(points):
d = (p[0]-x)**2 + (p[1]-y)**2
if d < 14:
selected = i
break
print('click', selected)
if selected is None:
points.append([x,y])
else:
points.pop(selected)
# cv2.circle(img,(x,y),100,(255,0,0),-1)
# mouseX,mouseY = x,y
cv2.namedWindow('original image')
cv2.setMouseCallback('original image',add_point)
# cap = cv2.VideoCapture("./hof2-hikvision.mp4")
cap = cv2.VideoCapture(dataset + "/" + snapshot_img)
img_w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
img_h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
print(w,h)
print(img_w,img_h)
# scale saved points to snapshot
points = [
[p[0]*(img_w/w), p[1]*(img_h/h)] for p in points
]
imgOld = None
while True: # (found < needed): # Here, 10 can be changed to whatever number you like to choose
ret, img = cap.read() # Capture frame-by-frame
if not ret:
img = imgOld
else:
imgOld = img
# Method 1 to undistort the image
# dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
# dstPoints = cv2.undistortPoints(np.array(points).astype('float32'), mtx, dist, None, P=newcameramtx)
dst = undistorted_img(img)
dstPoints = undistort_points(np.array(points).astype('float32'))[0]
# dst = cv2.undistort(img, mtx, dist, None)
# # Method 2 to undistort the image
# mapx,mapy=cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
# dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
# Displaying the undistorted image
drawImg = img.copy()
drawDst = dst.copy()
for i, p in enumerate(dstPoints):
x = int(p[0])
y = int(p[1])
cv2.circle(drawDst, (x,y), radius=2, color=(0, 0, 255), thickness=-1)
for i, p in enumerate(points):
x = int(p[0])
y= int(p[1])
cv2.circle(drawImg, (x,y), radius=2, color=(0, 0, 255), thickness=-1)
cv2.putText(drawImg, f"{i}", (x,y-5), cv2.FONT_HERSHEY_COMPLEX, 4, (0,0,255))
cv2.imshow("undistorted image",drawDst)
cv2.imshow("original image",drawImg)
if cv2.waitKey(5) == ord('q'):
break
print("write points.json")
with open(points_fname, 'w') as fp:
points = [
[p[0]*(w/img_w), p[1]*(h/img_h)] for p in points
]
json.dump(points, fp)