首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于迭代自适应阈值和形状分析的圆形目标聚类检测

基于迭代自适应阈值和形状分析的圆形目标聚类检测
EN

Stack Overflow用户
提问于 2012-07-24 12:47:20
回答 1查看 5.6K关注 0票数 16

我一直在开发一个应用程序,用于从图片中计数圆形物体,如细菌菌落。

使它变得容易的是,物体通常与背景有很好的区别。

然而,很少有困难使分析变得棘手:

  1. 背景将呈现渐进式和快速性的强度变化。
  2. 在容器的边缘,对象将是椭圆形的,而不是圆形的。
  3. 物体的边缘有时相当模糊。
  4. 对象将聚集在一起。
  5. 物体可以很小(直径为6px)。
  6. 最终,这些算法将被那些对图像分析没有深入了解的人使用(通过GUI),因此参数必须是直观的,而且非常少。

这一问题已在科学文献中多次得到解决,例如,使用圆形Hough变换或分水岭方法,但我从未对结果感到满意。

描述的一种简单方法是使用距离变换通过自适应阈值和分割(正如我在this post中所描述的)获得前景。

我已经成功地实现了这个方法,但它并不总是能处理强度的突然变化。另外,我也被同行们要求拿出一种更“新颖”的方法。

因此,I正在寻找一种提取前景的新方法.

因此,我研究了其他阈值/blob检测方法。我试过MSER,但发现在我的情况下,它们不太健壮,速度也很慢。

我最终提出了一种算法,到目前为止,它给了我很好的结果:

  1. 我分割我的图像的三个通道,并减少他们的噪音(模糊/中值模糊)。对于每个频道:
  2. 通过计算原始信道和卷积信道之间的绝对差(通过较大的核模糊),对自适应阈值的第一步进行了手动实现。然后,对于所有相关的阈值:
  3. 我对结果应用了一个阈值
  4. 寻找轮廓
  5. 根据形状(大小、面积、凸性.)验证或失效等高线。
  6. 然后,只有有效的连续区域(即由等高线分隔)在累加器(每个通道一个累加器)中重新绘制。
  7. 在超过阈值的连续区域累积后,我最终得到一个“区域数”的地图。强度最高的区域是那些符合形态学滤波标准的区域。
  8. 然后将三个映射(每个通道一个)转换为灰度和阈值(阈值由用户控制)。

为了让你看到我必须要处理的那种形象:

这张图片代表了顶部的3个示例图像的一部分,以及底部各个部分的my算法(blue =前台)的结果。

以下是我的C++实现: 3-7

代码语言:javascript
复制
/*
 * 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);

我有两个问题:

  1. 这种前景提取方法的名称是什么?您认为在这种情况下使用它可能是不恰当的原因吗?
  2. 由于递归查找和绘制等高线相当密集,所以我想使算法更快。你能告诉我实现这个目标的方法吗?

非常感谢你的帮助,

EN

回答 1

Stack Overflow用户

发布于 2012-07-24 14:37:53

几年前,我写了一个应用程序来检测显微镜图像中的细胞。代码是用Matlab编写的,我认为这比应该的复杂(这是我的第一个简历项目),所以我只会概述一些对你有帮助的技巧。顺便说一句,这是致命的慢,但它真的很好地分离大群的孪生细胞。

我定义了一种度量来评估给定的点是细胞中心的概率:-亮度在它周围的圆形图案中减少--纹理亮度的变化跟随一个给定的模式--一个单元将不会覆盖一个相邻单元的超过%。

使用它,我开始迭代地找到最好的单元格,标记为找到,然后查找下一个单元格。因为这样的搜索是昂贵的,所以我使用了遗传算法在我的特征空间中进行更快的搜索。

以下是一些结果:

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11631188

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档