1.矩是计算:moments()函数
moments()函数用于计算多边形和光栅形状的最高达三阶的所有矩。矩用来计算形状的重心,面积,主轴和其他形状特征。
Moments moments(InputArray array, //InputArray类型的array,输入参数,可以是光栅图像(单通道,8位或浮点的二维数组)或二维数组(1N或2N)
bool binaryImage = false)//bool类型的binaryImage,默认值false。若此参数为true,则所有非零像素为1,。此参数仅对于图像使用
注:此参数的返回值返回运行后的结果。
2.计算轮廓面积:contourArea()函数
double contourArea(InputArray contour,//InputArray类型的contour,输入的向量,二维点可以为std::vector或Mat类型
bool oriented = false)//bool类型的oriented,面向区域标识符。若为true,该函数返回一个带符号的面积值,其正负取决于轮廓的方向(顺时针还是逆时针)
调用方法:
vectorcontour;
contour.push_back(Point2f(0,0));
contour.push_back(Point2f(10,0));
contour.push_back(Point2f(10,10));
contour.push_back(Point2f(5,4));
double area0 = contourArea(contour);
vectorapprox;
approxPolyDP(contour,approx,5,true);
double area1 = contourArea(approx);
cout<<"area0 = "<
3.计算轮廓长度:arcLength()函数
double arcLength(InputArray curve, //输入的二维点集,可以为std::vector或Mat类型
bool closed)//用于指示曲线是否封闭的标识符,默认closed
查找和绘制图像轮廓矩
#include
#include
#include
using namespace cv;
using namespace std;
#define WINDOW_NAME1 "原图"
#define WINDOW_NAMW2 "效果图"
Mat g_srcImage;
Mat g_grayImage;
int g_nThresh = 100;//阈值
int g_nMaxThresh = 255;//阈值最大值
RNG g_rng(12345);
Mat g_cannyMat_output;
vector>g_vContours;
vectorg_vHierarchy;
void on_ThreshChange(int, void*);
int main()
{
//载入3通道原图像
g_srcImage = imread("1.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);
if (!g_srcImage.data) {
printf("读取图片失败");
return -1;
}
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);
//找到轮廓
findContours(g_cannyMat_output, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
//计算矩
vectormu(g_vContours.size());
for (unsigned int i = 0; i < g_vContours.size(); i++)
mu[i] = moments(g_vContours[i], false);
//计算中心距
vectormc(g_vContours.size());
for (unsigned int i = 0; i < g_vContours.size(); i++)
mc[i] = Point2f(static_cast(mu[i].m10 / mu[i].m00), static_cast(mu[i].m01 / 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_NAMW2,WINDOW_AUTOSIZE);
imshow(WINDOW_NAMW2, drawing);
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);
}
}
void water(InputArray image, //源图像
InputOutputArray markers)//函数调用后的运算结果存在这里,输入/输出32位单通道图像的标记结果。
#include
#include
#include
using namespace cv;
using namespace std;
#define WINDOW_NAME1 "原图"
#define WINDOW_NAME2 "效果图"
Mat g_srcImage;
Mat g_maskImage;
Point prevPt(-1, -1);
static void on_Mouse(int event, int x, int y, int flags, void*);
int main(int agrc, char**agrv)
{
g_srcImage = imread("1.jpg", 1);
namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME1, g_srcImage);
Mat srcImage, grayImage;
g_srcImage.copyTo(srcImage);
cvtColor(g_srcImage, g_maskImage, COLOR_BGR2GRAY);
cvtColor(g_maskImage, grayImage, COLOR_GRAY2BGR);
g_maskImage = Scalar::all(0);
//设置鼠标回调函数
setMouseCallback(WINDOW_NAME1, on_Mouse, 0);
if (!g_srcImage.data) {
printf("读取图片失败");
return -1;
}
while (1) {
int c = waitKey(0);//获取键值
if ((char)c == 27)
break;
if ((char)c == '2') {
g_maskImage = Scalar::all(0);
srcImage.copyTo(g_srcImage);
imshow("image", g_srcImage);
}
if ((char)c == '1' || (char)c == ' ') {
int i, j, compCount = 0;
vector>contours;
vectorhierarchy;
//寻找轮廓
findContours(g_maskImage, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
//轮廓为空时的处理
if (contours.empty())
continue;
Mat maskImage(g_maskImage.size(), CV_32S);
maskImage = Scalar::all(0);
//循环绘制出轮廓
for (int index = 0; index >= 0; index = hierarchy[index][0], compCount++)
drawContours(maskImage, contours, index, Scalar::all(compCount + 1), -1,8, hierarchy, INT_MAX);
if (compCount == 0)
continue;
//生产随机颜色
vectorcolorTab;
for (i = 0; i < compCount; i++) {
int b = theRNG().uniform(0, 255);
int g = theRNG().uniform(0, 255);
int r = theRNG().uniform(0, 255);
colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
}
//计算处理时间并输出到窗口
double dTime = (double)getTickCount();
watershed(srcImage, maskImage);
dTime = (double)getTickCount() - dTime;
printf("\t处理时间 = %gms\n");
//双层循环将分水岭图像遍历存入watershedImage中
Mat watershedImage(maskImage.size(), CV_8UC3);
for (i = 0; i < maskImage.rows; i++)
for (j = 0; j < maskImage.cols; j++) {
int index = maskImage.at(i, j);
if (index == -1)
watershedImage.at(i, j) = Vec3b(255, 255, 255);
else if (index <= 0 || index > compCount)
watershedImage.at(i, j) = Vec3b(0, 0, 0);
else
watershedImage.at(i, j) = colorTab[index - 1];
}
//混合灰度图和分水岭效果图并显示在窗口
watershedImage = watershedImage * 0.5 + grayImage * 0.5;
imshow(WINDOW_NAME2, watershedImage);
}
}
return 0;
}
static void on_Mouse(int event, int x, int y, int flags, void*)
{
if(event == EVENT_LBUTTONDOWN||!(flags&EVENT_FLAG_LBUTTON))
prevPt = Point(-1,-1);
else if(event == EVENT_LBUTTONDOWN)
prevPt = Point(x,y);
else if (event == EVENT_MOUSEMOVE && (flags&EVENT_FLAG_LBUTTON)) {
Point pt(x,y);
if(prevPt.x<0)
prevPt = pt;
line(g_maskImage,prevPt,pt,Scalar::all(255),5,8,0);
line(g_srcImage,prevPt,pt,Scalar::all(255),5,8,0);
prevPt = pt;
imshow(WINDOW_NAME1, g_srcImage);
}
}