gpt4 book ai didi

python - 相机标定,像素方向反投影

转载 作者:太空狗 更新时间:2023-10-30 01:25:45 24 4
gpt4 key购买 nike

我正在使用 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} 角对应的图像点明显偏离了图像中心,如下所示(出于隐私原因,相机图像已被黑色背景取代): Reverse projected center point

我真的没有看到一种简单而有效的测量精度的方法(我能想到的唯一方法是使用带有激光的伺服电机,就在相机下方并将其指向计算的方向) .

这是用 15 张图像校准后的内在矩阵:

Intrisic matrix

我得到大约 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)

编辑:另一种测试方法是使用已知角度点的白板并通过与实验结果比较来估计误差,但我不知道如何设置这样的系统

最佳答案

关于您的第一个问题,主点偏离图像中心是正常的。估计点,即零仰角和方位角的点,是最小化径向失真系数的点,对于低值广角镜头(例如,典型的网络摄像头),它可以很容易地偏离明显的量。

在调用 calibrateCamera 之前,您的校准应该没问题。但是,在您的代码片段中,您似乎忽略了失真系数。缺少的是 initUndistortRectifyMap,如果重要的话,它还可以让您重新居中主要点。

h,  w = img.shape[:2]
# compute new camera matrix with central principal point
new_mtx,roi = cv2.getOptimalNewCameraMatrix(mtx,disto_coef,(w,h),1,(w,h))
print(new_mtx)
# compute undistort maps
mapx,mapy = cv2.initUndistortRectifyMap(mtx,disto_coef,None,new_mtx,(w,h),5)

它本质上使焦距在两个维度上都相等,并使主点居中(有关参数,请参阅 OpenCV python 文档)。

然后,在每个

_, img = cap.read()

在渲染之前你必须去扭曲图像

# apply the remap
img = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
# crop the image
x,y,w,h = roi
img = img[y:y+h, x:x+w]

在这里,我将背景设为绿色以强调桶形失真。输出可能是这样的(出于隐私原因,相机图像被棋盘替换):

distortion

如果您执行了所有这些操作,那么您的校准目标就是准确的,并且您的校准样本会填满整个图像区域,您应该对计算充满信心。但是,为了验证相对于未失真图像像素读数的测量方位角和仰角,我可能建议从镜头的第一个主点开始进行卷尺测量,并在相机正前方以法角放置一个校准板。您可以在那里计算预期角度并进行比较。

希望这对您有所帮助。

关于python - 相机标定,像素方向反投影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49571491/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com