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
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的图效果较好