一、数学中的矩
矩是概率与统计中的一个概念,假设有随机变量X,常数c,正整数k,则有
E[(X−c)k]称X为c 的k阶矩。
1.c=0->ak=E(Xk)称为X的k阶原点矩
2. c=E(X)。这时μk=E[(X−EX)k]称为X的k阶中心矩。
同理当随机变量是X 、Y的二维时候有如下:
1、A1=A2=0->上式称为X的p+q阶混合原点矩
2. A1=E(X),A2=E(Y)->上式称为X的p+q阶混合中心矩。
这里只说离散的情况。联系的不谈
二、图像中的几何矩
假设二维图像坐标(x,y)对应的p、q对应的公式:
三、Hu矩
Hu矩具有旋转、平移等不变性,所以Hu矩在图像中用的更加广泛,Hu矩是有二阶和三阶中心矩得到的七个不变矩,
原点矩:
中心矩:
归一化中心矩:
四、算子解释与使用
矩:moments()函数用于计算中心矩
moments(InputArray array, //计算矩的区域2D像素坐标集合或者单通道的CV_8U图像
bool binaryImage = false //是否将所有非0像素值视为1的标志
)
Hu矩:基于moments()的HuMoments
void HuMoments(
const Moments& moments, // moments即为上面一个函数计算得到的moments类型
double* hu // hu是一个含有7个数的数组,就是上面第三种说的7个不变矩)
利用Hu矩进行轮廓匹配的matchShapes()函数
double cv::matchShapes
(InputArray contour1, // 目标图像、轮廓
InputArray contour2, // 模板图像、轮廓
int method, // 匹配的方法: CONTOURS_MATCH_I1
CONTOURS_MATCH_I2
CONTOURS_MATCH_I3
double parameter
)
1、找到图像的质心和轮廓:
代码显示:
Mat src, gray_src;
int threshold_value = 80;
int max_threshold = 255;
const char* output_win = "resultImage";
const char* trackbar_title = "Threshold:";
void Callback_Moments(int, void*) {
vector<vector<Point>> contours;
vector<Vec4i> h;
Mat cannyImage;
//canny
Canny(gray_src, cannyImage, threshold_value, threshold_value * 2, 3, false);
imshow("Canny", cannyImage);
// 找轮廓
findContours(cannyImage, contours, h, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); // 找最外层的轮廓
// 找到轮廓个数个矩
vector<Moments> contours_moments(contours.size());
// 质心
vector<Point2f> centers(contours.size());
for (int i = 0; i < contours.size(); i++)
{
contours_moments[i] = moments(contours[i]);
centers[i] = Point(
(static_cast<float>(contours_moments[i].m10 / contours_moments[i].m00)), // x0
(static_cast<float>(contours_moments[i].m01 / contours_moments[i].m00)));//y0
}
printf("%d\n", contours.size());
// 画出轮廓和各个轮廓对应的质心
Mat resultImage;
cannyImage.copyTo(resultImage);
for (int i = 0; i < contours.size(); i++)
{
if (contourArea(contours[i]) < 1000) { // 轮廓的面积都是>1000的
continue;
}
printf("质心坐标 x : %.2f y : %.2f\n", centers[i].x, centers[i].y);
printf("contours %d area : %.2f arc length : %.2f\n", i, contourArea(contours[i]), arcLength(contours[i], true));
drawContours(resultImage, contours, i, Scalar(255, 255, 255), 2, 8, h, 0);
circle(resultImage, centers[i], 3, Scalar(255, 255, 255), 6, 8);
}
imshow(output_win, resultImage);
}
int main() {
src = imread("C:\\Users\\19473\\Desktop\\opencv_images\\513.png");
if (!src.data)
{
cout << "could not load image !";
waitKey(0);
return -1;
}
cvtColor(src, gray_src, CV_BGR2GRAY);
GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);
namedWindow(output_win, CV_WINDOW_AUTOSIZE);
imshow("原图", src);
createTrackbar("Threshold", output_win, &threshold_value, max_threshold, Callback_Moments);
Callback_Moments(0, 0);
waitKey(0);
return 0;
}
Hu矩的模板匹配:
int main() {
Mat template_A, src, gray_src,brinaryImage,brinaryImage_A, gray_src_A,result;
src = imread("C:\\Users\\19473\\Desktop\\opencv_images\\516.png");
template_A= imread("C:\\Users\\19473\\Desktop\\opencv_images\\517.png");
if (!src.data)
{
cout << "could not load image !";
waitKey(0);
return -1;
}
imshow("模板图像", template_A);
imshow("待找图像", src);
// 1.待测图像-- 灰度图像--》二值图像
cvtColor(src, gray_src, CV_BGR2GRAY);
GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);
threshold(gray_src,brinaryImage,10,255,THRESH_BINARY);
imshow("threshold", brinaryImage);
vector<vector<Point>> contours;
vector<Vec4i> h;// 拓补结构
// 2、查找轮廓
findContours(brinaryImage, contours, h, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
printf("待测图像的轮廓个数 : %d\n", contours.size());
// 3、模板图像处理
cvtColor(template_A, gray_src_A, CV_BGR2GRAY);
threshold(gray_src_A, brinaryImage_A, 10, 255, THRESH_BINARY);
imshow("A", brinaryImage_A);
vector<vector<Point>> contour_A;
vector<Vec4i> h_A;
findContours(brinaryImage_A, contour_A, h_A, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
int a = contour_A.size();
printf("模板图像的轮廓个数 : %d\n", a);
// 4 在待测图像中寻找
result = gray_src.clone();
Moments m_A = moments(contour_A[0]);
Mat m_A_hu;
HuMoments(m_A, m_A_hu);
for (int n = 0; n < contours.size(); n++)
{
Moments mm = moments(contours[n]);
Mat hum;
HuMoments(mm, hum);
//Hu矩匹配
double dist;
dist = matchShapes(hum, m_A_hu, CONTOURS_MATCH_I1, 0);
if (dist < 1)
{
drawContours(result, contours, n, Scalar(255,0, 255), 3, 8);
}
}
imshow("结果", result);
waitKey(0);
return 0;
}