【OpenCV-Python】教程:6-1 相机标定

OpenCV Python 相机标定

【目标】

  • 摄像机引起的失真类型
  • 如何找到相机的内参和外参
  • 如何基于这些特性校正这些图像

【理论】

一些针孔相机会导致图像发生严重失真,主要有两种,一是径向畸变,一是切向畸变。

径向畸变使直线看起来弯曲。距离图像中心越远的点,径向畸变越大。如下图,棋盘的两个边缘用红线标记。但是,你可以看到,棋盘的边界不是一条直线,与红线不匹配,所有预期的直线都凸出来了,访问 Distortion (optics) 了解更多细节。

在这里插入图片描述

径向畸变可以由下面的方程表示:

x d r = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) y d r = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) x_{dr}=x(1+k_1r^2+k_2r^4+k_3r^6) \\ y_{dr}=y(1+k_1r^2+k_2r^4+k_3r^6) xdr=x(1+k1r2+k2r4+k3r6)ydr=y(1+k1r2+k2r4+k3r6)

类似的,切向畸变主要是因为图像拍摄镜头没有完全与成像平面平行对齐。因此,图像中的某些区域可能看起来比预期的更近。切向畸变量可表示为:

x d t = x + [ 2 p 1 x y + p 2 ( r 2 + 2 x 2 ) ] y d t = y + [ 2 p 2 x y + p 1 ( r 2 + 2 y 2 ) ] x_{dt}=x + [2p_1xy+p_2(r^2+2x^2)] \\ y_{dt}=y + [2p_2xy + p_1(r^2+2y^2)] xdt=x+[2p1xy+p2(r2+2x2)]ydt=y+[2p2xy+p1(r2+2y2)]

其中:

r 2 = x 2 + y 2 r^2=x^2+y^2 r2=x2+y2

简单来说,我们需要 5 5 5个参数,失真参数如下:

D i s t o r t i o n − c o e f f i c i e n t s = ( k 1 , k 2 , p 1 , p 2 , k 3 ) Distortion-coefficients=(k_1,k_2, p_1,p_2,k_3) Distortioncoefficients=(k1,k2,p1,p2,k3)

除此以外,我们还需要其他一些信息,比如相机的内参和外参;内在参数是相机特有的,他们包括焦距 ( f x , f y ) (f_x,f_y) (fx,fy)和光学中心 ( c x , c y ) (c_x,c_y) (cx,cy)等信息。焦距和光学中心可以用来创建一个相机矩阵,可以用来消除由于特定相机的镜头造成的失真。相机矩阵对于特定的相机是唯一的,因此一旦计算出来,就可以在同一相机拍摄的其他图像上重复使用。它表示为3x3矩阵:

c a m e r a . m a t r i x = [ f x 0 c x 0 f y c y 0 0 1 ] camera.matrix=\begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} camera.matrix=fx000fy0cxcy1

外部参数对应旋转和平移向量,会将3D坐标点(世界坐标系)转换为直角坐标系。

对于立体应用,首先需要校正这些失真,为了找到这些参数,我们必须提供一些定义好的模式,例如棋盘格图像。我们找到一些我们已经直到相对位置的特定点,例如,国际象棋棋盘上的正方形角,我们直到这些点在现实空间中的坐标,也直到图像中的坐标,所以我们可以解出失真参数,为了获得更好的结果,我们至少需要10个测试模式。

如上所述,我们至少需要10个测试模式来进行相机标定。我们将利用OpenCV自带的 棋盘格图像(见samples/data/left01.jpg - left14.jpg)。相机标定所需的重要输入数据是图像中三维真实世界点的集合以及这些点对应的二维图像坐标。我们可以很容易地从图像中找到对应的坐标。(这些图像点是国际象棋中两个黑色方块相互接触的位置)

那么来自真实世界空间的3D点呢?这些图像是由静态相机拍摄的,棋盘被放置在不同的位置和方向。我们需要知道(X,Y,Z)的值。但为了简单起见,我们可以说象棋棋盘在XY平面上保持静止,(所以Z总是=0),相机也相应地移动。这种考虑有助于我们只找到X和Y的值。现在对于X,Y的值,我们可以简单地将这些点传递为(0,0),(1,0),(2,0),…表示点的位置。在这种情况下,我们得到的结果将以棋盘正方形的大小为尺度。但是如果我们知道正方形的大小(比如30毫米),我们可以传递值为(0,0),(30,0),(60,0),… .因此,我们以毫米为单位得到结果(在这种情况下,我们不知道正方形大小,因为我们没有拍摄这些图像,所以我们根据正方形大小传递)。

3D点称为目标点,2D图像点称为图像点;

因此,我们可以使用函数cv2.findChessboardCorners()来查找棋盘中的模式。我们还需要传递什么样的模式,我们正在寻找,像8x8网格,5x5网格等。在本例中,我们使用7x6网格。(通常一个国际象棋棋盘有8x8的正方形和7x7的内角)。它返回角点和retval,如果获得pattern,则retval将为True。这些角将按顺序摆放(从左到右,从上到下)

【代码】

在这里插入图片描述

在这里插入图片描述

import numpy as np 
import cv2 
import glob

criteria = (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1, 2)

objpoints = []
imgpoints = []

images_name_list = glob.glob("assets/left/left*.jpg")

for im_name in images_name_list:
    # print(im_name)
    img = cv2.imread(im_name) 
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  
    ret, corners = cv2.findChessboardCorners(gray, (7,6), None)
  
    if ret == True:
        objpoints.append(objp)
  
        corners2 = cv2.cornerSubPix(gray, corners, (11,11), (-1, -1), criteria)
        imgpoints.append(corners)
  
        cv2.drawChessboardCorners(img, (7,6), corners2, ret)
        cv2.imshow("image", img)
        cv2.waitKey(100)


############ 相机标定
# 3D点和图像点
# cv2.calibrateCamera 相机标定
# 返回 camera matrix, distortion coefficients, rotation and translation vectors etc.
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

print("camera matrix:", mtx)
print("distortion", dist)

############## 保存参数
np.savez("left.npz", mtx=mtx, dist=dist,rvecs=rvecs,tvecs=tvecs )

############# 去失真
## OpenCV 有两种方法,
## 我们可以使用cv2.getOptimalNewCameraMatrix()基于自由缩放参数来细化相机矩阵。
## 如果缩放参数alpha=0,它将返回未扭曲的图像,其中包含最少的不需要像素。因此,它甚至可以删除图像角落的一些像素。
## 如果alpha=1,所有像素都保留一些额外的黑色图像。此函数还返回一个图像ROI,可用于裁剪结果。
imgtest = cv2.imread("assets/left/left12.jpg")
h, w = imgtest.shape[0:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))

cv2.imshow("left12", imgtest)

#### 方法一: cv2.undistort(),方法一的效率更高一些
# undistort
dst = cv2.undistort(imgtest, mtx, dist, None, newcameramtx)

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

cv2.imshow("left12-undistort", dst)
#### 方法二: using remapping
# undistort
mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w,h), 5)
dst2 = cv2.remap(imgtest, mapx, mapy, cv2.INTER_LINEAR)

# crop the image
x, y, w, h = roi
dst2 = dst[y:y+h, x:x+w]
cv2.imshow("left12-remapping", dst)

cv2.waitKey(0)
cv2.destroyAllWindows()

# 反向投影计算误差
# print(objpoints)
mean_error = 0
for i in range(len(objpoints)):
    imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv2.norm(imgpoints[i], imgpoints2, cv2.NORM_L2)/len(imgpoints2)
    mean_error += error
print( "total error: {}".format(mean_error/len(objpoints)) )

  • output
camera matrix: [[534.07088364   0.         341.53407554]
 [  0.         534.11914595 232.94565259]
 [  0.           0.           1.        ]]
distortion [[-2.92971637e-01  1.07706962e-01  1.31038376e-03 -3.11018780e-05
   4.34798110e-02]]

【接口】

  • findChessboardCorners
cv2.findChessboardCorners(	image, patternSize[, corners[, flags]]	) ->	retval, corners

找到棋盘格里内部角点

  • image: 源棋盘格图像,必须是8位灰度或彩色图像
  • patternSize: 棋盘特征的尺寸,行和列里的角点数
  • corners: 返回找到的角点
  • flags: 一个操作标志,可以为0或者其他标志组合:
    • cv2.CALIB_CB_ADAPTIVE_THRESH: 使用自适应阈值将图像转换为黑白,而不是固定的阈值水平(从平均图像亮度计算)。
    • cv2.CALIB_CB_NORMALIZE_IMAGE: 在应用固定或自适应阈值之前,用直方图均衡化对图像进行归一化
    • cv2.CALIB_CB_FILTER_QUADS: 使用附加的标准(如轮廓面积,周长,类似正方形的形状)来过滤掉在轮廓检索阶段提取的虚假四边形。
    • cv2.CALIB_CB_FAST_CHECK: 快速检查图像以寻找棋盘角,如果没有找到,则通过快捷方式调用。当没有观察到棋盘时,这可以大大加快退化条件下的调用速度。

该函数尝试确定输入图像是否是棋盘图案的视图,并定位棋盘内部的角点。如果找到了所有的角点,并且它们按一定的顺序(每行从左到右)放置,则该函数返回一个非零值。否则,如果函数无法找到所有的角点或重新排列它们,则返回0。例如,一个普通的棋盘有8 × 8个正方形和7 × 7个内角,即黑色正方形相互接触的点。检测到的坐标是近似的,为了更准确地确定它们的位置,函数调用了cornerSubPix。如果返回的坐标不够精确,你也可以使用带有不同参数的cornerSubPix函数。

该功能需要棋盘周围有一些空白空间(就像一个方的厚的的边框,越宽越好),以使检测在各种环境中更加健壮。否则,如果没有边框,背景较暗,外围黑色方块就无法正确分割,方块分组排序算法就会失败。

使用 gen_pattern.py (Create calibration pattern) 创建棋盘格。

  • drawChessboardCorners
cv2.drawChessboardCorners(	image, patternSize, corners, patternWasFound	) ->	image

绘制棋盘角点

  • image: 源棋盘格图像,必须是8位灰度或彩色图像
  • patternSize: 棋盘特征的尺寸,行和列里的角点数
  • corners: 返回找到的角点
  • patternWasFound: 显示完全的棋盘是否找到,

该函数显示每个单独的角点,如果棋盘没有找到,显示检测到的检测为红色的圆圈,如果找到了棋盘,则显示彩色的角点和其连线;

  • calibrateCamera
cv2.calibrateCamera(	objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs[, rvecs[, tvecs[, flags[, criteria]]]]	) ->	retval, cameraMatrix, distCoeffs, rvecs, tvecs

cv.calibrateCameraExtended(	objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs[, rvecs[, tvecs[, stdDeviationsIntrinsics[, stdDeviationsExtrinsics[, perViewErrors[, flags[, criteria]]]]]]]	) ->	retval, cameraMatrix, distCoeffs, rvecs, tvecs, stdDeviationsIntrinsics, stdDeviationsExtrinsics, perViewErrors

从标定板不同视图中找到相机内参和外参

  • objectPoints: 在新的接口中,它是校准模式坐标空间中校准模式点向量的向量(例如 std::vector<std::vector<cv::Vec3f> >)。外层向量包含与模式视图数量一样多的元素。如果在每个视图中显示相同的校准模式,并且它是完全可见的,那么所有的向量将是相同的。尽管,在不同的视图中使用部分遮挡的模式甚至不同的模式是可能的。然后向量就不一样了。虽然这些点是3D的,但如果使用的校准模式是平面,那么它们都位于校准模式的XY坐标平面上(因此z坐标为0)。在旧接口中,不同视图下的所有对象点向量都被连接在一起。
  • imagePoints: 在新的接口中,它是校准模式点投影向量的向量(例如 std::vector<std::vector<cv::Vec2f>>)imagePoints.size()objectPoints.size(),以及每个 iimagePoints[i].size()objectPoints[i].size()必须分别相等。在旧接口中,不同视图下的所有对象点向量都被连接在一起。
  • imageSize: 仅用于初始化相机内禀矩阵的图像大小。
  • cameraMatrix:
    A = [ f x 0 c x 0 f y c y 0 0 1 ] A=\begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} A=fx000fy0cxcy1

