相机校准与姿态估计

一、相机校准

本末节中我们首要学习:

  1. 相机导致的歪曲类型
  2. 怎样找到相机的内在和外在属性
  3. 怎样根据这些属性使图像不失真

1.变量与函数 基础概念

一些针孔相机会给图像带来显着windwindows怎么激活ows许可证行将过期怎样办的失真。 两种首要的畸变是径向畸变和切向畸变。

径向变形会导致直线看起来是曲折的。 点离图像中心越远,径向畸变越大。 例如,下图显现了一个图像,其间棋盘的两个边际用红线符号。 但是,你可以看到棋盘的边界不是一windows7旗舰版条直线,与红线不匹配。 全部预期的直windows怎样激活线都凸出。 拜访失真(apple光学)了解更appstore多详情。

OpenCV Tutorials 26 - 相机校准与姿态估计

径向畸变可表明如下:xdistortedappstore=x(1+k1r2+k22r4+k3r6)ydistorted=y(1+k1r2+k22r4appear+k3r6)x_{distorted} = x(1+k_1r^2+k_22r^4+k算法导论_3r^6) \ y_{distortedopencv目标检测} = y(1+k变量名_1r^2+kapproach_22r^4+k_3r^6)

类似地算法的特征,因为摄像镜头没有彻底平行于成像平面对齐,所以会产生opencv是软件还是库切向畸变。 因此,图像中算法剖析的意图是的某些区域或许看起来比预期的更近。 切向畸变量可以表明如下:

xdistorted=x+[2p1xy+p2(r2+2×2)]ydistorte算法是指什么d=y+[2p2xy+p1(r2+2y2)]x_{distorted} = x+[2p_1xy+p_2(r^2+2x^2)] \ y_{distorted} = y+[2p_2xy+p_1(r^2+2y^2)]

简而言之,我们需求找到opencv是软件还是库五个参数,称为失真系数,由下式给出:

Distortion coefficients=(k1k2p1p2k3) (k_1 k_2 p_1 p_2 k_3)

除此之外,我们还需求一些其他信息,比方相机的内在和外在参数。 内变量与函数涵参数是特定于相机的。 它们包括焦距 (fx,fy)(f_x,f_y) 和光学中心 (cx,cy)(c_x算法规划变量是什么意思与剖析,c_y) 等信息。 焦距和光学中心可用于创建相机矩阵,该矩阵可用appear于消appointment除因为特approach定相机镜头引起的失真。 相机矩阵关于特定的windows10相机是唯一的,因此一旦核算出来,它就可以在同一相机摄影的其他图像上重复运变量是什么意思用。 它表windows7怎样重装体系明为一个 3×3 矩阵:

cameramatrix=[fx0cx0fycy001]text { camera matrix }=left[begin{array}{ccc} f_{x} & 0 & c_{x} \ 0 & f_{y} & c_{y} \ 0 & 0 & 1 end{array}right]

外部参数对应于将 3D 点的坐标转化为坐标系的旋转平缓移向量。

关于立体声运用,首要windows更新有必要吗需求纠正这些失真。 为了找到这些参数,我们有必要供应一些定义清晰的图像的样appeara变量nce本图像(例如棋盘)。 我们找到一些我们已经知道相对方位的特定点(例如棋盘中的方角)。 我们知道这些点opencv和yolo的差异在实际世界空间中的坐标,我们知道图像windows系统中的坐标,所以我们可以求解失真系数。 为了获得更好的效果,我们至少需求 10 个测验方法。

2. 代码

如上所述,我们需求至少 10 个测验方法来进行相机校准。 OpenCV 附带了一些棋盘图像(拜见 sopencv是软件还是库算法工程师amples/data/left01appstore.japprovepg – left14.jpgappearance),因此我们将运用这些图像。考虑一个算法的特征棋盘的图像。相机校准变量所需的重要输入数据是一组 3D 真算法的空间复杂度是指实世界点以及图像中这些点对应的 2D 坐标。二维图像点是可以的,我们可以从图像中变量是什么意思轻松opencv是什么找到。 (这些图像点是棋盘中两个黑色方块彼此接触的方位)

来自真实世界空间的 3D 点呢?这些图像是从静态相机摄影的,棋盘放置在不同的方位和方向。所以我们需求windows许可证行将过期怎样办知道 (X,Y,Z) 值。但为简略起见,我们可以说棋盘在 XY 平面上坚持静止(因此 Z=0 始终)而且Windows相机相应地移动。这种考虑有助于我们仅找到 X、Y 值。现在关于 X,Y 值,我变量们可以简略地将点传递为 (0,0), (1,0), (2,0), … 这表明点的方位。在这种情况下Windows,我们得到的效果将APP算法的五个windows11有必要升级吗特性棋盘正方形大小的份额。但是,假设我们知道正方形大小(例如 30 毫米),我们可以将值传递为 (0,0)、(30,0)、(60,0)、.opencv安装教程..。因此,我们得到以变量名 mm 为单位的效果。 (在这种情况下,我们不知道正方形大小,因为我们没有apple摄影这些图像,所以我们通过正方形大小)。

3D 点称为物点,2D 像点称为像点。appreciate

1. 设置

因此,要在棋盘变量是什么意思中查找方法,我们可以运appstore用函数 cv.findChessboardCorners()。 我们还需applicationOpenCV传递我们正在寻approve觅什么样的图像,比方 8×8 网变量类型有哪些格、5×5 网格等。在这个比如中,我们运用 7×6 网格。 (一般棋盘有opencv轮廓提取 8×8 方格和 7×7 内角)。 假设获得方法,它将回来角点和 retval,这将是 True。 这些角将按顺序排列(从左Windows到右,从上到下)

  • 用法如下:cv.findChessboaopencv人员技术rdCorners( image, pattern算法的空间复杂度是指Siapproachze[, corners[, flags]] ) –变量类型有哪些> retval, corners

  • 注意:此功用或许无法在算法的特征全部图像中找到所需的图像。 因此,一个不错的选择是编写代码,以便发动相机并查看每一帧appliwindows许可证即将过期怎么办cation是否有appear所需opencv安装教程的图像。 获得图像后,找到角并将其存储在列表中。 另外,在阅读下一帧之前供应appointment一些间隔,opencv和yolo的区别以便我们可以在不同方向调整我们的棋盘。 持续windoappetitews7怎样重装体系此进程,直到获得所需数量的杰出方法。算法工程师 即便在此windows7旗舰版处供应的示例中,我们也不确定给出的 1windows怎么激活4 个图像中有多少变量是什么意思是好的。 因此,我们有必要阅读全部图像并只摄影好的图像算法的空间复杂度是windows是什么意思

除了棋盘,我们也可以运用圆形网格。 在这种情况下opencv人脸识别,我们算法规划与剖析有必要运用函数 cv.findCirclesGrid() 来查找方法。 更少的图像足以运用圆形网格执行相机校准。

  • 用法如下:
  1. cv.findCirclesGr变量之间的关系iappetited( image, patternSize, flags, blobDetectappearoopencv是什么r, parameters[, centers] ) -&g算法的五个特性t; retval, centers算法是指什么
  2. cv.findCirclewindows是什么意思sGrid( image, patternSize[, centers[, flags[, blobDetector]]] ) -> retval, centers

approapplicationach旦我算法分析的目的是们找到角点,我们可以运用 cv.cornerSubPix算法规划与剖析() 来前进它们的精确性。 我们还可以运用 cvopencv教程.draapplewChessboardCowindows10rners() 制造图像。 全部这些进程都包括在以下代码中:

  • 用法如下apple:cv.cornerSubPix( iopencv装置magappreciatee, cwindows怎么激活orners, winapproachSize, zeroZone, criteria ) -&a变量值mp;gOpenCVt; corners
import numpy as np
import cv2 as cv
import matplotlib
import matplotlib.pyplot as plt
import glob
%matplotlib inline
def cv_show(name,img):
    cv.imshow(name,img)
    cv.waitKey(0)
    cv.destroyAllWindows()
# 停止规范
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# 准备方针点集, 如 (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)
# 定义存储方针点集和存储全部图像像素的阵列
objpoints = [] # 实际空间的三维点
imgpoints = [] # 图像平面的二维点
# 读取同目录下的全部后缀名为 .jpg的图像文件
images = glob.glob('*.jpg')
for fname in images:
    img = cv.imread(fname)
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # 找出棋盘的图像角点
    ret, corners = cv.findChessboardCorners(gray, (7,6), None)
    # 若找到则在提炼之后参加阵列
    if ret == True:
        objpoints.append(objp)
        corners2 = cv.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria)
        imgpoints.append(corners)
        # 绘出角点并演示
        cv.drawChessboardCorners(img, (7,6), corners2, ret)
        cv.imshow('img', img)
        cv.waitKey(0)
cv.destroyAllWindows()

OpenCV Tutorials 26 - 相机校准与姿态估计

2. 校准

现在我们有了方针点windows许可证行将过期怎样办和图像点,我们可以进行校approve准了。 我opencv安装们可以运用函数 cv.算法设计与分析calibwindows更新Windows有必要吗rateCamera() 回来相机矩阵、失真系数、旋转平缓移向量等。

  • 用法算法的五个特性算法的空间复杂度是指如下:ret, mtx, dOpenCVist, rvecs, tvecs = cv.calibrateCwindows7旗舰版amera(objpoints, imgpoints, gray.shape[::-1], None, None)
ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
# 保存文件便于下一节运用
np.savez('B.npz', mtx=mtx, dist=dist, rvecs=rvecs, tvecs=tvecs)

3算法的空间复杂度是指. 修正失真

现在,我们可以摄影图像并使其不失真。 OpenCV 有两种方法可以做到这一点。 但是首要,我们可以运用 cv.getOptimalNewCameraMatrix() 根据自由缩放参数细化相机矩阵。 假设缩放参数 alpha=0,则回来具有最opencv安装少不需求像素的未失真图像。 所以它乃变量英语至或许会删去图像旮旯的一些像素。 假设 alpha=1opencv是软件还是库,全部像素都会保留一些额外的黑色图像。 此函数还变量泵回来可用于裁剪效果的图像 ROI。

所以,我们摄影一张新图片(本例中为left12.jpg。Windows这是本Windows章的第一张图片)

  • 用法如下: cv.getOptimalNopencv人员技术ewCamerawindows11有必要升级吗Matrix( cameraMatrix, distCoeffs, imageSize, awindows7怎么重装系统lpha[, newImgSize[, centerPrincipalPoint]] ) -> retval, validPixROI
img = cv.imread('left12.jpg')
h,  w = img.shape[:2]
newcameramtx, roi = cv.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))
运用cv.appearundistorwindows体系t()
  • 用法如下: cv.undopencv人脸辨认istort( src, camer变量泵aMatrix, distCoeffs[, dst[, newCameraMatrix]] ) –变量值> dst

这是最简略的方法。 只需调用该appetite函数并运用windows10变量类型有哪些面获得的 ROI 来裁剪效果。

# undistort
dst = cv.undistort(img, mtx, dist, None, newcameramtx)
# crop the image
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv_show('calibresult.png', dst)

OpenCV Tutorials 26 - 相机校准与姿态估计

运用重映射

这种方法有点难度。 首要,找到从失真图像到未app变量是什么意思ear失真图像的windows系统映射函数。 然后运用重映射opencv是软件还是库功用。

# undistort
mapx, mapy = cv.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w,h), 5)
dst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)
# crop the image
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv_show('calibresult.png', dst)

OpenCV Tutorials 26 - 相机校准与姿态估计

您可以在效果中看到全部边际都是直的。

现在,您可以运用approve NumPy(np.savez、np.s算法的五个特性avetxt 等)中的写入函数opencv教程application储相机矩阵和失真系数,以备将来运用。

3. 从头投影appreciate过失

APP投影过失opencv方针检测可以很好地估计找到的参数的精确程度。 重投影过失越接近于零,我们找到的参数就变量英语越精确。 给定固有矩阵、失真矩阵、变量英语旋转矩阵平缓移矩阵,我们有必要首要运用 cv.projectPoints() 将变量英语方针点转化为图像点。 然后,我们可以核算通过改换得算法到的值与角点变量类型有哪些查找算法之间的肯定范数。 为了找到均匀过失,我们核算了为全部校准图像核算的算法工程师过失的算术均匀appointment值。

  • 用法如下: cv.projectPoints( obopencv概括提取jectPoints, rvec, tvec, cameraMatrix, distCoeffs[, imagePoints[, jacobian[, aspectRatio]]] ) -> imAPPagePoints, jacobian
mean_error = 0
for i in range(len(objpoints)):
    imgpoints2, _ = cv.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv.norm(imgpoints[i], imgpoints2, cv.NORM_L2)/len(imgpoints2)
    mean_error += error
print( "total error: {}".format(mean_error/len(objpoints)) )
total error: 0.024498458465990365

二、姿态估计

本末节中我们将学习运用 caliappreciateb3d 模块在图像中创建一变量泵些 3D 效果。

1. 基本概念opencv目标检测

这将是一小部分。 在上一次关于相机校准的课程中,opencv概括提取您已经找到了相机矩阵、畸变系数等。给定一个图像图算法的特征像,我们可以运用上述信息来核算它的位姿,或许物体变量泵在空间中的方位,比方它是怎样旋转的, 它是怎样位移的等等。关于一个平面物体,我们可以假定 Z=0,这样,现在的问题就变成了怎样将相机放置在空间中以查看我们的图像图像。 因此,假设我们知道物体在空间中的方位,我们可以在其间制造一些 2D 图来APP仿照 3D 效果。 让我们看看怎样做。

我们算法的问题是,我们想在棋opencv是什么盘的第一个角上制造 3D 坐标轴(算法工程师X、Y、Z 轴)。 X轴为蓝色,Y轴为绿色,Z轴为赤色。appetite 所以实际上,Z 轴应该感觉它垂直于变量英语我们的棋盘平面。

首要appstore,让我们opencv是什么从之前的校准效果中加载相机矩阵和畸变系数。

import numpy as np
import cv2 as cv
import glob
# 导入之前保存的数据
# 需求在上一末节中进行保存
with np.load('B.npz') as X:
  mtx, dist, _, _ = [X[i] for i in ('mtx','dist','rvecs','tvecs')]

现在让我们a变量类型有哪些ppointment创建一个函数draw ,用于获取棋盘中的角(运用 cv.appearancefindChessboardCorners() 获得)和轴点来制造 3D 轴。

def draw(img, corners, imgpts):
  corner = tuple(corners[0].ravel())
  # line的两头只能传入整数,所以需求进行数据转化,一定要转化为np.uint32,np.uint8会形成丢失
  corner = np.array(corner, np.uint32)
  imgpts = np.array(imgpts, np.uint32)
  img = cv.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5)
  img = cv.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5)
  img = cv.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5)
  return img

然后和前面的比如相同,我们创建停止规范、方针点(棋盘角的 3D 点变量的定义)和轴点。 轴点是 3D 空间中用于制造轴的点。 我们制变量名造长度opencv人员技术为 3 的轴(单位将根据国windows11有必要晋级吗际象棋正方形大小,因为我们变量名的命名规则根据该大小进行校准)。 所以我们的 X 轴是从 (0,0,0) 到 (3,0,0) 制造算法的时刻复杂度取决于的,所以关于 Y 轴。 关于opencv方针检测 Z 轴,从 (0,0,0) 到 (0,0,-3) 制造。 负数表明它被拉向相机。

criteria = (cv.TERM_CRITERIA_EPS + cv.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)
axis = np.float32([[3,0,0], [0,3,0], [0,0,-3]]).reshape(-1,3)

现在,像往常相同,我们加载每个图像。 查找 7×6 网格。 假设找到,我们用子角opencv人脸辨认像素对其进行细化。 然后核算旋转平缓移,我们运用函数 cv.solvePnPRansac()。 一旦我们有了这些改换矩阵,我们就可以运用它们将我们的轴点投影到图像平面。 简而言之,我们在 3D 空appointment间中找到与 (3,0,0),算法分析的目的是(0,3,0),(0,0,3) 中的算法剖析appearance的意图是每一个相对应的图opencv是什么画平面上的点windows体appointment。 一appear旦我们得到它们,我们就算法工程师运用我们的 draw() 函数从第一个角到每个点变量是什么意思画线。 结束 !!!

  • 用法如下appstore;
  1. cv.sowindows怎样激活lvePnPRansac( objectPoints, imagePoints, cameraMatrix, distCoe变量Windowsfopencv教程fs[, rvec[, tvec[, useExtrinsicGuess[, iterationsCount[, reprojectionError[, confidence[, inliers[, flags]]]]]]]] ) -> retval, rvec, twindows10激活密钥vec, inliers
  2. cv.solvePnPRansac( objectPoints变量名, imagePoints, cameraMatrix, diwindwindows7旗舰版ows许可证行将过期怎样办stCowindows怎么激活effs[, rvec[, tvec[, inliers[, params]]]]
for fname in glob.glob('left*.jpg'):
  img = cv.imread(fname)
  gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
  ret, corners = cv.findChessboardCorners(gray, (7,6),None)
  if ret == True:
    corners2 = cv.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
    # Find the rotation and translation vectors.
    ret,rvecs, tvecs = cv.solvePnP(objp, corners2, mtx, dist)
    # project 3D points to image plane
    imgpts, jac = cv.projectPoints(axis, rvecs, tvecs, mtx, dist)
    img = draw(img,corners2,imgpts)
    cv.imshow('img',img)
    k = cv.waitKey(0) & 0xFF
    if k == ord('s'):
      cv.imwrite(fname[:6]+'.png', img)
cv.destroyAllWindows()

效果如下:

OpenCV Tutorials 26 - 相机校准与姿态估计

2. 烘托立方体

假设要制造立方windows7怎么重装系统体,修正draw()函数和轴点如下。

变量英语正 draw() 函数:

def draw(img, corners, imgpts):
  imgpts = np.int32(imgpts).reshape(-1,2)
  # draw ground floor in green
  img = cv.drawContours(img, [imgpts[:4]],-1,(0,255,0),-3)
  # draw pillars in blue color
  for i,j in zip(range(4),range(4,8)):
    img = cv.line(img, tuple(imgpts[i]), tuple(imgpts[j]),(255),3)
  # draw top layer in red color
  img = cv.drawContours(img, [imgpts[4:]],-1,(0,0,255),3)
  return img

修正轴点。 它们是 3D 空间中立方体的 8 个角:

axis = np.float32([[0,0,0], [0,3,0], [3,3,0], [3,0,0],
          [0,0,-3],[0,3,-3],[3,3,-3],[3,0,-3] ])
for fname in glob.glob('left*.jpg'):
  img = cv.imread(fname)
  gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
  ret, corners = cv.findChessboardCorners(gray, (7,6),None)
  if ret == True:
    corners2 = cv.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
    # Find the rotation and translation vectors.
    ret,rvecs, tvecs = cv.solvePnP(objp, corners2, mtx, dist)
    # project 3D points to image plane
    imgpts, jac = cv.projectPoints(axis, rvecs, tvecs, mtx, dist)
    img = draw(img,corners2,imgpts)
    cv.imshow('img',img)
    k = cv.waitKey(0) & 0xFF
    if k == ord('s'):
      cv.imwrite(fname[:6]+'.png', img)
cv.destroyAllWindows()

效果如下:变量是什么意思

OpenCV Tutorials 26 - 相机校准与姿态估计

OpenCV Tutorials 26 - 相机校准与姿态估计