Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Primitive Pictures (github.com/fogleman)
894 points by fogleman on Sept 20, 2016 | hide | past | favorite | 170 comments

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!

There is lots of work on "artistic rendering" like yours, from the early 1990s to the present. It started with work by Paul Haeberli at SGI [1]. The first chapter in "Image and Video-Based Artistic Stylisation", edited by Paul Rosin and John Collomosse [2] describes many techniques you might be interested in. Have a look; you will like what you see.



Hey, that book looks right up my alley... I just ordered a copy. :)

Do you have nay plans on putting a website front end on this? It would be great to upload an image and get a result

A few people have asked that, so maybe. Another thought was you could tweet an image to the Twitter bot and have it tweet back the result, but then your image is out there for the world to see, so maybe that's not as good.

If you create a frontend, it may be a good idea to add a button for buying a print (which you could do through one of the many online services available). Some of these look very nice and I'm considering printing something like this on a canvas to hang on the wall.

All the +1 in the world for this. I've been browsing the Twitter bot for a while just thinking "some of these are great; I'd happily hang one".

absolutely +1 for this

I was about to create such a website a couple of years ago, but isn't this too much computational expensive to be a free service? It's going to make people wait a lot if the service hits HN or something like that. Or maybe my code was too much unoptimized and it's possible to train the images in a quite faster fashion after all. Anyway would be great to have such a site.

EDIT: Now I checked better your implementation and is very different, and indeed, can be made a lot faster. What I (and others before me) do is to have a fixed set of polygons and move, rotate, change color in order to find the best arrangement. In your case instead you add shapes incrementally in order to lower the error.

Is it pure Go? Could you compile with GopherJS and do the processing all client side?

That would be cool. It is pure Go...

I could see this becoming super popular in some twitter circles, though.

You could also make it an app the way Prisma did...

Grab primitivepics.com NOW.

Also available is primitive.pics. I'm surprised no one has grabbed these yet...

That's a terrible name if he's planning to monetize this tho.


I assume because "primitive" generally has negative connotations. (Don't try to make rational arguments about that doesn't apply here or how obvious it is that it's not the "bad" sort of primitive. We're talking about marketing here. Rational arguments are a category error.) I'm not creative enough to come up with a positive, just some more neutral ideas that you would have the opportunity to shape, like Shapify (taken by other things though), something with "simplify", something with "fun" maybe ("fun up your photos!").

And to me, Shapify is just another generic "web 2.0" name. Lost in the sea of a million other "ify" domains. The point here is that they should at least claim the domain name for their product, regardless if that is going to be the actual public facing product.

This is another one of those "your tone suggests you disagree with me, but you're just repeating my point back at me" posts. I told you "Shapify" was a neutral word that you can pour your own connotations into. A lot of brands are. What's a "Cisco"? What's a "Nike" in a country where most people won't get the classical allusion? What's a "Coke"?

Those brands aren't generic "ify" names that sound like they came from a domain name generator. Primitive sounds like a pretty good company name to me. There is already a skateboarding company of the same name that does well.

You could accept DMs as well

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

Will share another time, thanks again for the post.

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

Can you link to the algorithm itself? Thanks - cool work.

This is really impressive. I'll bet if you printed these out as high quality giclees and didn't tell anyone how you did it you could sell them for thousands of dollars in fine art galleries.

I feel compelled to note that "giclée" is a fancy word for "inkjet printed". It has connotations of higher quality, but it's not a distinct process. See https://en.wikipedia.org/wiki/Gicl%C3%A9e

That's not quite true. It's a particularly high quality of ink-jet print. You can easily tell the difference between a giclee and the output of an HP OfficeJet.

Since we're talking art and commerce, I smell a business opportunity - selling inkjet printers with Giclée Enabled™ label, at extra markup.

From Wikipedia (and professional photographers I've spoken to mirror this sentiment), “since [giclée] is an unregulated word it has no associated warranty of quality.” It's like “premium”.

It's still the same process. The printers used to make "giclée" printes are ordinary inkjet printers, they're just not HP OfficeJet printers—probably.

Depends on what you consider "ordinary". A giclee printer can fill a room and cost many thousands of dollars. e.g.:


I have a similar printer.

The word "giclee" does not even appear in the description, but "inkjet" does. It's still an ordinary injet printer. It's bigger and more accurate than most. I've never seen them put in rooms so small that they'd "fill the room", I've usually seen them in rooms with several printers.

> It's bigger and more accurate than most.

Then it isn't ordinary.

Also it's often done on some type of canvas.

You could probably sell them even though you revealed how you did it.

On a related note, perhaps Richard P Gabriel could also sell his machine generated poetry. The future will be interesting for artists.

I dunno, I think a lot of the hoity-toity types who are willing to overpay for art would be put off by knowing that it was done by computer. For them, the value is in the scarcity more than the aesthetics: they want to have something that their friends don't (and can't!) have. So if it were me, I would choose not to reveal that anyone who knows how to use github and an inkjet printer can reproduce the results.

