OpenCV学习(十九) :图像的矩:moments(),HuMoments()

OpenCV学习(十九) :图像的矩:moments(),HuMoments()

参考博客:
图像的矩特征
Structural Analysis and Shape Descriptors:opencv 形态描述
【图像算法】图像特征:几何不变矩–Hu矩
如何理解概率论的“矩”?

一、概述

1、图像识别的一个核心问题是图像的特征提取,简单描述即为用一组简单的数据(数据描述量)来描述整个图像,这组数据月简单越有代表性越好。良好的特征不受光线、噪点、几何形变的干扰,图像识别技术的发展中,不断有新的描述图像特征提出,而图像不变矩就是其中一个。
2、从图像中计算出来的矩通常描述了图像不同种类的几何特征如:大小、灰度、方向、形状等,图像矩广泛应用于模式识别、目标分类、目标识别与防伪估计、图像编码与重构等领域。.
严格来讲矩是概率与统计中的一个概念,是随机变量的一种数字特征。设 x 为随机变量,C为常数,则量E[(x−c)^k]称为X关于C点的k阶矩。比较重要的两种情况如下:
在这里插入图片描述
一阶原点矩就是期望,一阶中心矩μ_1=0,二阶中心矩μ_2就是X的方差Var(X)。在统计学上,高于4阶的矩极少使用,μ_3可以去衡量分布是否有偏,μ_4可以衡量分布(密度)在均值拘谨的陡峭程度。

3、针对一幅图像,我们把像素的坐标看成是一个二维随机变量(X, Y),那么一副灰度图可以用二维灰度图密度函数来表示,因此可以用矩来描述灰度图像的特征。 图像可以看成是一个平板的物体,其一阶矩和零阶矩就可以拿来计算某个形状的重心,而二阶矩就可以拿来计算形状的方向。
在这里插入图片描述
其中M00即零阶矩,M20和M02为二阶矩,接下来计算物体形状的方向
在这里插入图片描述
在这里插入图片描述

4、不变矩(Invariant Moments)是一种高度浓缩的图像特征,具有平移、灰度、尺度、旋转不变性,由M.K.Hu在1961年首先提出,1979年M.R.Teague根据正交多项式理论提出了Zernike矩。不变矩的物理含义:

**如果把图像看成是一块质量密度不均匀的薄板,其图像的灰度分布函数f(x,y)就是薄板的密度分布函数,则其各阶矩有着不同的含义,如零阶矩表示它的总质量;一阶矩表示它的质心;二阶矩又叫惯性矩,表示图像的大小和方向。**事实上,如果仅考虑阶次为2的矩集,则原始图像等同于一个具有确定的大小、方向和离心率,以图像质心为中心且具有恒定辐射率的椭圆。由三阶矩以下矩构成的七个矩不变量具有平移、旋转和尺度不变性等等。当密度分布函数发生改变时,图像的实质没有改变,仍然可以看做一个薄板,只是密度分布有所改变。虽然此时各阶矩的值可能发生变化,但由各阶矩计算出的不变矩仍具有平移、旋转和尺度不变性。通过这个思想,可对图像进行简化处理,保留最能反映目标特性的信息,再用简化后的图像计算不变矩特征,可减少计算量。

(研究表明,只有基于二阶矩的不变矩对二维物体的描述才是真正的与旋转、平移和尺度无关的。较高阶的矩对于成像过程中的误差,微小的变形等因素非常敏感,所以相应的不变矩基本上不能用于有效的物体识别。即使是基于二阶矩的不变矩也只能用来识别外形相差特别大的物理,否则他们的不变矩会因为很相似而不能识别。)

在OpenCV中,还可以很方便的得到Hu不变距,Hu不变矩在图像旋转、缩放、平移等操作后,仍能保持矩的不变性,所以有时候用Hu不变距更能识别图像的特征。

不变矩的应用过程一般包括:
1)选择合适的不变矩类型;
2)选择分类器(如神经网络、最短距离等);
3)如果是神经网络分类器,则需要计算学习样例的不变矩去训练神经网络;
4)计算待识别对象的不变矩,输入神经网络就可得到待识别对象的类型,或者计算待识别对象不变矩与类别对象不变矩之间的距离,选择最短距离的类别作为待识别对象的类别。

