花老湿学习OpenCV:图像矩与轮廓匹配

引言:

矩的概念介绍

       矩函数在图像分析中有着广泛的应用,如模式识别、目标分类、目标识别与方位估计、图像的编码与重构等。从一幅图像计算出来的矩集,不仅可以描述图像形状的全局特征,而且可以提供大量关于该图像不同的几何特征信息,如大小,位置、方向和形状等。图像矩这种描述能力广泛应用于各种图像处理、计算机视觉和机器人技术领域的目标识别与方位估计中。

一阶矩:与形状有关;

二阶矩:显示曲线围绕直线平均值的扩展程度;

三阶矩:关于平均值的对称性测量;由二阶矩和三阶矩可以导出7个不变矩。而不变矩是图像的统计特性,满足平移、伸缩、旋转均不变的不变性、在图像识别领域得到广泛的应用。

API:

1.moments()用于计算多边形和光栅形状的最高达三阶的所有矩。矩用来计算形状的重心、面积,主轴和其他形状特征,如7Hu不变量等。

 

 

2.contourArea()用于计算整个轮廓或部分轮廓的面积。

 

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

4. matchShapes()比较轮廓是基于Hu矩计算的,结果越小相似度越高。

 

代码示例:


#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int thresholdval = 8;
int thresholdmax = 255;

int mode = 0;
void Moments_demo(int pos, void* userdata);

Mat src;
Mat blursrc;
RNG rng(getTickCount());

int main()
{
	//待检测图像
	src = imread("F:\\visual studio\\Image\\gesture1.jpg");
	if (src.empty())
	{
		cout << "Can't load the image" << endl;
		return -1;
	}
	imshow("src", src);
	
	//转化为灰度图
	Mat graysrc;
	cvtColor(src, graysrc, COLOR_BGR2GRAY);

	//高斯模糊
	GaussianBlur(graysrc, blursrc, Size(3, 3), 0, 0);

	namedWindow("dst", WINDOW_AUTOSIZE);
	createTrackbar("Threshold", "dst", &thresholdval, thresholdmax, Moments_demo);
	createTrackbar("mode", "dst", &mode, 3, Moments_demo);
	Moments_demo(0, 0);
	
	waitKey(0);

}

void Moments_demo(int pos, void* userdata)
{
	//阈值化
	Mat bin;
	threshold(~blursrc, bin, thresholdval, thresholdmax, CV_THRESH_BINARY);
	imshow("bin", bin);

	//轮廓检测
	vector<vector<Point>> Contours;
	vector<Vec4i> hierachy;
	findContours(bin, Contours, hierachy, mode, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

	//轮廓绘制
	Mat dst = Mat::zeros(src.size(), CV_8UC3);
	for (int i = 0; i < Contours.size(); i++)
	{
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(dst, Contours, i, color, 2, LINE_AA);
	}
	

	//计算矩
	vector<Moments> mu(Contours.size());
	for (int i = 0; i < Contours.size(); i++)
	{
		mu[i]=moments(Contours[i], true);
	}
	
	vector<Point2f> mc(Contours.size());
	for (int i = 0; i < Contours.size(); i++)
	{
		//计算中心并绘制
		mc[i] = Point2f(static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m01 / mu[i].m00));
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		circle(dst, mc[i], 2, color, FILLED, LINE_AA);
		//计算轮廓面积与长度
		double area = contourArea(Contours[i],true);
		double length = arcLength(Contours[i], true);
		cout << "contours " << i << " : <m00> =  " << mu[i].m00 << " Area = " << contourArea(Contours[i]) << " Arc length = " << arcLength(Contours[i], true) << endl;
	}
	imshow("dst", dst);	
}

效果展示:

源图像与二维图像:

画出轮廓、根据图像矩的值计算并绘制出中心点、计算轮廓的面积与长度。

 

 

#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int thresholdval = 8;
int thresholdmax = 255;

int mode = 0;
void Moments_demo(int pos, void* userdata);

Mat src;
Mat temp;
Mat blursrc;
Mat blurtemp;

RNG rng(getTickCount());

int main()
{
	//待检测图像
	src = imread("F:\\visual studio\\Image\\gesture1.jpg");
	if (src.empty())
	{
		cout << "Can't load the image" << endl;
		return -1;
	}
	resize(src, src, Size(), 1, 0.8);
	//imshow("src", src);
	//转化为灰度图
	Mat graysrc;
	cvtColor(src, graysrc, COLOR_BGR2GRAY);

	//高斯模糊
	GaussianBlur(graysrc, blursrc, Size(3, 3), 0, 0);

    imshow("src", src);

	//模板图像
	temp = imread("F:\\visual studio\\Image\\temp.jpg");
	if (temp.empty())
	{
		cout << "Can't load the image" << endl;
		return -1;
	}
	imshow("temp", temp);
	
	//转化为灰度图
	Mat graytemp;
	cvtColor(temp, graytemp, COLOR_BGR2GRAY);
	//高斯模糊
	GaussianBlur(graytemp, blurtemp, Size(3, 3), 0, 0);
	
	namedWindow("dst", WINDOW_AUTOSIZE);
	createTrackbar("Threshold", "dst", &thresholdval, thresholdmax, Moments_demo);
	createTrackbar("mode", "dst", &mode, 3, Moments_demo);
	Moments_demo(0, 0);

	waitKey(0);

}

void Moments_demo(int pos, void* userdata)
{
	//阈值化
	Mat binsrc;
	threshold(~blursrc, binsrc, thresholdval, thresholdmax, CV_THRESH_BINARY);
	imshow("binsrc", binsrc);

	//轮廓检测
	vector<vector<Point>> Contours1;
	vector<Vec4i> hierachy1;
	findContours(binsrc, Contours1, hierachy1, mode, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

	//轮廓绘制
	//Mat dst = Mat::zeros(src.size(), CV_8UC3);
	//for (int i = 0; i < Contours1.size(); i++)
	//{
	//	Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
	//	drawContours(dst, Contours1, i, color, 2, LINE_AA);
	//}

	
	Mat bintemp;
	threshold(~blurtemp, bintemp, thresholdval, thresholdmax, CV_THRESH_BINARY);
	imshow("bintemp", bintemp);

	//轮廓检测
	vector<vector<Point>> Contours2;
	vector<Vec4i> hierachy2;
	findContours(bintemp, Contours2, hierachy2, mode, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

	//轮廓绘制
	Mat dst = Mat::zeros(src.size(), CV_8UC3);
	//for (int i = 0; i < Contours2.size(); i++)
	//{
	//	Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
	//	drawContours(dst, Contours2, i, color, 2, LINE_AA);
	//}

	cout << Contours2.size() << endl;

	for (int i = 0; i < Contours2.size(); i++)
	{
		for (int j = 0; j < Contours1.size(); j++)
		{
			double matchRate = matchShapes(Contours2[i], Contours1[j], CV_CONTOURS_MATCH_I1, 0.0);
			cout << matchRate << endl;
			if (matchRate <= 0.01)
			{
				drawContours(dst, Contours1, j, Scalar(0, 255, 0), 2, 8);
			}
			imshow("dst", dst);
		}
	}
}

效果如下: 

待检测图像与其二值图像:

 

模板图像与其二值图像: 

匹配程度最高的轮廓: 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值