Que*_*ann 16 c++ algorithm opencv image-processing openmp
我一直在开发一个应用程序来计算圆形物体,如图片中的细菌菌落.
容易的是这些物体通常与背景明显不同.
但是,很少有困难使分析变得棘手:
这个问题已在科学文献中多次解决并"解决",例如,使用圆形Hough变换或分水岭方法,但我从未对结果感到满意.
这是描述的一个简单的方法是通过获得自适应阈值和分裂前景(如我在描述这个交使用距离变换)的群集对象.
我已经成功地实现了这种方法,但它并不总能处理强度的突然变化.此外,同行们也要求我提出更"新颖"的方法.
因此,我正在寻找一种新方法来提取前景.
因此,我研究了其他阈值/斑点检测方法.我尝试了MSER但发现它们不是很强大而且在我的情况下非常慢.
我最终提出了一种算法,到目前为止,它给了我很好的结果:
只是为了向您展示我必须使用的图像类型:
该图片代表顶部3个样本图像的一部分,以及底部各个部分的算法结果(蓝色=前景).
这是我的C++实现:3-7
/*
* cv::Mat dst[3] is the result of the absolute difference between original and convolved channel.
* MCF(std::vector<cv::Point>, int, int) is a filter function that returns an positive int only if the input contour is valid.
*/
/* Allocate 3 matrices (1 per channel)*/
cv::Mat accu[3];
/* We define the maximal threshold to be tried as half of the absolute maximal value in each channel*/
int maxBGR[3];
for(unsigned int i=0; i<3;i++){
double min, max;
cv::minMaxLoc(dst[i],&min,&max);
maxBGR[i] = max/2;
/* In addition, we fill accumulators by zeros*/
accu[i]=cv::Mat(compos[0].rows,compos[0].cols,CV_8U,cv::Scalar(0));
}
/* This loops are intended to be multithreaded using
#pragma omp parallel for collapse(2) schedule(dynamic)
For each channel */
for(unsigned int i=0; i<3;i++){
/* For each value of threshold (m_step can be > 1 in order to save time)*/
for(int j=0;j<maxBGR[i] ;j += m_step ){
/* Temporary matrix*/
cv::Mat tmp;
std::vector<std::vector<cv::Point> > contours;
/* Thresholds dst by j*/
cv::threshold(dst[i],tmp, j, 255, cv::THRESH_BINARY);
/* Finds continous regions*/
cv::findContours(tmp, contours, CV_RETR_LIST, CV_CHAIN_APPROX_TC89_L1);
if(contours.size() > 0){
/* Tests each contours*/
for(unsigned int k=0;k<contours.size();k++){
int valid = MCF(contours[k],m_minRad,m_maxRad);
if(valid>0){
/* I found that redrawing was very much faster if the given contour was copied in a smaller container.
* I do not really understand why though. For instance,
cv::drawContours(miniTmp,contours,k,cv::Scalar(1),-1,8,cv::noArray(), INT_MAX, cv::Point(-rect.x,-rect.y));
is slower especially if contours is very long.
*/
std::vector<std::vector<cv::Point> > tpv(1);
std::copy(contours.begin()+k, contours.begin()+k+1, tpv.begin());
/* We make a Roi here*/
cv::Rect rect = cv::boundingRect(tpv[0]);
cv::Mat miniTmp(rect.height,rect.width,CV_8U,cv::Scalar(0));
cv::drawContours(miniTmp,tpv,0,cv::Scalar(1),-1,8,cv::noArray(), INT_MAX, cv::Point(-rect.x,-rect.y));
accu[i](rect) = miniTmp + accu[i](rect);
}
}
}
}
}
/* Make the global scoreMap*/
cv::merge(accu,3,scoreMap);
/* Conditional noise removal*/
if(m_minRad>2)
cv::medianBlur(scoreMap,scoreMap,3);
cvtColor(scoreMap,scoreMap,CV_BGR2GRAY);
Run Code Online (Sandbox Code Playgroud)
我有两个问题:
这种前景提取方法的名称是什么?您是否认为在这种情况下使用它的任何原因可能是不正确的?
由于递归查找和绘制轮廓是非常密集的,我想让我的算法更快.你能指出我实现这个目标的方法吗?
非常感谢你的帮助,
几年前,我编写了一个应用程序来检测显微镜图像中的细胞。代码是用 Matlab 编写的,我认为现在比应有的更复杂(这是我的第一个 CV 项目),所以我只会概述对您实际上有帮助的技巧。顺便说一句,它的速度慢得要命,但它确实很擅长分离大群的双胞胎细胞。
我定义了一个度量标准,用于评估给定点是单元格中心的机会: - 亮度在其周围的圆形图案中减小 - 纹理亮度的方差遵循给定的模式 - 单元格覆盖的范围不会超过 %相邻小区的
有了它,我开始迭代地找到最好的单元格,将其标记为已找到,然后寻找下一个。因为这样的搜索成本很高,所以我采用遗传算法在特征空间中更快地搜索。
一些结果如下:
