利用findcontours实现仅查找内轮廓

这篇博客介绍了如何使用OpenCV的findContours函数检测图像中的内轮廓,重点在于理解CV_RETR_CCOMP检索模式和hierarchy参数。通过设置mode为CV_RETR_CCOMP,可以将轮廓分为外轮廓和内轮廓两级关系,然后通过判断hierarchy[i][3]是否为-1来获取内轮廓。作者提供了代码示例,展示了从HSV颜色空间提取红色区域并检测内轮廓的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一次尝试写博客,就当做写一次随笔吧!

最近在做一个小项目,需要检测目标轮廓,而且只需要内轮廓,OpenCV自带的轮廓检测函数findContours使用起来特别方便,利用轮廓之间层级关系即可实现内轮廓查找。

findContours函数的具体使用方法自行查看相关教程和手册,下面仅对本算法相关的关键点进行一些强调和补充,如有错误,还请批评指正。

findContours( InputOutputArray image, OutputArrayOfArrays contours,
                              OutputArray hierarchy, int mode,
                              int method, Point offset=Point());

参数列表中有个数据结构参数:hierarchy(译层次结构),hierarchy是一个向量,其元素个数与查找到的轮廓总数相同,每一个元素中包含4个int类型数据hierarchy[i][0]~hierarchy[i][3]。
分别表示:

  1. 表示同一级轮廓的下个轮廓的编号,如果这一级轮廓没有下一个轮廓,则为-1。
  2. 表示同一级轮廓的上个轮廓的编号,如果这一级轮廓没有上一个轮廓,则为-1。
  3. 表示该轮廓包含的下一级轮廓的第一个的编号,假如没有,则为-1。
  4. 表示该轮廓的上一级轮廓的编号,假如没有上一级,则为-1。

具体参考博客:findContour函数详解

参数:int mode:定义轮廓的检索模式,mode不同,轮廓之间的拓扑结构就不同,具体参数定义可参考其他博客。

本文在仅检测内轮廓时使用了mode:CV_RETR_CCOMP 其检测所有的轮廓,但所有轮廓只建立两个等级关系,即外轮廓和内轮廓,如果内轮廓中还含有其他轮廓,则内轮廓内的所有轮廓均归属于外轮廓,以此类推。


程序中所用测试图像如下:
在hsv颜色空间下通过红色阈值分割得到二值化图像测试图片需要在hsv颜色空间下通过红色阈值分割得到二值化图像,对应代码段中find_color()函数,代码如下:

void find_color(const cv::Mat& inputimage, cv::Mat& outputimage)
{
	cv::Mat imageHsv;
	cv::Mat Imagemask, mask1, mask2;

	cv::cvtColor(inputimage, imageHsv, COLOR_BGR2HSV);

	cv::inRange(imageHsv, Scalar(0, 82, 45), Scalar(12, 255, 255), mask1);       
	cv::inRange(imageHsv, Scalar(162, 82, 45), Scalar(180, 255, 255), mask2);
	//merge the two mask
	Imagemask = mask1 + mask2;
	outputimage = Imagemask.clone();

}

内轮廓查找代码如下,很简单:

int main()
{
	cv::Mat dstImage, SrcImage, drawImage;
	string path = "F:\\Image_design\\circle4.png";
	
	SrcImage = imread(path);							//source image
	if (!SrcImage.data) {
		std::cout << "Could not open or find the image" << std::endl;
		return -1;
	}
	
   //hsv颜色空间提取红色部分
	find_color(SrcImage, dstImage);					  
	cv::Mat markers = dstImage.clone();
	drawImage = cv::Mat::zeros(SrcImage.size(), SrcImage.type());

	std::vector< std::vector<cv::Point> > contours;
	std::vector<cv::Vec4i> hierarchy;
    //层级关系只选择两层
	cv::findContours(markers, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);  
	for (int i = 0; i < contours.size(); i++)
	{
		if (hierarchy[i][3] != -1 && contourArea(contours[i]) > 50)
		{
			drawContours(SrcImage, contours, i, Scalar(0, 255, 0), 2);
			drawContours(drawImage, contours, i, Scalar(0, 255, 0), 1);

			cout << "向量hierarchy的第" << to_string(i) << " 个元素内容为:" << endl << hierarchy[i] << endl << endl;
		}
	}

	cv::imshow("contours", SrcImage);
	cv::waitKey(0);
	return 0;
}

代码执行效果如下:
绿色即为检测到的内轮廓(绿色即为检测到的内轮廓)

总结:其实只要理解了mode:CV_RETR_CCOMP 和hierarchy的实际意义,算法的关键点就是一句话:
if (hierarchy[i][3] != -1 ) 就保存该轮廓;
上文测试图的层级结构数据
(选用CV_RETR_CCOMP时,上文测试图的层级结构数据)

因为层级关系就两层,当向量hierarchy元素中最后一位数据不为-1时,表示该轮廓存在外轮廓,那么此轮廓就是内轮廓了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值