day22:轮廓检测

1:轮廓发现与绘制:

 

 

 

 

 实现:

void visionagin::Myfindcontours(Mat& img)
{
	Mat gry, binary;
	//GaussianBlur(img, img, Size(3, 3),10,20);
	cvtColor(img, gry, COLOR_BGR2GRAY);
	threshold(gry, binary, 140, 255, THRESH_BINARY);
	imshow("二值化图像", binary);
	vector<vector<Point>> contours;//存放检测结果
	vector<Vec4i> h;//存放检测出的轮廓结构矩阵
	findContours(binary, contours, h, RETR_TREE, CHAIN_APPROX_SIMPLE);
	for (int i = 0; i < contours.size(); ++i)
	{
		drawContours(img, contours, i, Scalar(0, 0, 200));
	}
	imshow("轮廓", img);
	for (int j = 0; j < h.size(); ++j)
	{
		cout << h[j] << endl;
	}
}

 2:轮廓面积:

 3:轮廓长度:

 4:轮廓外接多边形:

矩形是常见的几何形状,矩形的处理和分析方法也较为简单 OpenCV4 提供了两个函数用于
求取轮廓外接矩形,分别是求取轮廓最大外接矩形的boundingRect()函数和求取轮廓最小外接矩形
minAreaRect().
寻找轮廓 外接最大矩形就是寻找轮廓X 方向和Y 方向两端的像素,该矩形的长和宽分别与图
像的两条轴平行.

 

 实现:

void visionagin::Mycontours_areaANDlength()
{
	vector<Point>contour;//存放轮廓结果
	contour.push_back(Point(10, 30));
	contour.push_back(Point(20, 43));
	contour.push_back(Point(0, 24));
	contour.push_back(Point(30, 30));
	double res=contourArea(contour, false);//返回double
	double length = arcLength(contour, 1);//返回double 
	cout << res << endl;
	cout << length << endl;
	Mat src = imread("C:\\Users\\86176\\Downloads\\visionimage\\contour.jfif");
	Mat binary;
	Canny(src, binary, 500, 900, 5);
	imshow("binary", binary);
	vector<vector<Point>>contours;
	findContours(binary, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);
	for (int i = 0; i < contours.size(); ++i)
	{
		//drawContours(src, contours, i, Scalar(0, 200, 0));//绘制检测出的轮廓
		Rect rect = boundingRect(contours[i]);//最大外接矩形
		//rectangle(src, rect, Scalar(0, 0, 200));
		RotatedRect rrect = minAreaRect(contours[i]);//旋转矩形类RotatedRect,最小外接矩形
		Point2f points[4];
		rrect.points(points);//旋转矩形类points方法
		Point center = rrect.center;
		circle(src, center, 1, Scalar(0, 200, 0));
		for (int i = 0; i < 4; ++i)
		{
			if (i == 3)
			{
				line(src, points[i], points[0], Scalar(200, 0, 0));
				break;
			}
				line(src, points[i], points[i + 1], Scalar(200, 0, 0));
		}
	}
	namedWindow("res", WINDOW_NORMAL);
	imshow("res", src);
}

先画出检测出的轮廓绿色:

最大外接矩形红色:

最小外接矩形 蓝色:

 

有时候用矩形逼近轮廓会造成较大的误差 , 对于圆形轮廓的逼近矩形围成的面积比真实轮廓面积大,如果寻找逼近轮廓 的多边形,那么多 边形围成的面 积会更 加接近真实的圆形轮廓面积. OpenCV 提供了 appro xP oly DP()  函数用于 寻找逼近轮廓的多边形

 实现:

​
void visionagin:: Myapproxpolydp()
{
	Mat src = imread("C:\\Users\\86176\\Downloads\\visionimage\\contour.jfif");
	imshow("原图", src);
	Mat canny;
	Canny(src, canny, 20, 50);
	imshow("边缘", canny);
	Mat core = getStructuringElement(0, Size(3, 3));//结构元素
	dilate(canny, canny, core);//腐蚀
	imshow("dilate",canny);
	vector<vector<Point>> contours;
	findContours(canny, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);//轮廓检测
	for (int i = 0; i < contours.size(); ++i)
	{
		RotatedRect rrect;
		rrect = minAreaRect(contours[i]);//每个轮廓的最小外接矩形
		Point center = rrect.center;
		circle(src, center, 2, Scalar(0, 0, 200));//用最小外接矩形的中心绘制轮廓中心
		Mat result;
		approxPolyDP(contours[i], result, 4, true);
		for (int j = 0; j < result.rows; ++j)//绘制多边形轮廓
		{
			if (j == result.rows - 1)//绘制最后一个顶点与第一个顶点的连线
			{
				Point p1 = result.at<Vec2i>(j);
				Point p2 = result.at<Vec2i>(0);
				line(src, p1, p2, Scalar(0, 200, 0));
				break;
			}
			Point p1 = result.at<Vec2i>(j);
			Point p2 = result.at<Vec2i>(j + 1);
			line(src, p1, p2, Scalar(0, 200, 0));
		}
		if (result.rows == 3)
		{
			putText(src, "three", center, 0, 1, Scalar(200, 0, 0));//不支持中文
		}
		if (result.rows == 4)
		{
			putText(src, "4", center, 0, 1, Scalar(200, 0, 0));
		}
		if (result.rows == 5)
		{
			putText(src, "5", center, 0, 1, Scalar(200, 0, 0));
		}
		if (result.rows == 6)
		{
			putText(src, "6", center, 0, 1, Scalar(200, 0, 0));
		}
		if (result.rows == 8)
		{
			putText(src, "8", center, 0, 1, Scalar(200, 0, 0));
		}
		if (result.rows >12)
		{
			putText(src, "circle", center, 0, 1, Scalar(200, 0, 0));
		}
	}
	imshow("结果", src);

}

​

 5.点到轮廓的距离

点到轮廓的距离,对于计算轮廓在图像中的位置、两个轮廓之间的距离以及确定图像上某一点
是否在轮廓内部具有重要的作用. OpenCV 提供了计算像素点距离轮廓最小距离的
pointPolygonTestO函数

 6.凸包检测

有时物体的形状过于复杂,用多边形逼近后处理起来依然较为复杂 例如入手、海星等.对于
形状较为复杂的物体,可以利用凸包近似表示.凸包是图形学中常见的概念 将二维平面上的点集
最外层的点连接起来构成的凸多边形称为凸包.虽然凸包检测也是对轮廓 进行多边 形逼近,但是逼
近结果一定为凸多边形.

 实现:

void visionagin:: Myconvxhull()
{
	Mat src = imread("C:\\Users\\86176\\Downloads\\visionimage\\seastar.jfif");
	namedWindow("原图", WINDOW_NORMAL);
	imshow("原图", src);
	Mat canny;
	Canny(src, canny, 150, 100);
	Mat core = getStructuringElement(0, Size(5, 5));//结构元素
	dilate(canny, canny, core);//腐蚀
	namedWindow("canny", WINDOW_NORMAL);
	imshow("canny", canny);
	vector<vector<Point>>contours;
	findContours(canny, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);
	for (int i = 0; i < contours.size(); i++)
	{
		vector<Point>result;
		convexHull(contours[i], result, true, true);
		for (int j = 0; j < result.size(); j++)
		{
			if (j == result.size() - 1)
			{
				line(src, result[j], result[0], Scalar(0, 0, 200));
				break;
			}
			line(src, result[j], result[j + 1], Scalar(0, 0, 200));
		}
	}
	imshow("res", src);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值