如果指定了 CALIB_USE_INTRINSIC_GUESS和/或 CALIB_FIX_ASPECT_RATIO, CALIB_FIX_PRINCIPAL_POINTCALIB_FIX_FOCAL_LENGTH ,则在调用函数之前必须初始化 fx, fy, cx, cy的部分或全部。

  • distCoeffs: 输入或输出的失真系数 ( k 1 , k 2 , p 1 , p 2 [ , k 3 [ , k 4 , k 5 , k 6 [ , s 1 , s 2 , s 3 , s 4 [ , τ x , τ y ] ] ] ] ) (k_1,k_2,p_1,p_2[,k_3[,k_4,k_5,k_6[,s_1,s_2,s_3,s_4[,τ_x,τ_y]]]]) (k1,k2,p1,p2[,k3[,k4,k5,k6[,s1,s2,s3,s4[,τx,τy]]]]) ,个数为 4, 5, 8, 12 或14.
  • rvecs: 每个模式视图估计的旋转向量的输出向量(Rodrigues)(例如 std::vector<cv::Mat>>)。也就是说,每个第 i个旋转向量与对应的第 i个平移向量(参见下一个输出参数说明)将校准模式从物体坐标空间(其中指定了物体点)带到相机坐标空间。用更专业的术语来说,第 i个旋转和平移向量的元组执行了从对象坐标空间到相机坐标空间的基的变化。由于它的对偶性,这个元组相当于校准模式相对于相机坐标空间的位置。
  • tvecs: 每个模式视图估计的平移向量的输出向量,见上面的参数说明。
  • stdDeviationsIntrinsics: 对内在参数估计的标准偏差的输出向量。值的偏差顺序: ( f x , f y , c x , c y , k 1 , k 2 , p 1 , p 2 , k 3 , k 4 , k 5 , k 6 , s 1 , s 2 , s 3 , s 4 , τ x , τ y ) (f_x,f_y,c_x,c_y,k_1,k_2,p_1,p_2,k_3,k_4,k_5,k_6,s_1,s_2,s_3,s_4,τ_x,τ_y) (fx,fy,cx,cy,k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4τxτy)如果有一个参数没有估计到,其偏差等于零。
  • stdDeviationsExtrinsics: 外部参数估计标准差的输出向量。偏差值的顺序: ( R 0 , T 0 , … , R M − 1 , T M − 1 ) (R_0,T_0,…,R_{M−1},T_{M−1}) (R0,T0RM1,TM1),其中 M M M为模式视图的数量。 R i R_i Ri T i T_i Ti是连接在一起的 1 × 3 1×3 1×3个向量。
  • perViewErrors: 每个模式视图估计RMS重投影误差的输出向量。
  • flags: 不同的标志,可能是0或以下值的组合:
    • cv2.CALIB_USE_INTRINSIC_GUESS: cameraMatrix包含有效的初始值 f x , f y , c x , c y fx, fy, cx, cy fx,fy,cx,cy,进一步优化。否则, ( c x , c y ) (cx, cy) (cx,cy)最初被设置为图像中心(使用imageSize),并且以最小二乘方式计算焦距。注意,如果内在参数是已知的,就没有必要只使用这个函数来估计外在参数。使用solvePnP代替。
    • cv2.CALIB_FIX_PRINCIPAL_POINT: 在全局优化过程中,主点不变。当也设置了 CALIB_USE_INTRINSIC_GUESS时,它位于中心或指定的另一个位置。
    • cv2.CALIB_FIX_ASPECT_RATIO: 函数只考虑fy作为自由参数。比率fx/fy保持与输入cameraMatrix中的相同。当 CALIB_USE_INTRINSIC_GUESS未设置时,fx和fy的实际输入值将被忽略,只计算它们的比值并进一步使用。
    • cv2.CALIB_ZERO_TANGENT_DIST: 切向失真系数(p1,p2)设置为零并保持为零。
    • cv2.CALIB_FIX_FOCAL_LENGTH: 如果设置了 CALIB_USE_INTRINSIC_GUESS,那么在全局优化过程中焦距不会改变。
    • cv2.CALIB_FIX_K1,…, CALIB_FIX_K6: 优化过程中不改变相应的径向畸变系数。如果设置了 CALIB_USE_INTRINSIC_GUESS,则使用提供的distCoeffs矩阵中的系数。否则,设置为0。
    • cv2.CALIB_RATIONAL_MODEL: 启用系数k4、k5和k6。为了提供向后兼容性,应该显式指定这个额外的标志,以使校准函数使用合理模型并返回8个或更多系数。
    • cv2.CALIB_THIN_PRISM_MODEL: 启用系数s1、s2、s3和s4。为了提供向后兼容性,应该显式指定这个额外的标志,以使校准函数使用薄棱镜模型并返回12个或更多系数。
    • cv2.CALIB_FIX_S1_S2_S3_S4: 优化过程中不改变薄棱镜畸变系数。如果设置了 CALIB_USE_INTRINSIC_GUESS,则使用提供的distCoeffs矩阵中的系数。否则,设置为0。
    • cv2.CALIB_TILTED_MODEL: 启用系数tauX和tauY。为了提供向后兼容性,应该显式指定这个额外的标志,以使校准函数使用倾斜的传感器模型并返回14个系数。
    • cv2.CALIB_FIX_TAUX_TAUY: 优化过程中不改变倾斜传感器模型的系数。如果设置了 CALIB_USE_INTRINSIC_GUESS,则使用提供的distCoeffs矩阵中的系数。否则,设置为0。
  • criteria: 迭代优化算法的终止参数
  • getOptimalNewCameraMatrix
