欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python+OpenCV:摄像机标定(Camera Calibration)

程序员文章站 2023-12-27 10:26:03
...

Python+OpenCV:摄像机标定(Camera Calibration)

理论

Some pinhole cameras introduce significant distortion to images. Two major kinds of distortion are radial distortion (径向畸变) and tangential distortion (切向畸变).

Radial distortion causes straight lines to appear curved. Radial distortion becomes larger the farther points are from the center of the image.

For example, one image is shown below in which two edges of a chess board are marked with red lines.

But, you can see that the border of the chess board is not a straight line and doesn't match with the red line.

All the expected straight lines are bulged out.

Python+OpenCV:摄像机标定(Camera Calibration)

Radial distortion can be represented as follows:

Python+OpenCV:摄像机标定(Camera Calibration)

Similarly, tangential distortion occurs because the image-taking lense is not aligned perfectly parallel to the imaging plane.

So, some areas in the image may look nearer than expected. The amount of tangential distortion can be represented as below:

Python+OpenCV:摄像机标定(Camera Calibration)

In short, we need to find five parameters, known as distortion coefficients given by:

Python+OpenCV:摄像机标定(Camera Calibration)

In addition to this, we need to some other information, like the intrinsic and extrinsic parameters of the camera.

Intrinsic parameters are specific to a camera. They include information like focal length ( fx,fy) and optical centers ( cx,cy).

The focal length and optical centers can be used to create a camera matrix, which can be used to remove distortion due to the lenses of a specific camera.

The camera matrix is unique to a specific camera, so once calculated, it can be reused on other images taken by the same camera.

It is expressed as a 3x3 matrix:

Python+OpenCV:摄像机标定(Camera Calibration)

Extrinsic parameters corresponds to rotation and translation vectors which translates a coordinates of a 3D point to a coordinate system.

For stereo applications, these distortions need to be corrected first.

To find these parameters, we must provide some sample images of a well defined pattern (e.g. a chess board).

We find some specific points of which we already know the relative positions (e.g. square corners in the chess board).

We know the coordinates of these points in real world space and we know the coordinates in the image, so we can solve for the distortion coefficients.

For better results, we need at least 10 test patterns.

Camera Calibration in OpenCV

####################################################################################################
# 摄像机标定(Camera Calibration)
def lmc_cv_camera_calibration():
    """
        函数功能: 摄像机标定(Camera Calibration)。
    """

    # termination criteria
    criteria = (lmc_cv.TERM_CRITERIA_EPS + lmc_cv.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.
    # 读取所有匹配的图像
    image = lmc_cv.imread('D:/99-Research/Python/Image/calib_radial.jpg', lmc_cv.IMREAD_UNCHANGED)
    image = lmc_cv.cvtColor(image, lmc_cv.COLOR_BGR2RGB)
    corners_image = image.copy()
    gray_image = lmc_cv.cvtColor(image, lmc_cv.COLOR_BGR2GRAY)
    # Find the chess board corners
    ret, corners = lmc_cv.findChessboardCorners(gray_image, (7, 6), None)
    # If found, add object points, image points (after refining them)
    if ret:
        objpoints.append(objp)
        corners2 = lmc_cv.cornerSubPix(gray_image, corners, (11, 11), (-1, -1), criteria)
        imgpoints.append(corners)
        # Draw and display the corners
        lmc_cv.drawChessboardCorners(corners_image, (7, 6), corners2, ret)
        ret, mtx, dist, rvecs, tvecs = lmc_cv.calibrateCamera(objpoints, imgpoints, gray_image.shape[::-1], None, None)
        h, w = image.shape[:2]
        newcameramtx, roi = lmc_cv.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))
        # undistort using undistort()
        undistort_image = lmc_cv.undistort(image, mtx, dist, None, newcameramtx)
        # crop the image
        x, y, w, h = roi
        undistort_image = undistort_image[y:y + h, x:x + w]
        # undistort using remapping
        mapx, mapy = lmc_cv.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w, h), 5)
        remapping_image = lmc_cv.remap(image, mapx, mapy, lmc_cv.INTER_LINEAR)
        # crop the image
        x, y, w, h = roi
        remapping_image = remapping_image[y:y + h, x:x + w]
        # Re-projection Error
        mean_error = 0
        for i in range(len(objpoints)):
            imgpoints2, _ = lmc_cv.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
            error = lmc_cv.norm(imgpoints[i], imgpoints2, lmc_cv.NORM_L2) / len(imgpoints2)
            mean_error += error
        print("total error: {}".format(mean_error / len(objpoints)))
        titles = ['Original Image', 'Corners', 'Undistortion using undistort()', 'Undistortion using remapping']
        images = [image, corners_image, undistort_image, remapping_image]

        # 显示图像
        for i in range(len(images)):
            pyplot.figure('Camera Calibration')
            pyplot.subplot(2, 2, i + 1)
            pyplot.imshow(images[i], 'gray')
            pyplot.title(titles[i])
            pyplot.xticks([])
            pyplot.yticks([])
        pyplot.show()

    # 根据用户输入保存图像
    if ord("q") == (lmc_cv.waitKey(0) & 0xFF):
        # 销毁窗口
        pyplot.close('all')
    return

Python+OpenCV:摄像机标定(Camera Calibration)

上一篇:

下一篇: