【学习OpenCV】用opencv绘制图形轮廓并筛选面积操作

findcontours和drawcontours2个算子

//! retrieves contours and the hierarchical information from black-n-white image.
CV_EXPORTS_W void findContours( InputOutputArray image, OutputArrayOfArrays contours,
                              OutputArray hierarchy, int mode,
                              int method, Point offset=Point());

Image必须为二值图,可以通过compare(),inRange(),threshold(),adaptiveThreshold(),Canny()这些算子来实现对原图的二值化。

contours为输出的轮廓数组,每一个轮廓用Point类型的vector容器表示。

hierarchy参数和轮廓个数相同,每一个轮廓contour[i]都包含着hieracrchy[i][0],hieracrchy[i][1],hieracrchy[i][2],hieracrchy[i][3],分别表示前一个轮廓,后一个轮廓,父轮廓,内嵌轮廓的索引编号。

mode 表示轮廓的检索模式;

RETR_EXTERNAL表示只检索最外延的轮廓。

RETR_LIST表示检测的轮廓不建立等级关系

RETR_CCOMP建立两个等级的轮廓,上面一层为外边界,里面一层为内孔边界信息,如果孔内还有一个联通物体,这个物体的边界也在顶上,

RETR_TREE建立一个等级树的轮廓,这个实例中采用这种方法。


method表示轮廓的逼近方法

CHAIN_APPROX_NONE存储所有的轮廓点,相邻两个轮廓点的位置差不超过1,

CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形只保留4个点来保存轮廓信息。

CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法 offset表示轮廓的偏移数据,可以设定任何值,在ROI中寻找轮廓,并要在这个图像中分析时,还是很有用的。


//! draws contours in the image

CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours,
                              int contourIdx, const Scalar& color,
                              int thickness=1, int lineType=8,
                              InputArray hierarchy=noArray(),
                              int maxLevel=INT_MAX, Point offset=Point() );

contouridx指明画第几个轮廓,如果该参数为负数,-1,则画全部轮廓,

color为轮廓的颜色

thickness为轮廓的线宽,如果为负数或者CV_FILLED表示轮廓内部填充。

linetype表示线型

//绘制轮廓  
for (int i = 0; i < (int)contours.size(); i++)
{
drawContours(cannyImage, contours, i, Scalar(255), 1, 8);
}
imshow("【处理后的图像】", cannyImage);

等效于以下代码:

Mat result(srcImage.size(), CV_8U, Scalar(0));
drawContours(result, contours, -1, Scalar(255), 1);   // -1 表示所有轮廓  


#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;

//opencv也可以对图形的轮廓进行面积的筛选,剔除无效区域。

	int main()
{
	Mat srcImage = imread("1.png");
	imshow("【原图】", srcImage);

	//首先对图像进行空间的转换  
	Mat grayImage;
	cvtColor(srcImage, grayImage, CV_BGR2GRAY);
	//对灰度图进行滤波  
	GaussianBlur(grayImage, grayImage, Size(3, 3), 0, 0);
	imshow("【滤波后的图像】", grayImage);

	//为了得到二值图像,对灰度图进行边缘检测  
	Mat cannyImage;
	Canny(grayImage, cannyImage, 128, 255, 3);
	//在得到的二值图像中寻找轮廓  
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(cannyImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));


	//绘制轮廓  
	for (int i = 0; i < (int)contours.size(); i++)
	{
		drawContours(cannyImage, contours, i, Scalar(255), 1, 8);
	}
	imshow("【处理后的图像】", cannyImage);


	//计算轮廓的面积  
	cout << "【筛选前总共轮廓个数为】:" << (int)contours.size() << endl;
	for (int i = 0; i < (int)contours.size(); i++)
	{
		double g_dConArea = contourArea(contours[i], true);
		cout << "【用轮廓面积计算函数计算出来的第" << i << "个轮廓的面积为:】" << g_dConArea << endl;
	}

	//筛选剔除掉面积小于100的轮廓
	vector <vector<Point>>::iterator iter = contours.begin();
	for (; iter != contours.end();)
	{
		double g_dConArea = contourArea(*iter);
		if (g_dConArea < 100)
		{
			iter = contours.erase(iter);
		}
		else
		{
			++iter;
		}
	}
	cout << "【筛选后总共轮廓个数为:" << (int)contours.size() << endl;
	for (int i = 0; i < (int)contours.size(); i++)
	{
		double g_dConArea = contourArea(contours[i], true);
		cout << "【用轮廓面积计算函数计算出来的第" << i << "个轮廓的面积为:】" << g_dConArea << endl;
	}
	Mat result(srcImage.size(), CV_8U, Scalar(0));
	drawContours(result, contours, -1, Scalar(255), 1);   // -1 表示所有轮廓  
	namedWindow("result");
	imshow("result", result);
	waitKey(0);
	return 0;

}
轮廓为负数值

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值