Hey apai25 - likely cause is a model mismatch plus a small OpenCV bug: OAK‑D‑W uses a fisheye distortion model, but your host-side code uses the standard perspective model. That will over‑correct. Also, cv2.getOptimalNewCameraMatrix returns (matrix, roi), so new_intrinsics is a tuple right now.
Try this code:
import depthai as dai
import cv2
import numpy as np
device = dai.Device()
calib = device.readCalibration()
pipeline = dai.Pipeline(device)
cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_A)
out_w, out_h = 640, 480
output_queue = cam.requestOutput((out_w, out_h), enableUndistortion=False, fps=30).createOutputQueue()
K = np.array(calib.getCameraIntrinsics(dai.CameraBoardSocket.CAM_A, out_w, out_h), dtype=np.float64)
D = np.array(calib.getDistortionCoefficients(dai.CameraBoardSocket.CAM_A), dtype=np.float64).flatten()
model = calib.getDistortionModel(dai.CameraBoardSocket.CAM_A)
if model == dai.CameraModel.Fisheye:
D = D[:4]
new_K = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(
K, D, (out_w, out_h), np.eye(3), balance=0.0
)
map_x, map_y = cv2.fisheye.initUndistortRectifyMap(
K, D, np.eye(3), new_K, (out_w, out_h), cv2.CV_32FC1
)
else:
new_K, _ = cv2.getOptimalNewCameraMatrix(K, D, (out_w, out_h), alpha=0.0)
map_x, map_y = cv2.initUndistortRectifyMap(
K, D, None, new_K, (out_w, out_h), cv2.CV_32FC1
)
pipeline.start()
while True:
frame = output_queue.get().getCvFrame()
undistorted = cv2.remap(frame, map_x, map_y, interpolation=cv2.INTER_LINEAR)
cv2.imshow("Original", frame)
cv2.imshow("Undistorted (Host-Side)", undistorted)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cv2.destroyAllWindows()
device.close()