首页 > 其他分享 >OpenCV 图像的矩moments()

OpenCV 图像的矩moments()

时间:2023-03-15 12:13:49浏览次数:52  
标签:中心矩 moments OpenCV 灰度 contours 图像 contour

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

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

  严格来讲矩是概率与统计中的一个概念,是随机变量的一种数字特征。设 <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()

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

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

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

contourArea()

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

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

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

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

 1 vector<Point> contour;
 2 contour.push_back(Point2f(0, 0));
 3 contour.push_back(Point2f(10, 0));
 4 contour.push_back(Point2f(10, 10));
 5 contour.push_back(Point2f(5, 4));
 6 double area0 = contourArea(contour);
 7 vector<Point> approx;
 8 approxPolyDP(contour, approx, 5, true);
 9 double area1 = contourArea(approx);
10 cout << "area0 =" << area0 << endl <<
11         "area1 =" << area1 << endl <<
12         "approx poly vertices" << approx.size() << endl;

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

1 double cv::arcLength    (   InputArray  curve,
2                             bool    closed 
3                             )

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

3.示例代码

 1 #include <iostream>
 2 #include <stdlib.h>
 3 #include <stdio.h>
 4 #include <opencv2\core\core.hpp>
 5 #include <opencv2\highgui\highgui.hpp>
 6 #include <opencv2\imgproc\imgproc.hpp>
 7 #include <Windows.h>
 8 
 9 using namespace std;
10 using namespace cv;
11 
12 //定义全局变量
13 Mat srcImage, grayImage;
14 int thresh = 100;
15 const int threshMaxValue = 255;
16 RNG rng(12345);
17 
18 //声明回调函数
19 void thresh_callback(int, void*);
20 
21 int main()
22 {
23     srcImage = imread("image_moments_1.jpg");
24 
25     //判断文件是否加载成功
26     if (!srcImage.data)
27     {
28         cout << "图像加载失败...";
29         return -1;
30     }
31     else
32         cout << "图像加载成功..." << endl << endl;
33 
34     namedWindow("原图像", WINDOW_AUTOSIZE);
35     imshow("原图像", srcImage);
36 
37     //图像转化为灰度图并平滑
38     cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
39     blur(grayImage, grayImage, Size(3, 3));
40 
41     namedWindow("灰度图", WINDOW_AUTOSIZE);
42     imshow("灰度图", grayImage);
43 
44     //创建轨迹条
45     createTrackbar("Thresh:", "灰度图", &thresh, threshMaxValue, thresh_callback);
46     thresh_callback(thresh, 0);
47     waitKey(0);
48 
49     return 0;
50 }
51 
52 void thresh_callback(int, void*)
53 {
54     Mat canny_output;
55     vector<vector<Point>>contours;
56     vector<Vec4i>hierarchy;
57 
58     //canny边缘检测
59     Canny(grayImage, canny_output, thresh, thresh * 2, 3);
60     //轮廓提取
61     findContours(canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
62 
63     //计算图像矩
64     vector<Moments>mu(contours.size());
65     for (int i = 0; i < contours.size(); i++)
66     {
67         mu[i] = moments(contours[i], false);
68     }
69 
70     //计算图像的质心
71     vector<Point2f>mc(contours.size());
72     for (int i = 0; i < contours.size(); i++)
73     {
74         mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
75     }
76 
77     //绘制轮廓
78     Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
79     for (int i = 0; i < contours.size(); i++)
80     {
81         Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
82         drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
83         circle(drawing, mc[i], 4, color, -1, 8, 0);
84     }
85 
86     namedWindow("轮廓图", WINDOW_AUTOSIZE);
87     imshow("轮廓图", drawing);
88 
89     //用moments矩集计算轮廓面积并与opencv函数计算结果进行比较
90     printf("\t Info: Area and Contour Length \n");
91     for (int i = 0; i < contours.size(); i++)
92     {
93         printf("* Contour[%d] - Area(M_00)=%.2f-Area OpenCV:%.2f - Length:%.2f\n", i, mu[i].m00, contourArea(contours[i]), arcLength(contours[i], true));
94         Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
95         drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
96         circle(drawing, mc[i], 4, color, -1, 8, 0);
97     }
98 }

4.运行结果

 

 

标签:中心矩,moments,OpenCV,灰度,contours,图像,contour
From: https://www.cnblogs.com/ybqjymy/p/17218012.html

相关文章

  • 图像数据集的均值与方差
    使用Pytorch进行预处理时,通常使用torchvision.transforms.Normalize(mean,std)方法进行数据标准化,其中参数mean和std分别表示图像集每个通道的均值和标准差序列。首先,给出......
  • opencv-python笔记(1)
    openCV笔记图像灰度图像​ 0代表纯黑色,255代表白色(类似亮度)通道拆分通过索引拆分:importcv2lena=cv2.imread("lenacolor.png")cv2.imshow("lena1",lena)b=lena[:......
  • opencv基础
    Python和OpenCV的结合是计算机视觉领域中应用最为广泛的一种方式,它们的结合使得开发者可以快速、高效地完成各种视觉任务。本文将介绍Python和OpenCV的基础使用,包括......
  • opencv图像处理基础操作之边缘检测
    概述边缘检测是利用图像中边缘像素值会发生剧烈变化来进行检测的,主要用于分割图像、提取特征等多个方面。opencv中常用的算法有Canny边缘检测算法、Sobel算子、Laplacian算......
  • Matlab常用图像处理命令108例(三)
    文章和代码以及样例图片等相关资源,已经归档至【Github仓库:​​digital-image-processing-matlab​​】或者公众号【AIShareLab】回复数字图像处理也可获取。26.edge功能:识......
  • opencv之绘制透明图
    voidcreateAlpaMat(Mat&mat){for(inti=0;i<mat.rows;i++){for(intj=0;j<mat.cols;j++){Vec4b&rgba=mat.at<Vec4b>(i,j);......
  • 【图像】【OpenGL】VAO和VBO的关系
    目录一、VBO的作用二、VAO的作用三、一个VAO和多个VBO注:VAO和VBO都是用来存储顶点信息的,并把这些信息送入顶点着色器。至于什么是顶点和顶点着色器,这里就不多说了,不了解的......
  • 图像处理踩坑笔记
    训练模型时候一定要知道,模型使用的是什么格式的输入,是BGR还是RGB。数据增强过程中,要看到其中是否经过了BGR和RGB的变换。测试的时候,一定要和训练时候的格式保持......
  • 【图像】【OpenGL】VAO和VBO的关系
    目录一、VBO的作用二、VAO的作用三、一个VAO和多个VBO注:VAO和VBO都是用来存储顶点信息的,并把这些信息送入顶点着色器。至于什么是顶点和顶点着色器,这里就不多说了,不了解的......
  • python opencv绘制矩形框
    绘制矩形框defplot_one_box_PIL4(box,img,fontSize1,color=None,label=None,line_thickness=None):img=Image.fromarray(img)draw=ImageDraw.Draw(img......