疏化过程中不需要的分支
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');
输入:
输出:
所需图片:
我的方法包含三个关键步骤
- 识别线之间的交点。
bwmorph
有一个 branchpoint
选项,但它不够激进。我用 conv2
代替 来计算相邻像素
- 使用
bwconncomp
将像素分组为线段
- 使用阈值删除小线段,同时检查图像是否保持连接。
我使用了 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
我正在尝试编写代码来细化图像,并且在一定程度上得到了输出。但最终输出仍然有一些从不同区域出现的不需要的小线条。我的下一步是找到交点。由于这些细线,我得到的点实际上不是交点。我怎样才能改进我的代码以避免这些行。
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');
输入:
输出:
所需图片:
我的方法包含三个关键步骤
- 识别线之间的交点。
bwmorph
有一个branchpoint
选项,但它不够激进。我用conv2
代替 来计算相邻像素
- 使用
bwconncomp
将像素分组为线段
- 使用阈值删除小线段,同时检查图像是否保持连接。
我使用了 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