引言:
矩的概念介绍
矩函数在图像分析中有着广泛的应用,如模式识别、目标分类、目标识别与方位估计、图像的编码与重构等。从一幅图像计算出来的矩集,不仅可以描述图像形状的全局特征,而且可以提供大量关于该图像不同的几何特征信息,如大小,位置、方向和形状等。图像矩这种描述能力广泛应用于各种图像处理、计算机视觉和机器人技术领域的目标识别与方位估计中。
一阶矩:与形状有关;
二阶矩:显示曲线围绕直线平均值的扩展程度;
三阶矩:关于平均值的对称性测量;由二阶矩和三阶矩可以导出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);
}
}
}
效果如下:
待检测图像与其二值图像:
模板图像与其二值图像:
匹配程度最高的轮廓: