1 几何矩和中心距
矩:描述图像特征的算子,广泛应用于图像检索和识别,图像匹配,图像重建,图像压缩以及运动图像序列分析等领域。
几何矩 :
I(x,y)是像素(x,y)处的像素值。i、j同时为0时,称为零阶矩,零阶矩可用于计算某个形状的质心。i、j分别取0和1时,称为一阶矩,以此类推。
图像质心:
中心距:
归一化中心距:
moments(contours[t], true)
输入:图像或者二维坐标集合
输出:Moments类型的变量,含有几何矩、中心距、归一化中心距的数值属性
#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
#include<math.h>
#include <opencv2/imgproc.hpp>
#include<vector>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
//QuickDemo qd;
//qd.myFilter_demo(src);
system("color F0");
Mat img = imread("D:/images/hand.jpg");
imshow("img", img);
resize(img, img, Size(img.cols / 3, img.rows / 3), 0, 0, INTER_LINEAR);
if (img.empty()) {
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat gary, binary;
cvtColor(img, gary, COLOR_BGR2GRAY);
//GaussianBlur(gary, gary, Size(9, 9), 2, 2);
threshold(gary, binary, 105, 255, THRESH_BINARY);
//开运算消除细小区域
Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
morphologyEx(binary, binary, MORPH_OPEN, k);
imshow("binary", binary);
//轮廓发现与绘制
vector<vector<Point>> contours; //轮廓
vector<Vec4i> hierarchy; //存放轮廓结构变量
findContours(binary, contours, hierarchy, 0, 2, Point());
for (int t = 0; t < contours.size(); t++) {
Moments M;
M = moments(contours[t], true);
cout << "spatial moment:" << endl
<< " m00:" << M.m00 << " m01:" << M.m01 << " m10:" << M.m10 << endl
<< " m11:" << M.m11 << " m02:" << M.m02 << " m20 : " << M.m20 << endl
<< " m12:" << M.m12 << " m21:" << M.m21 << " m03:" << M.m03 << " m30:" << M.m30 << endl;
cout << "central moment:" << endl
<< " mu20:" << M.mu20 << " mu02:" << M.mu02 << " mu11:" << M.mu11 << endl
<< " mu30:" << M.mu30 << " mu21:" << M.mu21 << " mu12:" << M.mu12 << " mu03:" << M.mu03 << endl;
cout << "central normalized moment:" << endl
<< " nu20:" << M.nu20 << " nu02:" << M.nu02 << " nu11:" << M.nu11 << endl
<< " nu30:" << M.nu30 << " nu21:" << M.nu21 << " nu12:" << M.nu12 << " nu03:" << M.nu03 << endl;
}
//waitKey(0);
//destroyAllWindows();
return 0;
}
2 Hu矩
特点:具有旋转、平移、缩放不变性,应用更广
Hu矩是由二阶、三阶中心距计算得到的7个不变矩
HuMoments(M, hu)
输入:Moments类型的图像矩
输出:长度为7的double类型的数组或者Mat类型 的不变矩
#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
#include<math.h>
#include <opencv2/imgproc.hpp>
#include<vector>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
//QuickDemo qd;
//qd.myFilter_demo(src);
system("color F0");
Mat img = imread("D:/images/hand.jpg");
imshow("img", img);
resize(img, img, Size(img.cols / 3, img.rows / 3), 0, 0, INTER_LINEAR);
if (img.empty()) {
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat gary, binary;
cvtColor(img, gary, COLOR_BGR2GRAY);
//GaussianBlur(gary, gary, Size(9, 9), 2, 2);
threshold(gary, binary, 105, 255, THRESH_BINARY);
//开运算消除细小区域
Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
morphologyEx(binary, binary, MORPH_OPEN, k);
imshow("binary", binary);
//轮廓发现与绘制
vector<vector<Point>> contours; //轮廓
vector<Vec4i> hierarchy; //存放轮廓结构变量
findContours(binary, contours, hierarchy, 0, 2, Point());
for (int t = 0; t < contours.size(); t++) {
Moments M;
M = moments(contours[t], true);
Mat hu;
HuMoments(M, hu);
cout << hu << endl;
}
//waitKey(0);
//destroyAllWindows();
return 0;
}
3 基于Hu矩的轮廓匹配
#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
#include<math.h>
#include <opencv2/imgproc.hpp>
#include<vector>
using namespace cv;
using namespace std;
void findcontours(Mat& img, vector<vector<Point>>& contours) {
Mat gary, binary;
cvtColor(img, gary, COLOR_BGR2GRAY);
//GaussianBlur(gary, gary, Size(9, 9), 2, 2);
threshold(gary, binary, 105, 255, THRESH_BINARY);
vector<Vec4i> hierarchy; //存放轮廓结构变量
findContours(binary, contours, hierarchy, 0, 2);
}
int main(int argc, char** argv) {
//QuickDemo qd;
//qd.myFilter_demo(src);
//system("color F0");
Mat img = imread("D:/images/ABC.png");
Mat img_B = imread("D:/images/B.png");
//resize(img, img, Size(img.cols / 3, img.rows / 3), 0, 0, INTER_LINEAR);
if (img.empty()|| img_B.empty()) {
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
imwrite("B.png", img_B);
imshow("B", img_B);
//轮廓提取
vector<vector<Point>> contours1;
vector<vector<Point>> contours2;
findcontours(img, contours1);
findcontours(img_B, contours2);
//Hu矩计算
Moments mm2 = moments(contours2[0]);
Mat hu2;
HuMoments(mm2, hu2);
//轮廓匹配
for (int t = 0; t < contours1.size(); t++) {
Moments mm;
mm = moments(contours1[t]);
Mat hum;
HuMoments(mm, hum);
//Hu矩匹配
double dist;
dist = matchShapes(hum, hu2, CONTOURS_MATCH_I1, 0);
if (dist < 1) {
drawContours(img, contours1, t, Scalar(0, 0, 255), 3, 8);
}
}
imshow("result", img);
waitKey(0);
//destroyAllWindows();
return 0;
}