How to redistribute pixels?

Tony D (view profile)

on 26 Jan 2013

Posted is a picture of a cross section of a vein. I have transformed the red interior line into a circle and need to have the pixels on the black line surround the new circular red line, both red and black lines having the same centers. The transformed black line should not be a perfect circle. As you can see in the picture, the distance between the black and red lines differ and once the black line is transformed, it should maintain the same varying distance between it and the red line as before. My question is how can I do this?

Products

Image Analyst (view profile)

on 27 Jan 2013

It's not too hard if you think about it systematically. Just take it one step at a time. The key is to convert the lines into masks and use bwdist().

2. use poly2mask on the red line to get a smaller mask
3. subtract the two masks to get the "in between" region.
4. call bwdist() to get the Euclidean Distance Transform (EDT). This is the distance from the region to the nearest edge, so twice that is the thickness of the region at that point. So multiply the EDT by 2.
5. call bwmorph() to get the skeleton. This is the centerline of the region.
6. Multiply the skeleton by the EDT. This will give you the thickness of the region.
7. bwdist will also give you the pixel on the red line that is closest to the black line.
8. Now you know the radius and center of the red circle. Radius is just perimeter/(2*pi). So you just run around the black circle, and get the red pixel that is closest to it.
9. You know the position of each red pixel - it's index on the circle. So you plot a red point there, and then plot a black point at that red radius plus 2*EDT for that black pixel.

Image Analyst

Image Analyst (view profile)

on 29 Jan 2013

(4) The region thickness is twice the EDT value at the center. Let's say you had a region 20 pixels wide. Well, at the center it will be 10 pixels to either side because if you're at the center line it has to go only half the thickness to get outside the region. So you need to double the value at the center to get the full thickness.

6) You multiply by the skeleton to give you the value along the centerline of the region. The EDT you get in (4) is a thick image. It's like a wide swatch the same size as the region in between your two curves. And the values of the EDT go from 0 or 1 at the edge (where a pixel inside the swath does not have far to go to get outside) all the way to half the thickness at the centerline. If you're 3 pixels away from the background, the EDT value is 3, if you're 4 pixels away it's 5, if you're 5 pixels away it's 5, and so on until you're the radius (half thickness) away from the edge. If you proceed toward the other side, it starts going down again until it again reaches 0 at the other edge (boundary).

Think of it like this. You're taking an inflatable ball and running it along the region between the two lines. The ball is always inflated as much as it can go and still be a circle. Sometimes, when the thickness is large, you can fit a large ball, and sometimes, when the thickness is small, you'll have a small ball. The EDT along the centerline (skeleton, spine) is the radius of the ball at that point.

Does that explain it better?

Tony D

Tony D (view profile)

on 30 Jan 2013

Thanks for the clarification, I understand what the EDT and skeleton are now. So far I have: #1 created the masks #2 gotten the "in between" region and made it hollow #3 did a EDT calc between the two boundary lines of the region #4 found the skeleton of the hollow region #5 removed the branches from the skeleton (don't know purpose of branches) #6 found the perimeter of the region that will be transformed in a circle #7 used that perimeter to find the diameter for the transformed circle

When I did the EDT it gave me a giant "logic" matrix. So now how can I use MATLAB to go through all of the pixels on a boundary of the matrix and find the distance to the nearest pixel on the opposing line?

Tony D

Tony D (view profile)

on 30 Jan 2013

Or is there a way of taking a pixel on a line, lets say the black line, and then find the shortest path to the red line and storing that path as a vector?

Matt J (view profile)

on 4 Feb 2013

So now how can I use MATLAB to go through all of the pixels on a boundary of the matrix and find the distance to the nearest pixel on the opposing line?

If the rows of A are the pixel coordinates on the black line and B the red line, then you can use

http://www.mathworks.com/matlabcentral/fileexchange/18937-ipdm-inter-point-distance-matrix

as follows

s=ipdm(A,B,'Subset', 'NearestNeighbor','Result','Structure');

Then s.columnindex will be the indices in B of the closest points on the red line. The corresponding distances will be in s.distance.

When run with this specific syntax, the column index is what will be most useful. It tells you that

B(short_dist.columnindex(i), :)

is the closest point on the red line to A(i,:). And if you want the vector between the two points, just do

