MATLAB: How to get a centerline from a contour

centerline

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

Best Answer

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