矩函数常用于模式识别、目标分类、目标标识和方位估计及图像编码与重构等,图像矩通常包含了图像形状的全局特征,如大小,位置,方向,形状等。其中,一阶矩与形状有关,二阶矩显示曲线围绕直线平均值的扩展成都,三阶矩则是关于平均值的对称性的测量。
在opencv中一般由moments、contourArea、ARCLength这三个函数配合求一个图像的矩。
其中,moments计算图像所有的矩(最高到3阶);
contourArea计算轮廓面积;
arcLength计算轮廓或曲线长度。
moments:
Moments cv::moments | ( | InputArray | array, //输入参数可以是单通道,8位或浮点的二维数组 |
bool | binaryImage = false | ||
) |
contourArea:
double cv::contourArea | ( | InputArray | contour, //输入的向量,二维点(轮廓顶点) |
bool | oriented = false | ||
) |
arcLength:
double cv::arcLength | ( | InputArray | curve,//输入的二维点集vector或Mat类型 |
bool | closed //表示曲线是否封闭的标识符 | ||
) |
案例:
#include<iostream>
#include<opencv2/imgproc.hpp>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Administrator/Desktop/3.png");
if (src.empty())
{
cout << "请检查图像是否存在..." << endl;
return -1;
}
namedWindow("src");
imshow("src", src);
Mat grayimg;
cvtColor(src, grayimg, COLOR_BGR2GRAY);
blur(grayimg, grayimg, Size(5, 5));
vector<vector<Point>>contours;
vector<Vec4i>hierarchy;
Mat edgeimg;
int thresh = 100;
int thresh_max = 255;
Canny(grayimg, edgeimg, thresh, thresh * 2, 3);
//轮廓查找
findContours(edgeimg, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
//计算矩
vector<Moments>mu(contours.size());
for (unsigned int i = 0; i < contours.size(); i++)
{
mu[i] = moments(contours[i], false);
}
//计算中心矩
vector<Point2f>mc(contours.size());
for (unsigned 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));
}
//绘制轮廓
Mat drawimg = Mat::zeros(edgeimg.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++)
{
//绘制外层和内层轮廓
drawContours(drawimg, contours, i, Scalar(122, 160, 144), 2, 8, hierarchy, 0, Point(0, 0));
//绘制圆
circle(drawimg, mc[i], 4, Scalar(122, 160, 144), -1, 8, 0);
}
namedWindow("drawimg");
imshow("drawimg", drawimg);
通过m00计算轮廓面积并和opencv函数比较
//cout << "------------" << endl;
//for (unsigned int i = 0; i < contours.size(); i++)
//{
// printf("m00计算%d面积:m00=%.2f \n opencv计算面积=%.2f,长度=%.2f\n\n", i, mu[i].m00, contourArea(contours[i]), arcLength(contours[i], true));
// drawContours(drawimg, contours, i, Scalar(120, 140, 160), 2, 8, hierarchy, 0, Point());
// circle(drawimg, mc[i], 4, Scalar(120, 140, 160), -1, 8, 0);
//}
//通过m00计算轮廓面积
cout << "------------" << endl;
for (unsigned int i = 0; i < contours.size(); i++)
{
printf("m00计算%d面积:m00=%.2f", i, mu[i].m00);
drawContours(drawimg, contours, i, Scalar(120, 140, 160), 2, 8, hierarchy, 0, Point());
circle(drawimg, mc[i], 4, Scalar(120, 140, 160), -1, 8, 0);
}
waitKey(0);
return 0;
}
结果展示: