opencv4 c++ 提取图片中的白色区域_【从零学习OpenCV 4】图像矩的计算与应用

点击上方“ 小白学视觉 ”,选择“ 星标 ”公众号
重磅干货,第一时间送达
经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《从零学习OpenCV 4》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。

矩是描述图像特征的算子,被广泛用于图像检索和识别、图像匹配、图像重建、图像压缩以及运动图像序列分析等领域。本节中将介绍几何矩与Hu矩的计算方法以及应用Hu矩实现图像轮廓的匹配。

几何矩与中心矩

图像几何矩的计算方式如式(7.8)所示:

4232ff28e7922a57db4fca0fa71f5955.png

其中是像素处的像素值。当x和y同时取值0时称为零阶矩,零阶矩可以用于计算某个形状的质心,当x和y分别取值0和1时被称为一阶矩,以此类推。图像质心的计算公式如(7.9)所示:

b2992ea0f184937db67361ade5358d30.png

图像中心距计算方式如式(7.10)所示:

211486596f52b5eee7a8b88645c4899a.png

图像归一化几何矩计算方式如式所示:

b58ebd0658deedd8415e7c629b2c12b3.png

OpenCV 4提供了计算图像矩的moments()函数,该函数的函数原型在代码清单7-28中给出。

代码清单7-28 moments()函数原型Moments cv::moments(InputArray  array,                    bool  binaryImage = false                     )
  • array:计算矩的区域2D像素坐标集合或者单通道的CV_8U图像
  • binaryImage:是否将所有非0像素值视为1的标志。

该函数用于计算图像连通域的几何矩和中心距以及归一化的几何矩。函数第一个参数是待计算矩的输入图像或者2D坐标集合。函数第二个参数为是否将所有非0像素值视为1的标志,该标志只在第一个参数输入为图像类型的数据时才会有作用。函数会返回一个Moments类的变量,Moments类中含有几何矩、中心距以及归一化的几何矩的数值属性,例如Moments.m00是零阶矩,Moments.m01和Moments.m10是一阶矩。Moments类中所有的属性在表7-5给出。

表7-5 Moments类的属性
种类属性
spatial momentsm00、m10、m01、m20、m11、m02、m30、m21、m12、m03
central momentsmu20、mu11、mu02、mu30、mu21、mu12、mu03
central normalized momentsnu20、nu11、nu02、nu30、nu21、nu12、nu03

为了了解函数的使用方法,在代码清单7-29中给出了计算图像矩和读取每一种矩数值方法的示例程序,程序的部分运行结果如图7-24所示。

代码清单7-29 myMoments.cpp计算图像的矩#include #include #include using namespace cv;using namespace std;int main(){	Mat img = imread("approx.png");	// 二值化	Mat gray, binary;	cvtColor(img, gray, COLOR_BGR2GRAY);	threshold(gray, binary, 105, 255, THRESH_BINARY);	//开运算消除细小区域	Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));	morphologyEx(binary, binary, MORPH_OPEN, k);	// 轮廓发现	vector> contours;	vector hierarchy;	findContours(binary, contours, hierarchy, 0, 2, Point());	for (int n = 0; n < contours.size(); n++) 	{		Moments M;		M = moments(contours[n], true);		cout << "spatial moments:" << endl			<< "m00:" << M.m00 << " m01:" << M.m01 << " m10:" << M.m10 << endl			<< "m11:" << M.m11 << " m02:" << M.m02 << " m20:" << M.m20 << endl			<< "m12:" << M.m12 << " m21:" << M.m21 << " m03:" << M.m03 << " m30:"<< M.m30 << endl;		cout << "central moments:" << endl			<< "mu20:" << M.mu20 << " mu02:" << M.mu02 << " mu11:" << M.mu11 << endl			<< "mu30:" << M.mu30 << " mu21:" << M.mu21 << " mu12:" << M.mu12 << " mu03:" << M.mu03 << endl;		cout << "central normalized moments:" << endl			<< "nu20:" << M.nu20 << " nu02:" << M.nu02 << " nu11:" << M.nu11 << endl			<< "nu30:" << M.nu30 << " nu21:" << M.nu21 << " nu12:" << M.nu12 << " nu03:" << M.nu03 << endl;	}	return 0;}
d3116f9f5af067ad0608cac91ac8ea7e.png
图7-24 myMoments.cpp程序部分运行结果

Hu矩

Hu矩具有旋转、平移和缩放不变性,因此在图像具有旋转和放缩的情况下Hu矩具有更广泛的应用领域。Hu矩是由二阶和三阶中心距计算得到七个不变矩,具体计算公式如式(7.12)所示:

0671c7335f253a8f991c3a0852f584c5.png

OpenCV 4提供了用于计算Hu矩的HuMoments()函数,根据参数类型的不同该函数具有两种原型。在代码清单7-30中给出这两种函数原型。

代码清单7-30 HuMoments()函数原型void cv::HuMoments(const Moments &  moments,                   double  hu[7]                    )	void cv::HuMoments(const Moments &  m,                   OutputArray  hu                    )
  • moments:输入的图像矩
  • hu[7]:输出Hu矩的七个值
  • m:输入的图像矩
  • hu:输出Hu矩的矩阵

该函数可以根据图像的中心距计算图像的Hu矩。两个函数原型只有第二个参数的数据类型不同,第一个参数是输入图的Moments类的图像矩,第二个参数是输出的Hu矩,第一种函数原型输出值存放在长度为7的double类型数组中,第二种函数原型输出值为Mat类型。

为了了解函数的使用方法,在代码清单7-31中给出了计算图像Hu的示例程序,程序的部分运行结果如图7-25所示。

代码清单7-31 myHuMoments.cpp计算图像的Hu矩#include #include #include using namespace cv;using namespace std;int main(){	system("color F0");  //更改输出界面颜色	Mat img = imread("approx.png");	if (img.empty())	{		cout << "请确认图像文件名称是否正确" << endl;		return -1;	}	// 二值化	Mat gray, binary;	cvtColor(img, gray, COLOR_BGR2GRAY);	threshold(gray, binary, 105, 255, THRESH_BINARY);	//开运算消除细小区域	Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));	morphologyEx(binary, binary, MORPH_OPEN, k);	// 轮廓发现	vector> contours;	vector hierarchy;	findContours(binary, contours, hierarchy, 0, 2, Point());	for (int n = 0; n < contours.size(); n++)	{		Moments M;		M = moments(contours[n], true);		Mat hu;		HuMoments(M, hu);  //计算Hu矩		cout << hu << endl;	}	return 0;}
bfbbe38b28ad11df5a30f8a22120b676.png
图7-25 myHuMoments.cpp程序部分运行结果

基于Hu矩的轮廓匹配

Hu矩具有旋转、平移和比例不变性,因此可以通过Hu实现图像轮廓的匹配。OpenCV 4提供了利用Hu矩进行轮廓匹配的matchShapes()函数,该函数的函数原型在代码清单7-32中给出。

代码清单7-32 matchShapes()函数原型double cv::matchShapes(InputArray  contour1,                       InputArray  contour2,                       int  method,                       double  parameter                        )
  • contour1:原灰度图像或者轮廓
  • contour2:模板图像或者轮廓
  • method:匹配方法的标志,可以选择的参数及含义在表7-6给出。
  • parameter:特定于方法的参数(现在不支持)

该函数用于实现在图像或者轮廓中寻找与模板图像或者轮廓像素匹配的区域。函数的第一个参数是原灰度图像或者轮廓,第二个参数是模板图像或者轮廓。函数第三个参数是两个轮廓Hu矩匹配的计算方法标志,可以选择的参数和每种方法相似性计算公式在表7-6给出。函数最后一个参数在目前的OpenCV 4版本中没有意义,可以将参数设置为0。

表7-6 matchShapes()函数中匹配方法的标志
标志参数简记原理
CONTOURS_MATCH_I11
CONTOURS_MATCH_I22
CONTOURS_MATCH_I33

为了了解函数的用法,在代码清单7-33中给出了利用Hu矩实现模板与原图像或者轮廓之间匹配的示例程序。程序中原图像有三个字母,模板图像有一个字母,并且模板图像中字母的尺寸小于原图像中字母的尺寸。通过对两张图像提取轮廓并计算每个轮廓的Hu矩,之后寻找原图像和模板图像中Hu矩最相似的两个轮廓,并在原图像中绘制出相似轮廓,程序运行结果在图7-26给出。

