图像的矩 图像的轮廓面积和长度

1. 矩的概念

图像识别的一个核心问题是图像的特征提取,简单描述即为用一组简单的数据(图像描述量)来描述整个图像,这组数据越简单越有代表性越好。良好的特征不受光线、噪点、几何形变的干扰。图像识别发展几十年,不断有新的特征提出,而图像不变矩就是其中一个。

矩是概率与统计中的一个概念,是随机变量的一种数字特征。设XX为随机变量,cc为常数,kk为正整数。则量E[(x?c)k]E[(x?c)k]称为XX关于cc点的kk阶矩。

比较重要的有两种情况:

1. c=0c=0。这时ak=E(Xk)ak=E(Xk)称为XX的kk阶原点矩

2. c=E(X)c=E(X)。这时μk=E[(X?EX)k]μk=E[(X?EX)k]称为XX的kk阶中心矩。

一阶原点矩就是期望。一阶中心矩μ1=0μ1=0,二阶中心矩μ2μ2就是XX的方差Var(X)Var(X)。在统计学上,高于4阶的矩极少使用。μ3μ3可以去衡量分布是否有偏。μ4μ4可以去衡量分布(密度)在均值附近的陡峭程度如何。

针对于一幅图像,我们把像素的坐标看成是一个二维随机变量(X,Y)(X,Y),那么一幅灰度图像可以用二维灰度密度函数来表示,因此可以用矩来描述灰度图像的特征。

不变矩(Invariant Moments)是一处高度浓缩的图像特征,具有平移、灰度、尺度、旋转不变性。M.K.Hu在1961年首先提出了不变矩的概念。1979年M.R.Teague根据正交多项式理论提出了Zernike矩。下面主要介绍这两种矩特征的算法原理与实现。

2. Hu矩

一幅M×NM×N的数字图像f(i,j)f(i,j),其p+qp+q阶几何矩mpqmpq和中心矩μpqμpq为:

mpq=∑i=1M∑j=1Nipjqf(i,j)mpq=∑i=1M∑j=1Nipjqf(i,j)

μpq=∑i=1M∑j=1N(i?iˉ)p(j?jˉ)qf(i,j)μpq=∑i=1M∑j=1N(i?iˉ)p(j?jˉ)qf(i,j)

其中f(i,j)f(i,j)为图像在坐标点(i,j)(i,j)处的灰度值。iˉ=m10/m00,jˉ=m01/m00iˉ=m10/m00,jˉ=m01/m00

若将m00m00看作是图像的灰度质量,则(iˉ,jˉ)(iˉ,jˉ)为图像的质心坐标,那么中心矩μpaμpa反映的是图像灰度相对于其灰度质心的分布情况。可以用几何矩来表示中心矩,0~3阶中心矩与几何矩的关系如下:

μ00=∑Mi=1∑Nj=1(i?iˉ)0(j?jˉ)0f(i,j)=m00μ00=∑i=1M∑j=1N(i?iˉ)0(j?jˉ)0f(i,j)=m00

μ10=∑Mi=1∑Nj=1(i?iˉ)1(j?jˉ)0f(i,j)=0μ10=∑i=1M∑j=1N(i?iˉ)1(j?jˉ)0f(i,j)=0

μ01=∑Mi=1∑Nj=1(i?iˉ)0(j?jˉ)1f(i,j)=0μ01=∑i=1M∑j=1N(i?iˉ)0(j?jˉ)1f(i,j)=0

μ11=∑Mi=1∑Nj=1(i?iˉ)1(j?jˉ)1f(i,j)=m11?yˉm10μ11=∑i=1M∑j=1N(i?iˉ)1(j?jˉ)1f(i,j)=m11?yˉm10

μ20=∑Mi=1∑Nj=1(i?iˉ)2(j?jˉ)0f(i,j)=m20?yˉm01μ20=∑i=1M∑j=1N(i?iˉ)2(j?jˉ)0f(i,j)=m20?yˉm01