cv2.getOptimalNewCameraMatrix(	cameraMatrix, distCoeffs, imageSize, alpha[, newImgSize[, centerPrincipalPoint]]	) ->	retval, validPixROI

返回基于自由缩放参数的新相机固有矩阵。

  • cameraMatrix: 输入相机内参
  • distCoeffs: 失真系数 ( k 1 , k 2 , p 1 , p 2 [ , k 3 [ , k 4 , k 5 , k 6 [ , s 1 , s 2 , s 3 , s 4 [ , τ x , τ y ] ] ] ] ) (k_1,k_2,p_1,p_2[,k_3[,k_4,k_5,k_6[,s_1,s_2,s_3,s_4[,τ_x,τ_y]]]]) (k1,k2,p1,p2[,k3[,k4,k5,k6[,s1,s2,s3,s4[,τx,τy]]]]) ,个数为 4, 5, 8, 12 或14. 如果为空,则假设没有失真;
  • imageSize: 原始图像大小
  • alpha: 自由缩放参数介于0(当未失真图像中的所有像素都有效时)和1(当源图像中的所有像素都保留在未失真图像中时)之间。详情见stereoRectify。
  • newImgSize: 新的映射图像大小,默认时原图大小
  • validPixROI: 有效的ROI区域
  • centerPrincipalPoint: 可选标志,用于指示在新的相机固有矩阵中主点是否应位于图像中心。默认情况下,主点的选择是为了使源图像的一个子集(由alpha决定)最适合修正后的图像。

返回:
相机的新内参矩阵;

该函数根据自由缩放参数计算并返回最优的新相机内参矩阵。通过改变这个参数,您可以只检索合理的像素alpha=0,如果角落中有有价值的信息alpha=1,则保留所有原始图像像素,或者获得介于两者之间的东西。当alpha>0时,未失真的结果很可能有一些黑色像素对应于捕获的失真图像之外的“虚拟”像素。原始相机固有矩阵、失真系数、计算出的新相机固有矩阵和newImageSize应该传递给initUndistortRectifyMap来生成用于重新映射的remap

  • undistort
cv2.undistort(	src, cameraMatrix, distCoeffs[, dst[, newCameraMatrix]]	) ->	dst

