【发布时间】:2018-09-09 07:43:32
【问题描述】:
我正在使用 OpenCV 从一系列棋盘图像中估计网络摄像头的固有矩阵 - 如tutorial 中所述,并将像素反向投影到一个方向(根据方位角/仰角)。
最终目标是让用户在图像上选择一个点,估计该点相对于网络摄像头中心的方向,并将其用作波束成形算法的 DOA。强>
因此,一旦我估计了内在矩阵,我就会反向投影用户选择的像素(参见下面的代码)并将其显示为方位角/仰角。
result = [0, 0, 0] # reverse projected point, in homogeneous coord.
while 1:
_, img = cap.read()
if flag: # If the user has clicked somewhere
result = np.dot(np.linalg.inv(mtx), [mouse_x, mouse_y, 1])
result = np.arctan(result) # convert to angle
flag = False
cv2.putText(img, '({},{})'.format(mouse_x, mouse_y), (20, 440), cv2.FONT_HERSHEY_SIMPLEX,
0.5, (0, 255, 0), 2, cv2.LINE_AA)
cv2.putText(img, '({:.2f},{:.2f})'.format(180/np.pi*result[0], 180/np.pi*result[1]), (20, 460),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2, cv2.LINE_AA)
cv2.imshow('image', img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
我的问题是我不确定我的结果是否一致。主要的不连贯之处在于,对应于 {0,0} 角的图像点明显偏离图像中心,如下所示(出于隐私原因,相机图像已被黑色背景替换):
我真的没有看到一种简单而有效的测量精度的方法(我能想到的唯一方法是使用带有激光的伺服电机,就在相机下方并将其指向计算的方向) .
这是用 15 张图像校准后的内在矩阵:
我得到一个大约 0.44 RMS 的误差,这看起来很令人满意。
我的校准代码:
nCalFrames = 12 # number of frames for calibration
nFrames = 0
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) # termination criteria
objp = np.zeros((9*7, 3), np.float32)
objp[:, :2] = np.mgrid[0:9, 0:7].T.reshape(-1, 2)
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
cap = cv2.VideoCapture(0)
previousTime = 0
gray = 0
while 1:
# Capture frame-by-frame
_, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Find the chess board corners
ret, corners = cv2.findChessboardCorners(gray, (9, 7), None)
# If found, add object points, image points (after refining them)
if ret:
corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
if time.time() - previousTime > 2:
previousTime = time.time()
imgpoints.append(corners2)
objpoints.append(objp)
img = cv2.bitwise_not(img)
nFrames = nFrames + 1
# Draw and display the corners
img = cv2.drawChessboardCorners(img, (9, 7), corners, ret)
cv2.putText(img, '{}/{}'.format(nFrames, nCalFrames), (20, 460), cv2.FONT_HERSHEY_SIMPLEX,
2, (0, 255, 0), 2, cv2.LINE_AA)
cv2.putText(img, 'press \'q\' to exit...', (255, 15), cv2.FONT_HERSHEY_SIMPLEX,
0.5, (0, 0, 255), 1, cv2.LINE_AA)
# Display the resulting frame
cv2.imshow('Webcam Calibration', img)
if nFrames == nCalFrames:
break
if cv2.waitKey(1) & 0xFF == ord('q'):
break
RMS_error, mtx, disto_coef, _, _ = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
编辑:另一种测试方法是使用已知角度点的白板并通过与实验结果比较来估计误差,但我不知道如何设置这样的系统
【问题讨论】:
-
查看这些answers 以检查相机校准的准确性。
-
是的,我已经看到了,我的 RMS 错误看起来很令人满意,但我想知道我的代码是否正确...
-
我可能在这里偏离了基础(已经有一段时间了),但是在执行 arctan 函数之前,您是否还需要将结果乘以 [R|t] 矩阵的倒数?我认为你在度量相机坐标方面有你的观点,但不是世界坐标。
-
你是对的,如果我想要世界坐标中的点,我需要外在矩阵,但考虑到我只想要一个方向向量,我认为度量坐标中的图像点就足够了:我的向量从相机原点到这一点,它的 az/el 角与外部参数无关(如果我错了,请纠正我)。移动相机,穿过像素的光线不会改变方向
标签: python image opencv matrix camera-calibration