μ02=∑Mi=1∑Nj=1(i?iˉ)0(j?jˉ)2f(i,j)=m02?yˉm01μ02=∑i=1M∑j=1N(i?iˉ)0(j?jˉ)2f(i,j)=m02?yˉm01

μ30=∑Mi=1∑Nj=1(i?iˉ)3(j?jˉ)0f(i,j)=m30?2xˉm20+2xˉ2m10μ30=∑i=1M∑j=1N(i?iˉ)3(j?jˉ)0f(i,j)=m30?2xˉm20+2xˉ2m10

μ12=∑Mi=1∑Nj=1(i?iˉ)1(j?jˉ)2f(i,j)=m12?2yˉm11?xˉm02+2yˉ2m10μ12=∑i=1M∑j=1N(i?iˉ)1(j?jˉ)2f(i,j)=m12?2yˉm11?xˉm02+2yˉ2m10

μ21=∑Mi=1∑Nj=1(i?iˉ)2(j?jˉ)1f(i,j)=m21?2xˉm11?yˉm20+2xˉ2m01μ21=∑i=1M∑j=1N(i?iˉ)2(j?jˉ)1f(i,j)=m21?2xˉm11?yˉm20+2xˉ2m01

μ03=∑Mi=1∑Nj=1(i?iˉ)0(j?jˉ)3f(i,j)=m03?2yˉm02+2yˉ2m01μ03=∑i=1M∑j=1N(i?iˉ)0(j?jˉ)3f(i,j)=m03?2yˉm02+2yˉ2m01

为了消除图像比例变化带来的影响,定义规格化中心矩如下:

ηpq=μpaμγ00,(γ=p+q2,p+q=2,3,…)ηpq=μpaμ00γ,(γ=p+q2,p+q=2,3,…)

利用二阶和三阶规格中心矩可以导出下面7个不变矩组(Φ1 Φ7)(Φ1 Φ7),它们在图像平移、旋转和比例变化时保持不变。

Φ1=η20+η02Φ1=η20+η02

Φ2=(η20?η02)2+4η211Φ2=(η20?η02)2+4η112

Φ3=(η20?3η12)2+3(η21?η03)2Φ3=(η20?3η12)2+3(η21?η03)2

Φ4=(η30+η12)2+(η21+η03)2Φ4=(η30+η12)2+(η21+η03)2

Φ5=(η30+3η12)(η30+η12)[(η30+η12)2?3(η21+η03)2]+(3η21?η03)(η21+η03)[3(η30+η12)2?(η21+η03)2]Φ5=(η30+3η12)(η30+η12)[(η30+η12)2?3(η21+η03)2]+(3η21?η03)(η21+η03)[3(η30+η12)2?(η21+η03)2]

Φ6=(η20?η02)[(η30+η12)2?(η21+η03)2]+4η11(η30+η12)(η21+η03)Φ6=(η20?η02)[(η30+η12)2?(η21+η03)2]+4η11(η30+η12)(η21+η03)

Φ7=(3η21?η03)(η30+η12)[(η30+η12)2?3(η21+η03)2]+]+(3η12?η30)(η21+η03)[3(η30+η12)2?(η21+η03)2]

3. 利用OpenCV计算Hu矩

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

Moments moments(InputArray array, bool binaryImage=false )

参数说明

  • 输入参数:array是一幅单通道,8-bits的图像,或一个二维浮点数组(Point of Point2f)。binaryImage用来指示输出图像是否为一幅二值图像,如果是二值图像,则图像中所有非0像素看作为1进行计算。
  • 输出参数:moments是一个类

4.contourArea()

contour:是一个向量,二维点,可以是vector或Mat类型

oriented:有默认值false,面向区域标识符,如果为true,该函数返回一个带符号的面积,其正负取决于轮廓的方向(顺时针还是逆时针)。根据这个特性可以根据面积的符号来确定轮廓的位置。如果是默认值false,则面积以绝对值的形式返回.

