效果图

三幅图像分别为矫正前、校正后和裁减后的图片。

矫正后的图像有些奇怪,需要把无用的部分裁剪掉。


在这里插入图片描述

代码

步骤一:拍摄棋盘图片

运行该程序,按空格键拍摄棋盘信息(注意拍摄的棋盘要完整),拍摄20张左右即可,按q键退出。

import cv2

# 图片保存路径
IMG_SAVE_PATH = "img/"


if __name__ == '__main__':
    num = 1
    camera = cv2.VideoCapture(0)
    while True:
        state, src = camera.read()
        cv2.imshow('src', src)

        if cv2.waitKey(10) & 0xff == ord(' '):
            cv2.imwrite(IMG_SAVE_PATH + str(num) + '.jpg', src)
            print("Saved img_" + str(num) + "!")
            num += 1
        if cv2.waitKey(10) & 0xff == ord('q'):
            break
    cv2.destroyAllWindows()

在这里插入图片描述

步骤二:计算畸变矩阵

计算畸变矩阵,并保存畸变数据到parameter文件。

import cv2
import glob
import numpy as np
import pickle
import os

# 棋盘规格
BOARD_RAW = 19
BOARD_COL = 13

# 图片保存路径
IMG_SAVE_PATH = "img/"
IMG_RESULT_PATH = "result/"

if __name__ == '__main__':
    obj_p = np.zeros((BOARD_RAW*BOARD_COL, 3), np.float32)

    # np.mgrid[0:raw, 0:col]的shape为(2, 19, 13)转置后为(13, 19, 2),reshape后为(13*19, 2)
    # obj_p[:, :2]===>obj_p[:, 0] and obj_p[:, 1]
    obj_p[:, :2] = np.mgrid[0:BOARD_RAW, 0:BOARD_COL].T.reshape(-1, 2)
    # print('obj_p:', obj_p)

    obj_points = []
    img_points = []

    images = glob.glob(IMG_SAVE_PATH + '*.jpg')
    for name in images:
        print('name:', name)
        img = cv2.imread(name)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        # 寻找角点
        ret, corners = cv2.findChessboardCorners(gray, (BOARD_RAW, BOARD_COL), None)
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
        sub_corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)

        obj_points.append(obj_p)
        img_points.append(sub_corners)

        img = cv2.drawChessboardCorners(gray, (BOARD_RAW, BOARD_COL), sub_corners, ret)
        cv2.imshow('img', img)
        cv2.imwrite(IMG_RESULT_PATH + 'img'+name.split(os.sep)[-1], img)
        cv2.waitKey(500)

    # 标定结果:相机的内参数矩阵,畸变系数,旋转矩阵和平移向量
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None)
    print('ret:', ret)
    print('mtx:', mtx)
    print('dist:', dist)
    print('rvecs:', rvecs)
    print('tvecs:', tvecs)

    # 保存参数
    cal_parameter = {'ret': ret, 'mtx': mtx, 'dist': dist, 'rvecs': rvecs, 'tvecs': tvecs}
    pickle.dump(cal_parameter, open("parameter", "wb"), 0)
    print("Save successfully!")

步骤三:读取广角摄像头图像

打开广角摄像头,进行矫正,分别获得原图像、矫正图像和裁剪图像。

import cv2
import pickle

if __name__ == '__main__':
    # 获取矫正参数
    f = pickle.load(open('parameter', 'rb'))  # 读取矫正参数
    ret, mtx, dist, rvecs, tvecs = f['ret'], f['mtx'], f['dist'], f['rvecs'], f['tvecs']

    # 获取图像尺寸
    img = cv2.imread('img\\1.jpg')
    h, w = img.shape[:2]
    new_camera_mtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))
    x, y, w, h = roi      # roi 提取的不准确,可能需要手动调整
    vid = cv2.VideoCapture(0)
    while True:
        state, src = vid.read()
        cv2.imshow('src', src)
        dst = cv2.undistort(src, mtx, dist, None, new_camera_mtx)
        cv2.imshow('img1', dst)
        dst = dst[y:y + h, x:x + w]
        cv2.imshow('img2', dst)
        cv2.waitKey(1)

在这里插入图片描述