Hu矩的确很神奇,它具有平移不变性、旋转不变性和缩放不变性,是图形匹配的一个不错的工具。

通过大致对Hu矩的学习,我认为对Hu矩的学习应该有一下几步,第一步要了解什么是矩;第二步再开始了解Hu矩。为了方便大家的使用,先简单介绍下Hu矩用于模板匹配的用法。

用法:

其实Hu矩用于匹配已经在opencv中的cvMatchShape函数中应用了,下面是cvMatchShape的源代码(可以跳过):

cvMatchShapes( const void* contour1, const void* contour2,
               int method, double )
{
    CvMoments moments;
    CvHuMoments huMoments;
    double ma[7], mb[7];
    int i, sma, smb;
    double eps = 1.e-5;
    double mmm;
    double result = 0;

CV_FUNCNAME( "cvMatchShapes" );

__BEGIN__;

if( !contour1 || !contour2 )
        CV_ERROR( CV_StsNullPtr, "" );

CV_CALL( cvMoments( contour1, &moments ));

CV_CALL( cvGetHuMoments( &moments, &huMoments ));

ma[0] = huMoments.hu1;
    ma[1] = huMoments.hu2;
    ma[2] = huMoments.hu3;
    ma[3] = huMoments.hu4;
    ma[4] = huMoments.hu5;
    ma[5] = huMoments.hu6;
    ma[6] = huMoments.hu7;

CV_CALL( cvMoments( contour2, &moments ));

CV_CALL( cvGetHuMoments( &moments, &huMoments ));

mb[0] = huMoments.hu1;
    mb[1] = huMoments.hu2;
    mb[2] = huMoments.hu3;
    mb[3] = huMoments.hu4;
    mb[4] = huMoments.hu5;
    mb[5] = huMoments.hu6;
    mb[6] = huMoments.hu7;

switch (method)
    {
    case 1:
        {
            for( i = 0; i < 7; i++ )
            {
                double ama = fabs( ma[i] );
                double amb = fabs( mb[i] );

if( ma[i] > 0 )
                    sma = 1;
                else if( ma[i] < 0 )
                    sma = -1;
                else
                    sma = 0;
                if( mb[i] > 0 )
                    smb = 1;
                else if( mb[i] < 0 )
                    smb = -1;
                else
                    smb = 0;

if( ama > eps && amb > eps )
                {
                    ama = 1. / (sma * log10( ama ));
                    amb = 1. / (smb * log10( amb ));
                    result += fabs( -ama + amb );
                }
            }
            break;
        }

case 2:
        {
            for( i = 0; i < 7; i++ )
            {
                double ama = fabs( ma[i] );
                double amb = fabs( mb[i] );

if( ma[i] > 0 )
                    sma = 1;
                else if( ma[i] < 0 )
                    sma = -1;
                else
                    sma = 0;
                if( mb[i] > 0 )
                    smb = 1;
                else if( mb[i] < 0 )
                    smb = -1;
                else
                    smb = 0;

if( ama > eps && amb > eps )
                {
                    ama = sma * log10( ama );
                    amb = smb * log10( amb );
                    result += fabs( -ama + amb );
                }
            }
            break;
        }

case 3:
        {
            for( i = 0; i < 7; i++ )
            {
                double ama = fabs( ma[i] );
                double amb = fabs( mb[i] );

if( ma[i] > 0 )
                    sma = 1;
                else if( ma[i] < 0 )
                    sma = -1;
                else
                    sma = 0;
                if( mb[i] > 0 )
                    smb = 1;
                else if( mb[i] < 0 )
                    smb = -1;
                else
                    smb = 0;

if( ama > eps && amb > eps )
                {
                    ama = sma * log10( ama );
                    amb = smb * log10( amb );
                    mmm = fabs( (ama - amb) / ama );
                    if( result < mmm )
                        result = mmm;
                }
            }
            break;
        }
    default:
        CV_ERROR_FROM_STATUS( CV_BADCOEF_ERR );
    }

__END__;

return result;
}