可以看出,不变矩作用主要目的是描述事物(图像)的特征。人眼识别图像的特征往往又表现为“求和”的形式,因此不变矩是对图像元素进行了积分操作。不变矩能够描述图像整体特征就是因为它具有平移不变形、比例不变性和旋转不变性等性质。然而,另一方面图像的各阶不变矩究竟代表的什么特征很难进行直观的物理解释。

二、相关算子

1、moments()函数

特征矩的知识在概率论和数理统计中有介绍,空间矩的方法在图像应用中比较广泛,包括零阶矩求面积、一阶矩确定重心、二阶矩确定主方向、二阶矩和三阶矩可以推导出七个不变矩-Hu不变矩,不变矩具有旋转,平移、缩放等不变性,因此在工业应用和模式识别中得到广泛的应用。

该函数计算多边形或栅格化形状(一个矢量形状或光栅形状)的最高达三阶所有矩。结果在结构cv::Moments 中返回

Moments cv::moments(
InputArray array,			// 光栅图像(单通道、8位或浮点二维数组)或二维点(点或点2f)的数组(1×N或N×1)
bool binaryImage = false 	// binaryImage用来指示输出图像是否为一幅二值图像,如果是二值图像,则图像中所有非0像素看作为1进行计算。
)	

结构 Moments 成员数据:

cv::Moments::Moments	
(
// 空间矩(10个)
double 	m00,double 	m10,double 	m01,double 	m20,double 	m11,double 	m02,double 	m30,double 	m21,double 	m12,double 	m03  
// 中心矩(7个)
double mu20, double mu11, double mu02, double mu30, double mu21 , double mu12,double mu03
// 中心归一化矩() 
double nu20, double nu11, double nu02, double nu30, double nu21, double nu12,double nu03;
)		

在这里插入图片描述
1)空间矩 Moments::mji 的计算公式:
在这里插入图片描述
对于01二值化的图像,m00即为轮廓的面积
2)中心距 Moments::muji 计算公式:
在这里插入图片描述
其中:(x¯,y¯)为轮廓质心
在这里插入图片描述
3)归一化的中心矩Moments::nuji计算公式为:
在这里插入图片描述
注意:
mu00=m00, nu00=1nu10=mu10=mu01=mu10=0 , 因此不存储值。
轮廓的矩是用同样的方法定义的,但是使用格林公式计算(参见http://en.wikipedia.org/wiki/Green_theorem)。因此,由于栅格分辨率的限制,计算轮廓的矩与计算相同栅格化轮廓的矩略有不同。
由于轮廓的矩是用格林公式计算的,对于具有自交点的轮廓,你可能会得到看似奇怪的结果,例如蝴蝶形轮廓的面积(m00)。

2、示例:(绘制轮廓及其质心,计算轮廓面积和长度)

使用到的算子:
1)绘制带箭头的直线(arrowedLine)
2)OpenCV—椭圆拟合fitEllipse

