13
$\begingroup$

I want to use Mathematica to turn a picture into low poly style. That is, to make the following conversion: Bill to Bill low poly(Using Image Triangulator App).

I think the biggest difficulty is how to extract the points on the boundaries of different colors appropriately. Too much points make the output picture messy, while the picture generated by too little points are not beautiful.

And then, after I have extract the points of the original picture, how to turn the original picture to the low poly style? Is using DelaunayMesh possible? Or, extract the color of a certain point in a triangle(using ImageValue or some functions similar) and make it to be the main color of the triangle?

Edit: No, I don't think that the answers in artistic image vectorization fit my problem. Because you can see that the question is not using Delaunay mesh or other triangular mesh.

$\endgroup$
5
  • 1
    $\begingroup$ You could build on top of this previous answer by Simon Woods: "This vectorisation attempts to represent the image with coloured triangles." $\endgroup$ Commented Sep 11, 2014 at 4:13
  • $\begingroup$ It is amazing, and I will have a try. Thank you.@RahulNarain $\endgroup$ Commented Sep 11, 2014 at 5:03
  • 1
    $\begingroup$ possible duplicate of Artistic image vectorization $\endgroup$ Commented Sep 11, 2014 at 9:31
  • 4
    $\begingroup$ @m_goldberg would not entirely agree - this question is more specific, while the alleged dupe was (originally) about hi-res printing. $\endgroup$ Commented Sep 11, 2014 at 10:31
  • 1
    $\begingroup$ Google en.wikipedia.org/wiki/Robert_Delaunay. Great question for art lovers (and, hopefully, some mathematicians too). $\endgroup$ Commented Sep 11, 2014 at 20:28

2 Answers 2

7
$\begingroup$

My take on this, with some inspiration from shrx's great answer. I pick points randomly, but weighted by the image gradient to try to get more points on edges in the image. Then I use a Delaunay triangulation so that those edges are maintained in the mesh. Finally I colour it by taking the single pixel value at the centre of each triangle (rather than the slower but more accurate averaging approach used by shrx).

i = ExampleData[{"TestImage", "House"}]; n = 1000; {x, y} = ImageDimensions[i]; pts = Reverse /@ RandomChoice[ Flatten @ ImageData @ GradientFilter[i, 2] -> Tuples @ {Range[y, 1, -1], Range[x]}, n]; pts = Join[pts, {{0, 0}, {x, 0}, {x, y}, {0, y}}]; m = DelaunayMesh @ pts; Graphics[With[{col = RGBColor @ ImageValue[i, Mean @@ #]}, {EdgeForm @ col, col, #}] & /@ MeshPrimitives[m, 2]] 

enter image description here

$\endgroup$
1
  • $\begingroup$ I have tested several images to compare your code with shrx's, and I think your code runs faster and takes up less system resources. And your output is more similar to the original picture, great job! $\endgroup$ Commented Sep 12, 2014 at 5:38
8
$\begingroup$
i = ExampleData[{"TestImage", "Mandrill"}]; id = ImageDimensions[i]; 

Create some keypoints and use them to make a triangular mesh:

xy = ImageKeypoints[i, MaxFeatures -> 50]; m = VoronoiMesh[xy, {0, #} & /@ id]; mt = TriangulateMesh[#, MaxCellMeasure -> ∞, MeshQualityGoal -> "Minimal"] & /@ Map[MeshRegion[MeshCoordinates[m], #] &, MeshCells[m, 2]]; p = Flatten[MeshPrimitives[#, 2] & /@ mt]; 

Create masks for calculations of mean color of triangles:

bp = Transpose[{Table[Black, {Length[p]}], p}]; masks = ParallelTable[ Rasterize[ Graphics[{EdgeForm[Black], ReplacePart[bp, {n, 1} -> White]}, PlotRangePadding -> None], ImageSize -> id], {n, Length[p]}]; c = ParallelMap[ RGBColor @@ ImageMeasurements[i, "Mean", Masking -> Opening[#, 1]] &, masks]; 

Put the colored triangles together:

Graphics[Transpose[{c, EdgeForm /@ c, p}], PlotRangePadding -> None] 

triangulated picture

$\endgroup$
4
  • $\begingroup$ Wonderful, very cubistic! +1 $\endgroup$ Commented Sep 11, 2014 at 17:13
  • $\begingroup$ Excellent, much better than the original :D $\endgroup$ Commented Sep 11, 2014 at 18:01
  • $\begingroup$ Your answer is good, but there is a little regret that it runs a little bit slow and takes up a lot of system resources. How should I optimize it? $\endgroup$ Commented Sep 12, 2014 at 5:46
  • $\begingroup$ Determining the mean color of each triangle takes most of the time and resources. There are different ways to speed it up: you can scale down your image, or you can use a combination of ColorQuantize and DominantColors insteand of ImageMeasurements for each triangle, or you can just take the color from the center of each triangle, like @Simon Woods did in his approach. $\endgroup$ Commented Sep 12, 2014 at 11:32

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.