三十、图像矩(Image Moments)
1、矩的概念介绍
- 几何矩
- 几何矩
- 中心矩
- 中心归一化矩
- 轮廓中心
C
e
n
t
e
r
(
x
0
,
y
0
)
Center(x_0, y_0)
Center(x0,y0)
x 0 x_0 x0 = m 10 m 00 \frac{m10}{m~00~} m 00 m10
y 0 y_0 y0 = m 01 m 00 \frac{m01}{m~00~} m 00 m01
2、API介绍与使用cv::moments
计算生成数据
- 得到的结果是存储了几何矩、中心距、中心归一化矩的结果
moments(
InputArray array,//输入数据
bool binaryImage=false//是否为二值图像
)
- 得到轮廓的面积
contourArea(
InputArray contour,//输入轮廓数据
bool oriented//默认false,返回绝对值
)
- 得到曲线的弧长
arcLength(
InputArray curve,//输入曲线数据
bool closed//是否是封闭曲线
)
3、步骤
- 转灰度
cvtColor
- 提取图像边缘
Canny
- 发现轮廓
findContours
- 计算每个轮廓对象的矩
moments
- 计算每个对象的中心、弧长、面积
contourArea
arcLength
示例代码:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int threshold_value = 80;
int threshold_max = 255;
RNG rng(12345);
void Threshold_Callback(int, void*);
char output_win[] = "rectangle demo";
Mat src, dst, src_gray;
int main (int argc, char** argv) {
src = imread("添加图片路径");
if (!src.data) {
cout << "could not load image..." << endl;
return -1;
}
imshow("input image", src);
namedWindow(output_win, WINDOW_AUTOSIZE);
cvtColor(src, src_gray, COLOR_BGR2GRAY);
GaussianBlur(src_gray, src_gray, Size(3, 3),0,0);
createTrackbar("Threshold Value:", output_win, &threshold_value, threshold_max, Threshold_Callback);
Threshold_Callback(0, 0);
waitKey(0);
return 0;
}
void Threshold_Callback(int, void*) {
Mat canny_output;
vector<vector<Point>> contours;
vector<Vec4i> hierachy;
Canny(src_gray, canny_output, threshold_value, threshold_value * 2, 3, false);
findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
vector<Moments> contours_moments(contours.size());
vector<Point2f> ccs(contours.size());
for (size_t i = 0; i < contours.size(); i++) {
contours_moments[i] = moments(contours[i]);//获得第i个轮廓的矩
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));//计算轮廓的中心坐标
}
src.copyTo(dst);
for (size_t i = 0; i < contours.size(); i++) {
if (contours[i].size() < 100) {//设置一个阈值,当轮廓点数大于某个阈值时,才视为轮廓
continue;
}
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
printf("center point x : %.2f y : %.2f", ccs[i].x, ccs[i].y);
printf("contours %d area : %.2f arc length : %.2f\n", i, contourArea(contours[i]), arcLength(contours[i], true));//计算轮廓的面积和弧长
drawContours(dst, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));
circle(dst, ccs[i], 2, color, 2, 8);
char buffer[20];
sprintf_s(buffer, "(%.2f,%.2f)", ccs[i].y, ccs[i].x);
putText(dst, buffer, Point(ccs[i].x, ccs[i].y), FONT_HERSHEY_COMPLEX, 0.5, Scalar(0, 0, 255), 1, 8);//绘制圆心坐标
}
imshow(output_win, dst);
return ;
}
输出结果显示:
分析:根据图像矩,可以获得图像轮廓的中心坐标以及其对应的轮廓面积及弧长。