【问题标题】:How can I separate same colored connected object from an image?如何从图像中分离相同颜色的连接对象?
【发布时间】:2019-09-30 13:22:55
【问题描述】:

我有一张如下图:

我正在应用代码中的某种阈值。我可以像下面这样分离蓝色对象:

但是,现在我在分离这些蓝色对象时遇到了问题。我应用了分水岭(我不知道我做对了还是错了)但没有成功,所以我需要帮助来分离这些连接的对象。

我尝试使用的代码如下所示:

RGB=imread('testImage.jpg');
RGB = im2double(RGB);
cform = makecform('srgb2lab', 'AdaptedWhitePoint', whitepoint('D65'));
I = applycform(RGB,cform);
channel1Min = 12.099;
channel1Max = 36.044;
channel2Min = -9.048;
channel2Max = 48.547;
channel3Min = -53.996;
channel3Max = 15.471;
BW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
    (I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
    (I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
maskedRGBImage = RGB;
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
figure
imshow(maskedRGBImage)

【问题讨论】:

    标签: matlab image-processing image-segmentation


    【解决方案1】:

    一般来说,这种类型的分割是一个严肃的研究问题。在您的情况下,使用morphology operations 的组合可以做得很好。这些在显微图像处理中得到广泛应用。

    首先,通过去除小斑点和填充孔来稍微清理BW

    BWopen = imopen(BW, strel('disk', 6));
    BWclose = imclose(BWopen, strel('disk', 6));
    

    (您可能需要稍微调整结构元素,“6”只是一个似乎适用于您的测试图像的半径。)

    然后你可以使用侵略性侵蚀来生成一些种子

    seeds = imerode(BWclose, strel('disk', 35));
    

    您可以将其用于分水岭,或者只是将 BW 中的每个点分配给其最近的种子

    labels = bwlabel(seeds);
    
    [D, i] = bwdist(seeds);
    closestLabels = labels(i);
    originalLabels = BWopen .* closestLabels;
    
    imshow(originalLabels, []);
    

    【讨论】:

      【解决方案2】:

      我会尝试以下步骤:

      1. 将图像转换为灰色,然后转换为二进制蒙版。

      2. 应用形态开口 (imopen) 来清理小的嘈杂对象。

      3. 使用 bwlabel 应用连接组件分析 (CCA)。每个连接的组件至少包含 1 个对象。

      4. 这些蓝色物体看起来真的像拉伸/扭曲的圆圈,所以我会尝试 Hough 变换来检测每个标记组件内的圆圈。有一个内置函数 (imfindcircles) 或在线可用代码 (Hough transform for circles),具体取决于您的 Matlab 版本和可用的工具箱。

      5. 然后,您需要对每个组件内的对象数量 N 做出一些决定 (N>=1)。我事先不知道最佳标准应该是什么,但您也可以应用这些简单的规则: [i] 对象必须具有最小尺寸。 [ii] 重叠的圆圈对应同一个对象(或不对应,取决于重叠量)。

      6. 然后圆心可以作为种子来完成最终的对象分割。当然,如果每个组件中只有一个圆圈,你就直接把它当成一个对象就行了。

      我没有在 Matlab 中检查所有步骤的有效性,但我很快检查了 1、2 和 4,它们似乎很有希望。我在图像的中心显示了最困难组件的圆形检测结果:

      我用来创建这个图像的代码是:

      close all;clear all;clc;
      
      addpath 'circle_hough'; % add path to code of [Hough transform for circles] link above
      
      im = imread('im.jpg');
      img = rgb2gray(im);
      
      mask = img>30; mask = 255*mask; % create a binary mask
      figure;imshow(mask)
      
      % filter the image so that only the central part of 6 blue objects remains (for demo purposes only)
      o = zeros(size(mask)); o(170:370, 220:320) = 1;
      mask = mask.*o; 
      figure;imshow(mask);
      
      se = strel('disk',3); 
      mask = imopen(mask,se); % apply morphological opening
      figure;imshow(mask);
      
      % check for circles using Hough transform (see also circle_houghdemo.m in [Hough transform for circles] link above)
      radii = 15:5:40; % allowed circle radii 
      h = circle_hough(mask, radii, 'same', 'normalise');
      % choose the 10 biggest circles
      peaks = circle_houghpeaks(h, radii, 'nhoodxy', 15, 'nhoodr', 21, 'npeaks', 10);
      
      % show result
      figure;imshow(im);
      for peak = peaks
          [x, y] = circlepoints(peak(3));
          hold on;plot(x+peak(1), y+peak(2), 'g-');
      end
      

      【讨论】:

      • 您用来重现结果的实际代码会很好地完成您的答案。
      • 感谢@rayryeng 的建议,我添加了代码。
      • 非常好。谢谢你。 +1。
      【解决方案3】:

      一些自发的想法。我认为最终目标是计算蓝色微粒。如果是这样,我会寻找一种方法来确定这些物体的总面积和一个微粒的平均面积。作为第一步转换为二进制(黑白):

      level = graythresh(RGB);
      BW = im2bw(RGB,level);
      

      由于形态学操作(打开/关闭)不会保留这些区域,我会使用 bwlabel 来查找连接的组件。看着图片,我看到了 12 个孤立的微粒,两个相连的组,一些边缘被截断的微粒和一些小的嘈杂碎片。所以首先去除小物体和那些接触的边缘。然后确定总面积(bwarea)和物体的中值大小作为一个红细胞平均面积的代表。

      【讨论】:

        猜你喜欢
        • 2020-07-02
        • 1970-01-01
        • 1970-01-01
        • 2019-11-16
        • 2013-01-04
        • 1970-01-01
        • 2014-10-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多