该函数使用Green formula计算轮廓面积,返回面积和非零像素数量如果使用drawContours或fillPoly绘制轮廓,可能导致不同。

5. arcLength()

用于计算封闭轮廓的周长或曲线的长度

curve:输入二维点集,可以是vector或Mat类型 
closed:曲线是否封闭的标志位,true则封闭否则不封闭

 1 #include<opencv2/imgproc/imgproc.hpp>
 2 #include<opencv2/highgui/highgui.hpp>
 3 #include<iostream>
 4
 5 using namespace cv;
 6 using namespace std;
 7
 8 Mat src, grayImage;
 9 int Thresh = 100;
10 int MaxThresh = 255;
11 RNG rng(12345);
12 Mat canny_output;
13 vector<vector<Point>>contours;
14 vector<Vec4i>hierarchy;
15
16 void on_threshChange(int, void *);
17
18 int main()
19 {
20     src = imread("D:/meinv.jpg");
21
22     cvtColor(src, grayImage, COLOR_BGR2GRAY);
23     blur(grayImage, grayImage, Size(3, 3));
24
25     namedWindow("原图", CV_WINDOW_AUTOSIZE);
26     imshow("原图", src);
27
28     //创建滚动条并进行初始化
29     createTrackbar("阈值", "原图", &Thresh, MaxThresh, on_threshChange);
30     on_threshChange(0, 0);
31     waitKey(0);
32     return(0);
33 }
34
35 void on_threshChange(int, void*)
36 {
37     //使用Canny检测边缘
38     Canny(grayImage, canny_output, Thresh, Thresh * 2, 3);
39     //找到轮廓
40     findContours(canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
41     //计算矩
42     vector<Moments>mu(contours.size());
43     for (int i = 0; i < contours.size(); i++)
44     {
45         mu[i] = moments(contours[i], false);
46     }
47     //计算图像的质心
48     vector<Point2f>mc(contours.size());
49     for (int i = 0; i < contours.size(); i++)
50     {
51         mc[i] = Point2f(static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m01 / mu[i].m00));
52     }
53     //绘制轮廓
54     Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
55     for (int i = 0; i < contours.size(); i++)
56     {
57         Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
58         drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
59         circle(drawing, mc[i], 4, color, -1, 8, 0);
60     }
61     //显示到窗口中
62     namedWindow("轮廓图", WINDOW_AUTOSIZE);
63     imshow("轮廓图", drawing);
64
65     //用moments矩集计算轮廓面积并与opencv函数计算结果进行比较
66     printf("\t Info: Area and Contour Length \n");
67     for (int i = 0; i < contours.size(); i++)
68     {
69         printf("* Contour[%d] - Area(M_00)=%.2f-Area OpenCV:%.2f - Length:%.2f\n", i, mu[i].m00, contourArea(contours[i]), arcLength(contours[i], true));
70         Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
71         drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
72         circle(drawing, mc[i], 4, color, -1, 8, 0);
73     }
74 }

效果图:

本文参考自:https://blog.csdn.net/keith_bb/article/details/70197104

      http://www.cnblogs.com/ronny/p/3985810.html

原文地址:https://www.cnblogs.com/carlber/p/9726347.html

时间: 2024-08-24 11:13:58

图像的矩 图像的轮廓面积和长度的相关文章

图像的矩

1 矩的计算:moments()函数 Moments moments(InputArray array,bool binaryImage=false) 2 就是轮廓面积:contourArea()函数 double contourArea(InputArray contour,bool oriented=false) 3 计算轮廓长度:arcLength()函数 double arcLength(InputArray curve,bool closed) //例子 include "opencv

切割图像(五)主动轮廓模型Snake简要模型

切割图像(五)主动轮廓模型Snake简要模型 [email protected] http://blog.csdn.net/zouxy09 在"图像切割之(一)概述"中咱们简单了解了眼下主流的图像切割方法.以下咱们主要学习下基于能量泛函的切割方法.这里学习下Snake模型简单的知识,Level Set(水平集)模型会在后面的博文中说到. 基于能量泛函的切割方法: 该类方法主要指的是活动轮廓模型(active contour model)以及在其基础上发展出来的算法,其基本思想是使用连续

