How to get a centerline from a contour ?

5 visualizzazioni (ultimi 30 giorni)
MMSAAH
MMSAAH il 26 Lug 2019
Modificato: Rik il 31 Lug 2019
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');

Risposta accettata

Rik
Rik il 26 Lug 2019
Modificato: Rik il 31 Lug 2019
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 Commenti
MMSAAH
MMSAAH il 31 Lug 2019
It doesn't work even when I change by 1:size(result,2)
Rik
Rik il 31 Lug 2019
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.

Accedi per commentare.

Più risposte (0)

Community Treasure Hunt

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

Start Hunting!

Translated by