【opencv 450 Image Processing】Image Moments 图像矩

Goal

在本教程中,您将学习如何:

使用 OpenCV 函数 cv::moments

使用 OpenCV 函数 cv::contourArea

使用 OpenCV 函数 cv::arcLength

Theory

Code

本教程代码如下所示。 你也可以从这里下载

https://github.com/opencv/opencv/tree/4.x/samples/cpp/tutorial_code/ShapeDescriptors/moments_demo.cpp

/**
 * @function moments_demo.cpp
 * @brief Demo code to calculate moments
 * @author OpenCV team
 */

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <iomanip>

using namespace cv;
using namespace std;

Mat src_gray;
int thresh = 100;//边缘检测阈值
RNG rng(12345);

/// Function header
void thresh_callback(int, void* );

/**
 * @function main
 */
int main( int argc, char** argv )
{
    /// Load source image
    CommandLineParser parser( argc, argv, "{@input | stuff.jpg | input image}" );
    Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ) );

    if( src.empty() )
    {
        cout << "Could not open or find the image!\n" << endl;
        cout << "usage: " << argv[0] << " <Input image>" << endl;
        return -1;
    }

    /// Convert image to gray and blur it
    cvtColor( src, src_gray, COLOR_BGR2GRAY );
    blur( src_gray, src_gray, Size(3,3) );

    /// Create Window
    const char* source_window = "Source";
    namedWindow( source_window );
    imshow( source_window, src );

    const int max_thresh = 255;
    createTrackbar( "Canny thresh:", source_window, &thresh, max_thresh, thresh_callback );
    thresh_callback( 0, 0 );

    waitKey();
    return 0;
}

/**
 * @function thresh_callback
 */
void thresh_callback(int, void* )
{
    /// Detect edges using canny
    Mat canny_output;
    Canny( src_gray, canny_output, thresh, thresh*2, 3 );
    /// Find contours
    vector<vector<Point> > contours;
    findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE );

    /// 计算矩Get the moments
    vector<Moments> mu(contours.size() );
    for( size_t i = 0; i < contours.size(); i++ )
    {//https://zhuanlan.zhihu.com/p/101297923 
        mu[i] = moments( contours[i] );//多边形的矩
    }

    /// 获取质心 Get the mass centers
    vector<Point2f> mc( contours.size() );
    for( size_t i = 0; i < contours.size(); i++ )
    {
        //add 1e-5 to avoid division by zero 添加 1e-5 以避免被零除
        mc[i] = Point2f( static_cast<float>(mu[i].m10 / (mu[i].m00 + 1e-5)),
                         static_cast<float>(mu[i].m01 / (mu[i].m00 + 1e-5)) );//计算多边形的质心:一阶矩/零阶矩
        cout << "mc[" << i << "]=" << mc[i] << endl;//输出质心坐标
    }

    /// 绘制轮廓Draw contours
    Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
    for( size_t i = 0; i< contours.size(); i++ )
    {
        Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) );//随机颜色
        drawContours( drawing, contours, (int)i, color, 2 );//绘制轮廓
        circle( drawing, mc[i], 4, color, -1 );//绘制质心
    }

    /// 在窗口显示 Show in a window
    imshow( "Contours", drawing );

    /// Calculate the area with the moments 00 and compare with the result of the OpenCV function
	//计算矩为 00 的面积并与 OpenCV 函数的结果进行比较
    cout << "\t Info: Area and Contour Length \n";
    for( size_t i = 0; i < contours.size(); i++ )
    {
        cout << " * Contour[" << i << "] - Area (M_00) = " << std::fixed << std::setprecision(2) << mu[i].m00
             << " - Area OpenCV: " << contourArea(contours[i]) << " - Length: " << arcLength( contours[i], true ) << endl;
    }
}

Explanation

Result

 

 参考:

【从零学习OpenCV 4】图像矩的计算与应用 - 知乎 (zhihu.com)

OpenCV学习(33) 轮廓的特征矩Moment

OpenCV学习(33) 轮廓的特征矩Moment - 迈克老狼2012 - 博客园 (cnblogs.com)

  在OpenCV中,可以很方便的计算多边形区域的3阶特征矩,opencv中的矩主要包括以下几种:空间矩,中心矩和中心归一化矩。

class Moments { public: ...... 

// 空间矩 

double m00, m10, m01, m20, m11, m02, m30, m21, m12, m03; 

// 中心矩 

double mu20, mu11, mu02, mu30, mu21, mu12, mu03; 

// 中心归一化矩

 double nu20, nu11, nu02, nu30, nu21, nu12, nu03; }

空间矩的公式为:

 

可以知道,对于01二值化的图像,m00即为轮廓的面积。

中心矩的公式为:

 

其中:

 

归一化的中心矩公式为:

 

OpenCV中计算矩的函数为:Moments

moments(InputArray array, bool binaryImage=false )

在OpenCV中,还可以很方便的得到Hu不变距,Hu不变矩在图像旋转、缩放、平移等操作后,仍能保持矩的不变性,所以有时候用Hu不变距更能识别图像的特征。Hu不变矩的基本概念请参考paper:Hu. Visual Pattern Recognition by Moment Invariants, IRE Transactions on Information Theory, 8:2, pp. 179-187, 1962, 或者参考中文介绍:【图像算法】图像特征:几何不变矩--Hu矩 - SkySeraph - 博客园

Hu不变矩主要是利用归一化中心矩构造了7个不变特征矩:

 

OpenCV中计算Hu矩的公式为:

HuMoments(const Moments& m, OutputArray hu)

matchShapes函数其实比较的是两个轮廓的Hu不变矩,第三个参数决定比较的方式,下面是第三个参数的三个可选值。

什么叫图像的矩,在数字图像处理中有什么作用? - 知乎 (zhihu.com)

矩用来抽取图像(块)特征。

本质上,Hu矩其实就是泰勒级数展开的对应项。其他类型的矩也是对应多项式展开的级数(如Legendre矩对应Legendre级数)。

所以在图像里,低阶矩反映低频(主要的)信息,高阶矩反映高频(细节)信息。

矩用来抽取图像(块)特征。

本质上,Hu矩其实就是泰勒级数展开的对应项。其他类型的矩也是对应多项式展开的级数(如Legendre矩对应Legendre级数)。

所以在图像里,低阶矩反映低频(主要的)信息,高阶矩反映高频(细节)信息。

普通几何矩是基于图像原点计算的,对于图像f(x),其p+q阶普通矩的计算公式为:

上式中C和R分别表征图像的列和行。

利用几何矩进行基于区域的特征描述时,不同的阶数表示了不同的特性。各阶矩的物理意义可以表述如下。

1)零阶矩

根据几何矩的定义,0阶矩m00表征目标区域面积

2)一阶矩

一阶矩m01和m10分别为图像关于x轴和y轴的矩,可以用来确定目标区域的质心,其坐标可表示为:

3)二阶矩

图像的二阶矩m20和m02分别表示目标区域在水平和垂直方向上的伸展均衡度m20大于0表示目标区域下部的水平伸展度比上部大小于0表示上部的水平伸展度比下部大;m02大于0表示图像右边的垂直伸展比左边大,小于0则正相反。m11表示目标区域的倾斜度,m11大于0表示图像向左上倾斜,小于0表示图像向右上倾斜。另外,m20和m02为对x轴和y轴的惯性矩,通过组合它们可以确定几个重要的特性,例如主轴比方向离心率圆形度等等。

4) 三阶矩

三阶矩或者三阶以上矩,是目标区域轮廓细节低阶矩变化的具体表现。其中,m30和m03描述了边界曲线投影的扭曲程度,即关于均值对称分布的偏差程度,分别表示轮廓在水平和垂直方向上的重心偏移度。m30大于0表示重心偏左,小于0表示重心偏右;m03大于0表示重心向上偏移,小于0表示重心向下偏移。m21和m12表示目标区域的水平和垂直伸展的均衡程度,m21大于0表示目标区域上部的水平伸展比下部大,小于零则相反,m12大于零表示目标区域右边的垂直伸展比左边大,小于零则相反。

上述图像矩为普通矩,其值随目标区域的旋转、平移、尺度变化而改变,在实际应用中,为了提高图像矩的适用能力,需要将普通矩转换为具有旋转、平移和尺度不变性的Hu矩。针对平移不变性、尺度不变性和旋转不变性,构造Hu矩。

平移不变性:根据目标区域质心坐标x0,y0,构造中心矩:

由于选择以目标质心为基准构造中心矩,因此矩的计算结果只与目标质心的相对位置有关,而与目标绝对位置无关,从而具有了平移不变性。

尺度不变性:已知零阶中心矩u00表征目标区域的面积,为在计算图像矩时剔除尺度因素影响,可以利用0阶中心矩u00对各阶中心矩做归一化处理,得到归一化中心矩:

旋转不变性:根据中心矩的二阶矩和三阶矩,构造出7个不变矩组,其再图像平移、尺度变化和旋转时保持不变。

对于图像的Hu矩特征,由于Hu矩包含低阶特征例如面积、以及高阶特征例如旋转半径、方位等其单帧静态数值和多帧的动态变化都可能对图像识别有效果。

Hu矩是描述目标区域形状特性的重要特征,一般在图像检测仿真中实现此特征,并通过有效的特征筛选方法评估此特征的有效性,再决定是否使用该特征。

【从零学习OpenCV 4】图像矩的计算与应用 - 知乎 (zhihu.com)

(6条消息) 图像中的矩概念_Edgar_U的博客-CSDN博客_图像块的矩

什么叫图像的矩,在数字图像处理中有什么作用? - 知乎 (zhihu.com)

图像的矩是用来描述图像形状特征的,以及形状的概率分布矩是统计学和概率论的一个概念,是均值、方差概念的扩展。所以可以用矩来描述和表征不同的形状,可以作为目标识别的一种特征来训练机器学习系统具体效果怎么样,我还不知道,但可以肯定的是,用矩来描述不同形状的图像的准确性肯定没有深度学习的特征好。只能算是表述形状的一个初等特征,类似圆形度,密实度这一水平的特征。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值