# How to highlight image edge with spline/bezier when mouse moved over?

It is known that EdgeDetect can find image edges in an image. Suppose the image edges consists of sets of lines. Can the detected edge line near the mouse pointer be highlighted as spline/bezier when mouse moves over, so that i can change the bezier shape by drag the mouse?

(manually highlighting is time-consuming and not accurate, so I want to automatically highlight some part of the edges first, then I can manually change it.)

## Update 2014/10/15:

bobthechemist's answer solve part of the question for contour image. Can that be possible when mouse click some position of the grayscale image or true color image?

Here is my code learning from bobthechemist, but it doesn't work. why?

i = ExampleData[{"TestImage", "Lena"}];
ia = ImageData[i, Interleaving -> False][[2]];
im = EdgeDetect[i, 5];
imm = MorphologicalComponents[im];
{n, m} = Dimensions@imm;
trans[{x_, y_}] := {Max[1, Min[n, Floor[n - y] + 1]], Max[1, Min[m, Floor@x + 1]]};

DynamicModule[{ncurve},
EventHandler[
ImageCompose[Image[ia], Graphics[ListLinePlot[ncurve]]],
{"MouseClicked" :>
(ncurve = Position[imm, imm[[##]] & @@ trans@(MousePosition[] /. None -> {0, 0})])}]]


There must be some grammar issue for the last line as it raised two error information:

Union::normal: Nonatomic expression expected at position 1 in Union[ncurve$3420]. ListLinePlot::lpn: ncurve$3420 is not a list of numbers or pairs of numbers.

The result is expected that when mouse click at the grayscale image, the corresponding edge found by MorphologicalComponents at the position should be highlighted or plotted.

I think you are asking for a rather sophisticated project in this question, and it is probably too broad. However, here's one way to approach the highlighting of lines.

im = EdgeDetect[ExampleData[{"TestImage", "Lena"}], 5];
imm = MorphologicalComponents[im];
trans[{x_, y_}] := {Max[1, Min[n, Floor[n - y] + 1]],
Max[1, Min[m, Floor@x + 1]]};
rep[mat_, val_Integer] := If[val == 0, mat, mat /. {val -> 1000}];
{n, m} = Dimensions@imm;
Dynamic@MatrixPlot[
rep[imm, imm[[##]] & @@
trans@(MousePosition["Graphics"] /. None -> {0, 0})],
Frame -> False, ImageSize -> 800]


Don't expect high response times from this code, especially if your images are large. What I've done here is use MorphologicalComponents to create a matrix of connections. Then I stole copiously from this answer to convert a Dynamic@MousePosition@"Graphics" into a number that corresponds to the lines in the image. (Note, there are Union@Flatten@imm lines or connections in the image.) rep is there just to avoid the screen wonking out when it tries to replace all the zero values with my highlighter color.

It should be possible to alter rep to remove the MatrixPlot artistic shading of Lena; however, that would come with a decent performance hit with the code as written. Extracting an interpolating BSpline from the highlighted portion of the image will have to wait until after lunch.

Lunch is over - now get the points for each of the lines found from MorphologicalComponents. I'm also converting from Image coordinates to plotting coordinates:

lenapts = {#[[1]], m - #[[2]]} & /@ (Reverse /@ Position[imm, #]) & /@
Rest@Union@Flatten@imm;
ListPlot[lenapts, AspectRatio -> 1]


Last, we can turn each of these (213 in my case) lines into BSpline to do whatever it is you want to do. Warning, though, some of them are funky as shown below.

Graphics@(BSplineCurve /@ lenapts)


• Thank you, bobthechemmist. You really give me very useful hints. – xibinke Oct 14 '14 at 14:31