使用OpenCV进行相机标定 - 如何调整棋盘格方块大小?

4

我正在使用OpenCV/Python示例(来源:OpenCV教程)作为指南,开发一个相机标定程序。

问题:如何修改这个示例代码来考虑特定棋盘图案上方格的大小? 我对相机标定过程的理解是必须以某种方式使用此信息,否则由以下语句给出的值就无法正确表达:

cv2.calibrateCamera()

这段代码负责读取图像文件并进行校准过程,以生成相机矩阵和其他值。

如果出现错误,则会导致输出结果不正确。

#import cv2
#import numpy as np
#import glob

"""
Corner Finding
"""
# termination criteria 
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# Prepare object points, like (0,0,0), (1,0,0), ....,(6,5,0)
objp = np.zeros((5*5,3), np.float32)
objp[:,:2] = np.mgrid[0:5,0:5].T.reshape(-1,2)

# Arrays to store object points and image points from all images
objpoints = []
imgpoints = []

counting = 0

# Import Images
images = glob.glob('dir/sub dir/Images/*')

for fname in images:

    img = cv2.imread(fname)     # Read images
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)    # Convert to grayscale



    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(gray, (5,5), None)

    # if found, add object points, image points (after refining them)
    if ret == True:
        objpoints.append(objp)

        cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
        imgpoints.append(corners)

        #Draw and display corners
        cv2.drawChessboardCorners(img, (5,5), corners, ret)
        counting += 1

        print str(counting) + ' Viable Image(s)'

        cv2.imshow('img', img)
        cv2.waitKey(500)

cv2.destroyAllWindows()        


# Calibrate Camera    
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)    

objpoints是您在三维空间中的棋盘点。它们可能是(0,0);(0,1);(1,1);(1,0);(2,0);等等。在这个例子中,正方形大小(和边长)为1。只需调整这些点的位置大小即可获得任何其他正方形大小。 - Micka
@Micka 所以如果我的棋盘上的方块平均为25.3毫米,那么这些值应该计算为(0,0);(0,0.0253):.... ? - M. Ruffolo
如果您希望使用[mm]作为3D坐标(和相机内参)单位,则返回(0, 25.3) - Micka
2个回答

7

如果您的正方形大小为30毫米,则可以将此值乘以objp[:,:2]。就像这样

objp[:,:2] = np.mgrid[0:9,0:6].T.reshape(-1,2)*30   # 30 mm size of square

由于objp[:,:2]是一组棋盘角点,其坐标为(0,0),(0,1), (0,2) ....(8,5)。(0,0)点是左上角的方格,(8,5)点是右下角的方格。在这种情况下,这些点没有单位,但如果我们将这些值乘以方格大小(例如30毫米),那么这些点就变成了真实世界的单位,即(0,0),(0,30), .....(240,150)。在这种情况下,您的平移向量将以毫米单位表示。


点 (0,0) .. (8,5)是以 (行,列) 或 (x,y) 的形式表示的吗? 我认为它们是以 (行,列) 的形式表示的,但我不确定。 - Abhijit Balaji

0

从这里开始: https://docs.opencv.org/4.5.1/dc/dbb/tutorial_py_calibration.html

那么对于来自真实世界空间的三维点怎么办呢?这些图像是从静态相机拍摄的,棋盘以不同的位置和方向放置。因此我们需要知道(X,Y,Z)值。但为了简单起见,我们可以说棋盘被保持在XY平面上静止不动,(所以Z始终为0),相机随之移动。这种考虑帮助我们找到只有X、Y值的结果。现在对于X、Y值,我们可以简单地将点传递为(0,0)、(1,0)、(2,0)...表示点的位置。在这种情况下,我们得到的结果将按照棋盘格子大小的比例尺度。但是如果我们知道方格的大小(例如30毫米),我们可以将值传递为(0,0)、(30,0)、(60,0)...。这样,我们就可以得到毫米级的结果。(在这种情况下,我们不知道方块大小,因为我们没有拍摄这些图像,所以我们按方块大小传递值)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接