B(short_dist.columnindex(i), :) - A(i,:)

for all i=1...1856. Or, in vectorized form, simply

B(short_dist.columnindex, :) - A

Matt J

Matt J (view profile)

on 8 Jun 2013

For now, compressibility effects are assumed to be non existent. All I want for this first transformation is to preserve the distance and area between the two curves, make the black line circular,

I was just looking back at March 11. It seems like you were implying here that incompressibility implies the preservation of curve separation "distance", however that's supposed to be defined (I still think you haven't supplied a definition). Incompressibility obviously implies that the total area does not change (as long as the density of the material between the curves is uniform), but there is no clear distance preservation rule that this implies, as far as I can see, even combined with the fact that the outer curve's perimeter does not change.

As a counter-example, consider the case of 2 concentric squares with corresponding edges parallel. Let the outer square have area=2 and the inner square have area=1. Now transform by rotating the inner square 45 degrees so that its corners are now touching the centers of the sides of the outer square. It is simple to verify that the total area separating the squares has not changed, and obviously the outer square's perimeter hasn't changed. The transformation is also 1-1.

However, separation distances between the curves have obviously changed. For one thing, the minimum distance between the curves as now zero, i.e., where the inner square's corners touch the outer square. Corresponding points before and after the transformation, have also changed in separation distance, regardless of how you define that correspondence. For example, let's suppose that point A on the outer square corresponds to point B on the inner square (pre-transformation) if they have the same polar coordinate theta. Thus, initially, the corners of the outer square correspond with the corners of the inner square. The distance from the outer to inner corners changes from 0.2929 to 0.7071 after the rotation, however.

Conclusion: Non-compressibility plus constant outer perimeter doesn't imply separation distance preservation. So why are you pursuing it?

Tony D

Tony D (view profile)

on 10 Jun 2013

Well, if you perform the transform on a single pair of points at the command line, you should be able to find them on the before/after plots just by looking at the coordinates that the transformation gives you.

I was looking for a more efficient way than visual inspection. Maybe plotting individual points? I would just use the IPDM output to track the points?

Non-compressibility plus constant outer perimeter doesn't imply separation distance preservation. So why are you pursuing it?

The transformation process from beginning to end has many steps. In the first couple of steps I wanted to only take the deformed boundary layers that were folded in and just make them circular. This transformation would be similar to taking a wet spaghetti noodle and moving it (without stretching) to make a circle.

To do this, it would take two steps. First, I wanted to remap the curves based on pre-transform distance. Then, I would change the spacing between the two curves so that the areas between the two curves post-transform were the same as pre-transform (I know that doing this would then change the distances between the two curves and that is OK, because what I mainly cared about was area conservation). So for this part I am not applying a internal pressure that would stretch the curves, so no bio-mechanical laws are needed here in the first steps.

Then, one of the last steps is to take this circular geometry and apply a internal pressure. This will stretch the curves and so the bio-mechanical laws are needed here.

Matt J

Matt J (view profile)

on 10 Jun 2013

I was looking for a more efficient way than visual inspection. Maybe plotting individual points? I would just use the IPDM output to track the points?

It's not really clear to me what you're trying to "track". Are you just trying to verify that a pair of points A and B have the same separation distance after transformation? If so, you could just transform an individual pair of points and use the norm() function to verify that distance has remained the same.

This transformation would be similar to taking a wet spaghetti noodle and moving it (without stretching) to make a circle.

Okay. But what I was saying at that time is that the ability of wet spaghetti noodle to behave so malleably, and yet not dissipate completely like a gas, is probably still due to mechanical laws that aren't trivial. Otherwise, other things (e.g., dry spaghetti noodles and gas) would be able to do so as well. If we knew what those mechanical laws were, we might have better luck at identifying the "wet spaghetti noodle transform" in mathematical form :-)

It also seems to me that wet spaghetti must have some ability to stretch/compress to allow it to reshape as it can, and that lengths/distances aren't perfectly preserved when it does so. For example, if you lay a spaghetti noodle out straight on a table, the length of the noodle is the same, no matter along which edge of the noodle you measure the length. However, if you then join the tips and reshape the noodle into a circle, then obviously the outer edge has a longer circumference than the inner edge. So, obviously lengths/distances have changed somewhere.

Join the 15-year community celebration.

Play games and win prizes!

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi