【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, eigenvaluescv.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)(KP)

  • 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 512print(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)  # 仅绘制最大轮廓 cntprint("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.6cv2.circle(markedCnt, center, 6, 255, -1)  # 在PCA中心位置画一个圆圈  RGBcv2.arrowedLine(markedCnt, center, p1, (255, 0, 0), thickness=3, tipLength=0.1)  # 从 center 指向 pt1cv2.arrowedLine(markedCnt, center, p2, (255, 0, 0), thickness=3, tipLength=0.2)  # 从 center 指向 pt2print("center:{}, P1:{}, P2:{}".format(center, p1, p2))# 根据主方向角度和中心旋转原始图像alignCnt = img.copy()cv2.circle(alignCnt, center, 8, (255,255,255), 2)  # 在PCA中心位置画一个圆圈  BGRcv2.arrowedLine(alignCnt, center, p1, (0,0,255), thickness=3, tipLength=0.1)  # 从 center 指向 pt1cv2.arrowedLine(alignCnt, center, p2, (0,255,0), thickness=3, tipLength=0.2)  # 从 center 指向 pt2x0, 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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/565340.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

swoole 捕捉php错误,swoole怎么处理错误

在协程编程中可直接使用try/catch处理异常。但必须在协程内捕获,不得跨协程捕获异常。不仅是应用层throw的Exception,底层的一些错误也是可以被捕获的,如function、class、method不存在下面的代码中,try/catch和throw在不同的协程…

【OpenCV 例程200篇】235. 特征提取之主成分分析(sklearn)

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程 300篇】235. 特征提取之主成分分析(sklearn) 特征提取是指从原始特征中通过数学变换得到一组新的特征,以降低特征维数,消除相关性,减少无用信息…

Linux 进程资源分配,linux 进程管理和内存分配

1、进程相关概念进程:正在运行中的程序内核功用:进程管理、文件系统、网络功能、内存管理、驱动程序、安全功能等Process:运行中的程序的一个副本,是被载入内存的一个指令集合进程 ID(Process ID,PID)号码被用来标记各…

【OpenCV 例程300篇】234. 特征提取之主成分分析(PCA)

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程300篇】234. 特征提取之主成分分析(PCA) 5.1 特征提取的方法 初步获取的图像特征维数通常很大,而且往往包含一定的无关或冗余特征。特征提取是指从原始特征中通过数学变…

Java并发编程基础

线程的简介 什么是线程 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。 为什么要使用多线…

【OpenCV 例程200篇】236. 特征提取之主成分分析(OpenCV)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】236. 特征提取之主成分分析(OpenCV) 文章目录【youcans 的 OpenCV 例程200篇】236. 特征提取之主成分分析(OpenCV)5.2 主成分分析的数学方法5.4 OpenC…

linux 访问共享内存,Linux下的共享内存(03)---通过指针访问共享内存中的数据...

环境:Vmware Workstation;CentOS-6.4-x86_64说明:1、将共享内存挂载至进程:void *shmat(int shmid, const void *shmaddr,int shmflg);参数shmid是要附加的共享内存区标示符。总是把参数shmaddr设为0。参数shmflg可以为SHM_RDON…

Java中锁的使用和实现

首先,我们要了解一个概念,JAVA中的锁到底是什么呢? 锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源。 Lock接口 在Java SE 5之后,并发包中新增了Lock接口&am…

【OpenCV 例程200篇】225. 特征提取之傅里叶描述子

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】225. 特征提取之傅里叶描述子 目标特征的基本概念 通过图像分割获得多个区域,得到区域内的像素集合或区域边界像素集合。我们把感兴趣的人或物称为目标,目标所处的区域就是目…

【OpenCV 例程300篇】238. OpenCV 中的 Harris 角点检测

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程 300篇】238. OpenCV 中的 Harris 角点检测 角是直线方向的快速变化。角点通常被定义为两条边的交点,或者说角点的邻域应该具有两个不同区域的不同方向的边界。 角是高度有效的特征。角点检测&…

基础线性规划实现(matlab,lingo)

目录 一、本次所需解的问题 二、matlab解题 1)语法 2)数学思维 3)matlab解题 运行结果: 三、lingo解题 lingo解题如下: 运行结果: 最后: 一、本次所需解的问题 需解出下面该线性规划问…

cwntos linux kde桌面,Centos如何安装KDE的桌面

其实KDE其实在初次安装系统的时候就可以选择,我下面是进入系统后的安装方法:第一步:检查KDE首先查看自己是否安装了KDE# yum grouplist在grouplist的输出结果中的“Installed Groups:”部分中,如果你能找到“X Window System”和“…

【OpenCV 例程 300篇】239. Harris 角点检测之精确定位(cornerSubPix)

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程 300篇】239. Harris 角点检测之精确定位(cornerSubPix) 角是直线方向的快速变化。角点通常被定义为两条边的交点,或者说角点的邻域应该具有两个不同区域的不同方向的边界…

基础线性规划实现---python

目录 一、问题 何为线性规划问题: 二、python进行求解 1.通过观察matlab解线性规划步骤进行求解 2.python求解步骤 1)求解用到的模块(scipy 和 numpy): 2)对 max z2x13x2-5x3 该问题确定c如下&…

【OpenCV 例程 300篇】240. OpenCV 中的 Shi-Tomas 角点检测

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程 300篇】240. OpenCV 中的 Shi-Tomas 角点检测 角是直线方向的快速变化。角点通常被定义为两条边的交点,或者说角点的邻域应该具有两个不同区域的不同方向的边界。 角是高度有效的特征。角点检测…

多元统计分析1

第一章 多元正态分布 文章目录 1.1 多元分布的基本概念 1.1.1 随机向量 1.1.2 分布函数与密度函数 联合分布函数: 联合密度函数: 条件密度函数: 分量的独立性: 1.1.3 随机向量的数字特征 1.随机向量的均值 2、随机…

Java并发容器和框架

ConcurrentHashMap 我们为什么要使用 ConcurrentHashMap呢? 原因有三: 并发编程中HashMap会导致死循环;HashTable效率又非常低;ConcurrentHashMap的锁分段技术可有效提升并发访问率。在并发编程使用HashMap会导致死循环。 在多线…

【OpenCV 例程 300篇】241. 尺度不变特征变换(SIFT)

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程 300篇】241. 尺度不变特征变换(SIFT) 6.4.1 简介 尺度不变特征转换算法(Scale-invariant feature transform,SIFT)是图像处理中经典的局部特征描…

整数线性规划实现(matlab分枝界定法)

文章目录 一、本次问题 1.利用第一天所学知识求解: 2.本题理解: (1)分支界定法 背景: 基本理论(解题步骤): 求解实现1: 1.第一步 2.第二步 3.第三步 4.第四步…

linux opencv gtk 没窗口,OpenCV GTK+2.x error

可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):问题:I had installed OpenCV following these steps ().After trying to compile one examples,i got this error :OpenCV Error: Unspecified error (The function …