OpenCV学习笔记(六)

一、图像的矩

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);
	}
}

OpenCV学习笔记(六)_第1张图片
4.分水岭算法
实现分水岭算法:watershed()函数

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);
	}
}

OpenCV学习笔记(六)_第2张图片

你可能感兴趣的:(OpenCV学习笔记,OpenCV学习笔记,C++)