Python - OpenCV - 校准相机和矩形的边框检测

时间:2017-02-08 12:57:06

标签: python opencv camera webcam camera-calibration

在使用带棋盘的OpenCV official文档进行相机校准后检测矩形边框时遇到问题。这是我正在使用的以下代码:

cap = cv2.VideoCapture(0)

while True:
    _, img = cap.read()

    if img is not None:

        # load data for undistortion
        with np.load('R1.npz') as X:
            mtx, dist, _, _ = [X[i] for i in ('mtx', 'dist', 'rvecs', 'tvecs')]

        h, w = img.shape[:2]
        newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))

        # undistort
        dst = cv2.undistort(img, mtx, dist, None, newcameramtx)

        # crop the image
        x, y, w, h = roi
        dst = dst[y:y + h, x:x + w]

        # convert to gray scale
        gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
        # gaussian blur to remove noise
        gray = cv2.GaussianBlur(gray, (5, 5), 0)
        # threshold
        thresh = cv2.adaptiveThreshold(gray, 255, 1, 1, 11, 2)
        # find contours in the thresholded image
        _, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        # get image area
        image_area = gray.size

        for i in contours:
            # if area of box > half of image area, it is possibly the biggest blob
            if cv2.contourArea(i) > image_area / 2:
                perimeter = cv2.arcLength(i, True)
                # approximate the contours
                approx = cv2.approxPolyDP(i, 0.02 * perimeter, True)
                # draw the contours
                cv2.drawContours(dst, [approx], 0, (0, 255, 0), 2, cv2.LINE_AA)

这是我如何存储相机矩阵和失真系数:

# 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), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
# omitted code
for fname in images:
    # omitted code
    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(gray, (7,6),None)

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

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

        # global mtx, dist, rvecs, tvecs
        # calibrate webcam and save output

        ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
        np.savez("R1", ret=ret, mtx=mtx, dist=dist, rvecs=rvecs, tvecs=tvecs)

在相机校准之后,当在x方向上水平移动1000 px(从x = 1000 px到x = 1240 px)后移动网格时,系统不会检测到网格的边框。

这非常奇怪,因为校准相机的输出没有弯曲,程序在检测矩形边框时不会有问题。

在相机校准(带曲线输出)之前,它用于完美地检测矩形的边框。我真的很困惑,因为应该是另一种方式。

为了校准相机,我已经使用了大约90张图像,试图从所有可能的角度更精确。在这一点上,当我使用np.load检索相机矩阵,失真系数,旋转和平移向量时,我不知道是否做错了,如上面的代码片段所示。

这些是undistort函数的参数:

Mtx:  [[  1.44771567e+03   0.00000000e+00   5.47978617e+02]
 [  0.00000000e+00   1.45032420e+03   3.76928336e+02]
 [  0.00000000e+00   0.00000000e+00   1.00000000e+00]]
Dist:  [[-0.10714946  0.00687251  0.00295331 -0.00231975 -0.18869188]]
New Camera Matrix: [[  1.38938562e+03   0.00000000e+00   5.38801146e+02]
 [  0.00000000e+00   1.38108777e+03   3.79614791e+02]
 [  0.00000000e+00   0.00000000e+00   1.00000000e+00]]

任何人都可以帮我一把吗?我真的不知道自己做错了什么。

提前谢谢

0 个答案:

没有答案