Coffee beans separation algorithm

后端 未结 5 773
日久生厌
日久生厌 2020-12-23 15:36

What is proper algorithm for separating (counting) coffee beans on binary image? Beans can touch and partially overlap.


(source: beucher at cmm.ensmp.fr)

5条回答
  •  忘掉有多难
    2020-12-23 16:02

    There are some elegant answers, but I thought of sharing what I tried because it is bit different to other approaches.

    After thresholding and finding the distance transform, I propagate the local maxima of the distance-transformed image. By adjusting the extent of maxima propagation I segment the distance transformed image, then filter these segments by their area, rejecting smaller segments.

    This way I can achieve a reasonably good segmentation of the given image, though it does not clearly define the boundaries. For the given image I get a segment count of 42 using the parameter values that I use in the Matlab code to control the extent of maxima propagation and the area threshold.

    Results:

    enter image description here

    enter image description here

    Here's the Matlab code:

    clear all;
    close all;
    
    im = imread('ex2a.gif');
    % threshold: coffee beans are black
    bw = im2bw(im, graythresh(im));
    % distance transform
    di = bwdist(bw);
    % mask for coffee beans
    mask = double(1-bw);
    
    % propagate the local maxima. depending on the extent of propagation, this
    % will transform finer distance image to coarser segments 
    se = ones(3);   % 8-neighbors
    % this controls the extent of propagation. it's some fraction of the max
    % distance of the distance transformed image (50% here)
    mx = ceil(max(di(:))*.5);
    peaks = di;
    for r = 1:mx
        peaks = imdilate(peaks, se);
        peaks = peaks.*mask;
    end
    
    % how many different segments/levels we have in the final image
    lvls = unique(peaks(:));
    lvls(1) = []; % remove first, which is 0 that corresponds to background
    % impose a min area constraint for segments. we can adjust this threshold
    areaTh = pi*mx*mx*.7;
    % number of segments after thresholding by area
    nseg = 0;
    
    % construct the final segmented image after thresholding segments by area
    z = ones(size(bw));
    lblid = 10;  % label id of a segment
    for r = 1:length(lvls)
        lvl = peaks == lvls(r); % pixels having a certain value(level)
        props = regionprops(lvl, 'Area', 'PixelIdxList'); % get the area and the pixels
        % threshold area
        area = [props.Area];
        abw = area > areaTh;
        % take the count that passes the imposed area threshold
        nseg = nseg + sum(abw);
        % mark the segments that pass the imposed area threshold with a unique
        % id
        for i = 1:length(abw)
            if (1 == abw(i))
                idx = props(i).PixelIdxList;
                z(idx) = lblid; % assign id to the pixels
                lblid = lblid + 1; % increment id
            end
        end
    end
    
    figure,
    subplot(1, 2, 1), imshow(di, []), title('distance transformed')
    subplot(1, 2, 2), imshow(peaks, []), title('after propagating maxima'), colormap(jet)
    figure,
    subplot(1, 2, 1), imshow(label2rgb(z)), title('segmented')
    subplot(1, 2, 2), imshow(im), title('original')
    

提交回复
热议问题