I have an image with a colorized blob that has fuzzy edges (top half), and I want to create an outline for it made of straight lines (bottom half):
I don\'
Not really a complete answer, but maybe enough to get you started, or enough to make someone else comment and add in some more ideas - and no-one said answers had to be complete anyway.
I used ImageMagick just from the command line to segment your image into three - the blurred grey-red is a bit of a pain if you try and do a simple colour-reduction to three colours. ImageMagick is installed on most Linux distros and is available for OSX and Windows.
First, I want to make all the grey in the top-left of the image one shade of yellow. Then I want to make all the black in the bottom-right of the image another, slightly different shade of yellow. Then I want to make everything that is not remotely yellow into red. Each sentence above corresponds to one line of code below:
convert wave.jpg \
-fuzz 50% -fill "rgb(255,255,0)" -opaque white \
-fuzz 20% -fill "rgb(250,250,0)" -opaque black \
-fuzz 10% -fill red +opaque yellow result.png
Now I can change the two temporary shades of yellow back into white and black:
convert result.png -fuzz 0 \
-fill white -opaque "rgb(255,255,0)" \
-fill black -opaque "rgb(250,250,0)" result2.png
And then I can smooth the jaggies with a median filter:
convert result2.png -median 25x25 result3.png
I can detect the edges now, using -edge
:
convert result3.png -edge 1 result4.png
Now you see how it works, you can do all that in one simple command:
convert wave.jpg \
-fuzz 50% -fill "rgb(255,255,0)" -opaque white \
-fuzz 20% -fill "rgb(250,250,0)" -opaque black \
-fuzz 10% -fill red +opaque yellow \
-fuzz 0 -fill white -opaque "rgb(255,255,0)" \
-fill black -opaque "rgb(250,250,0)" -median 25x25 -edge 1 result.png
Now, you can find all the points where a red pixel touches a white pixel - I would suggest you do that in Magick++ (the C++ binding of ImageMagick - though there are Ruby and Python and PHP bindings if you prefer) and put those points in a STL list and apply the Ramer–Douglas–Peucker algorithm to get line segments.
Then do likewise for all points where a red pixel touches a black pixel to get the line segments on the lower side.