相关理论
几何矩
-
几何矩 M j i = ∑ x , y ( P ( x , y ) ⋅ x j ⋅ y i ) M_{j i}=\sum_{x, y}\left(P(x, y) \cdot x^{j} \cdot y^{i}\right) Mji=∑x,y(P(x,y)⋅xj⋅yi),其中(i+j)和等于几就叫做几阶距
-
中心距 m u j i = ∑ x , y ( P ( x , y ) ⋅ ( x − x ˉ ) j ⋅ ( y − y ˉ ) i ) m u_{j i}=\sum_{x, y}\left(P(x, y) \cdot(x-\bar{x})^{j} \cdot(y-\bar{y})^{i}\right) muji=∑x,y(P(x,y)⋅(x−xˉ)j⋅(y−yˉ)i),其中 x ˉ , y ˉ \bar{x}, \bar{y} xˉ,yˉ表示它的中心质点。
-
中心归一化距 n u j i = m u j i m 00 ( i + j ) / 2 + 1 \mathrm{nu}_{j i}=\frac{\mathrm{mu}_{j i}}{\mathrm{m}_{00}^{(i+j) / 2+1}} nuji=m00(i+j)/2+1muji
-
矩的概念介绍
- 图像中心Center(x0,y0)
x 0 = m 10 m 00 y 0 = m 01 m 00 \mathrm{x}_{0}=\frac{m_{10}}{m_{00}} y_{0}=\frac{m_{01}}{m_{00}} x0=m00m10y0=m00m01
- 图像中心Center(x0,y0)
-
API介绍与使用-计算矩cv::moments
moments(
InputArray array,//输入数据
bool binaryImage=false // 是否为二值图像
)
contourArea(
InputArray contour,//输入轮廓数据
bool oriented// 默认false、返回绝对值
)
arcLength(
InputArray curve,//输入曲线数据
bool closed// 是否是封闭曲线
)
代码 & 效果展示
- 演示代码 - 步骤
- 提取图像边缘
- 发现轮廓
- 计算每个轮廓对象的矩
- 计算每个对象的中心、弧长、面积
相关代码:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
using namespace std;
using namespace cv;
#ifndef P31
#define P31 31
#endif
#if P31 //图形矩形
Mat src, gray_src;
int threshold_value = 80;
int threshold_max = 255;
const char* output_win = "image moents demo";
RNG rng(12345);
void Demo_Moments(int, void*) {
Mat canny_output;
vector<vector<Point>> contours;
vector<Vec4i> hierachy;
Canny(gray_src, 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]);
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 drawImg;// = Mat::zeros(src.size(), CV_8UC3);
src.copyTo(drawImg);
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\n", ccs[i].x, ccs[i].y);
printf("contours %d area : %.2f arc length : %.2f\n", i, contourArea(contours[i]), arcLength(contours[i], true));
drawContours(drawImg, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));
circle(drawImg, ccs[i], 2, color,2, 8);
}
imshow(output_win, drawImg);
return;
}
#endif
int main() {
std::string path = "../circle.JPG";
cv::Mat img = cv::imread(path, 5);
string str_input = "input image";
string str_output = "output image";
if (img.empty()) {
std::cout << "open file failed" << std::endl;
return -1;
}
namedWindow(str_input, WINDOW_AUTOSIZE);
namedWindow(str_output, WINDOW_AUTOSIZE);
imshow(str_input, img);
#if P31
src = img;
cvtColor(src, gray_src, CV_BGR2GRAY);
GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);
char input_win[] = "input image";
namedWindow(input_win, WINDOW_AUTOSIZE);
namedWindow(output_win, WINDOW_AUTOSIZE);
imshow(input_win, src);
createTrackbar("Threshold Value : ", output_win, &threshold_value, threshold_max, Demo_Moments);
Demo_Moments(0, 0);
#endif
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
展示效果: