I'm currently in the works of making an auto-aiming turret, and my camera's have a noticeable fish eye effect, which is totally fine. I'm using OpenCV's undistort()
function to handle this, with data from a camera checkerboard calibration.
I will most likely be running the vision system on a raspberry pi 4, and currently, my undistort
function takes 80-90% of my CPU (i5-8600k OC 5GHz) when processing both of my cameras at 1280x720px, ideally this px as it's the largest and will provide best accuracy. Also note I'm aiming for a 15Hz update time.
Any ideas on how to make this more lightweight? Here's my code that I'm currently running as a test:
from cv2 import cv2
import numpy as np
import yaml
import time
cam1 = cv2.VideoCapture(0)
cam2 = cv2.VideoCapture(1)
cam1.set(3, 1280)
cam1.set(4, 720)
cam2.set(3, 1280)
cam2.set(4, 720)
#load calibration matrix
with open ("calibration_matrix.yaml") as file:
documents = yaml.full_load(file)
x=0
for item, doc in documents.items():
if x == 0:
mtx = np.matrix(doc)
x = 1
else:
dist = np.matrix(doc)
def camera(ID, asd):
if asd == -1:
ID.release()
ret, frame = ID.read()
if ret:
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
undistortedFrame = cv2.undistort(frame, mtx, dist, None, newcameramtx)
undistortedFrame = undistortedFrame[y:y+h, x:x+w]
return undistortedFrame
while True:
frame1 = camera(cam1, 0)
frame2 = camera(cam2, 0)
cv2.imshow('Frame 1', frame1)
cv2.imshow('Frame 2', frame2)
if cv2.waitKey(1) & 0xFF == ord('q'):
camera(cam1, -1)
camera(cam2, -1)
cv2.destroyAllWindows()
Comments above resolved, here's the solution:
As @Micka said,
use
initundistortrectifymap()
(once) andremap()
(for each image)
initundistortrectifymap()
basically takes the heavy load off of the undistort function (Micka) In practice, you run initundistortrectifymap()
at the start of the program with the image calibration matrix and distance coefficients, and then initundistortrectifymap()
returns two maps, map1 and map2.
These maps can be passed into the remap()
function to remap your image, which is a significantly lighter function than undistort()
. In my particular case, I have a fisheye camera, and OpenCV has fisheye modules that are optimized to undistort fish eye cameras with ease.