图像处理之计算物体的方向(C++)

图像处理之计算物体的方向(C++)


文章目录

  • 图像处理之计算物体的方向(C++)
  • 前言
  • 一、PCA获取物体主要方向
    • 1.原理
    • 2.代码实现
  • 二、Hu矩获取物体主要方向
    • 1.原理
    • 2.代码实现
  • 总结


前言

在图像处理中,物体的方向(倾斜角度)计算的应用非常常见,总结如下方法:PCA获得物体的主要方向以及Hu矩计算物体的主要方向。


一、PCA获取物体主要方向

1.原理

PCA的主要思想是寻找到数据的主轴方向,由主轴构成一个新的坐标系,这里的维数可以比原维数低,然后数据由原坐标系向新的坐标系投影(可以理解为一根轴最能代表物体的方向(红色),另外一根轴最不能代表物体的方向(绿色)),这个投影的过程就可以是降维的过程。(具体推导略,可以参考其他博客)
PCA

2.代码实现

#include <opencv.hpp>
#include <iostream>

struct Orientation
{
	cv::Point centroid;	//重心
	double angle;		//倾斜角度
};

/*
* @param const std::vector<cv::Point>& pts 轮廓点集
* @param Orientation& orientation	物体的主要方向结果
* @brief 计算物体的主要方向
*/
void pca_getOrientation(const std::vector<cv::Point>& pts, Orientation& orientation)
{
	// 构建pca数据,将轮廓信息转换为Mat数据结构,后续pca处理需要Mat数据结构
	cv::Mat contoursMat(pts.size(), 2, CV_64FC1);
	for (int i = 0; i < pts.size(); i++)
	{
		contoursMat.at<double>(i, 0) = pts[i].x;
		contoursMat.at<double>(i, 1) = pts[i].y;
	}

	// 执行pca分析
	cv::PCA pca(contoursMat, cv::Mat(), 0);
	// 获得最主要分量(均值),即图像轮廓中心
	orientation.centroid = cv::Point(pca.mean.at<double>(0, 0), pca.mean.at<double>(0, 1));
	//存储特征向量
	cv::Point2d eigen_vecs= cv::Point2d(pca.eigenvectors.at<double>(0, 0), pca.eigenvectors.at<double>(0, 1));
	orientation.angle = atan2(eigen_vecs.y, eigen_vecs.x);
	std::cout << orientation.angle <<std:: endl;
}

