
Show HN: Primitive Pictures - fogleman
https://github.com/fogleman/primitive
======
fogleman
Hi HN, OP here. I've tinkered with this problem a few times over the years,
but only now am I happy with the results. This time I wrote it in Go and
implemented things a bit differently that helped performance quite a bit.

I plan on implementing SVG output pretty soon. It won't be hard I just haven't
done it yet.

For the Twitter bot, I'm planning on adding another mode where it posts a GIF
showing the iterative progression of drawing an image.

Let me know if you have any questions or if you have ideas for other features!

~~~
gedy
This is great work! I've tinkered with another algorithm recently that gives
similar results: [http://imgur.com/a/djqnR](http://imgur.com/a/djqnR)

Will share another time, thanks again for the post.

~~~
anilgulecha
Very cool. One variation I'd like to see in the same algorithm is without the
padding or borders, just the gradient-ed quadrants.

------
TeMPOraL
So I wondered how this algorithm behaves when applied to its own output. I
know there won't be a fixed point because of random component, but here's the
program applied 11 times to itself, starting from a red dot:

[http://imgur.com/a/8Vs9z](http://imgur.com/a/8Vs9z)

~~~
fogleman
That's really interesting! I'm sure it'd be a bit different using circles. ;)

------
camtarn
I'm extremely short-sighted. After looking at all the pictures, and thinking
"Okay, that's pretty nifty," it occurred to me to try taking off my glasses
and viewing them again. The result is amazing :) All of the individual shapes
blur into invisibility, leaving only a very recognisable if fuzzy version of
the original image.

~~~
teddyh
That’s “near-sighted”, not “short-sighted”, which is another thing entirely.

~~~
petercooper
Near-sightedness and short-sightedness are the same thing in the context of
ophthalmology, no? [https://en.wikipedia.org/wiki/Near-
sightedness](https://en.wikipedia.org/wiki/Near-sightedness)

~~~
teddyh
Originally they were synonyms, but one of them has come to have a more
metaphorical meaning, to the point of using it literally is actually
confusing.

~~~
tombrossman
OP is from Scotland, same as my wife, and I can confirm 'short-sighted' is the
correct usage in Britain for what most Americans call 'near sighted'. The term
does not have the negative connotation in Europe that it does in America.

~~~
contingencies
Same in Australia/New Zealand AFAIK.

------
rsp1984
This may be a bit of a "visual Turing Test" actually. Humans are easily
capable of seeing the picture "through" the shapes, but image recognition
algorithms would probably find this kind of input quite hard.

I'd be interested what the latest Neural Networks have to say about input like
this.

~~~
user24
> image recognition algorithms would probably find this kind of input quite
> hard.

I doubt it; they could just run it through a blur filter and then apply normal
CV to it.

------
Mao_Zedang
If the images are small enough SVG versions of these would be nice as
preloaded images while the originals download.

~~~
euyyn
Likewise, if the random component could be removed, it might make for a very
nice video encoding.

~~~
peterwaller
You might have to wait a while on the encoding side. It's taking a minute a
frame to encode here! :)

~~~
euyyn
As long as decoding is fast enough, it can be worthwhile :)

~~~
Mao_Zedang
What if the seed for the next frame is the previous frame once it hits a
certain fitness.

------
tromp
Wow, they look quite artistic.

Jürgen Schmidhuber has done extensive study of so-called low complexity art,
see