代码清单7-33 myMatchShapes.cpp基于Hu矩的轮廓匹配#include #include #include using namespace cv;using namespace std;void findcontours(Mat &image, vector> &contours){	Mat gray, binary;	vector hierarchy;	//图像灰度化	cvtColor(image, gray, COLOR_BGR2GRAY);	//图像二值化	threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);	//寻找轮廓	findContours(binary, contours, hierarchy, 0, 2);}int main(){	Mat img = imread("ABC.png");	Mat img_B = imread("B.png");	if (img.empty() || img_B.empty())	{		cout << "请确认图像文件名称是否正确" << endl;		return -1;	}	resize(img_B, img_B, Size(), 0.5, 0.5);	imwrite("B.png", img_B);	imshow("B", img_B);	// 轮廓提取	vector> contours1;	vector> contours2;	findcontours(img, contours1);	findcontours(img_B, contours2);	// hu矩计算	Moments mm2 = moments(contours2[0]);	Mat hu2;	HuMoments(mm2, hu2);	// 轮廓匹配	for (int n = 0; n < contours1.size(); n++)	{		Moments mm = moments(contours1[n]);		Mat hum;		HuMoments(mm, hum);		//Hu矩匹配		double dist;		dist = matchShapes(hum, hu2, CONTOURS_MATCH_I1, 0);		if (dist < 1)		{			drawContours(img, contours1, n, Scalar(0, 0, 255), 3, 8);		}	}	imshow("match result", img);	waitKey(0);	return 0;}
5f323f913c9d897c835c8aa923d1e299.png
图7-26 myMatchShapes.cpp程序运行结果
从零学习OpenCV 4往期推荐

【从零学习OpenCV 4】Windows系统中安装OpenCV 4

【从零学习OpenCV 4】Ubuntu系统中安装OpenCV 4

【从零学习OpenCV 4】opencv_contrib扩展模块的安装

【从零学习OpenCV 4】Mat类介绍

【从零学习OpenCV 4】Mat类构造与赋值

【从零学习OpenCV 4】Mat类支持的运算

【从零学习OpenCV 4】这4种读取Mat类元素的的方法你都知道么?

【从零学习OpenCV 4】namedWindow函数&imshow函数的使用

【从零学习OpenCV 4】颜色模型与转换

【从零学习OpenCV 4】多通道分离与合并

【从零学习OpenCV 4】图像像素统计

【从零学习OpenCV 4】两图像间的像素操作

【从零学习OpenCV 4】图像二值化

【从零学习OpenCV 4】LUT查找表

【从零学习OpenCV 4】图像仿射变换

【从零学习OpenCV 4】图像透视变换

【从零学习OpenCV 4】极坐标变换

【从零学习OpenCV 4】绘制几何图形

【从零学习OpenCV 4】图像金字塔

【从零学习OpenCV 4】创建图像窗口滑动条

【从零学习OpenCV 4】鼠标响应

【从零学习OpenCV 4】图像直方图绘制

【从零学习OpenCV 4】直方图归一化

【从零学习OpenCV 4】直方图比较

【从零学习OpenCV 4】直方图均衡化

【从零学习OpenCV 4】直方图匹配

【从零学习OpenCV 4】图像卷积

【从零学习OpenCV 4】图像中添加椒盐噪声

【从零学习OpenCV 4】图像中添加高斯噪声

【从零学习OpenCV 4】均值滤波

【从零学习OpenCV 4】方框滤波

【从零学习OpenCV 4】高斯滤波

【从零学习OpenCV 4】双边滤波

【从零学习OpenCV 4】边缘检测原理

【从零学习OpenCV 4】Sobel算子 

【从零学习OpenCV 4】Scharr算子

【从零学习OpenCV 4】Laplacian算子

【从零学习OpenCV 4】Canny算法

【从零学习OpenCV 4】图像距离变换

【OpenCV 4开发详解】图像连通域分析

……

经过几个月的努力,市面上第一本OpenCV 4入门书籍《从零学习OpenCV 4》将春节后由人民邮电出版社发行。如果小伙伴觉得内容有帮助,希望到时候多多支持!
关注小白的小伙伴可以提前看到书中的内容,我们创建了学习交流群,欢迎各位小伙伴添加小白微信加入交流群,添加小白时请备注“学习OpenCV 4”。
8e3279c2ab728ea692acd2348e274d53.png
65cb8c909370aaf2e726cf54f056cb9e.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值