图像链接 与 图像映射 的区别

既然是讲到图像,那就先介绍一下 HTML 中有关图像的元素:( 根据W3标准 ,元素不推荐的 属性 不做分析 )  <img>元素------向网页中嵌入一幅图像 img元素的属性: (1)src:图片来源URL. (2)alt: 规定图像的替代文本. (3)height和width:单位为像素,如果不指定,则为默认:如果只指定height或width,则自动调整大小. (4)ismap :将图像定义为服务器端图像映射. (5)usemap:将图像定义为客户器端图像映射. (6)longdes

【OpenCV入门教程之四】 ROI区域图像叠加&amp;初级图像混合 全剖析(转)

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/20911629 作者:毛星云(浅墨)    邮箱: [email protected] 写作当前博文时配套使用的OpenCV版本: 2.4.8 在这篇文章里,我们一起学习了在OpenCV中如何定义感兴趣区域ROI,如何使用addWeighted函数进行图像混合操作,以及将ROI和addWeighted函数结合起来使用,对指定区域进行图像

图像滤镜艺术---图像光照效果滤镜

图像光照滤镜 图像光照提滤镜主要是模拟阳光照射下的图像效果,通常使用在暗光环境下拍摄的照片中,或者是没有太阳的日景照片中.可调参数主要包括光源位置,光照半径和光照强度,通过调整这些参数,来达到我们想要的阳光明媚的效果.算法过程如下: 图像光照效果就是在图像中添加上一个太阳光源,以此模仿光照条件.主要算法包括:1光源选择:2光照像素值求取. 1,光源选择.我们假设光源位置坐标为S(X,Y),其中光源坐标一定要保证在图像大小范围内.有了光源位置,我们就可以来构建一个圆形区域模拟光照了.我们设定光源半

Ubuntu使用dense_flow提取视频图像的光流图像

使用dense_flow求取图像的光流图像,原项目地址: https://github.com/wanglimin/dense_flow 该方法使用的是opecnv最基本的光流图像计算方法,输出为 flow_x 和flow_y 两个图像. 因为输入同程序要求不同(视频 -> 连续帧图像),因此对程序进行部分修改,大体相同. 对该程序的编译方法为: 假设程序的目录为:$ROOT_DENSE 在对该程序进行编译之前应该首先在CMakelist里面修改要进行编译的源文件. 将第5, 6行修改为: ad

本图片处理类功能非常之强大可以实现几乎所有WEB开发中对图像的处理功能都集成了,包括有缩放图像、切割图像、图像类型转换、彩色转黑白、文字水印、图片水印等功能

import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Toolkit; import java.awt.color.ColorSpace; import java.awt.geom.AffineTransform;

Android资源之图像资源(图像级别资源)

图像状态资源只能定义有限的几种状态.如果需要更多的状态,就要使用图像级别资源.在该资源文件中可以定义任意多个图像级别.每个图像级别是一个整数区间,可以通过ImageView.setImageLevel或Drawable.setLevel方法切换不同状态的图像. 图像级别资源是XML格式的文件,必须将<level-list>标签作为XML的根节点.<level-list>标签中可以有任意多个<item>标签,每一个<item>标签表示一个级别区间.级别区间用a

[实例]ROS使用OpenCV读取图像并发布图像消息在rviz中显示

思路: (1)使用opencv读取本地图像 (2)调用cv_bridge::CvImage().toImageMsg()将本地图像发送给rviz显示 一.使用opencv读取本地图像并发布图像消息 (1)利用catkin新建一个工程叫rosopencv,并进行初始化 mkdir -p rosopencv/src cd rosopencv/src catkin_create_pkg rosopencv sensor_msgs cv_bridge roscpp std_msgs image_tran