int main()
{
	// 读取图片
	std::string filepath = "F://work_study//algorithm_demo//orientation.jpg";
	cv::Mat src = cv::imread(filepath, cv::IMREAD_GRAYSCALE);
	if (src.empty())
	{
		return -1;
	}

	cv::Mat dst;
	cv::threshold(src, dst, 10, 255, cv::THRESH_BINARY_INV);

	// 寻找轮廓
	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(dst, contours, hierarchy,cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
	cv::cvtColor(dst, dst, cv::COLOR_GRAY2BGR);

	// 轮廓分析
	for (size_t i = 0; i < contours.size(); i++)
	{
		cv::drawContours(dst, contours, i, cv::Scalar(0, 255, 0), 2, 8, hierarchy, 0);
		Orientation orien;
		pca_getOrientation(contours[i], orien);
		cv::circle(dst, orien.centroid, 3, cv::Scalar(255, 0, 0),-1);
		cv::line(dst, orien.centroid, orien.centroid + cv::Point(200, 200 * tan(orien.angle)),cv::Scalar(255,0,0),2);
	}
	cv::imshow("dst", dst);
	cv::waitKey(0);
	return 0;
}

结果图

二、Hu矩获取物体主要方向

1.原理

如果把图像看成是一块质量密度不均匀的薄板,其图像的灰度分布函数f(x,y)就是薄板的密度分布函数,则其各阶矩有着不同的含义,如零阶矩表示它的总质量;一阶矩表示它的质心;二阶矩又叫惯性矩,表示图像的大小和方向。
一阶矩
二阶矩
研究表明,只有基于二阶矩的不变矩对二维物体的描述才是真正的与旋转、平移和尺度无关的。较高阶的矩对于成像过程中的误差,微小的变形等因素非常敏感,所以相应的不变矩基本上不能用于有效的物体识别。即使是基于二阶矩的不变矩也只能用来识别外形相差特别大的物理,否则他们的不变矩会因为很相似而不能识别。
**在OpenCV中,还可以很方便的得到Hu不变距,Hu不变矩在图像旋转、缩放、平移等操作后,仍能保持矩的不变性,所以有时候用Hu不变距更能识别图像的特征。**不变矩能够描述图像整体特征就是因为它具有平移不变形、比例不变性和旋转不变性等性质。

2.代码实现

#include <opencv.hpp>
#include <iostream>

struct Orientation
{
	cv::Point centroid;	//重心
	double angle;		//倾斜角度
};

int main()
{
	// 读取图片
	std::string filepath = "F://work_study//algorithm_demo//orientation.jpg";
	cv::Mat src = cv::imread(filepath, cv::IMREAD_GRAYSCALE);
	if (src.empty())
	{
		return -1;
	}

	cv::Mat dst;
	cv::threshold(src, dst, 10, 255, cv::THRESH_BINARY_INV);

	// 寻找轮廓
	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(dst, contours, hierarchy,cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
	cv::cvtColor(dst, dst, cv::COLOR_GRAY2BGR);

	// 轮廓分析
	// 计算每个轮廓所有矩
	std::vector<cv::Moments> mu(contours.size());    // 创建一个vector,元素个数为contours.size()
	for (int i = 0; i < contours.size(); i++)
	{
		mu[i] = moments(contours[i], false);   // 获得轮廓的所有最高达三阶所有矩
	}
	// 计算轮廓的质心
	std::vector<Orientation> oriens(contours.size());
	for (size_t i = 0; i < contours.size(); i++)
	{
		cv::drawContours(dst, contours, i, cv::Scalar(0, 255, 0), 2, 8, hierarchy, 0);
		Orientation orien;
		cv::Point2d center(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);		 // 质心的 X,Y 坐标:(m10/m00, m01/m00)
		// 计算方向
		double a = mu[i].m20 / mu[i].m00 - center.x * center.x;
		double b = 2*(mu[i].m11 / mu[i].m00 - center.x * center.y);
		double c = mu[i].m02 / mu[i].m00 - center.y * center.y;
		orien.angle = atan2(b, (a - c))/2;
		orien.centroid = cv::Point(static_cast<int>(center.x), static_cast<int>(center.y));   // 质心的 X,Y 坐标:(m10/m00, m01/m00)
		cv::circle(dst, orien.centroid, 3, cv::Scalar(255, 0, 0), -1);
		cv::line(dst, orien.centroid, orien.centroid + cv::Point(200, 200 * tan(orien.angle)),cv::Scalar(255,0,0),2);
	}
	cv::imshow("dst", dst);
	cv::waitKey(0);
	return 0;
}

总结

本文总结了两种计算物体主要方向的方法,分别是PCA以及HU矩实现的计算物体主要方向,欢迎大家有问题交流。

参考资料:
opencv学习——Moments()函数,计算物体形状方向
图像的矩,以及利用矩求图像的重心,方向

[opencv实战——PCA算法的应用 (https://www.cnblogs.com/xyf327/p/14824106.html#!comments)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Habicht定理中有关子结式命题3.4.6的证明

个人认为红色区域有问题&#xff0c;因为 deg ⁡ ( ϕ ( S j ) ) r \deg{\left( \phi\left( S_{j} \right) \right) r} deg(ϕ(Sj​))r&#xff0c;当 i ≥ r i \geq r i≥r时&#xff0c; s u b r e s i ( ϕ ( S j 1 ) , ϕ ( S j ) ) subres_{i}\left( \phi(S_{j 1}),\p…

“不是我兄弟”!刘强东内部“狼性训话”流出!

今天&#xff0c;京东创始人刘强东5月24日的线上讲话流出。 在这次线上讲话中&#xff0c;刘强东首先宣布为全体采销员工涨薪20%—100%&#xff0c;随后进行了一番“狼性训话”。往期报道可戳&#xff1a;刘强东怒了&#xff1a;“不是我兄弟”&#xff01; 刘强东在讲话中指…

矩阵对角化在机器学习中的奥秘与应用

在机器学习的广阔领域中&#xff0c;矩阵对角化作为一种重要的数学工具&#xff0c;扮演着不可或缺的角色。从基础的线性代数理论到复杂的机器学习算法&#xff0c;矩阵对角化都在其中发挥着重要的作用。 矩阵对角化的概念与原理 矩阵对角化是矩阵理论中的一个基本概念&#x…

FreeRtos进阶——栈保存现场的几种场景

MCU架构 在认识栈的结构前&#xff0c;我们先来认识以下单片机的简单架构。在我们的CPU中有着很重要的一个模块——寄存器&#xff08;R0-R15&#xff09;&#xff0c;其中R13&#xff0c;R14&#xff0c;R15的别称分别为SP栈顶指针、LR返回地址、PC当前指令地址。外部RAM是单片…

有限元法之有限元空间的构造

目录 一、区域Ω的剖分 二、三角形一次元 三、一次元的基函数与面积坐标 四、三角形二次元及其基函数 前两节我们介绍了有限元基本概念和变分理论的推导&#xff0c;本节我们继续探讨有限元空间的构造。 一、区域Ω的剖分 对矩形区域进行三角剖分&#xff0c;其中x方向剖…

yolov8+ROS+ubuntu18.04——学习记录

参考文献 1.Ubuntu配置Yolov8环境并训练自己的数据集 ROS实时运行 2.https://juejin.cn/post/7313979467965874214 前提&#xff1a; 1.CUDA和Anaconda&#xff0c;PyTorch 2.python>3.8 一、创建激活环境&#xff0c;安装依赖 1.创建虚拟环境 conda create -n yol…

Dream

好像很多人梦寐以求的都是别人已经拥有的&#xff0c;多少人奋斗一生的目标&#xff0c;却只是别人的起点&#xff0c;人生而自由&#xff0c;只是不在枷锁之中&#xff0c;生活中没有人不遗憾&#xff0c;只是没有人喊疼&#xff0c;时间不会重来&#xff0c;已经过去了就让它…

node.js学习P3-P10

P3 npm package.json&#xff08;package解读npm工具换镜像源&#xff09; 一个package.json文件可以的作用 作为一个描述文件&#xff0c;描述了你的项目依赖哪些包 &#xff0c;用来干什么的允许我们使用“语义版本规则”&#xff0c;指明你项目依赖的版本让你的构建更好的…

C++ 数据结构算法 学习笔记(33) -查找算法及企业级应用

C 数据结构算法 学习笔记(33) -查找算法及企业级应用 数组和索引 日常生活中&#xff0c;我们经常会在电话号码簿中查阅“某人”的电话号码&#xff0c;按姓查询或者按字母排 序查询&#xff1b;在字典中查阅“某个词”的读音和含义等等。在这里&#xff0c;“电话号码簿”和…

地信专业大二准备学开发,3大编程语言应该怎么选

地信专业同学学编第一步就是编程语言。 但是编程语言那么多&#xff0c;地信专业需要学什么语言呢&#xff1f;小编在这儿给你介绍三个我们专业常用的编程语言。 01.Python Python 是地理空间分析和一般数据科学中最流行的编程语言之一。它的流行来自于 Python 的高级、人类可…

统信UOS专业版操作系统如何安装惠普打印机驱动

通用集成驱动安装方法 以惠普P1566激光打印机为例介绍一下&#xff0c;在打印机管理器中选择打印机&#xff0c;手动选择安装驱动&#xff0c;找到品牌&#xff1a;惠普&#xff0c;型号&#xff1a;1566&#xff0c;安装驱动后测试打印&#xff1b;LaserJet Pro P1566 Foomati…

大语言模型PEFT

目录 一、PEFT的关键概念和方法 部分参数微调 概念 方法 优势 适配器&#xff08;Adapters&#xff09; 方法 优势 低秩分解&#xff08;Low-rank Factorization&#xff09; 方法 优势 差分微调&#xff08;Delta Tuning&#xff09; 方法 优势 多任务学习&…

[8] CUDA之向量点乘和矩阵乘法

CUDA之向量点乘和矩阵乘法 计算类似矩阵乘法的数学运算 1. 向量点乘 两个向量点乘运算定义如下&#xff1a; #真正的向量可能很长&#xff0c;两个向量里边可能有多个元素 (X1,Y1,Z1) * (Y1,Y2,Y3) X1Y1 X2Y2 X3Y3这种原始输入是两个数组而输出却缩减为一个(单一值)的运…

CLIP源码详解:clip.py 文件

前言 这是关于 CLIP 源码中的 clip.py 文件中的代码带注释版本。 clip.py 文件的作用&#xff1a;封装了 clip 项目的相关 API&#xff0c;通过这些 API &#xff0c;我们可以轻松使用 CLIP 项目预训练好的模型进行自己项目的应用。 另外不太容易懂的地方都使用了二级标题强…

mysql高级篇学习(数据表的设计方法,索引优化)

使用docker 安装 mysql 安装 docker # yum 包更新到最新 yum update# 卸载旧的 docker yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine # 安装 gcc 环境 yum -y install…

nodejs安装配置

nodejs安装 打开nodejs官网(https://nodejs.org/en/download/package-manager)&#xff0c;参考安装步骤操作。 更新镜像源 输入以下命令&#xff0c;将npm的镜像源设置为淘宝镜像。网上资料中&#xff0c;淘宝镜像地址多为https://registry.npm.taobao.org&#xff0c;这个…

DOS学习-目录与文件应用操作经典案例-comp

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一.前言 二.使用 三.案例 案例 1: 基本比较 案例 2: 十进制显示差异 案例 3: 字符形式显…

中小学校活动怎样投稿给媒体报道宣传?

身为一名学校老师,同时承担起单位活动向媒体投稿的宣传重任,我深知每一次校园活动背后的故事,都承载着师生们的辛勤汗水与教育的无限可能。起初,我满怀着对教育的热情,希望通过文字传递校园的温暖与光芒,却在投稿的道路上遇到了前所未有的挑战。 最初,我选择了最传统的路径——…

网络流量探针与流量回溯分析:提升网络性能的关键工具

目录 什么是网络流量探针&#xff1f; 网络流量探针的主要功能 流量回溯分析的作用 流量回溯分析的优势 AnaTraf网络流量分析仪&#xff1a;高效的网络性能监测工具 AnaTraf的特点 如何利用网络流量探针与流量回溯分析提升网络性能&#xff1f; 部署高效的网络流量探针…

ComfyUI简单介绍

&#x1f353;什么是ComfyUI ComfyUI是一个为Stable Diffusion专门设计的基于节点的图形用户界面&#xff0c;可以通过各种不同的节点快速搭建自己的绘图工作流程。 软件打开之后是长这个样子&#xff1a; 同时软件本身是github上的一个开源项目&#xff0c;开源地址为&#…