Intensities along border of cylindrical object

Hi,
I want to measure and plot the intensities of a signal along the border of a cylindrical object.
The plot should be intensities over border length/coordinate. I have a lot of objects that kind of look like in the picture. They are orientated in all kinds of directions. My algorithm so far as an outline:
  • Segmentation of objects
  • Create label image
  • Get region properties via regionprops ( Here I'm mainly interested in all the ellipse related values)
  • Then for each objects get the Centroid and compute the point where the ellipse main axis intersects with the border of the object
  • Walk along the border of each object using bwtraceboundary
  • With these Locations measure intensities of these points
With this I have two major problems right now: First I get the centroid and compute the intersection point using MajorAxisLength*sind(Orientation) and *cosd(Orientation). But this gives me a numerical value like 4.8 22.4 What would a good way to find the nearest nonzero pixel of the perimeter image? (Image with only object border)
My second problem is that in this approach I will only get the intensities along a one pixel line. I would prefer to get the average along the line of a certain width, say 5 pixels. My idea would be to just do the trace, subtract the perimeter and then do the trace again so and so many times and then average the intensity values of corresponding values. But this sounds rather inefficient. Would there be a better way to address this?
Thank you very much for your help!

Réponses (1)

Image Analyst
Image Analyst le 27 Oct 2014

1 vote

I'd threshold, fill, find the centroid. Then use improfile() to send out rays from the centroid at a bunch of angles between 0 and 360 degrees. Then get the average of the non-zero values. Not too hard. Give it a shot. If you can't figure it out, come back and ask. Or if you need something more accurate (because the shape is not always perpendicular to the rays at the intersection point) - there are more complicated and accurate ways.

6 commentaires

David
David le 28 Oct 2014
Modifié(e) : David le 28 Oct 2014
I would need something more precise. Since the objects can vary significantly in length and I want to measure and compare the length of the white parts. That's why I had the idea to trace the outline and then let improfile work on the outline. But then it's only 1 pixel wide.
I have already implemented segmentation and region props. So that's not an issue.
So you have the ring segmented. Then you can skeletonize it to get the centerline. Then pick a point to start at. Then take a stretch of pixels along the skeleton, say 11 points. Put them into polyfit() to get the equation of a polynomial going through them, say a quadratic or cubic, using polyfit. You can construct the derivative of the polynomial using simple calculus. Knowing the locations of the coordinates and the coefficients from polyfit, you can determine the slope of the line at that point. Take -1/slope to get the slope of the perpendicular line. Using the point slope formula, get two endpoints of the perpendicular line that cut across the ring and call improfile. Get the mean of the non-zero parts of the profile. Then move on to the next point.
I have done this for one project so I know it's possible.
David
David le 31 Oct 2014
That's a great idea. First of all thank you for your help.
I'm having one problem while implementing it. I have my segmented ring and I thin it to the middle ring that's 1 pixel wide. When doing the profile I want to start always at the same point (relative to the structure). As I said I want to analyse multiple of these objects and they can be orientated in various angles. I tried implementing it the following way:
  • Take centroid and Orientation of ellipse fit via regionprops
  • Compute [cx,cy,c]=improfile(middle_ring_image,line) along line that starts at the centroid and goes to an endpoint way out of the object (e.g. 2*MajorAxisLength) for my middle ring picture (1px wide)
  • Find first nonzero value and its coordinates
The idea was to get the point that lies on the Major Axis of the object as a starting point for each object. But I have the problem that with varying angles improfile often does not find any nonzero values. I checked and the start and endpoints lie on opposing sides of the middle ring. But apparently improfile line passes right along the corner where two pixels meet and hence outputs zero as intensity value. Any other smart ways to find the nonzero value of the middle ring that lies on the major axis ? I thought about rotating the whole image by the orientation angle but this would mean I also have to rotate my signal image and I thought maybe there's a more efficient way.
Sorry but that approach won't work, as you discovered. You can't use the orientation, midpoint, or major axis of the whole ring to get cross sections. That's what I suggested first and you rejected saying it was too inaccurate for your needs. In order to get cross sections perpendicular to the local axis, you're going to have to do what I described. It works - I've done it, but it's not trivial. One watchout is that the endpoints will flip on either side of the ring if the local curvature changes sign, and that could mess up your profiles if you were summing them, for example to get an edge profile of an embossment or something. Since your path curves in just one direction, and because you wouldn't care anyway if the profile were reversed, you don't have to worry about that.
I was working on a general purpose method to get the average perpendicular profile along a hand-drawn path but the code seems to have vanished from my computer. I'll continue to look for it.
David
David le 31 Oct 2014
I feel like there's a misunderstanding. I'm trying to implement your second approach. As I said since it seems to be exactly what I need. So I want to take point on the middle ring. From this take some pixels ( say 5 in each direction) in clockwise and counterclockwise direction. Then do a polynomial fit. Then compute the perpendicular slope and then compute the average along this perpendicular curve and this is my intensity profile for this value. Then move on to the next pixel in counter clockwise direction and do the same thing again. In the end I will have an average intensity across the border for each point on the middle ring. This is fine. The only problem I'm facing is that I want to have a reproducible starting point. Meaning the first point on the middle ring where I will start this procedure. I don't want to take any point on the middle ring but rather one (of the two) that lies on the major axis of the ellipse. So I will get the same profile for the same object no matter at which angle it is orientated in space. (If I rotate my above image by 30° the algorithm should give me the exact same profile, not the profile shifted by a value). What would be a good way to find this point on my 1 pixel middle ring line?
David
David le 7 Nov 2014
Ok I solved the problem of finding a starting point by computing all the distances of points from the perimeter/middle line to a line corresponding to the major axis and choose the minimum value. I think there could be a smarter/more efficient way. Let me know if you know one. Now I will try to implement the polyfit.

Connectez-vous pour commenter.

Question posée :

le 26 Oct 2014

Commenté :

le 7 Nov 2014

Community Treasure Hunt

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

Start Hunting!

Translated by