矩:主要指几何矩 Mji = ∑ (P(x,y) · x^j · y^i) 其中 (i+j) 和等于几就是几阶矩,P(x,y)表示图像x,y坐标位置的像素值,i j 为变量
x,y
还有中心矩(MUji), 中心归一化矩(NUji) 它们不考虑0阶,1阶?
图像中心 Center(x0, y0) x0 = M10 / M00 , y0 = M01 / M00 此非图像坐标的中心点,而是图像 质 的中心,质点
moments( // 计算矩,返回 0阶到3阶所有的几何矩,2阶到3阶所有的中心矩,2阶到3阶所有的中心归一矩
InputArray array, // 输入数据,findContours 找到的轮廓数据
bool binaryImage=false // 是否为二值图像
)
contourArea( // 求轮廓面积
InputArray contour, // 输入轮廓数据
bool oriented // 默认false、返回绝对值
)
arcLength( // 求轮廓弧长
InputArray curve, // 输入曲线数据
bool closed // 是否是封闭曲线
)
步骤:
提取图像边缘
发现轮廓
计算每个轮廓对象的矩
计算每个对象的中心、弧长、面积
代码
#include "../common/common.hpp"
static Mat src, gray_src;
static int threshold_value = 80;
static int threshold_max = 255;
static const char* title = "moments";
static RNG rng(12345);
static void m_moments(int, void*);
void main(int argc, char** argv)
{
src = imread(getCVImagesPath("images/circle.png"), IMREAD_COLOR);// redball.png
imshow("src32", src);
cvtColor(src, gray_src, CV_BGR2GRAY);
GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);//这里用高斯模糊去噪,相比于均值,轮廓发现的准确
namedWindow(title, CV_WINDOW_AUTOSIZE);
createTrackbar("rect round:", title, &threshold_value, threshold_max, m_moments);
m_moments(0, 0);
waitKey(0);
}
void m_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++) {
//计算矩,返回 0阶到3阶所有的几何矩,2阶到3阶所有的中心矩,2阶到3阶所有的中心归一矩
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) { // 点数小于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(title, drawImg);
}
效果图