How to do this image transformation?

前端 未结 2 921
感情败类
感情败类 2020-11-28 15:55

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\'

2条回答
  •  自闭症患者
    2020-11-28 16:55

    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.

提交回复
热议问题