opencv contours 遇到边界

问题:目标物和图像边界相连,怎么填充内部孔洞?

上一篇  opencv contours 的问题 提到 如果先通过 findContours() 找到轮廓,再通过 drawContours() 画出该轮廓,两者的形状不会发生改变。

就像这样:

Mat src = imread("test2.bmp", 1);
	Mat gray;
	cvtColor(src, gray, CV_BGR2GRAY);
	Mat thre = gray > 1;
	imshow("thre", thre);
	int area1 = countNonZero(thre);
	cout<<"area1="<<area1<<endl;

	vector< vector<Point> > contours;
	vector< Vec4i> hierarchy;	
	findContours(thre, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
	Mat mask1 = Mat::zeros(src.size(), CV_8UC1);
	for(int i=0; i<contours.size(); ++i) {
		drawContours(mask1, contours, i, 255, CV_FILLED, 8, hierarchy);
	}
	int area2 = countNonZero(mask1);
	cout<<"area2="<<area2<<endl;
	imshow("mask1", mask1); imwrite("mask1.bmp", mask1);
原图和结果图:

处理前后计算面积:


两者是一样的。


但是今天发现一个问题,当目标物和边界相连的时候,以上规律就不对了。结果变成这样:


计算结果:


处理后的图片左边界向右移了一个像素,计算出的面积小了 1550-1500=50.  也就是左边界的边长:76-27+1=50(通过四个顶点计算出)。

把method 由CV_CHAIN_APPROX_SIMPLE  改成 CV_CHAIN_APPROX_NONE 结果是一样的。

从contours里面每个像素点的坐标看,是从左上角(x=1,y=27)开始,往下沿着左边界到左下角的点(x=1,y=76),接着下边界,逆时针绕一圈,最后是点(x=2,y=27)。看来是忽略掉边界上的点了。


恰好我需要把孔洞填充,结果变成这样:


左边界上的目标物如图:


经过findContours() 函数提取过后,这个被保存为一个轮廓,一个完整的外轮廓,且没有内轮廓。

而我想要填充黑色部分,怎么办呢?

我曲折的进行了以下处理:

	Mat src = imread("mask4.bmp", 1);
	Mat gray;
	cvtColor(src, gray, CV_BGR2GRAY);
	Mat mask4 = gray > 1;
	imshow("mask4", mask4);

	//--提取轮廓填充,得到磨粒区域mask-------
	vector< vector<Point> > contours1;
	vector< Vec4i> hierarchy1;	
	Mat mask5 = Mat::zeros(mask4.size(), mask4.type());
	findContours(mask4, contours1, hierarchy1, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
	for(int i=0; i<contours1.size(); ++i) {
		drawContours(mask5, contours1, i, 255, CV_FILLED, 8, hierarchy1);
	}
	imshow("mask5", mask5); imwrite("mask5.bmp", mask5);

	//----以上处理后,边界处的轮廓无法填充-------
	//----反色,提取靠近边界的目标物-------
	Mat mask5_inv;
	bitwise_not(mask5, mask5_inv);  imwrite("mask5_inv.bmp", mask5_inv);
	vector< vector<Point> > contours2;
	findContours(mask5_inv, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
	Mat mask5_border = Mat::zeros(mask4.size(), CV_8UC1);
	for(int i=0; i<contours2.size(); ++i){
		int area = contourArea(contours2[i]);
		if(area<2000)
			drawContours(mask5_border, contours2, i, 255, CV_FILLED, 8);
	}
	imshow("mask5_border", mask5_border);

	//----把靠近边界的磨粒区域合并---
	Mat mask6;
	addWeighted(mask5, 1.0, mask5_border, 1.0, 0.0, mask6);
	imshow("mask6", mask6); imwrite("mask6.bmp", mask6);
把 mask5 反色后提取所有外轮廓,通过面积大小排除大片背景区域,取得靠近边界线的目标物区域mask5_border,再叠加到mask5上面。

中间图及结果图:


问题暂时解决。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用OpenCV寻找颜色差边界线,你可以使用颜色空间转换和阈值化的方法。下面是一个简单的示例代码: ```python import cv2 import numpy as np # 读取图像 image = cv2.imread('image.jpg') # 将图像从BGR颜色空间转换为HSV颜色空间 hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 设置颜色范围(在HSV颜色空间中) lower_color = np.array([0, 50, 50]) upper_color = np.array([10, 255, 255]) # 根据颜色范围创建一个掩膜 mask = cv2.inRange(hsv, lower_color, upper_color) # 进行形态学处理,以去除噪声 kernel = np.ones((5, 5), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) # 找到边界线 contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 绘制边界线 cv2.drawContours(image, contours, -1, (0, 255, 0), 2) # 显示结果图像 cv2.imshow('Color Contours', image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个示例代码中,首先将图像从BGR颜色空间转换为HSV颜色空间。然后,根据你想要寻找的颜色范围,在HSV颜色空间中设置下界和上界。接下来,创建一个掩膜,将在颜色范围内的像素设置为白色,其余像素设置为黑色。然后,使用形态学处理方法(开运算)去除掩膜中的噪声。最后,使用findContours函数找到边界线,并使用drawContours函数绘制边界线。最后,显示结果图像。 请注意,这只是一个简单的示例,你可能需要根据你的具体需求进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值