#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;int thresh=50;
RNG rng(12345);int main()
{// 1、 读取图片//Mat src = imread( "F:/C++/2. OPENCV 3.1.0/TEST/b.jpg", 1 );Mat src = imread( "F:/C++/2. OPENCV 3.1.0/TEST/arrow.PNG", 1 );if(!src.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~! \n"); return false; }imshow( "image", src );// 2、转灰度图Mat src_gray;cvtColor( src, src_gray, CV_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );//    // 3、利用canny算法检测边缘
//    Mat canny_output;
//    Canny( src_gray, canny_output, thresh, thresh*2, 3 );
//    imshow( "canny", canny_output );// 4、查找轮廓vector<vector<Point> > contours;vector<Vec4i> hierarchy;findContours( src_gray, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );// 5、计算每个轮廓所有矩vector<Moments> mu(contours.size());    // 创建一个vector,元素个数为contours.size()for( int i = 0; i < contours.size(); i++ ){mu[i] = moments(contours[i], false );   // 获得轮廓的所有最高达三阶所有矩}// 6、计算轮廓的质心vector<Point2f> mc( contours.size() );for( int i = 0; i < contours.size(); i++ ){mc[i] = Point2f(static_cast<float>(mu[i].m10/mu[i].m00), static_cast<float>(mu[i].m01/mu[i].m00));   // 质心的 X,Y 坐标:(m10/m00, m01/m00)}// 7、输出轮廓面积、轮廓长度、轮廓方向,画轮廓及其质心Mat drawing = Mat::zeros( src.size(), CV_8UC3 );   // 背景图for( size_t i = 0; i< contours.size(); i++ ){// 7.1 轮廓面积和轮廓长度,画轮廓及其质心Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );drawContours( drawing, contours, i, color, -1, 8, hierarchy, 0, Point() );   // 画轮廓circle( drawing, mc[i], 4, color, -1, 8, 0 );                   // 画质心double area = mu[i].m00;                                        // 轮廓面积double perimeter = arcLength(contours.at(i), true);   // 轮廓周长printf(" * 轮廓[%d] :\n  通过轮廓空间距 (M_00)计算出的面积 = %.2f \ncontourArea(OpenCV_API)计算出的面积 = %.2f    长度 = %.2f \n", i, area, contourArea(contours[i]), perimeter );// 7.2 绘制轮廓方向// 拟合轮廓椭圆,画出size_t count = contours[i].size();if( count < 6 )	// 点数少于6 跳出循环continue;Mat pointsf;Mat(contours.at(i)).convertTo(pointsf, CV_32F); // 转化为点集RotatedRect r= fitEllipse(pointsf);// 长短轴比大于30跳出循环if( MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height)*30 )    continue;ellipse(drawing, r, Scalar(0,0,255), 1, CV_AA);	// 两种方式画椭圆ellipse(cimage, box.center, box.size*0.5f, box.angle, 0, 360, Scalar(0,255,255), 1, LINE_AA);	// 画外界矩形        Point2f r[4];box.points(r);for( int j = 0; j < 4; j++ )line(cimage, r[j], r[(j+1)%4], Scalar(0,255,0), 1, LINE_AA);// 拟合椭圆的长、短轴 大小;旋转角度、直径、离心率、圆滑度double majorAxis = r.size.height > r.size.width ? r.size.height : r.size.width; //长轴double minorAxis = r.size.height > r.size.width ? r.size.width : r.size.height; //短轴double orientation = r.angle-90;                                     // 角度制double orientation_rads = orientation*CV_PI/180;                     // 转化为弧度制double diameter = sqrt((4*area)/3.1416);                            // 直径double eccentricity = sqrt(1-pow(minorAxis/majorAxis,2));           // 离心率double roundness = pow(perimeter, 2)/(2*3.1416*area);               // 圆滑度printf(" 偏移角度 = %.2f ,直径 = %.2f,离心率 = %.2, 圆滑度 = %.2f \n\n", orientation,diameter,eccentricity,roundness);// 7.3 画出方向箭头//line(drawing, Point(mc[i].x, mc[i].y), Point(mc[i].x+30*cos(orientation_rads), mc[i].y+30*sin(orientation_rads)), cvScalar(0,0,255), 3);arrowedLine(drawing, Point(mc[i].x, mc[i].y), Point(mc[i].x+30*cos(orientation_rads), mc[i].y+30*sin(orientation_rads)),Scalar(0, 255, 0), 2, LINE_8, 0, 0.5);// 7.4 输出角度 坐标值char temp_text[100];sprintf(temp_text, "%.2f", orientation);putText(drawing, temp_text, Point(mc[i].x, mc[i].y), FONT_HERSHEY_SIMPLEX, 0.5, cvScalar(0,0,255),1.5);}imshow( "Contours", drawing );waitKey(0);return 0;
}

结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、HuMoments()函数

opencv里对Hu矩的计算有直接的API,它分为了两个函数:moments()函数用于计算中心矩,HuMoments函数用于由中心矩计算Hu矩。

