之前介绍了 OpenCV 完成畸变矫正的方法,本文记录直接使用矫正映射的方法。
initUndistortRectifyMap
函数获取映射矩阵remap
函数直接对图像进行映射矫正畸变。函数使用:
voidcv::initUndistortRectifyMap
(
InputArray cameraMatrix, // 输入的矫正前的相机参数(3X3矩阵)
InputArray distCoeffs, // 输入的畸变系数(5X1矩阵)
InputArray R, // 输入的第一和第二摄像头坐标系之间的旋转矩阵
InputArray newCameraMatrix, // 输入的校正后的3X3摄像机矩阵
Size size, // 摄像头采集的无失真图像尺寸
int m1type, // map1的数据类型,可以是 CV_32FC1, CV_32FC2 或 CV_16SC2
OutputArray map1, // 输出的X坐标重映射参数
OutputArray map2 // 输出的Y坐标重映射参数
)
计算方法如下:
函数使用:
voidcv::remap(
InputArray src, // 输入图像,即原图像,需要单通道8位或者浮点类型的图像
OutputArray dst, // 输出图像,即目标图像,需和原图形一样的尺寸和类型
InputArray map1, // 它有两种可能表示的对象:(1)表示点(x,y)的第一个映射;(2)表示CV_16SC2,CV_32FC1等
InputArray map2, // 有两种可能表示的对象:
//(1)若map1表示点(x,y)时,这个参数不代表任何值;
//(2)表示 CV_16UC1,CV_32FC1类型的Y值
int interpolation, // 插值方式,有四中插值方式:
// (1)INTER_NEAREST——最近邻插值
// (2)INTER_LINEAR——双线性插值(默认)
// (3)INTER_CUBIC——双三样条插值(默认)
// (4)INTER_LANCZOS4——lanczos插值(默认)
int borderMode = BORDER_CONSTANT, // 边界模式,默认BORDER_CONSTANT
const Scalar & borderValue = Scalar() // 边界颜色,默认Scalar()黑色
)
计算方法:
import numpy as np
import cv2 as cv
import mtutils as mt
# termination criteria
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,6,0)
W_num = 7
H_num = 7
objp = np.zeros((W_num*H_num,3), np.float32)
objp[:,:2] = np.mgrid[0:W_num,0:H_num].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.
img = mt.cv_rgb_imread('undistort.png', 1)
another = img.copy()
# Find the chess board corners
ret, corners = cv.findChessboardCorners(img, (W_num,H_num), None)
# If found, add object points, image points (after refining them)
if ret == True:
objpoints.append(objp)
corners2 = cv.cornerSubPix(img,corners, (11,11), (-1,-1), criteria)
imgpoints.append(corners2)
# Draw and display the corners
cv.drawChessboardCorners(img, (W_num, H_num), corners2, ret)
mt.PIS(img)
ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, img.shape[::-1], None, None)
h, w = img.shape[:2]
newcameramtx, roi = cv.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))
dst = cv.undistort(another, mtx, dist, None, newcameramtx)
# build map matrix
map1, map2 = cv.initUndistortRectifyMap(mtx, dist, None, newcameramtx, img.shape[::-1], cv.CV_32FC1)
frame2 = cv.remap(another2, map1, map2, cv.INTER_LINEAR)
mt.PIS([another, 'origin'], [img, 'marked'], [dst, 'undistort'], row_num=1)
pass