32-图形矩(Image Moments)
图形矩(Image Moments)- 求取图像质心,面积,长度
1、矩的概念;
2、API;
3、Code;
图形矩
1、几何矩: P(x,y) —像素值, x , y x,y x,y表示像素点的位置,有各阶矩;
2、中心距: m u ( j i ) mu_(ji) mu(ji);
3、中心归一化距: n u ( j i ) nu_(ji) nu(ji)
4、中心距与中心归一化距是几何矩的变种,矩用来对二值图像的轮廓进行计算从而得到图像的轮廓特征; 弧矩(用来进行模式识别)…还有很多其他的矩;
5、图像中心Center: 与对象的位置有关系,是对象的质心位置;
注: 这些值存储在Moment数据结构中
API
计算长度,面积,质心(实现图像的对象测量)
1、图像矩计算API : cv::moments()
: 求出图像从1阶到3阶的所有图像矩;
array : 输入数据为findContours()计算出来的数据
2、面积计算API : contourArea()
: 计算对象的面积;
3、弧长计算API : arcLength()
: 计算对象轮廓的弧长(长度);
使用步骤
1、提取图像边缘(Canny算法);
2、发现轮廓;
3、计算每个轮廓图像的矩;
4、计算每个图像的中心,弧长,面积;
Code
注意: findContours找到的图像轮廓有很多,应使用for循环将轮廓数据进行全部处理
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Mat src, gray_src;
int threshold_value = 50;
int threshold_max = 255;
const char *OUTPUT_WIN = "image moment demo";
const char *INPUT_WIN = "input image";
RNG rng(12345);
void Moments_Demo(int, void*);
int main(int argc, char** argv)
{
src = imread("C:\\Users\\hello\\Desktop\\24.jpg");
if (src.empty())
{
cout << "could not load the image..." << endl;
return -1;
}
cvtColor(src, gray_src, CV_BGR2GRAY);
GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0); //降低图像的噪声,Canny算法对噪声比较敏感
namedWindow(INPUT_WIN, WINDOW_AUTOSIZE);
namedWindow(OUTPUT_WIN, WINDOW_AUTOSIZE);
imshow(INPUT_WIN, gray_src);
createTrackbar("Threshold value: ", INPUT_WIN, &threshold_value, threshold_max, Moments_Demo);
Moments_Demo(threshold_value, 0);
waitKey(0);
return 0;
}
void Moments_Demo(int, void*)
{
Mat canny_output;
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
//边缘检测
Canny(gray_src, canny_output, threshold_value, threshold_value * 2, 3, false); //Sobel算子的大小3
//发现轮廓
findContours(canny_output, contours, RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(-1, -1));
//对每个轮廓计算矩 初始化一下大小
vector<Moments> contours_moments(contours.size());
vector<Point2f> ccs(contours.size()); //中心位置
for (size_t i = 0; i < contours.size(); i++)
{
if (contours[i].size() < 30) //轮廓像素点少的不打印
{
continue;
}
contours_moments[i] = moments(contours[i], true); //以函数返回值形式返回图形矩
ccs[i] = Point(static_cast<float>(contours_moments[i].m10 / contours_moments[i].m00),
static_cast<float>(contours_moments[i].m01 / contours_moments[i].m00)); //质心位置
}
//绘制中心位置
//Mat drawImage = Mat::zeros(src.size(), CV_8UC3);
Mat drawImage;
src.copyTo(drawImage);
for (size_t i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
printf("center point x : %.2f , y : %.2f\n", ccs[i].x, ccs[i].y);
printf("contours %d area : %.2f ; arc length : %.2f\r\n",
i, contourArea(contours[i], false), arcLength(contours[i], true));
circle(drawImage, ccs[i],2, color, 2, LINE_8); //圈出质心
drawContours(drawImage, contours, i, color,2, LINE_8, hierarchy, 0, Point(0, 0)); //层次结构给hierarchy
}
imshow(OUTPUT_WIN, drawImage); //显示图像
}
效果
图形矩可以有效的计算出图片中对象的面积,质心,长度数据: