疏化过程中不需要的分支

Unwanted branches in thinning process

我正在尝试编写代码来细化图像,并且在一定程度上得到了输出。但最终输出仍然有一些从不同区域出现的不需要的小线条。我的下一步是找到交点。由于这些细线,我得到的点实际上不是交点。我怎样才能改进我的代码以避免这些行。

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');

输入:

输出:

所需图片:

我的方法包含三个关键步骤

  1. 识别线之间的交点。 bwmorph 有一个 branchpoint 选项,但它不够激进。我用 conv2 代替
  2. 来计算相邻像素
  3. 使用 bwconncomp
  4. 将像素分组为线段
  5. 使用阈值删除小线段,同时检查图像是否保持连接。

我使用了 10 像素的简单阈值。如果你想要一个自适应阈值,你可以使用一个相对于中值或平均线段长度的度量。选择阈值在很大程度上取决于您的数据集中有多少变化。如果变化太多,您可能需要对每张图片进行人工交互。


%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);

输出图像与您想要的输出非常相似

我在做指静脉识别的时候遇到过类似的骨架图问题

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

结果会是这样

Orignal Skelton Image

After Applying this function