转换图像,补偿镜头失真,修复径向和切向畸变,该函数只是initUndistortRectifyMap和remap的组合。目标图像中那些源图像中没有对应像素的像素被填充为0;校正后的图像中可以看到源图像的特定子集,可以通过newCameraMatrix进行调节。您可以使用getOptimalNewCameraMatrix来计算适当的newCameraMatrix,这取决于您的需求。使用calibrateCamera可以确定摄像机矩阵和畸变参数。如果图像的分辨率与校准阶段使用的分辨率不同,则fx,fy,cx和cy需要相应缩放,而失真系数保持不变。

  • src: 输入失真图像
  • dst: 输出矫正图像
  • cameraMatrix: 相机矩阵
  • newCameraMatrix: 新的相机矩阵
  • distCoeffs: 失真系数 ( k 1 , k 2 , p 1 , p 2 [ , k 3 [ , k 4 , k 5 , k 6 [ , s 1 , s 2 , s 3 , s 4 [ , τ x , τ y ] ] ] ] ) (k_1,k_2,p_1,p_2[,k_3[,k_4,k_5,k_6[,s_1,s_2,s_3,s_4[,τ_x,τ_y]]]]) (k1,k2,p1,p2[,k3[,k4,k5,k6[,s1,s2,s3,s4[,τx,τy]]]]) ,个数为 4, 5, 8, 12 或14. 如果为空,则假设没有失真;
  • initUndistortRectifyMap
cv.initUndistortRectifyMap(	cameraMatrix, distCoeffs, R, newCameraMatrix, size, m1type[, map1[, map2]]	) ->	map1, map2

计算不失真和还原图

  • cameraMatrix: 输入的相机矩阵
  • distCoeffs: 失真系数 ( k 1 , k 2 , p 1 , p 2 [ , k 3 [ , k 4 , k 5 , k 6 [ , s 1 , s 2 , s 3 , s 4 [ , τ x , τ y ] ] ] ] ) (k_1,k_2,p_1,p_2[,k_3[,k_4,k_5,k_6[,s_1,s_2,s_3,s_4[,τ_x,τ_y]]]]) (k1,k2,p1,p2[,k3[,k4,k5,k6[,s1,s2,s3,s4[,τx,τy]]]]) ,个数为 4, 5, 8, 12 或14. 如果为空,则假设没有失真;
  • R: 目标空间( 3 × 3 3×3 3×3矩阵)中可选的还原变换。R1R2,通过 stereoRectify计算可以传递到这里。如果矩阵为空,则假设是恒等变换。
  • newCameraMatrix: 新的相机矩阵
  • size: 不失真图像的尺寸
  • m1type: 第一个输出图像的类型 CV_32FC1, CV_32FC2 or CV_16SC2
  • map1: 第一个输出映射 (x坐标映射)
  • map2: 第二个输出映射(y坐标映射)
  • remap
cv2.remap(	src, map1, map2, interpolation[, dst[, borderMode[, borderValue]]]	) ->	dst

不能 in-place 操作。

对图像应用通用几何变换,应用下述公式
d s t ( x , y ) = s r c ( m a p x ( x , y ) , m a p y ( x , y ) ) dst(x,y)=src(map_x(x,y), map_y(x,y)) dst(x,y)=src(mapx(x,y),mapy(x,y))

  • src: 输入图像
  • dst: 与 m a p 1 map_1 map1大小相同,与src类型相同
  • map1: 可以是 ( x , y ) (x,y) (x,y)的映射,也可以是 x x x的映射,CV_16SC2 , CV_32FC1, or CV_32FC2
  • map2: 是 y y y的映射图,如果map1是 ( x , y ) (x,y) (x,y),可以为空
  • interpolation: 插值类型,参考 InterpolationFlags 方法 INTER_AREAINTER_LINEAR_EXACT 不支持。
  • borderMode: 当borderMode=BORDER_TRANSPARENT时,这意味着目标图像中与源图像中的“异常值”对应的像素不被函数修改。
  • borderValue: 扩边值,默认为0;

【参考】

  1. Camera Calibration
  2. Distortion (optics)
  3. OpenCV: Camera Calibration and 3D Reconstruction
  • 2
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄金旺铺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值