void HuMoments(
const Moments& moments, // moments即为上面一个函数计算得到的moments类型。
double* hu	// hu是一个含有7个数的数组。
)
#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;int main()
{Mat image = imread( "F:/C++/2. OPENCV 3.1.0/TEST/test1.png", 1 );if(!image.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~! \n"); return false; }cvtColor(image, image, CV_BGR2GRAY);imshow( "image", image );Moments mts = moments(image);   //  对整副图像 求所有 矩double hu[7];HuMoments(mts, hu);                     // 对整副图像 求 Hu几何不变矩for (int i=0; i<7; i++){cout << log(abs(hu[i])) <<endl; // 取对数 (自然指数e 为底)}//testdouble x=9,y=10;cout<<log(x)<<endl;cout<<log(exp(x))<<endl;cout<<log10(y)<<endl;waitKey(0);return 0;
}

上面代码中,最终输出的值为log|Φi|
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

全球半导体现状分析

来源&#xff1a;行业报告研究院前景乐观当今科技创新迅猛发展&#xff0c;半导体行业有望持续增长。对半导体行业来说&#xff0c;2019年会相对疲软&#xff0c;但普华永道预计其将在2020年实现复苏并保持繁荣。2018年半导体行业销售总额为4,810亿美元。今后四年&#xff0c;即…

OpenCV学习(二十) :分水岭算法:watershed()

OpenCV学习(二十) &#xff1a;分水岭算法:watershed() 参考博客&#xff1a; OpenCV—分水岭算法 图像处理——分水岭算法 OpenCV学习(7) 分水岭算法(1) Opencv分水岭算法——watershed自动图像分割用法 -牧野- 分水岭算法是一种图像区域分割法&#xff0c;在分割的过程中&a…

人工智能的下一个道德挑战:如何对待动物

来源&#xff1a;爱范儿去年 11 月份&#xff0c;一段关于母熊和它幼崽的视频在网络上传播开来。根据画面中显示&#xff0c;在一片被白雪覆盖的陡峭斜坡上&#xff0c;一头雌性棕熊正带着它的幼崽艰难的攀爬。虽然因为陡峭的坡度和积雪导致小熊一直在打滑&#xff0c;但最终还…

SQLite的使用(二):数据增删改查

SQLiteDatabase 用来管理SQLite数据库的类。SQLiteDatabase新增、修改、删除和查询数据库数据的方法&#xff0c;还可以执行其他常见的数据库管理任务。 方法 描述 (void) execSQL(String sql) 执行一个SQL语句的方法 (long) insert(String table,String nullColumnHack,Co…

OpenCV学习(二十一) :计算图像连通分量:connectedComponents(),connectedComponentsWithStats()

OpenCV学习(二十一) &#xff1a;计算图像连通分量:connectedComponents(),connectedComponentsWithStats() 1、connectedComponents()函数 Connected Components即连通体算法用id标注图中每个连通体&#xff0c;将连通体中序号最小的顶点的id作为连通体的id。如果在图G中&am…

github上只下载部分文件

有时候我们不想在github上下载整个压缩包&#xff0c;因为压缩包可能比较大&#xff0c;而我们只想要其中的代码文件&#xff0c;也就是只想下载部分文件&#xff0c;例如下面这个网页我们只想下载后缀名为py的文件&#xff0c;这可以通过tortoisesvn来完成 https://github.co…

【机器视觉】机器视觉产业链

来源&#xff1a;产业智能官机器视觉&#xff08;Machine Vision&#xff09;指的是通过光学的装置和非接触的传感器自动的接收和处理真实物体的图像&#xff0c;以获得所需信息或控制机器人运动的装置&#xff0c;通俗的说就是应用在工业领域的视觉应用。▲机器视觉系统组成另…

OpenCV学习笔记(十七):图像修补:inpaint()

OpenCV学习笔记&#xff08;十七&#xff09;&#xff1a;图像修补&#xff1a;inpaint() inpaint()函数 使用区域邻域在图像中还原选定区域。 void inpaint( InputArray src, // 表示要修复的图像,8位三通道或三通道 InputArray inpaintMask, // 表示修复模板(掩模)&a…

plt.errorbar画误差曲线

plt.errorbar(x, y, yerrNone, xerrNone, fmt, ecolorNone, elinewidthNone, capsizeNone, capthickNone ) 功能&#xff1a;画误差曲线&#xff0c;也可以用于画置信区间/标准差/方差参数&#xff1a;x&#xff1a;横坐标的值&#xff0c;y&#xff1a;纵坐标的值&#xff0c…

OpenCV学习(二十) :直方图匹配、对比:calcHist(),minMaxLoc(),compareHist()

直方图匹配、对比:calcHist ,minMaxLoc,compareHist1、calcHist()函数2、归一化&#xff1a;normalize()函数3、minMaxLoc()函数4、compareHist()函数5、示例一&#xff1a;H-S彩色图像的色调、饱和度二维直方图绘制6、示例二&#xff1a;灰度值一维直方图绘制7、示例三&#x…

Intel和IBM押重注的神经模态计算,会给行业带来什么样的变化

Intel发布的Pohoiki Beach加速卡&#xff0c;含有64块Loihi芯片来源&#xff1a; 半导体行业观察上周&#xff0c;Intel发布了基于其神经模态&#xff08;neuromorphic&#xff09;计算芯片Loihi的加速卡Pohoiki Beach&#xff0c;该加速卡包含了64块Loihi芯片&#xff0c;共含…

OpenCV学习(二十二) :反向投影:calcBackProject(),mixChannels()

OpenCV学习(二十二) &#xff1a;反向投影:calcHist(),minMaxLoc(),compareHist() 参考博客&#xff1a; 反向投影backproject的直观理解 opencv 反向投影 颜色直方图的计算、显示、处理、对比及反向投影 一、概述 1、官方解释&#xff1a;反向投影是一种记录给定图像中的像…

美国正式宣告将在月球建立永久存在基地

来源&#xff1a;凤凰新闻央视网消息&#xff1a;7月20号是人类首次载人登陆月球50周年纪念日&#xff0c;美国公布了“阿尔忒弥斯计划”的官方标志图案&#xff0c;正式宣告将在月球建立永久存在基地。美国媒体直呼&#xff0c;美国要“占领”月球了。1969年&#xff0c;美国的…

一文看懂5G芯片背后的明争暗斗

来源&#xff1a;鲜枣课堂6月6日工信部正式发放5G商用牌照之后&#xff0c;国内5G网络建设的步伐大幅加快了。越来越多的城市出现了5G基站和5G信号&#xff0c;5G离我们的距离更近了。面对激动人心的5G&#xff0c;我们普通用户最关心的问题&#xff0c;当然是什么时候才能用上…

OpenCV学习(二十三) :模板匹配:matchTemplate(),minMaxLoc()

OpenCV学习(二十三) &#xff1a;模板匹配:matchTemplate() 1、概述 模板匹配是一种最原始、最基本的模式识别方法&#xff0c;研究某一特定对象物的图案位于图像的什么地方&#xff0c;进而识别对象物&#xff0c;这就是一个匹配问题。 它是图像处理中最基本、最常用的匹配方…

CSS3实现图形曲线阴形和翘边阴影

首先&#xff0c;来看看完成之后的效果图&#xff1a; 实现原理 ①曲线阴影实现&#xff1a; 多个阴影重叠&#xff0c;就是正常阴影曲线阴影 正常情况下&#xff0c;有个矩形有正常的阴影&#xff0c;作为主投影&#xff0c;这时候再定义一个有一定弧度圆角的圆角矩形&#xf…

腾飞资本任溶 :互联网大脑,新的天方夜谭?—评《崛起的超级智能》

作者&#xff1a;任 溶 腾飞资本董事长&#xff0c;城市大脑创新合伙人基金管理合伙人因为我做科技产业投资工作&#xff0c;投资领域涉及互联网等新经济、新模式和新技术等&#xff0c;所以这几年总是听到一些言论&#xff0c;诸如“互联网已死”&#xff0c;或者“互联网红利…

OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()

OpenCV学习(二十四 &#xff09;&#xff1a;角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack() 参考博客&#xff1a; Harris角点检测原理详解 Harris角点检测原理及C实现 OpenCV亚像素角点cornerSubPixel()源代码分析 Taylor公式&#xff08;泰勒公式&#x…

无人驾驶技术的7大典型应用场景

来源 | 数据观综合无人驾驶风口来临&#xff0c;引得各方资本竞相追逐。据业内预测&#xff0c;2019年到2020年无人驾驶L3&#xff08;条件自动&#xff09;级别的汽车将实现量产化&#xff0c;2022年后部分企业将实现L4&#xff08;高度自动&#xff09;量产&#xff0c;若要实…

数字图像处理学习笔记(一):特征检测和匹配概述

数字图像处理学习笔记&#xff08;一&#xff09;&#xff1a;特征检测和匹配概述 参考博客&#xff1a; 特征点的匹配SIFT特征详解数字图像处理学习笔记&#xff08;二&#xff09;&#xff1a;SIFT&#xff08;尺度不变特征变换&#xff09;算法 1、特征点概述 如何高效且…