Image processing for calculating length between two points on an image.

Hello,
I am investigating a soltuion for calculating the width of cracks in lithium-ion batteries that have been damaged. I have CT scans of cross sections of the batteries, and I am looking to use MATLAB Image Processing Toolbox to calculate the width of the crack from these images.
So far, I have worked to isolate the battery casing from the image using some image processing functions, including segmenting the image with a global threshold and then retaining the object with the largest perimeter (the battery casing) using the bwpropfilt function. The code I have used for this is below.
I = imread('2D top view_310822_1238.jpg');
imshow(I)
title('Original CT Scan');
Igray = rgb2gray(I);
imshow(Igray)
Igray2 = imadjust(Igray);
imshow(Igray2)
BW = imbinarize(Igray2,"global");
imshow(BW)
BW2 = bwpropfilt(BW, 'perimeter', 1);
figure;
imshow(BW2)
I have also attached images of the original CT scan and the image BW2.
What I would now like to do is to calculate the point-to-point distance between the two ends of the battery casing. I have attached a third image, "Question_demonstration", to demonstrate this question.
Therefore, can somebody please suggest solutions to this problem?

 Accepted Answer

load BW2
[I,J]=find(bwmorph(bwskel(BW2),'endpoints'));
[~,k]=mink(J,2);
d=norm([ diff(I(k)), diff(J(k))])
d = 607.2833

11 Comments

@Elliott Read it's not necessary to call imadjust before calling imbinarize.
@Image Analyst okay thank you. Is that a general rule or is it just applicable for this case?
@Matt J thank you for your answer and speed of response. However, when running your code in my live script, I get a different value for d, of 911.6123. Do you know what could cause this? I noticed that the bwmorph function generates 10 endpoints for this image, when I am only interested in the two that I have mentioned. Could this be something to do with it?
Also, can you please provide some instructions for how to impose the line and value that you have drawn for d on the binary image?
However, when running your code in my live script, I get a different value for d, of 911.6123. Do you know what could cause this?
Yes, I have a pretty good idea. You didn't provide us with a .mat file with the image you are actually using (tsk tsk). You provided us with a .jpg screenshot whose pixelization is different.
I noticed that the bwmorph function generates 10 endpoints for this image, when I am only interested in the two that I have mentioned.
The code finds those two out with mink.
Also, can you please provide some instructions for how to impose the line and value that you have drawn for d on the binary image?
It was hand-drawn with drawline. You could also use imdistline.
@Matt J I had a suspicion it might be that, thank you for clearing that up. Apologies for not providing the .mat file, I am relatively new to MATLAB, so the implications of some of the nuances such as that I am ignorant to.
Thanks for letting me know about the drawline function and imdistline object, that's most useful.
Going back to the point about the endpoints, is there a way to clean up the skeletonized image so that only the two endpoints that I am interested are found? (i.e. is there a way to remove the other end points from the image?). Currently, I believe that the mink works by selecting the two endpoints that are the leftmost in the image. Although the code seems to work for this image, I have thousands of cross section images that I plan to run this code on using batch processing, and this selection criteria for the endpoints doesn't always select the correct ones (see the other CT scan that I have just attached, for example). From this I think I need to either remove the other endpoints, or improve the selection criteria so that the correct ones are always selected. Can you help with that?
Your help with this is much appreciated.
Perhaps as follows?
load BW2
[I,J]=find(bwskel(BW2));
Im=median(unique(I));
up=I<=Im; down=I>=Im;
[I1,J1]=deal(I(up), J(up));
[I2,J2]=deal(I(down), J(down));
[~,k1]=min(J1);
[~,k2]=min(J2);
tip1=[I1(k1), J1(k1)]
tip1 = 1×2
346 462
tip2=[I2(k2), J2(k2)]
tip2 = 1×2
950 390
d=norm(tip1-tip2)
d = 608.2763
@Matt J thanks again for your reply. The code you have suggested does indeed work for some of the images, but unfortunately not all of them. I will continue to play around with it and will hopefully determine a universal solution for all my cases. Your input has been most useful and you did answer the question to my original post, so thanks for that! I'll mark your answer as accepted. Thanks again :)
@Matt J FYI, I think I found a solution. The bwskel function accepts additional inputs to define the minimum branch length, which can be used to prune some of the shorter branches on the skeleton image. I found this in the documentation for the bwskel function.
That is interesting, but I am surprised that it would be necessary to limit the branch lengths of bwskel for my revised solution to work. I would be interested to see the BW2 example that causes the solution as I proposed it to fail (but if you elect to provide it, please do so in .mat file form).
I might not have been the clearest - I used your original solution combined with limiting the branch lengths to get something that worked. However, I have now noticed that neither that solution, or the revised one that you proposed work for cases of CT scans of other batteries. The orientation of the batteries changes between the different battery scans, and I think this affects the way the code computes the d value. I have attached two more examples of BW2 (for two different batteries) along with their associated original CT scan images, I. They're in .mat format, so I hope I have provided them correctly.
I'm not sure how to proceed with this one. My mind turns to some sort of machine learning algorithm so that the true "ends" of the battery casing can be detected.
Let me know if you have any other thoughts.
One of your example BW2s seems to be completely closed. Where are the endpoints needed to calculate d in this example,
imshow( load('300822_BW2.mat').BW2 )
Apologies, you're right. The original image seems not to have been binarized well. I have just generated another binary image using the color thresholder app that seems to generate a much better binary image. I have attached it here. Thanks.

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2023b

Community Treasure Hunt

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

Start Hunting!