How to get a deformable mesh from this binarized image?
UPDATE 2
As I found in this answer, using MorphologicalTransform
instead of ImageFilter
gives performance gain and also works correctly in latest versions of Mathematica.
Also it is worth to note that the method suggested in the previous section gives false operations in situations like this (note the central part of the image):
img = Import["http://i.stack.imgur.com/2a2j6.png"];
Image[#, Magnification -> 8] & /@ {i = ImageTake[img, {493, 505}, {10, 20}],
MorphologicalTransform[i, If[#[[2, 2]] == 1 && Total[#, 2] == 3, 1, 0] &]}
This problem can be solved by applying Thinning
first:
Image[#, Magnification -> 8] & /@ {i = Thinning@ImageTake[img, {493, 505}, {10, 20}],
MorphologicalTransform[i, If[#[[2, 2]] == 1 && Total[#, 2] == 3, 1, 0] &]}
Also (if desirable) it is possible to avoid removal of the end points by slight modification of the filtering function:
Image[#, Magnification -> 8] & /@ {i = Thinning@ImageTake[img, {493, 505}, {10, 20}],
MorphologicalTransform[i, If[#[[2, 2]] == 1 && Total[#, 2] <= 3, 1, 0] &]}
UPDATE
The method of deleting the branch points in the original answer was quite crude, here is correct and more efficient approach based on ImageFilter
. Unfortunately it doesn't work in the most recent versions of Mathematica due to a bug introduced in version 9. But with version 8.0.4 it works nicely:
img = Pruning[Thinning[Binarize@ImageCrop@Import["http://i.stack.imgur.com/qYhEr.png"]],
1];
img2 = ImageFilter[If[#[[2, 2]] == 1 && Total[#, 2] == 3, 1, 0] &, img, 1];
edges = MorphologicalComponents[img2];
edges // Colorize
Here is a workaround which allows to use this method with recent (buggy) versions of ImageFilter
:
img2 = ImageFilter[If[#[[3, 3]] == 1 && Total[#[[2 ;; -2, 2 ;; -2]], 2] == 3, 1, 0] &, img, 2]
Original answer
(Not a complete answer but it could be a start.)
Here is how I would approach such a task. I'll show only an interactive approach for deleting and adding edges, but it can be extended for deformation of the edges (requires more work though).
First of all, I find the branch points:
img = Pruning[Thinning[Binarize@ImageCrop@Import["http://i.stack.imgur.com/qYhEr.png"]],
1];
branchPoints =
ImageValuePositions[MorphologicalTransform[img, "SkeletonBranchPoints"], White];
Now I delete them from the image and highlight the edges:
img2 = HighlightImage[img, {Opacity[1], Black, Disk[#, 1.6] & /@ branchPoints}];
edges = MorphologicalComponents[img2];
edges // Colorize
Then I transform it into a Graphics
object:
Graphics[GeometricTransformation[{RandomColor[], Point[Position[edges, #]]} & /@
Range[Max[edges]], {{0, 1}, {-1, 0}}], ImageSize -> 800]
I can easily select any edge by double-clicking on it:
... and then delete it by pressing Del:
Then it is easy to get the indices of the remaining edges back:
You also can draw new edges using the Freehand line tool of the Drawing Tools palette:
The line drawn can be extracted by applying Cases[#, edge_Line :> First@edge, Infinity] &
(but be aware that you'll need to convert obtained coordinates into indices using the inverse of the GeometricTransformation
used above):
Of course this approach can be extended further using Dynamic
functionality which allows interactive manipulations with the data.