OpenCV 例程200篇237. 基于主成分提取的方向校正(OpenCV)
Posted YouCans
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV 例程200篇237. 基于主成分提取的方向校正(OpenCV)相关的知识,希望对你有一定的参考价值。
『youcans 的 OpenCV 例程200篇 - 总目录』
【youcans 的 OpenCV 例程200篇】237. 基于主成分提取的方向校正(OpenCV)
主成分分析(Principal Components Analysis,PCA)是一种基于统计的数据降维方法,又称主元素分析、主分量分析。主成分分析只需要特征值分解,就可以对数据进行压缩、去噪,应用非常广泛。
主成分分析方法得到的主成分变量具有几个特点:(1)每个主成分变量都是原始变量的线性组合;(2)主成分的数目大大少于原始变量的数目;(3)主成分保留了原始变量的绝大多数信息;(4)各主成分变量之间彼此相互独立。
5.4 OpenCV 的主成分分析方法
OpenCV 中提供了主成分分析(Principal Components Analysis,PCA)方法的实现,即 cv::PCA 类。类的声明在 include/opencv2/core.hpp 文件中,类的实现在 modules/core/src/pca.cpp 文件中。
- 成员函数:
- PCA::PCA:默认构造并初始化一个空的 PCA 结构
- PCA::backproject:将数据从 PCA 空间投影回原始空间,重建原始数据
- PCA::operator():对提供的数据执行主成分分析操作
- PCA::project:将输入数据投影到 PCA 特征空间;
- PCA::read:从指定文件读入特征值、特征向量和均值;
- PCA::write:向指定文件写入特征值、特征向量和均值;
- 属性:
- PCA::eigenvalues:协方差矩阵的特征值
- PCA::eigenvectors:协方差矩阵的特征向量
- PCA::mean:均值,投影前减去均值,投影后加上均值
PCA 类使用 Karhunen-Loeve 变换,由协方差矩阵的特征向量计算得到一组向量的正交基。
在 Python 语言中,OpenCV 提供了 PCA 类的接口函数 cv.PCACompute(),cv.PCAProject() 和 cv.PCABackProject()。
函数说明:
cv.PCACompute(data, mean[, eigenvectors=None, maxComponents=0]) → mean, eigenvectors
cv.PCACompute(data, mean, retainedVariance[, eigenvectors=None]) → mean, eigenvectors
cv.PCACompute2(data, mean[, eigenvectors=None, eigenvalues=None, maxComponents=0]) → mean, eigenvectors, eigenvalues
cv.PCACompute2(data, mean, retainedVariance[, eigenvectors=None, eigenvalues=None]) → mean, eigenvectors, eigenvalues
cv.PCAProject(data, mean, eigenvectors[, result=None]) → result
cv.PCABackProject(data, mean, eigenvectors[, result=None]) → result
函数 cv.PCACompute 是 PCA::operator 的接口,用于对提供的数据执行主成分分析操作,返回均值、特征向量和特征值。
函数 **cv.PCAProject ** 是 PCA::project 的接口,用于将输入数据按选择的特征向量投影到 PCA 特征空间。
函数 cv.PCABackProject 是 PCA::backproject 的接口,用于将输入数据按选择的特征向量投影从 PCA 空间投影回原始空间,重建原始数据。
参数说明:
-
data:输入数据矩阵,对于 cv.PCACompute 和 PCAProject 是 m×P 原始数据矩阵,对于 PCABackProject 是 m×K 降维数据矩阵 ( K ≤ P ) (K \\le P) (K≤P)
-
mean:均值,形状为 (1,P),如果该参数的输入为空,则通过输入数据计算均值
-
maxComponents:保留主成分的个数,默认为保留全部主成份
-
retainedVariance:保留的累计方差的百分比,据此确定保留主成分的个数(至少保留 2个主成分)
-
eigenvectors:特征向量,全部特征向量的形状为 (P,P),前 K 个特征向量的形状为 (K,P)
-
eigenvalues:特征值,全部特征向量的形状为 (P,1),前 K 个特征向量的形状为 (K,1)
例程 14.18:特征描述之PCA 方向校正
特征描述应尽可能独立于大小、平移和旋转的变化。使用主成分分析方法,可以对目标进行归一化边界/区域,获得目标的主要方向。
本例对于二维图像,通过 PCA 方法对目标进行方向校正。
(1)通过主成分分析(PCA)获得目标的主方向,将数据投影到主方向及其垂直方向上。
(2)计算目标的均值,第一主方向的角度。
(3) 以目标的均值作为质心(旋转中心),按主方向角度旋转原始图像,得到归一化的目标图像。
# 14.18 基于 PCA 的方向矫正 (OpenCV)
img = cv2.imread("../images/airplane01.png", flags=1)
height, width = img.shape[:2] # 512 512
print(height, width)
# src = cv2.resize(img, (300, 300))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 205, 255, cv2.THRESH_BINARY_INV)
# 寻找二值化图中的轮廓,检索所有轮廓,输出轮廓的每个像素点
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # OpenCV4~
fullCnts = np.zeros(img.shape[:2], np.uint8) # 绘制轮廓函数会修改原始图像
fullCnts = cv2.drawContours(fullCnts, contours, -1, (255, 255, 255), thickness=3) # 绘制全部轮廓
# 按轮廓的面积排序,绘制面积最大的轮廓
cnts = sorted(contours, key=cv2.contourArea, reverse=True) # 所有轮廓按面积排序
cnt = cnts[0] # 第 0 个轮廓,面积最大的轮廓,(1445, 1, 2)
maxCnt = np.zeros(img.shape[:2], np.uint8) # 初始化最大轮廓图像
cv2.drawContours(maxCnt, cnts[0], -1, (255, 255, 255), thickness=3) # 仅绘制最大轮廓 cnt
print("len(contours) =", len(contours)) # contours 所有轮廓的数量
print("area of max contour: ", cv2.contourArea(cnt)) # 轮廓面积
print("perimeter of max contour: :.1f".format(cv2.arcLength(cnt, True))) # 轮廓周长
# 主成分分析方法提取目标的方向
markedCnt = maxCnt.copy()
ptsXY = np.squeeze(cnt).astype(np.float64) # 删除维度为1的数组维度,(1445, 1, 2)->(1445, 2)
mean, eigenvectors, eigenvalues = cv2.PCACompute2(ptsXY, np.array([])) # (1, 2) (2, 2) (2, 1)
print("mean:, eigenvalues:".format(mean.round(1), eigenvalues[:,0].round(2)))
# 绘制第一、第二主成分方向轴
center = mean[0, :].astype(int) # 近似作为目标的中心 [266 281]
e1xy = eigenvectors[0,:] * eigenvalues[0,0] # 第一主方向轴
e2xy = eigenvectors[1,:] * eigenvalues[1,0] # 第二主方向轴
p1 = (center + 0.01*e1xy).astype(np.int) # P1:[149 403]
p2 = (center + 0.01*e2xy).astype(np.int) # P2:[320 332]
theta = np.arctan2(eigenvectors[0,1], eigenvectors[0,0]) * 180/np.pi # 第一主方向角度 133.6
cv2.circle(markedCnt, center, 6, 255, -1) # 在PCA中心位置画一个圆圈 RGB
cv2.arrowedLine(markedCnt, center, p1, (255, 0, 0), thickness=3, tipLength=0.1) # 从 center 指向 pt1
cv2.arrowedLine(markedCnt, center, p2, (255, 0, 0), thickness=3, tipLength=0.2) # 从 center 指向 pt2
print("center:, P1:, P2:".format(center, p1, p2))
# 根据主方向角度和中心旋转原始图像
alignCnt = img.copy()
cv2.circle(alignCnt, center, 8, (255,255,255), 2) # 在PCA中心位置画一个圆圈 BGR
cv2.arrowedLine(alignCnt, center, p1, (0,0,255), thickness=3, tipLength=0.1) # 从 center 指向 pt1
cv2.arrowedLine(alignCnt, center, p2, (0,255,0), thickness=3, tipLength=0.2) # 从 center 指向 pt2
x0, y0 = int(center[0]), int(center[1])
print("x0=, y0=, theta=:.1f(deg)".format(x0, y0, theta))
MAR1 = cv2.getRotationMatrix2D((x0,y0), theta, 1)
alignCnt = cv2.warpAffine(alignCnt, MAR1, alignCnt.shape[:2], borderValue=(255,255,255)) # 白色填充
# 显示图像
plt.figure(figsize=(9, 6))
plt.subplot(231), plt.axis('off'), plt.title("Origin")
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(232), plt.axis('off'), plt.title("Binary")
plt.imshow(binary, 'gray')
plt.subplot(233), plt.axis('off'), plt.title("Contour")
plt.imshow(fullCnts, 'gray')
plt.subplot(234), plt.axis('off'), plt.title("Max contour")
plt.imshow(maxCnt, 'gray')
plt.subplot(235), plt.axis('off'), plt.title("Marked contour")
plt.imshow(markedCnt, 'gray')
plt.subplot(236), plt.axis('off'), plt.title("Alignment image")
plt.imshow(cv2.cvtColor(alignCnt, cv2.COLOR_BGR2RGB))
plt.tight_layout()
运行结果:
512 512
len(contours) = 42
area of max contour: 63499.5
perimeter of max contour: 1725.4
mean:[[266.2 281.6]], eigenvalues:[16866.21 7533.31]
center:[266 281], P1:[149 403], P2:[320 332]
x0=266, y0=281, theta=133.6(deg)
【本节完】
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/125782405)
Copyright 2022 youcans, XUPT
Crated:2022-7-15
234. 特征提取之主成分分析(PCA)
235. 特征提取之主成分分析(sklearn)
236. 特征提取之主成分分析(OpenCV)
237. 基于主成分提取的方向校正(OpenCV.PCA)
以上是关于OpenCV 例程200篇237. 基于主成分提取的方向校正(OpenCV)的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV 例程200篇236. 特征提取之主成分分析(OpenCV)
OpenCV 例程200篇236. 特征提取之主成分分析(OpenCV)
OpenCV 例程200篇235. 特征提取之主成分分析(sklearn)
OpenCV 例程200篇235. 特征提取之主成分分析(sklearn)