关于opencv4.1的dnn及findpeak二维极值

本文探讨了使用OpenCV进行图像分割的技术,包括利用极值法和分水岭算法处理粘连目标,以及在OpenCV中加载带有DropOut或BatchNorm节点的TensorFlow模型的方法。分享了图像分割资料和解决模型加载问题的思路。

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

matlab得找极值的函数findpeak只能找一维极值,而且opencv没有对应的函数,所谓极值就是比周围的值都大,然后看需求要什么程度的极值:对于粘连目标,我用这个极值法求出极值然后+分水岭分割,效果比我之前试过的分割方法都好,而且简单耗时少。

Mat dist_image,eachpeaks,peaksshow;
		distanceTransform(bwimg,dist_image, DIST_L2, 3);

		vector<Point> peaks;
		findPeaks(dist_image,lengthresh,peaks,eachpeaks);

		Mat imglabels,segresult;
		watershedSegmentProc(bwimg,eachpeaks,peaksshow,imglabels,segresult);

像这样找的中心区域点都比较准,然后分水岭分割时过分割就会较少。

但这个办法应该再优化一下,因为这样找的极值对单个大目标不友好,单个大目标会找出几个极值。至于优化的代码就不发了(公司内部使用)。

有一个疑惑:今天调试时,分水岭结果怎么还有未知区域没被分配:

这里竟然还有0---未知区域的值,明明是已经分水岭后的结果:

/*分水岭分割处理
	 * srcmatbw--------二值图  单通道
	 * everycenters----可分割石头的中心图,背景为黑色0,中心为白点255
	 * imglabels-------分水岭结果  背景是100,分界线是-1,可分割石头是1~N(可能有0已容错)
	 * */
int watershedSegmentProc(Mat &srcmatbw,Mat &everycenters,Mat &imglabels)
{
//	int not_zero_count=countNonZero(srcmatbw);
//	float white_count_thre=srcmatbw.rows*srcmatbw.cols;
//	white_count_thre*=0.8;
//	if((not_zero_count<20 )||(not_zero_count>(int)white_count_thre))
//	{
//		return 2;
//	}

	Mat element = getStructuringElement(MORPH_ELLIPSE, Size(11, 11));
	Mat element2 = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));

	Mat binary_dilate;//every centers
	dilate(everycenters, binary_dilate, element2, Point(-1, -1), 1);

	Mat binary_8UC3;
	vector<Mat> resultmats;
	resultmats.push_back(srcmatbw);
	resultmats.push_back(srcmatbw);
	resultmats.push_back(srcmatbw);
	merge(resultmats,binary_8UC3);

	Mat unknown;//得到未知区域 即分界线的划分涉及区域
	bitwise_xor(srcmatbw,binary_dilate,unknown);

	//合并标记图像
	Mat imgstats, imgcentroid;
	connectedComponentsWithStats(binary_dilate, imglabels, imgstats, imgcentroid);  //连通域标记

	imglabels.convertTo(imglabels, CV_32SC1); //图像类型转换

	imglabels = imglabels + 100;//背景区域像素为100

	for (int i=0;i<unknown.rows;i++)
	{
		uchar* ptr = unknown.ptr<uchar>(i);
		for (int j=0;j<unknown.cols;j++)
		{
			if (255==ptr[j])
			{
				imglabels.at<int>(i, j) = 0; //未知区域像素为0
			}
		}
	}

	//分水岭分割
	watershed(binary_8UC3, imglabels);
}

那个0不知道怎么回事?!

/**********************************************************************/

关于opencv4.1调用tensorflow训练好的带有DropOut或BatchNorm节点的.pb模型,一个新同事说opencv c++不支持,我查了下:

Export tensorflow graph with batchnorm to opencv dnn - OpenCV Q&A Forum

OpenCV: modules/dnn/src/tensorflow/tf_importer.cpp | Fossies

dnn: Unknown layer type Shape in op dropout/Shape in function populateNet · Issue #9563 · opencv/opencv · GitHub

How to load a Keras model build with tensorflow backend in OpenCV - OpenCV Q&A Forum

Tensorflow C++ 从训练到部署(3):使用 Keras 训练和部署 CNN - 技术刘

C++ and the phase_train node · Issue #357 · davidsandberg/facenet · GitHub

查了一下opencv4.1源码,看到是写了fushBatchNorm的接口的,如果不支持,那opencv为什么要写这个接口,不是鸡肋吗:

看,的确可以识别这个节点的。我觉得就是要按opencv c++规定的方式来,它才来加载python下训练好的模型。

至于dropout节点,opencv源码中我暂时没看到,但是我看到网上讲了解决办法:

而且另一个人连在python下训练好带有dropout节点的模型然后opencv c++调用的代码都写好了。

所以我觉得这些不是不支持,opencv c++只是比python下严苛一些而已,按它的规则来就可以加载,只是我们还在弄清楚这些规则的路上而已。

今天翻墙找到一些非常有用的图像分割资料,可惜没有对应代码,有一篇特别好,是讲通过形状匹配或拟合来分割重叠不规则目标的(如下图)。

我都上传在优快云 https://download.youkuaiyun.com/download/wd1603926823/88720961 

希望自己有时间将其实现可以用在另一个项目中。下图是论文中的结果:感觉对high overlapping & out of focus的图效果较好

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

元气少女缘结神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值