That's not necessarily true. There are many examples of fine art which is made by computer and easily replicated by anyone. However, the prints themselves are limited in quantity (or, there may just one official print).

Of course. But do people pay top dollar for those? I don't actually know, but I doubt it.

This is how photography nearly always worked. I think there's some early photo tech that did only result in one image, but all of film photography produced 'prints'.

Although I remember growing up with one print that deliberately had a fold in it, made by the artist as part of the art.

"I dunno, I think a lot of the hoity-toity types who are willing to overpay for art would be put off by knowing that it was done by computer. For them, the value is in the scarcity more than the aesthetics:"

There is a portion of the art market that caters for interior design. A client might say something like, "I want a dozen in this colour, style with an ocean breeze feel." As soul destroying as this may be to an artist, some clients want their art by the numbers, colours and feel.

I have tinkered with this myself. Have you tried a fitness function that doesn't just compare the source pixels, but also compares the source and approximation after each has been run through various convolution kernels, and adding the result to the overall score? it takes a little longer but it can let you fine tune things like giving a higher score to images whose edges line up.

Make stroke of a brush a geometric primitive and you have an interesting painter.

I was thinking along those lines, perhaps a general swash shape that is randomised at the edges a little.

Yeah, I briefly thought about that but haven't tried anything yet...

Great work so far, I hope you can pull it off.

... Then just come up with some fake name and portfolio website because I have a feeling that people will want to pay less for automatically generated art even if in a blind test they would like it more than a "real" one ;)

The code is very readable! Especially because it's not using a lot of external libraries. Including the twitter bot is a very nice touch. Awesome!

One of the key features of golang is concurrency. Your code is single-threaded, even though hill-climbing and annealing (and also all kinds of image operations) could be highly parallelized. Maybe that's something rewarding to look into at some point?

If you ever find the time, can you outline your strategy for your choosing a convergence algorithm? How did your experiments go for choosing the parameters (you called them maxAge, maxTemp, etc.) for those? Why did you currently end up choosing hill climbing over annealing, here: https://github.com/fogleman/primitive/blob/master/primitive/...

I like it. I noticed that the oval brushes were almost always of lower quality (in the sense of doing a worse job recreating the original). I think it's because you only take axis-aligned ellipses and not arbitrarily rotated ones, which might be fun to try too.

Actually ellipses perform pretty well. I've analyzed this a good bit... http://i.imgur.com/82Aksg0.png (lower is better, this shows average score over 100 different input images)

Can't believe you didn't input Duchamp's Nude Descending A Staircase ;)

I'd love to see this, please :)

I'd love to help with the SVG implementation. I'll follow the repo. Great project.

As an aside, it would be nice if you could cite the original sources of the images posted by the Twitter bot; it would be nice to compare, and probably most safe legally too.

to add to this, I want to compare to the source image! You should definitely link to the original.

Thanks. This is wonderful. I just put go on my mac and got this running in ~5 minutes. I am going to do a few images tonight and will share the google photo album as a comment to this comment when I get a chance tonight.

This is very cool. Thanks.

Not sure anyone will see this but I rendered some photos using this great tool. I like The Black Widow and the passage way the best.


Nice work!

As far as other ideas, morphing from one photo to the next one. Making changes (morphing shapes, changing colors, adding / removing shapes) would look interesting.

I noticed that the alpha default is 128, but usually the scale is 0-1. Is the scale then 0 - 256 for this option?

Awesome! Thanks for sharing this. Feature request: combine modes(e.g. triangle+rect).

Just wanted to say this is really awesome. Nice work!

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:


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

Might be fun to turn these into an animation, with a lot of frames.

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.

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

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

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.

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.

Same in Australia/New Zealand AFAIK.

Cheers for clearing that up :) I was rather confused by the comment.

You've failed to consider the rest of the world and their usage of the term; it's a bit short-sighted, really.

But not near-sighted. Only one of the terms is overloaded. ;)

Funny! I'd never heard "near-sighted" before that Wikipedia article.

Surely in using 'short' exclusively metaphorically, its metaphoric effect is lost entirely?

Don't feel too bad. I had to read it twice to get the meaning, myself. The fact that it's used in a literal sense outside of the U.S. isn't something that I would have considered. I suppose that my viewing of foreign media has had a dearth of references to optometry.

Huh, it really does. Very cool!

