相机校准和3D重建
相机校准
标定
- findChessboardCorners() 它返回角点和阈值,如果成功找到所有角点,则返回 True。这些角落将按顺序放置(从左到右,从上到下)
- cornerSubPix()用以寻找图案,找到角点后也可以用其来提高它们的准确性
- drawChessboardCorners() 绘制图案
import numpy as np
import cv2 as cv
import glob
# 终止标准
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 = [] # 在真实世界中的 3d 点
imgpoints = [] # 在图像平面中的 2d 点
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(500)
cv.destroyAllWindows()
校准
- calibrateCamera()函数
ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
矫正
-
getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))根据自由缩放系数细化相机矩阵。
-
如果缩放参数 alpha = 0,这个函数将返回最小不必要像素的校正图像。所以它甚至可能会移除图像角落的一些像素。如果 alpha = 1,则所有像素都会保留一些额外的黑色图像。此函数还返回图像 ROI,可用于裁剪结果。
-
undistort(img, mtx, dist, None, newcameramtx) 调用这个函数并使用使用上面获得的 ROI 来裁剪结果
# 矫正
dst = cv.undistort(img, mtx, dist, None, newcameramtx)
# 裁切图像
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv.imwrite('calibresult.png', dst)
- 重映射:首先,找到一个从畸变的图像到矫正过的图像的映射函数。然后使用重映射函数。
# 矫正
mapx, mapy = cv.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w,h), 5)
dst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)
# 裁切图像
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv.imwrite('calibresult.png', dst)
姿势估计
- 可以绘制2D图像模拟3D效果
- 绘制坐标系、立方体等
线性几何
-
两张图使用极线匹配
-
左边的图像所有的极线都汇聚到右侧图像外的一点。那个汇聚点便是极点。
立体图像的深度图
-
一个场景点的深度是与相应图像点及其相机投影中心的距离差成反比的
-
创建视差图
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
imgL = cv.imread('tsukuba_l.png',0)
imgR = cv.imread('tsukuba_r.png',0)
stereo = cv.StereoBM_create(numDisparities=16, blockSize=15)
disparity = stereo.compute(imgL,imgR)
plt.imshow(disparity,'gray')
plt.show()
K-Means聚类
- kmeans()函数进行数据聚类
- 输入参数:
- samples : 应该是 np.float32 数据类型,并且每个功能都应该放在一个列中。
- nclusters(K) : 结束时所需的集群数量
- criteria: 迭代终止标准。满足此条件时,算法迭代停止。实际上,这是一个有 3 个元素的 tuple。它们是
( type, max_iter, epsilon )
:- 终止标准的类型。 它有 3 个标志如下:
- cv.TERM_CRITERIA_EPS - 如果达到指定的精度 epsilon,则停止算法迭代。
- cv.TERM_CRITERIA_MAX_ITER - 在指定的迭代次数 max_iter 之后停止算法。
- cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER - 当满足上述任何条件时停止迭代。
- max_iter - 一个指定最大迭代次数的整数。
- epsilon - 要求的精度
- 终止标准的类型。 它有 3 个标志如下:
- attempts : 用于指定使用不同初始标记执行算法的次数的标志。算法返回产生最佳紧凑性的标签。该紧凑性作为输出返回。
- flags : 该标志用于指定初始中心的采用方式。通常会使用两个标志:cv.KMEANS_PP_CENTERS 和 cv.KMEANS_RANDOM_CENTERS
- 输出参数:
- compactness : 每个点到其相应中心的平方距离之和。
- labels : 标签数组(与前一篇文章中的’代码’相同),其中每个元素都标记为’0’,‘1’…
- centers : 聚类中心数组
图像去噪
-
OpenCV 提供了这种技术的四种变体。
-
cv.fastNlMeansDenoising() - 适用于单个灰度图像
-
cv.fastNlMeansDenoisingColored() - 适用于彩色图像。
-
cv.fastNlMeansDenoisingMulti() - 适用于短时间内拍摄的图像序列(灰度图像)
-
cv.fastNlMeansDenoisingColoredMulti() - 与上述相同,但适用于彩色图像。
-
参数:
- h:参数决定滤波器强度。较高的 h 值可以更好地消除噪声,但也会删除图像的细节。
- hForColorComponents:与 h 相同,但仅适用于彩色图像。 (通常与 h 相同)
- templateWindowSize:应该是奇数。 (推荐 7)
- searchWindowSize:应该是奇数。 (推荐 21)