[http://people.idsia.ch/~juergen/beauty.html](http://people.idsia.ch/~juergen/beauty.html)

------
striking
It's really cool how it isolates some of the really pretty colors and blends
them into the rest of the picture.

I'm loving their twitter, too:
[https://twitter.com/PrimitivePic](https://twitter.com/PrimitivePic)

~~~
allenu
Those pics remind me very much of the old game Out of this World. I wonder if
someone can modify this to encode video. It would make for an interesting
effect.

~~~
spython
I just tried using primitive on video frames - i has a nice effect, but
somewhat jittery. I blended some frames together to avoid it.

Here it is, with the bash scripts:
[http://rybakov.com/blog/primitive/](http://rybakov.com/blog/primitive/)

upd: used a better video example and cleaned up the scripts.

~~~
mastazi
Wow, I really loved the result! I actually find what you describe as "jittery
effect" to be a very interesting quality!

~~~
spython
If you like it, try lowering the number of shapes primitive uses. I added an
example video with n=15, it works really well for simple forms. Almost like a
low poly rendering.

------
abuzzooz
Nice!

A few years ago, there was an HN post about a similar algorithm:
[https://news.ycombinator.com/item?id=4912964](https://news.ycombinator.com/item?id=4912964)

Inspired by this, I wrote my own implementation in Perl:
[http://qumsieh.github.io/blog/2012/12/14/Evolutionary-
Image-...](http://qumsieh.github.io/blog/2012/12/14/Evolutionary-Image-
Replication-Using-Perl/)

Pretty cool effect.

~~~
echelon
Here's the original HN submission from 8 years ago:

[https://news.ycombinator.com/item?id=389727](https://news.ycombinator.com/item?id=389727)

------
antirez
Very cool looking results! In case somebody is interested in a C
implementation, I wrote one some time ago:
[https://github.com/antirez/shapeme](https://github.com/antirez/shapeme)

------
Franciscouzo
For those asking about a web version of this, I made a similar thing with
HTML5:
[https://franciscouzo.github.io/genetic_art/](https://franciscouzo.github.io/genetic_art/)

It employs hill climbing and supports different kinds of shapes.

~~~
web007
Looks like an implementation of
[http://alteredqualia.com/visualization/evolve/](http://alteredqualia.com/visualization/evolve/)
\- one of my favorite web-things ever made.

Edit: the "inspiration" for this is the same thing as Altered Qualia, Roger
Johansson's post about genetic image evolution
[https://rogeralsing.com/2008/12/07/genetic-programming-
evolu...](https://rogeralsing.com/2008/12/07/genetic-programming-evolution-of-
mona-lisa/)

------
aarreedd
If you like this you will like Neural Style:
[https://github.com/anishathalye/neural-
style](https://github.com/anishathalye/neural-style)

It uses TensorFlow to create come cool pictures.

------
binarymax
Very nice. I like the algorithm choice and the result. I spent a bit of time
exploring a similar process, and used it to generate multiple frames and
animate them with a nearest neighbor algo. Examples and writeup is here:
[http://max.io/articles/harissa/](http://max.io/articles/harissa/) and the
code:
[https://github.com/binarymax/harissa](https://github.com/binarymax/harissa)

~~~
fogleman
Interesting effects!

------
babak_ap
Worth pointing out: [https://rogeralsing.com/2008/12/07/genetic-programming-
evolu...](https://rogeralsing.com/2008/12/07/genetic-programming-evolution-of-
mona-lisa/) And also a JavaScript version:
[http://alteredqualia.com/visualization/evolve/](http://alteredqualia.com/visualization/evolve/)

------
thr0waway1239
Many of you may know about how you can squint your eyes to make the images
more clearer. Can someone explain why some of these images get a lot more
realistic - e.g. the lion [1], the girl [2]..while there is not much
improvement for the others - e.g. the barn[3], the small aircraft [4] (or at
least that is what I think it is)?

[1]
[https://camo.githubusercontent.com/0cb3ad89ff63a7fcca22e1f20...](https://camo.githubusercontent.com/0cb3ad89ff63a7fcca22e1f20b941eb74d44894e/68747470733a2f2f7777772e6d69636861656c666f676c656d616e2e636f6d2f7374617469632f7072696d69746976652f6578616d706c65732f31353139393233373039352e3230302e3132382e342e312e706e67)

[2]
[https://camo.githubusercontent.com/37d464fc15376c548a1ecf37a...](https://camo.githubusercontent.com/37d464fc15376c548a1ecf37aaa230b9a1a2c550/68747470733a2f2f7777772e6d69636861656c666f676c656d616e2e636f6d2f7374617469632f7072696d69746976652f6578616d706c65732f31313730373831393736342e3230302e3132382e342e312e706e67)

[3][https://camo.githubusercontent.com/95f92b2505523e8f23f733bb0...](https://camo.githubusercontent.com/95f92b2505523e8f23f733bb025bc4ef7f6df2ad/68747470733a2f2f7777772e6d69636861656c666f676c656d616e2e636f6d2f7374617469632f7072696d69746976652f6578616d706c65732f31353031313736383730392e3230302e3132382e342e312e706e67)

[4]
[https://camo.githubusercontent.com/5cc4416030a43025d6861b3e6...](https://camo.githubusercontent.com/5cc4416030a43025d6861b3e6541bfacd5e4ba77/68747470733a2f2f7777772e6d69636861656c666f676c656d616e2e636f6d2f7374617469632f7072696d69746976652f6578616d706c65732f31353031353431313837302e3230302e3132382e342e332e706e67)

------
tylerneylon
A guy I work with created something similar a couple years ago. He used a
different optimization technique which may be interesting to folks enjoying
this: [http://whoateallthepy.blogspot.co.uk/2014/01/shards-
building...](http://whoateallthepy.blogspot.co.uk/2014/01/shards-building-
image-out-of-triangles.html)

------
ggambetta
Possibly naive question: can this be used for image compression? Use this for
a rough approximation to the original colours, and encode the diff to the
actual image using some efficient algorithm (lossless or not)?

~~~
hxegon
It would definitely be lossy compression, but yeah. If you are just talking
about 50-200 polygon coordinates... It would be interesting to try and use
these types of images in demoscene or size based game competitions.

~~~
ggambetta
Why _definitely_ lossy? If you encode the deltas in a lossless manner, the
result will be identical to the original image.

------
darkFunction
Impressive work. I played around with the same idea before while learning a
bit of python, and found (in my project at least) a breeding strategy to give
better results than a hill-climbing algorithm.

[https://github.com/darkFunction/PolygonPainter](https://github.com/darkFunction/PolygonPainter)

------
jankovicsandras
Shameless plug: similar artistic effects can be achieved with ImageTracer,
however the algorithm is different. It's a Public Domain tracing and
vectorizing library, outputting SVG.

JavaScript
[https://github.com/jankovicsandras/imagetracerjs](https://github.com/jankovicsandras/imagetracerjs)
or Java
[https://github.com/jankovicsandras/imagetracerjava](https://github.com/jankovicsandras/imagetracerjava)
or "Android" Java
[https://github.com/jankovicsandras/imagetracerandroid](https://github.com/jankovicsandras/imagetracerandroid)

------
zakk
Have you tried using it as a lossy compression algorithm for images?

The position, shape, orientation and color of the primitives should provide a
rather synthetic representation of the starting image.

~~~
saynsedit
Yes, I'd love to see the compression ratio vs. image quality comparison.

------
emmelaich
It's interesting how quickly the Mona Lisa was recognisable.

You could make an image quiz out of this.

Or perhaps CAPTCHA?

------
tripzilch
> Hill Climbing or Simulated Annealing for optimization (hill climbing
> multiple random shapes is nearly as good as annealing and faster)

Great to see the author is using this instead of the GA / evolutionary
algorithm code it was inspired by.

You can see it in the results too, they are gorgeous! Annealing (and,
apparently hill-climbing too) are just faster to converge, allowing to tweak
better optimizations for the hyperparameters.

GAs are an attractive idea because, well, if you look around, evolution gives
rise to such clever solutions and beautiful shapes. But people tend to forget
natural evolution took billions of years, especially (sort of) the big leaps
in complexity. Annealing is almost always a better solution, with the possible
exception if your problem space is biologically inspired _and_ you come up
with a sensible crossover operation. If the crossover operation (or without
one) doesn't have the right properties, a GA is basically equivalent to
annealing (except in parallel), but much harder to tweak for fast convergence.

~~~
chris_st
"Genetic Algorithms run in Geological Time" \-- I forget who.

------
imaginenore
I feel like it's a perfect task for a GPU. Calculating diffs on every attempt
with the CPU must be slow.

------
boyter
Reminds me a lot of this [https://rogeralsing.com/2008/12/07/genetic-
programming-evolu...](https://rogeralsing.com/2008/12/07/genetic-programming-
evolution-of-mona-lisa/)

------
any626
Very cool. How did you create the gif? I tried -o filename.gif but i got
nothing.

~~~
fogleman
You need ImageMagick installed on your system.

~~~
any626
That did it! Thank you very much. What do you recommend for the number of
shapes when creating a gif?

------
DictumMortuum
This is awesome to generate art for prototypes, e.g. for boardgames (cards,
etc).

Please implement that svg output feature. If you need any help, you can find
my contact details in my profile.

------
_pius
This is really well done, nice work.

------
cdupiton
This is awesome, what motivated you to start such a project?

~~~
fogleman
My inspiration is mentioned in the README. :)

------
fit2rule
I'm reminded of my friend Amirs' work on using AI to approximate convolution
filters:

[https://github.com/kallaballa/Mimikry](https://github.com/kallaballa/Mimikry)

Some truly fascinating results to be had, depending on what you throw at it ..

------
nightcracker
This is similar to something I created a while back:
[http://codegolf.stackexchange.com/questions/50299/draw-an-
im...](http://codegolf.stackexchange.com/questions/50299/draw-an-image-as-a-
voronoi-map/50345#50345)

Drawing a target image using a voronoi diagram.

~~~
perfectfire
Yes! Thanks for this. Voronoi diagrams were on the tip of my tongue.

------
electic
This is amazing. Does anyone know if there is a prisma type open source
project as well in addition to this?

------
xioxox
Reminds me a bit of the technique I developed to spatially bin X-ray astronomy
data for spectral analysis: [https://www-
xray.ast.cam.ac.uk/papers/contbin/](https://www-
xray.ast.cam.ac.uk/papers/contbin/)

------
ChuckMcM
that is a lot of fun and much more "artsy" than many of the filters available
in paint programs.

------
joshaidan
What I find cool about this is that I ran it on my profile pic, and when
Facebook shrinks it down to the micro size image, you can't tell the
difference between the primitive version and the original.

------
the_cat_kittles
i can only imagine that a pretty video thats had each frame run through this
would come out incredible looking. you could probably get away with each frame
being pretty low quality render too.

------
jotato
How long until this is made a filter on Instagram? Soon, I hope :)

~~~
antirez
No way this can be done in real time... at least in the near future and using
the same technique :-)

~~~
web007
Probably not for real-time, but not impossible as a filter. I would imagine
it'll be more like Prisma, take your snap and let it chug for a few seconds to
give you a pretty picture.

~~~
alehander42
Prisma uses neural networks to learn the features, so it requires very hard
training, but it leads to fast generation

~~~
anchpop
I believe prisma uses Neural Style for most of its images, and that generally
doesn't take too long to train IIRC

------
mcjiggerlog
This is really really cool - great work!

I think if you could limit the internal angles of the triangles (as in, closer
to equilateral) then you would get more aesthetically pleasing results.

~~~
fogleman
The code already does that. ;) Perhaps you'd like a larger constraint:
[https://github.com/fogleman/primitive/blob/master/primitive/...](https://github.com/fogleman/primitive/blob/master/primitive/triangle.go#L61)

------
btbuildem
As you translate images into groups of primitives -- I wonder if this would
facilitate image search like:

\- given an image, find similar images

\- given image, find all images which it is a subset of

------
harperlee
Cool! Now someone should try doing this in 3D :)

~~~
ionforce
You absolutely could but the search space would be so much larger. Also, what
is your heuristic? It would only be one angle of 3D space?

~~~
harperlee
I thought this was reminding me of something.... and it turned out I had even
commented on it!

"Reconstruct a scene that is as similar as possible to a photograph"
[https://news.ycombinator.com/item?id=12371975](https://news.ycombinator.com/item?id=12371975)

------
harigov
Pretty cool! I think if you can introduce some bias towards smoother
primitives like ellipse or circle, it may look better.

------
sparaker
Some benchmarks on the algorithm in the README would be a nice addition, glad
this is MIT License.

------
evantahler
This is a cool way of de-rasterizing images... you can make infinitely
scalable vectors!

------
contingencies
Planning to use this to illustrate my new roguelike ... pet project to learn
Lua ;)

~~~
contingencies
Wound up making
[https://github.com/globalcitizen/svg2love](https://github.com/globalcitizen/svg2love)
as a _perl_ -based proof of concept then
[https://github.com/globalcitizen/svglover](https://github.com/globalcitizen/svglover)
(fully fledged Lua library)

------
huangc10
Really amazing. Great job! Looking forward to the front-end result and SVG
output.

------
happyslobro
I can paint terrible art. Thanks to this, I can also paint modern art
\fistbump

------
1_listerine_pls
It would be cool to gradually add detail wherever you press with the cursor.

~~~
fogleman
Yes! I had that idea too but haven't gotten around to it. :(

------
Ono-Sendai
I've also made something similar, but probably a bit fancier:
[https://dl.dropboxusercontent.com/u/8789055/computerart.png](https://dl.dropboxusercontent.com/u/8789055/computerart.png)

------
biztos
Very nice! Now I want a render farm so I can use this for 4K video. :-)

------
aji
this reminds me of the "GIMPressionist" plugin in the GIMP, which can be
coerced into producing pictures like this

------
overcast
If you were smart, you'd snag primitivepics.com , stat. Forget Twitter,
establish your brand. I wouldn't even open source it until you've done so.
It's unique, and non trivial.

~~~
abraae
"If you were smart"?

His results speak for themselves!

~~~
overcast
Sounds like a good reason to grab it then! Anyhow, looks like someone got it.

