opencv学习(四十三)之图像的矩moments()
来源:互联网 发布:强制写作软件 编辑:程序博客网 时间:2024/05/07 19:06
1.概述
图像识别的一个核心问题是图像的特征提取,简单描述即为用一组简单的数据(数据描述量)来描述整个图像,这组数据月简单越有代表性越好。良好的特征不受光线、噪点、几何形变的干扰,图像识别技术的发展中,不断有新的描述图像特征提出,而图像不变矩就是其中一个。
从图像中计算出来的矩通常描述了图像不同种类的几何特征如:大小、灰度、方向、形状等,图像矩广泛应用于模式识别、目标分类、目标识别与防伪估计、图像编码与重构等领域。
严格来讲矩是概率与统计中的一个概念,是随机变量的一种数字特征。设
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; } else cout << "图像加载成功..." << 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()
- opencv学习-imgprocess-计算图像矩moments
- opencv学习(四十)之寻找图像轮廓findContours()
- Opencv学习之图像的矩
- OpenCV学习之三:使用迭代器遍历图像
- OpenCV学习之矩阵图像处理(三)
- OpenCV学习之图像域的填充
- OpenCV学习之图像的直方图
- OpenCV&Qt学习之三——图像的初步处理
- opencv学习笔记之对灰度图像遍历的三种方法
- opencv入门学习之三: 图像的载入,显示和输出 一站式完全解析
- opencv学习笔记之对灰度图像遍历的三种方法
- Opencv学习之图像的均衡化、二值化图像
- 大数据学习笔记之四十三 深度学习的基本方法
- Opencv ,contour moments
- vim+python+OpenCV学习三 : 对图像的像素处理
- Opencv学习三-图像的载入,显示和输出
- Opencv学习笔记(三)--图像处理的基本操作
- NYOJ46 最少乘法次数(二进制思想)
- 2017.4.16 幂次方 思考记录
- POJ 2892-Tunnel Warfare(线段树单点更新-炸毁修复城市隧道)
- 关于Android单元测试
- java的枚举
- opencv学习(四十三)之图像的矩moments()
- mysql安装包方式安装及配置(Windows)
- How tomcat works——19 管理Servlet
- 初次接触堆排序
- propertyAnimator(属性动画)之objectanimator(动画执行类)
- HDU 1520 Anniversary party (树型dp)
- 自定义屏幕保护
- ApplicationContext国际化实例
- 学习淘淘商城第二十六课(内容分类管理)