Similarly, the mosaic effect that they use on TV to hide faces sometimes leaves them still recognizable if I take my glasses off, even if they're completely unrecognizable when seen clearly.

I wonder if this effect works for people who aren't short-sighted? Like, maybe short-sighted peoples' visual systems develop to use more focus-invariant features.

Most people can manually defocus their eyes to accomplish the same effect as a farsighted person taking off their glasses

Yes, but I think the GP was talking about learning, forming new (different) brain connections, because most near-sighted people navigate the world with blurry vision for at least a few minutes daily, sometimes more.

(personally, since my eyesight without glasses or contacts is pretty bad, no more than 15 mins until I get annoyed with the difficulty spotting small objects and go for my glasses :p gonna laser those puppies one day, maybe. it's amazing living in an age where they can actually fix this sort of thing, shame if I didn't take advantage of it)

You can get a similar effect by pressing Ctrl "-" a couple of times in your browser, to shrink the images. The result is that they look much sharper. But of course, this spoils the original effect.

What do you call "extremely" ? I am -6 and did not notice any of what you describe, so I assume I'm not nearly as bad a case as you are ?

-9 plus heavy astigmatism. My maximum clear vision distance without glasses is about six inches!

This may be of value to you if you have not done it already, but I came in from -8ish to -6ish just by doing these exercises.


-11 in both eyes here. Seeing the same thing!

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.

> 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.

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

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

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

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

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

Wow, they look quite artistic.

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


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

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.

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/

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

Nice! More iterations per frame would reduce the jitter probably.

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

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.

These look great!

Naive (probably non-realtime) version for video should pretty easy, just run the algorithm frame-by-frame. Biggest problem would be the lack of temporal stability ("jitter"), but I imagine using previous frame as the base state for next frame would help.

Real-time graphics rendering is another story altogether, I don't see any trivial ways of applying this sort of thing for typical graphics pipeline.

Heh, my coworker said the same thing.


A few years ago, there was an HN post about a similar algorithm: 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-...

Pretty cool effect.

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


Back there lots of people posted their implementation (been there, done that... an easy one with triangles in pure C). It's a fun exercise you can then show around and get very interesting output of

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

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

It employs hill climbing and supports different kinds of shapes.

Looks like an implementation of 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...

Here's things my shoddy attempt made :)


If you like this you will like Neural Style: https://github.com/anishathalye/neural-style

It uses TensorFlow to create come cool pictures.

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/ and the code: https://github.com/binarymax/harissa

Interesting effects!

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...

[2] https://camo.githubusercontent.com/37d464fc15376c548a1ecf37a...


[4] https://camo.githubusercontent.com/5cc4416030a43025d6861b3e6...

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...

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)?

You could store the combo shapes for 50 images in about 350 bytes. If you want to fix to axis and pick one shape, you can get it down to 300. (That's 256x256 images, for each shape you need two coordinate pairs, or 4 bytes, 1 byte for rotation, 3 values for rgb (15-bit color), and 2 bits per shape for choice between ellipse, rectangle, and triangle

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.

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

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.


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 or Java https://github.com/jankovicsandras/imagetracerjava or "Android" Java https://github.com/jankovicsandras/imagetracerandroid

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.

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

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

You could make an image quiz out of this.

Or perhaps CAPTCHA?

> 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.

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

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

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

You need ImageMagick installed on your system.

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

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.

This is really well done, nice work.

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

My inspiration is mentioned in the README. :)

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


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

This is similar to something I created a while back: http://codegolf.stackexchange.com/questions/50299/draw-an-im...

Drawing a target image using a voronoi diagram.

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

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

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/

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

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.

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.

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

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

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.

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

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

I'm just testing it and it takes ~1 minute per photo on a quad-core i7.

Yep, I later read the technique used by the OP, and is quite different compared to programs similar to this one, including mine, where a fixed set of shapes is evolved in order to find an optimal arrangement. This is a complex optimization problem that takes a lot of time. In the OP implementation old shapes are never re-arranged, just new ones are added in order to decrease the error. While the visual effect is still very interesting, you need more shapes this way to approximate the same level of details, and is in some way less interesting IMHO, at least conceptually, compared to "arrange N items to get the best result" which looks like a quasi-human task.

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.

The code already does that. ;) Perhaps you'd like a larger constraint: https://github.com/fogleman/primitive/blob/master/primitive/...

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

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

I suppose going volumetric and matching colored cubes to an input model would lead to a pretty neat mesh-to-Minecraft converter :).

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?

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

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

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

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

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

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

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

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

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

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

I've also made something similar, but probably a bit fancier: https://dl.dropboxusercontent.com/u/8789055/computerart.png

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

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

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.

"If you were smart"?

His results speak for themselves!

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

Applications are open for YC Summer 2021

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact