ANUSHA DEVI
ANUSHA DEVI

Reputation: 225

Unwanted branches in thinning process

I was trying to code for thinning an image and to an extent I got an output. But still the final output does have some small unwanted lines emerging from different areas. My next step was to find intersection points. Because of these small lines, I get points which are actually not intersection points. How can I improve my code in order to avoid those lines.

I = imread('img.jpg');
I = rgb2gray(I);
I = uint8(255*mat2gray(I));
I=imresize(I,[128 128]);

I1=edge(I,'canny',0.6);
I2=edge(I,'canny',0.1);
I = imsubtract(I2,I1);


si = imdilate(I,strel('line',3,0));
se = imerode(I,strel('line',3,0));
I = imsubtract(si,se);

si = imdilate(I,strel('disk',1));
se = imerode(I,strel('disk',3));
I = imsubtract(si,se);

I = imfill(I,'holes');


[L num]=bwlabel(I); %%number of connected objects found in binary%%%
A=[];
for i=1:num
    a=find(L==i);
    A(i)=size(a,1);
end
[b indxA]=max(A);

L2(128,128)=0;

for i=1:num
   if A(i)>=0.9*b
      L2(find(L==i))=1;
   end
end

I = imerode(L2,strel('disk',1));
I = bwmorph(I,'skel',Inf);

[i,j] = ind2sub(size(I),find(bwmorph(bwmorph(I,'thin',Inf),'branchpoint') == 1));
figure,imshow(I); hold on; plot(j,i,'rx');

Input:

enter image description here

Output:

enter image description here

Required img:

enter image description here

Upvotes: 1

Views: 1909

Answers (2)

Maaz Anzar
Maaz Anzar

Reputation: 141

I had a similar problem with skeleton image when i was working with finger vein recognition

function [ unbrachImg ] = removingSmallBraches( image ,brnchsize)
%Removing Small Branches from skelton image and also removes small loops 
%   Detailed explanation goes here

% image=bwmorph(bwmorph(image,'dilate',1),'erode',1);
% 
% image=bwmorph(bwmorph(image,'dilate',1),'skel','Inf');

Dmask=zeros(size(image));
B =  bwmorph(image,'branchpoints');
D = bwdistgeodesic(image,find(B),'quasi');
    Dmask(D < 2) =true;
    skelD=image-Dmask;

img1=bwmorph(image,'spur',brnchsize);

Dmask=zeros(size(img1));
B =  bwmorph(img1,'branchpoints');
D = bwdistgeodesic(img1,find(B),'quasi');
    Dmask(D < 2) =true;
    Dmask1=img1-Dmask;
brach=xor(img1,Dmask1);

unbrachImg=bwareaopen( skelD|brach|Dmask1,10);

unbrachImg=bwareaopen(unbrachImg,10);


end

It will result like that

Orignal Skelton Image

After Applying this function

Upvotes: 0

Cecilia
Cecilia

Reputation: 4721

My approach has three key steps

  1. Identify intersections between lines. bwmorph has a branchpoint option, but it wasn't aggressive enough. I used conv2 to count neighboring pixels instead
  2. Group pixels into line segments using bwconncomp
  3. Use threshold to remove small line segments while checking that the image remains connected.

I've used a simple threshold of 10 pixels. If you want an adaptive threshold, you could use a metric relative to the length of the median or mean line segment. Choosing the threshold depends greatly on how much variation you have in your dataset. If there is too much variation, you might need human interaction for each image.


%Start off with your code above then do the following

%I got a better starting image with the 'thin' option than the 'skel' option
I = bwmorph(I,'thin',Inf);

%Alternative splitting method to 'branchpoint'
%Use convolution to identify points with more than 2 neighboring pixels
filter = [1 1 1;
          1 0 1;
          1 1 1];

I_disconnect = I & ~(I & conv2(double(I), filter, 'same')>2);

cc = bwconncomp(I_disconnect);
numPixels = cellfun(@numel,cc.PixelIdxList);
[sorted_px, ind] = sort(numPixels);

%Remove components shorter than threshold
threshold  = 10;
for ii=ind(sorted_px<threshold)
    cur_comp = cc.PixelIdxList{ii};
    I(cur_comp) = 0; 

    %Before removing component, check whether image is still connected
    full_cc = bwconncomp(I);
    if full_cc.NumObjects>1
        I(cur_comp) = 1; 
    end
end

%Clean up left over spurs
I = bwmoph(I, 'spur');
figure; imshow(I);

The output image is very similar to your desired output

Output image

Upvotes: 2

Related Questions