27-图像的矩(EmguCV学习)
图像普通矩
1、矩函数在图像分析中有着广泛的应用;一个从数字图像中提取出来的矩集,通常描述了该图像形状的全局特征,并提供了大量的关于该图像不同类型的几何特征信息,比如大小、位置、方向、形状等。一阶矩与形状有关,二阶矩显示曲线围绕直线平均值的扩展程度,三阶矩是关于平均值的对称性的测量。
2、由图像二阶矩与三阶矩可以导出7个不变矩,不变矩是图像的统计特征,满足平移,伸缩,旋转不变性, 在图像识别领域具有广泛的应用;
3、轮廓矩代表一条轮廓、一幅图像、一组点集的某些高级特征,矩的数值定义:
M p , q {M}_{p,q} Mp,q代表对象中所有像素和;
4、矩的分类:
①空间矩(普通矩): 具体分为0阶矩:m00、1阶矩:m10, m01、2阶矩: m20,m02,m11、3阶矩:m30,m21,m12,m03;各阶矩物理意义如下:
②中心距(central moments):具有位移不变性,利用这些矩,可将出现在图像中任意位置的物体与参考图像中可能出现在另外位置的参考物体进行比较;
图像中心计算公式:
③归一化中心矩:具有缩放不变性,支持图像的缩放进行比较
5、图像矩通过Moments()函数计算:
图像的Hu矩
1、Hu矩是归一化中心矩的线型组合,具有平移、缩放、旋转、镜面映射不变性,一共有7个double元素组成一个向量;
2、Hu不变矩通过Humoments()函数计算:
3、Hu矩对物体形状具有较好的描述
形状匹配(matchShape()函数)
1、matchShape()函数比较轮廓相似度,根据Hu矩的原理进行计算:计算结果通过函数返回值返回,返回值越小,相似度越高,返回值为0 , 表示两轮廓完全相似。
Code
利用Hu矩进行形状匹配比模板匹配好用一点:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
using System.Drawing;
namespace lesson27
{
class Program
{
static void Main(string[] args)
{
///计算轮廓面积、周长、质心
Mat src = CvInvoke.Imread("mask2.jpg");
Mat dst = src.Clone();
Mat grayImg = new Mat();
CvInvoke.Imshow("input", src);
CvInvoke.CvtColor(src, grayImg, ColorConversion.Bgr2Gray);
CvInvoke.Threshold(grayImg, grayImg, 100, 255, ThresholdType.Binary);
CvInvoke.Imshow("threshold", grayImg);
//发现轮廓
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
VectorOfRect hierarchy = new VectorOfRect();
CvInvoke.FindContours(grayImg, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxNone);
CvInvoke.DrawContours(dst, contours, -1, new MCvScalar(255, 255, 0), 2);
for (int i = 0; i < contours.Size; i++)
{
double area = CvInvoke.ContourArea(contours[i], false); //计算面积周长
double length = CvInvoke.ArcLength(contours[i], true);
MCvMoments moments = CvInvoke.Moments(contours[i], false); //计算轮廓矩
Point ptCenter = new Point();
ptCenter.X = (int)(moments.M10 / moments.M00); //计算质心
ptCenter.Y = (int)(moments.M01 / moments.M00);
CvInvoke.Circle(dst, ptCenter, 3, new MCvScalar(0, 0, 255), -1);//绘制质心
}
CvInvoke.Imshow("result", dst);
CvInvoke.WaitKey(0);
///形状匹配(具有旋转、平移、缩放、镜像不变性)
//Mat temp = CvInvoke.Imread("0.jpg");
//Mat grayImg1 = new Mat();
//CvInvoke.Imshow("template", temp);
//CvInvoke.CvtColor(temp, grayImg1, ColorConversion.Bgr2Gray);
//CvInvoke.Threshold(grayImg1, grayImg1, 100, 255, ThresholdType.Binary);
//CvInvoke.Imshow("threshold1", grayImg1);
//VectorOfVectorOfPoint contours_temp = new VectorOfVectorOfPoint();
//VectorOfRect hierarchy_temp = new VectorOfRect();
//CvInvoke.FindContours(grayImg1, contours_temp, hierarchy_temp, RetrType.External, ChainApproxMethod.ChainApproxNone);
//Mat src = CvInvoke.Imread("1.jpg");
//Mat grayImg2 = new Mat();
//CvInvoke.Imshow("input", src);
//CvInvoke.CvtColor(src, grayImg2, ColorConversion.Bgr2Gray);
//CvInvoke.Threshold(grayImg2, grayImg2, 100, 255, ThresholdType.Binary);
//CvInvoke.Imshow("src threshold", grayImg2);
//VectorOfVectorOfPoint contours_src = new VectorOfVectorOfPoint();
//VectorOfRect hierarchy_src = new VectorOfRect();
//CvInvoke.FindContours(grayImg2, contours_src, hierarchy_src, RetrType.Tree, ChainApproxMethod.ChainApproxNone);
//for(int i = 0; i < contours_src.Size;i++)
//{
// //形状匹配
// double matchValue = CvInvoke.MatchShapes(contours_temp[0], contours_src[i], ContoursMatchType.I1);
// Console.WriteLine("contour {0} value:{1:F5}", i, matchValue); //控制输出格式
// //根据计算结果绘制轮廓
// if(matchValue < 0.1)
// {
// CvInvoke.DrawContours(src, contours_src, i, new MCvScalar(0, 255, 0), 2);
// }
// else
// {
// CvInvoke.DrawContours(src, contours_src, i, new MCvScalar(0, 0, 255), 2);
// }
//}
//CvInvoke.Imshow("result", src);
//CvInvoke.WaitKey(0);
}
}
}
效果
1、形状匹配:
2、寻找质心:
参考
1、https://blog.csdn.net/cp32212116/article/details/38374015
2、Learning OpenCV3