因此,我们只需要传入两个轮廓或两幅图片,再选择一种评价的方式,就可以用这个函数进行匹配了,至于hu矩,在这个函数中已经帮我们计算好了,我们只需要选择一种匹配的方法就可以的到一个评价相似性的值了,该函数提供了三种方法来评价这两幅图的相似性,值越小越相似。

如果我们要单独计算hu矩怎么办??

opencv中有一个结构体叫CvMoments,他的定义是

typedef struct CvMoments
     {
          double  m00, m10, m01, m20, m11, m02, m30, m21, m12, m03;
          double  mu20, mu11, mu02, mu30, mu21, mu12, mu03;
          double  inv_sqrt_m00;
     }
     CvMoments;

这个结构体是用来保存矩的数据的,其中第一行是普通矩,第二行是中心距。接着有一个函数叫做CVAPI(void) cvMoments( const CvArr* arr, CvMoments* moments, int binary CV_DEFAULT(0));,这个函数是用来计算矩的,其中第一个参数是传入的图像,第二个参数是之前创建的CvMoments变量,第三个参数是是否二值化(如果是0的话,那么原图像是什么值就是什么值,如果大于0,就二值化,其中阀值我也不知道怎么确定的,但是和这个参数是没有关系的)。

同样,要计算Hu矩也有一个结构体叫CvHuMoments,他的定义是

typedef struct CvHuMoments
     {
           double hu1, hu2, hu3, hu4, hu5, hu6, hu7;
     }
       CvHuMoments;

这里用于储存计算出来的七个值,同时又有一个函数叫CVAPI(void) cvGetHuMoments( CvMoments*  moments, CvHuMoments*  hu_moments );用来计算Hu矩,其中第一个参数就是上面所计算好的moments,第二个参数就是刚创建的CvHuMoments hu_moments,计算的结果就保存的这个变量中。

以上就是我认为用hu矩进行模板匹配的方法了。

接下来我按照第二段所述的步骤介绍下我对Hu矩的理解:

第一步什么是矩:个人认为,矩的理解可以从力矩上,在高中物理上力矩的定义是力乘以力臂,所以在图像中的矩也可以这么认为,它的定义参照http://www.cnblogs.com/skyseraph/archive/2011/07/19/2110183.html中所述,其中Xpq中p+q的值称为矩的阶数。

第二步什么是hu矩:hu矩就是利用矩里边的1阶矩、二阶矩和三阶矩经过算术运算构造出来的具有平移、缩放和旋转不变性的七个矩,在上面的网址中也有讲到,我也是从上面的那个网址中学习过。

本人初学opencv,以上仅是本人学习Hu矩的一点心得,如有发现错误,请回复,我将尽快更改,同时也希望对和我一样的初学者有一丝丝的帮助。

最后非常感谢以下作品及其作者:

http://www.cnblogs.com/skyseraph/archive/2011/07/19/2110183.html

http://v.youku.com/v_show/id_XNDcyOTE3MzQ4.html

opencv中Hu矩的学习心得相关推荐

  1. OpenCV 中的矩(moments)和 Hu不变矩(HuMoments)

    文章目录 引言 矩的定义 OpenCV中的矩(moments) OpenCV中的Hu不变矩(HuMoments) 矩的应用 代码示例 参考链接 引言 我们在图像处理的任务中,常常需要对某些形状区域进行 ...

  2. 中科大高级软件工程学习心得体会

    中科大高级软件工程学习心得体会 在本门课程中,首先我对一些基本开发工具,如VSCode.Git.Vim.正则表达式等,重新审视了自己的认知,顺便学了一手shell编程,并在课程的基础上又自定义了很多配 ...

  3. 学习OpenCV:hu矩

    hu矩为描述整体图像特征的一种方法,零阶矩表示它的总质量:一阶矩表示它的质心:二阶矩又叫惯性矩,表示图像的大小和方向. 通过计算普通矩可以知道图像的重心坐标.形状方向等: Moments 中的数据类型 ...

  4. android opencv hu moment,学习OpenCV:hu矩

    hu矩为描述整体图像特征的一种方法,零阶矩表示它的总质量:一阶矩表示它的质心:二阶矩又叫惯性矩,表示图像的大小和方向. 通过计算普通矩可以知道图像的重心坐标.形状方向等: Mat imgSrc = i ...

  5. Hu矩的学习,图像轮廓特征识别(二,c#实现)

    不变矩介绍: 先看教课书上的公式: 再看网上很认真的论文: 最后看冈萨雷斯的: Hu矩5,7的公式有争议,我采用数字图像处理冈萨雷斯三版的公式,不过,感到还是不满意,有问题. 我们获取轮廓的特征,在此 ...

  6. OpenCV中parallel_for 和 parallel_for_学习笔记

    OpenCV 从2.4.3开始加入了并行计算的函数parallel_for和parallel_for_(更准确地讲,parallel_for以前就存在于tbb模块中,但是OpenCV官网将其列在2.4 ...

  7. java中finalizer终结方法学习心得

    最近在看java的中finalizer终结方法,也就是用来释放内存的,但这绝对和C++中的析构函数不相同 C++中的析构函数是用来回收对象所占用的资源的方法,而在java中,当一个对象不可到达时(也就 ...

  8. 在OpenCV中基于深度学习的边缘检测

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:AI算法与图像处理 导读 分析了Canny的优劣,并给出 ...

  9. 深入学习OpenCV中图像相似度的算法

    最近一段时间学习并做的都是对图像进行处理,其实自己也是新手,各种尝试,所以我这个门外汉想总结一下自己学习的东西,图像处理的流程.但是动起笔来想总结,一下却不知道自己要写什么,那就把自己做过的相似图片搜 ...

最新文章

  1. 深入浅出K-Means算法
  2. Git之Stash(储藏)备份当前的工作区的内容
  3. 日期与时间(C/C++)
  4. Java面试题2021,文末有福利
  5. Linux系统编程7:入门篇之Linux项目自动化构建工具-Make/Makefile的超强使用指南
  6. Java网络编程之Socket和ServerSocket详解
  7. angular日期输入框html,html5 – Angular2:日期格式文本框ngModel不起作用
  8. java socket中的方法_Java中关于Socket的方法与作用详解
  9. JVM监控及诊断工具命令行篇之jstatd
  10. python程序设计基础
  11. LM358芯片中文资料(搬运)
  12. 【谷粒商城】【认证服务】验证码、社交登录、分布式session、单点登录
  13. PCB板材及生产流程详述
  14. 网络攻击术语(Technical terms of the attacks)
  15. 用eviews做svar模型_SVAR模型制作过程
  16. CVE-2013-5211漏洞整改方法
  17. 什么情况下选用mysql_在MySQL中,‘%’可以用在什么情况下?
  18. Android 强制设置横屏或竖屏 设置全屏
  19. 模拟动态登录,获取cookie和图片验证码登录(AcFun和豆瓣)
  20. 关于DEJA_VU3D - Cesium功能集专栏说明

热门文章

  1. 使用了flink官方示例,尽然提交任务后报错了
  2. 永信至诚蔡晶晶:用有温度的技术培育信息时代的安全感
  3. 【数电】(组合逻辑电路)组合逻辑电路的分析和设计方法
  4. java 中char占了几个字节
  5. B2 - H - Historic Exhibition(二分图匹配+优化建图)
  6. Android数据库与ContentProvider
  7. 同花顺趋势启动,低位启动 趋势指导指标源码
  8. 计算机领域经典故事,[转载]计算机的工作原理(1):一个经典的故事
  9. 如何生成和使用CLIPS动态链接库
  10. #python #jupyter notebook# to_excel将多个表格写入EXCEL一个sheet中