引言:
矩的概念介紹
矩函數在圖像分析中有着廣泛的應用,如模式識别、目标分類、目辨別别與方位估計、圖像的編碼與重構等。從一幅圖像計算出來的矩集,不僅可以描述圖像形狀的全局特征,而且可以提供大量關于該圖像不同的幾何特征資訊,如大小,位置、方向和形狀等。圖像矩這種描述能力廣泛應用于各種圖像處理、計算機視覺和機器人技術領域的目辨別别與方位估計中。
一階矩:與形狀有關;
二階矩:顯示曲線圍繞直線平均值的擴充程度;
三階矩:關于平均值的對稱性測量;由二階矩和三階矩可以導出7個不變矩。而不變矩是圖像的統計特性,滿足平移、伸縮、旋轉均不變的不變性、在圖像識别領域得到廣泛的應用。

API:
1.moments()用于計算多邊形和光栅形狀的最高達三階的所有矩。矩用來計算形狀的重心、面積,主軸和其他形狀特征,如7Hu不變量等。
2.contourArea()用于計算整個輪廓或部分輪廓的面積。
3.arcLength()函數用于計算封閉輪廓的周長或曲線的長度
4. matchShapes()比較輪廓是基于Hu矩計算的,結果越小相似度越高。
代碼示例:
#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int thresholdval = 8;
int thresholdmax = 255;
int mode = 0;
void Moments_demo(int pos, void* userdata);
Mat src;
Mat blursrc;
RNG rng(getTickCount());
int main()
{
//待檢測圖像
src = imread("F:\\visual studio\\Image\\gesture1.jpg");
if (src.empty())
{
cout << "Can't load the image" << endl;
return -1;
}
imshow("src", src);
//轉化為灰階圖
Mat graysrc;
cvtColor(src, graysrc, COLOR_BGR2GRAY);
//高斯模糊
GaussianBlur(graysrc, blursrc, Size(3, 3), 0, 0);
namedWindow("dst", WINDOW_AUTOSIZE);
createTrackbar("Threshold", "dst", &thresholdval, thresholdmax, Moments_demo);
createTrackbar("mode", "dst", &mode, 3, Moments_demo);
Moments_demo(0, 0);
waitKey(0);
}
void Moments_demo(int pos, void* userdata)
{
//門檻值化
Mat bin;
threshold(~blursrc, bin, thresholdval, thresholdmax, CV_THRESH_BINARY);
imshow("bin", bin);
//輪廓檢測
vector<vector<Point>> Contours;
vector<Vec4i> hierachy;
findContours(bin, Contours, hierachy, mode, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
//輪廓繪制
Mat dst = Mat::zeros(src.size(), CV_8UC3);
for (int i = 0; i < Contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(dst, Contours, i, color, 2, LINE_AA);
}
//計算矩
vector<Moments> mu(Contours.size());
for (int i = 0; i < Contours.size(); i++)
{
mu[i]=moments(Contours[i], true);
}
vector<Point2f> mc(Contours.size());
for (int i = 0; i < Contours.size(); i++)
{
//計算中心并繪制
mc[i] = Point2f(static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m01 / mu[i].m00));
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
circle(dst, mc[i], 2, color, FILLED, LINE_AA);
//計算輪廓面積與長度
double area = contourArea(Contours[i],true);
double length = arcLength(Contours[i], true);
cout << "contours " << i << " : <m00> = " << mu[i].m00 << " Area = " << contourArea(Contours[i]) << " Arc length = " << arcLength(Contours[i], true) << endl;
}
imshow("dst", dst);
}
效果展示:
源圖像與二維圖像:
畫出輪廓、根據圖像矩的值計算并繪制出中心點、計算輪廓的面積與長度。
#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int thresholdval = 8;
int thresholdmax = 255;
int mode = 0;
void Moments_demo(int pos, void* userdata);
Mat src;
Mat temp;
Mat blursrc;
Mat blurtemp;
RNG rng(getTickCount());
int main()
{
//待檢測圖像
src = imread("F:\\visual studio\\Image\\gesture1.jpg");
if (src.empty())
{
cout << "Can't load the image" << endl;
return -1;
}
resize(src, src, Size(), 1, 0.8);
//imshow("src", src);
//轉化為灰階圖
Mat graysrc;
cvtColor(src, graysrc, COLOR_BGR2GRAY);
//高斯模糊
GaussianBlur(graysrc, blursrc, Size(3, 3), 0, 0);
imshow("src", src);
//模闆圖像
temp = imread("F:\\visual studio\\Image\\temp.jpg");
if (temp.empty())
{
cout << "Can't load the image" << endl;
return -1;
}
imshow("temp", temp);
//轉化為灰階圖
Mat graytemp;
cvtColor(temp, graytemp, COLOR_BGR2GRAY);
//高斯模糊
GaussianBlur(graytemp, blurtemp, Size(3, 3), 0, 0);
namedWindow("dst", WINDOW_AUTOSIZE);
createTrackbar("Threshold", "dst", &thresholdval, thresholdmax, Moments_demo);
createTrackbar("mode", "dst", &mode, 3, Moments_demo);
Moments_demo(0, 0);
waitKey(0);
}
void Moments_demo(int pos, void* userdata)
{
//門檻值化
Mat binsrc;
threshold(~blursrc, binsrc, thresholdval, thresholdmax, CV_THRESH_BINARY);
imshow("binsrc", binsrc);
//輪廓檢測
vector<vector<Point>> Contours1;
vector<Vec4i> hierachy1;
findContours(binsrc, Contours1, hierachy1, mode, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
//輪廓繪制
//Mat dst = Mat::zeros(src.size(), CV_8UC3);
//for (int i = 0; i < Contours1.size(); i++)
//{
// Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
// drawContours(dst, Contours1, i, color, 2, LINE_AA);
//}
Mat bintemp;
threshold(~blurtemp, bintemp, thresholdval, thresholdmax, CV_THRESH_BINARY);
imshow("bintemp", bintemp);
//輪廓檢測
vector<vector<Point>> Contours2;
vector<Vec4i> hierachy2;
findContours(bintemp, Contours2, hierachy2, mode, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
//輪廓繪制
Mat dst = Mat::zeros(src.size(), CV_8UC3);
//for (int i = 0; i < Contours2.size(); i++)
//{
// Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
// drawContours(dst, Contours2, i, color, 2, LINE_AA);
//}
cout << Contours2.size() << endl;
for (int i = 0; i < Contours2.size(); i++)
{
for (int j = 0; j < Contours1.size(); j++)
{
double matchRate = matchShapes(Contours2[i], Contours1[j], CV_CONTOURS_MATCH_I1, 0.0);
cout << matchRate << endl;
if (matchRate <= 0.01)
{
drawContours(dst, Contours1, j, Scalar(0, 255, 0), 2, 8);
}
imshow("dst", dst);
}
}
}
效果如下:
待檢測圖像與其二值圖像:
模闆圖像與其二值圖像:
比對程度最高的輪廓: