/*模式识别 目标分类 目标识别 方位估计 图像编码重构
使用moments计算图像所有的矩 最高3阶
使用contourArea 计算轮廓面积
使用arcLength计算轮廓或曲线长度
矩的计算 Moments moments (inputarray array,// 可以是光栅图像 单通道 8位或浮点的二位数组
Bool binaryImage=false// 默认false 或是true则素有非零像素为1);
计算轮廓面积:
double contourArea(inputarray contour,//输入向量 mat vector
Bool oriented=false//面向区域标识符 若是true 返回一个带符号的面积值,取决于轮廓的方向
);
计算轮廓长度:double arcLength( inputarray curve,//点集 mat vector
Bool closed// 是否封闭
)
*/
#include <opencv2//highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
//*********************************
// 查找和绘制图像轮廓矩
//*********************************
#define WINDOW_NAME1 "【原始图】"
#define WINDOW_NAME2 "【图像轮廓】"
Mat g_srcImage;
Mat g_grayImage;
Mat g_cannyMat_output;
int g_nThresh = 100;
int g_nMaxThresh = 255;
RNG g_rng(12345);
vector<vector<Point> > g_vContours;
vector<Vec4i> g_vHierarchy;
void on_ThreshChange(int, void*);
static void ShowHelpText();
int main()
{
system("color 1E");
g_srcImage = imread("C:/Users/hasee-pc/Desktop/women.jpg",1);
//原图转灰度平滑
cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
blur(g_grayImage, g_grayImage, Size(3, 3));
namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME1, g_srcImage);
//创建滑动条
createTrackbar(" 阈值:", WINDOW_NAME1, &g_nThresh, g_nMaxThresh, on_ThreshChange);
on_ThreshChange(0, 0);
waitKey(0);
return 0;
}
void on_ThreshChange(int, void *)
{
//边缘检测
Canny(g_grayImage,//输入
g_cannyMat_output,//输出
g_nThresh, //最小阈值
g_nThresh * 2, //最大阈值
3//sobel算子
);
//找到轮廓
findContours(g_cannyMat_output,//输入图
g_vContours,//检测到的轮廓值
g_vHierarchy,//输出向量
RETR_TREE,//轮廓检索模式
CHAIN_APPROX_SIMPLE,//轮廓近似方法
Point(0, 0)//轮廓点偏移量
);
//计算矩
vector<Moments> mu(g_vContours.size());
for (unsigned int i = 0; i < g_vContours.size(); ++i)
{
mu[i] = moments(g_vContours[i], false);
}
//计算矩中心
vector<Point2f> mc(g_vContours.size());
for (unsigned int i = 0; i < g_vContours.size(); ++i)
{
mc[i] = Point2f(static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m10/mu[i].m00));
}
//绘制轮廓
Mat drawing = Mat::zeros(g_cannyMat_output.size(), CV_8UC3);
for (unsigned int i = 0; i < g_vContours.size(); ++i)
{
//随机颜色
Scalar color = Scalar(g_rng.uniform(0, 255),
g_rng.uniform(0, 255),
g_rng.uniform(0, 255)
);
//绘制内外层轮廓
drawContours(drawing,//输入图
g_vContours,//输入轮廓点集
i,//轮廓指示变量
color,//颜色
2,//线条粗细
8,//线条类型
g_vHierarchy,//层次结构
0,//绘制轮廓最大等级
Point()//可选的偏移参数
);
//绘制圆
circle(drawing,//输入图
mc[i],//圆心
4,//半径
color,//颜色
-1,//填充类型
8,//粗细
0//线条类型
);
namedWindow(WINDOW_NAME2, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME2, drawing);
//通过m00计算轮廓面积并且和Opecv函数比较
printf("\t 输出内容:面积和轮廓长度\n");
for (unsigned int i = 0; i < g_vContours.size(); ++i)
{
printf(" >通过 m00计算出轮廓[%d]的面积:(M_00) = %.2f \n OpenCV 函数计算出的面积=%.2f , "
"长度:%.2f \n\n",
i,
mu[i].m00,
contourArea(g_vContours[i]),//轮廓面积
arcLength(g_vContours[i],true)//轮廓曲线长度
);
//随机颜色
Scalar color = Scalar(g_rng.uniform(0, 255),
g_rng.uniform(0, 255),
g_rng.uniform(0, 255)
);
//绘制轮廓
drawContours(drawing,//图
g_vContours,//轮廓集合
i,//指示变量
color,//颜色
2,//线条粗细
8,//线条形态
g_vHierarchy,//层次结构
0,//轮廓最大等级
Point()//偏移量
);
circle(drawing,//输入图
mc[i],//圆心
4,//半径
color,//颜色
-1,//线条类型
8,//线条粗细
0);线条形态
}
}
}