How to get a centerline from a contour ?

13 次查看(过去 30 天)
Hello,
I want to get the centerline from a "cable orig image".
I tested the following code but I got wrong centerline (skeletonized image).
Could anyone help me correcting the code ?
Thanks in advance.
I=Data;
figure
imshow(I,[]);
title('cable orig image')
I=bwmorph(I,'remove'); % remove interior pixels
figure
imshow(I,[]);
title('exterior contour');
binaryImage = imfill(I, 'holes');
figure
imshow(binaryImage, []);
title('filled Image');
skeletonizedImage = bwmorph(binaryImage, 'skel', inf);
figure
imshow(skeletonizedImage);
title('Skeletonized Image');

采纳的回答

Rik
Rik 2019-7-26
编辑:Rik 2019-7-31
First let's load the image into a usable format. You already have code to get binaryImage, so you can use that.
%% read image
I=imread('filled image.jpg');
I=I(29:540,84:595,1);%cut out border
binaryImage=I>128;
Method 1 will probably not have a good performance, but as an approximation you could loop through the rows of the filled image and find the mean position.
result = false(size(binaryImage));
for row=1:size(binaryImage,1)
if any(binaryImage(row,:))%correct for empty lines in the image
ind=round(mean(find(binaryImage(row,:))));
result(row, ind)=true;
end
end
You can improve on this method by using bwdist on the flipped image and find the maximum value in each row. You can use the second output of the max function to improve performance by avoiding a loop. Because an IM(1:3,[2 1 3]) style syntax will set 9 elements, not 3, we need linear indices. We also need to correct for empty lines in the image, where max will return 1.
dist2edge=bwdist(~binaryImage);
result = false(size(binaryImage));
[~,ind]=max(dist2edge,[],2);
rowSub=(1:size(result,1))';%transpose to make the shape match ind
colSub=ind;
linind=sub2ind(size(result), rowSub, colSub);
result(linind)=true;
result(~binaryImage)=false;%correct for empty lines in the image
In summary, with a display section:
%% read image
I=imread('filled image.jpg');
I=I(29:540,84:595,1);%cut out border
binaryImage=I>128;
%% method 1
result = false(size(binaryImage));
for row=1:size(binaryImage,1)
if any(binaryImage(row,:))%correct for empty lines in the image
ind=round(mean(find(binaryImage(row,:))));
result(row, ind)=true;
end
end
method1=result;
%% method 2
dist2edge=bwdist(~binaryImage);
result = false(size(binaryImage));
[~,ind]=max(dist2edge,[],2);
rowSub=(1:size(result,1))';%transpose to make the shape match ind
colSub=ind;
linind=sub2ind(size(result), rowSub, colSub);
result(linind)=true;
result(~binaryImage)=false;%correct for empty lines in the image
method2=result;
%% display
merged1=cat(3,binaryImage,method1,false(size(binaryImage)));
merged1=double(merged1);
merged2=cat(3,binaryImage,method2,false(size(binaryImage)));
merged2=double(merged2);
figure(1),clf(1)
subplot(2,3,[1 4])
imshow(binaryImage)
title('binary image')
subplot(2,3,2)
imshow(method1)
title('skeletonized image (method 1)')
subplot(2,3,3)
imshow(merged1)
title('merged image (method 1)')
subplot(2,3,5)
imshow(method2)
title('skeletonized image (method 2)')
subplot(2,3,6)
imshow(merged2)
title('merged image (method 2)')
  6 个评论
MMSAAH
MMSAAH 2019-7-31
It doesn't work even when I change by 1:size(result,2)
Rik
Rik 2019-7-31
The number of elements was correct, just not the shape of the two vectors. I'll edit my answer so it works. I tested it with the image you've attached, which wasn't ideal, because jpg is not a lossless format, nor were they actually original images.

请先登录,再进行评论。

更多回答(0 个)

标签

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by