1.概述

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

从图像中计算出来的矩通常描述了图像不同种类的几何特征如:大小、灰度、方向、形状等,图像矩广泛应用于模式识别、目标分类、目标识别与防伪估计、图像编码与重构等领域。

严格来讲矩是概率与统计中的一个概念,是随机变量的一种数字特征。设 x <script type="math/tex" id="MathJax-Element-1">x</script> 为随机变量,C为常数,则量E[(x−c)^k]称为X关于C点的k阶矩。比较重要的两种情况如下:

1.c=0,这时a_k=E(X^k)称为X的k阶原点矩;

2.c=E(X),这时μ_k=E[(X−EX)^k]称为X的k阶中心矩

一阶原点矩就是期望,一阶中心矩μ_1=0,二阶中心矩μ_2就是X的方差Var(X)。在统计学上,高于4阶的矩极少使用,μ_3可以去衡量分布是否有偏,μ_4可以衡量分布(密度)在均值拘谨的陡峭程度。

针对一幅图像,我们把像素的坐标看成是一个二维随机变量(X, Y),那么一副灰度图可以用二维灰度图密度函数来表示,因此可以用矩来描述灰度图像的特征。
不变矩(Invariant Moments)是一种高度浓缩的图像特征,具有平移、灰度、尺度、旋转不变性,由M.K.Hu在1961年首先提出,1979年M.R.Teague根据正交多项式理论提出了Zernike矩

opencv中提供的API用来计算中心矩和Hu矩,下面主要介绍Hu的原理。

2.原理

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

其中f(i,j)为图像在坐标点(i,j)处的灰度值。

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

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

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

3.opencv API

opencv中提供了moments()来计算图像中的中心矩(最高到三阶),HuMoments()用于由中心矩计算Hu矩.同时配合函数contourArea函数计算轮廓面积和arcLength来计算轮廓或曲线长度

moments()

cv::moments (   InputArray  array,bool    binaryImage = false )

array:输入数组,可以是光栅图像(单通道,8-bit或浮点型二维数组),或者是一个二维数组(1 X N或N X 1),二维数组类型为Point或Point2f

binaryImage:默认值是false,如果为true,则所有非零的像素都会按值1对待,也就是说相当于对图像进行了二值化处理,阈值为1,此参数仅对图像有效。

contourArea()

double cv::contourArea  (   InputArray  contour,bool    oriented = false )

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

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

该函数使用Green formula计算轮廓面积,返回面积和非零像素数量如果使用drawContours或fillPoly绘制轮廓,可能导致不同。
官方文档中给出调用contourArea()函数示例如下:

vector<Point> contour;
contour.push_back(Point2f(0, 0));
contour.push_back(Point2f(10, 0));
contour.push_back(Point2f(10, 10));
contour.push_back(Point2f(5, 4));
double area0 = contourArea(contour);
vector<Point> approx;
approxPolyDP(contour, approx, 5, true);
double area1 = contourArea(approx);
cout << "area0 =" << area0 << endl <<"area1 =" << area1 << endl <<"approx poly vertices" << approx.size() << endl;

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

double cv::arcLength    (   InputArray  curve,bool    closed )

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

3.示例代码

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <Windows.h>using namespace std;
using namespace cv;//定义全局变量
Mat srcImage, grayImage;
int thresh = 100;
const int threshMaxValue = 255;
RNG rng(12345);//声明回调函数
void thresh_callback(int, void*);int main()
{srcImage = imread("image_moments_1.jpg");//判断文件是否加载成功if (!srcImage.data){cout << "图像加载失败...";return -1;}elsecout << "图像加载成功..." << endl << endl;namedWindow("原图像", WINDOW_AUTOSIZE);imshow("原图像", srcImage);//图像转化为灰度图并平滑cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);blur(grayImage, grayImage, Size(3, 3));namedWindow("灰度图", WINDOW_AUTOSIZE);imshow("灰度图", grayImage);//创建轨迹条createTrackbar("Thresh:", "灰度图", &thresh, threshMaxValue, thresh_callback);thresh_callback(thresh, 0);waitKey(0);return 0;
}void thresh_callback(int, void*)
{Mat canny_output;vector<vector<Point>>contours;vector<Vec4i>hierarchy;//canny边缘检测Canny(grayImage, canny_output, thresh, thresh * 2, 3);//轮廓提取findContours(canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//计算图像矩vector<Moments>mu(contours.size());for (int i = 0; i < contours.size(); i++){mu[i] = moments(contours[i], false);}//计算图像的质心vector<Point2f>mc(contours.size());for (int i = 0; i < contours.size(); i++){mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);}//绘制轮廓Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);for (int i = 0; i < contours.size(); i++){Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());circle(drawing, mc[i], 4, color, -1, 8, 0);}namedWindow("轮廓图", WINDOW_AUTOSIZE);imshow("轮廓图", drawing);//用moments矩集计算轮廓面积并与opencv函数计算结果进行比较printf("\t Info: Area and Contour Length \n");for (int i = 0; i < contours.size(); i++){printf("* Contour[%d] - Area(M_00)=%.2f-Area OpenCV:%.2f - Length:%.2f\n", i, mu[i].m00, contourArea(contours[i]), arcLength(contours[i], true));Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());circle(drawing, mc[i], 4, color, -1, 8, 0);}
}

4.运行结果


参考博客:

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

opencv学习(四十三)之图像的矩moments()相关推荐

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

    OpenCV学习(二十三) :模板匹配:matchTemplate() 1.概述 模板匹配是一种最原始.最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,这就是一个匹配 ...

  2. 【OpenCV学习笔记】之图像轮廓特征与图像的矩

    一.图像的轮廓(Contours of Image) 轮廓可以说是一个很好的图像目标的外部特征,这种特征对于我们进行图像分析,目标识别和理解等更深层次的处理都有很重要的意义.那么,怎么取提取轮廓呢? ...

  3. 结合openCV学习DIP之传统图像特征与匹配

    前言 关于图像的预处理部分参考  结合opencv学习DIP​​​​​​​ 概述 该笔记主要是基于DIP理论➕openCV实现,学习该笔记首先要确保通读DIP理论,并由自己的话描述相关知识,并且掌握o ...

  4. opencv学习笔记20:图像轮廓

    图像轮廓 Contours:轮廓 轮廓是将没有连着一起的边缘连着一起. 边缘检测检测出边缘,边缘有些未连接在一起. 注意问题 1.对象为二值图像,首先进行阈值分割或者边缘检测. 2.查找轮廓需要更改原 ...

  5. opencv学习笔记19:图像金字塔和图像拉普拉斯金字塔 (用于图像放大和缩小)

    图像金字塔原理 图像金字塔:只不同分辨率,不同尺寸子图构成的集合. 取样 向下取样:有一个图像G0,对它重新采样,得到分辨率小些的G1,以此类推. 向上取样:有一个图像G3,然后变成像素更多的G2,以 ...

  6. opencv学习笔记14:图像礼帽,图像黑帽

    python + OpenCV 图像礼帽 图像礼帽 也叫图像顶帽 礼帽图像=原始图像-开运算图像 得到噪声图像 开运算:先腐蚀再膨胀 使用对象:二值图像 使用方法:morphologyEx cv2.M ...

  7. opencv学习笔记12:图像腐蚀和图像膨胀

    语言:python+opencv 为什么使用图像腐蚀和图像膨胀 如图,使用图像腐蚀进行去噪,但是为压缩噪声. 对腐蚀过的图像,进行膨胀处理,可以去除噪声,并保持原样形状. 图像腐蚀 腐蚀主要针对的是二 ...

  8. opencv学习笔记11:图像滤波(均值,方框,高斯,中值)

    为什么要使用滤波 消除图像中的噪声成分叫作图像的平滑化或滤波操作.信号或图像的能量大部分集中在幅度谱的低频和中频段是很常见的,而在较高频段,感兴趣的信息经常被噪声淹没.因此一个能降低高频成分幅度的滤波 ...

  9. opencv 学习笔记9:图像缩放与图像翻转

    图像缩放 缩放包括缩小和放大 语法格式 cv2.resize()有很多参数,其中src和dsize必备 cv2.resize(src.dsize) src原始图像路径 dsize 目标图像大小 (列, ...

最新文章

  1. 数据导出为Excel(未完)
  2. 从计算机移到u盘如何加快速度,我的电脑移动文件到U盘里时进度很慢很慢,怎么让它变快?...
  3. 大数据与测试测量的结合
  4. spring源码分析之spring-core-env
  5. 理解“动心忍性”的含义
  6. 百度安全发布PaddleSleeve 面向产业实践开启AI模型安全与隐私探索
  7. java程序启动后就进行了7次younggc_程序员如何优化 Java GC
  8. influxdb mysql对比_influxdb基础入门
  9. c#发送简单的post、get请求
  10. 简单的redis使用watch完成秒杀抢购功能
  11. (十七)用JAVA编写MP3解码器——解码Layer1
  12. 用SQL语句复制数据表
  13. c语言计算圆周率的第100位,JavaScript实现计算圆周率到小数点后100位的方法示例...
  14. 计算机对操作系统函数的调用失败,win10调用DllRegisterServer失败怎么办_win10调用DllRegisterServer失败如何解决...
  15. python django企业固定资产管理系统pycharm项目源码lw
  16. Chinese Whisper 人脸聚类算法实现
  17. vb.net产生随机数Random代码实例
  18. 浅谈虚树(虚仙人掌)
  19. c++面试常见题·Part 1 基础
  20. 浅谈游戏数据分析---留存篇一-留存折损

热门文章

  1. 更新 | 2019年9月计算机二级office模拟题库
  2. win7显示方向旋转快捷键禁用及图形属性打开方法
  3. 贝加莱驱动器电源模块维修8B0C0320HW00.002-1
  4. RoBERTa:A Robustly Optimized BERT Pretraining Approach(2019-7-26)
  5. 《西游记》师徒四人给我们的职场启发
  6. tableau创建计算字段,进行年龄段分类
  7. 客户干货分享| 哈啰出行:以人与技术的多方出击,提效移动应用研发
  8. 如何在linux系统安装igh,Linux下IGH Ethercat Master安装
  9. 基于OpenMV和正点原子开发的自动追球小车(带云台舵机)
  10. 【无标题】threejs 使用composer后的场景变暗解决