primitive README

The project's README from github.com/fogleman/primitive. As one markdown file: README.md.

Primitive Pictures

Reproducing images with geometric primitives.

Example

How it Works

A target image is provided as input. The algorithm tries to find the single most optimal shape that can be drawn to minimize the error between the target image and the drawn image. It repeats this process, adding one shape at a time. Around 50 to 200 shapes are needed to reach a result that is recognizable yet artistic and abstract.

Primitive for macOS

Now available as a native Mac application!

https://primitive.lol/

Twitter

Follow @PrimitivePic on Twitter to see a new primitive picture every 30 minutes!

The Twitter bot looks for interesting photos using the Flickr API, runs the algorithm using randomized parameters, and posts the picture using the Twitter API.

You can tweet a picture to the bot and it will process it for you.

Command-line Usage

Run it on your own images! First, install Go.

go get -u github.com/fogleman/primitive
primitive -i input.png -o output.png -n 100

Small input images should be used (like 256x256px). You don't need the detail anyway and the code will run faster.

Flag Default Description
i n/a input file
o n/a output file
n n/a number of shapes
m 1 mode: 0=combo, 1=triangle, 2=rect, 3=ellipse, 4=circle, 5=rotatedrect, 6=beziers, 7=rotatedellipse, 8=polygon
rep 0 add N extra shapes each iteration with reduced search (mostly good for beziers)
nth 1 save every Nth frame (only when %d is in output path)
r 256 resize large input images to this size before processing
s 1024 output image size
a 128 color alpha (use 0 to let the algorithm choose alpha for each shape)
bg avg starting background color (hex)
j 0 number of parallel workers (default uses all cores)
v off verbose output
vv off very verbose output

Output Formats

Depending on the output filename extension provided, you can produce different types of output.

For PNG and SVG outputs, you can also include %d, %03d, etc. in the filename. In this case, each frame will be saved separately.

You can use the -o flag multiple times. This way you can save both a PNG and an SVG, for example.

Progression

This GIF demonstrates the iterative nature of the algorithm, attempting to minimize the mean squared error by adding one shape at a time. (Use a ".gif" output file to generate one yourself!)

Static Animation

Since the algorithm has a random component to it, you can run it against the same input image multiple times to bring life to a static image.

Pencils

Creative Constraints

If you're willing to dabble in the code, you can enforce constraints on the shapes to produce even more interesting results. Here, the rectangles are constrained to point toward the sun in this picture of a pyramid sunset.

Pyramids

Shape and Iteration Comparison Matrix

The matrix below shows triangles, ellipses and rectangles at 50, 100 and 200 iterations each.

Matrix

How it Works, Part II

Say we have a Target Image. This is what we're working towards recreating. We start with a blank canvas, but we fill it with a single solid color. Currently, this is the average color of the Target Image. We call this new blank canvas the Current Image. Now, we start evaluating shapes. To evaluate a shape, we draw it on top of the Current Image, producing a New Image. This New Image is compared to the Target Image to compute a score. We use the root-mean-square error for the score.

Current Image + Shape => New Image
RMSE(New Image, Target Image) => Score

The shapes are generated randomly. We can generate a random shape and score it. Then we can mutate the shape (by tweaking a triangle vertex, tweaking an ellipse radius or center, etc.) and score it again. If the mutation improved the score, we keep it. Otherwise we rollback to the previous state. Repeating this process is known as hill climbing. Hill climbing is prone to getting stuck in local minima, so we actually do this many different times with several different starting shapes. We can also generate N random shapes and pick the best one before we start hill climbing. Simulated annealing is another good option, but in my tests I found the hill climbing technique just as good and faster, at least for this particular problem.

Once we have found a good-scoring shape, we add it to the Current Image, where it will remain unchanged. Then we start the process again to find the next shape to draw. This process is repeated as many times as desired.

Primitives

The following primitives are supported:

More shapes can be added by implementing the following interface:

type Shape interface {
	Rasterize() []Scanline
	Copy() Shape
	Mutate()
	Draw(dc *gg.Context)
	SVG(attrs string) string
}

Features

Inspiration

This project was originally inspired by the popular and excellent work of Roger Johansson - Genetic Programming: Evolution of Mona Lisa. Since seeing that article when it was quite new, I've tinkered with this problem here and there over the years. But only now am I satisfied with my results.

It should be noted that there are significant differences in my implementation compared to Roger's original work. Mine is not a genetic algorithm. Mine only operates on one shape at a time. Mine is much faster (AFAIK) and supports many types of shapes.

Examples

Here are more examples from interesting photos found on Flickr.

Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example Example

primitive (fogleman/primitive)

Searching Database…

13.5K ·GitHub
这是做什么的?它用几何图形来重建一张目标图片:算法会不断添加新的形状,每一步都选择能让结果与原图差异最小的那个,直到画面既认得出原图,又带有艺术感和抽象感。
这是 Mac 应用还是命令行工具?两者都是。既有一个原生 Mac 应用,也有一个叫 'primitive' 的 Go 命令行工具,可以用来处理你自己的图片。
我想用它处理自己的照片,该怎么运行?先安装 Go,然后运行 'go get -u github.com/fogleman/primitive',再像这样调用:primitive -i input.png -o output.png -n 100,其中 -n 是形状的数量。
除了 Go,我还需要装别的东西吗?用命令行工具的话,只需要 Go。只有当你想要一张逐步添加形状的动画 GIF 时,才需要 ImageMagick(具体说是它的 convert 命令)。
它能用哪些形状来拼出图片?三角形、矩形、椭圆、圆形、旋转矩形,还有贝塞尔曲线、旋转椭圆和多边形,可以通过 -m 参数选择;模式 0 会把这些形状混合在一张图里。想要更多形状,可以实现一个接口来添加。
有没有办法不安装任何东西就能看到效果?有——关注 Twitter 上的 @PrimitivePic:这个机器人每 30 分钟发布一张新的 primitive 图片,素材来自有趣的 Flickr 照片,参数随机生成。你还可以把图片发给它,它会帮你处理。
这个想法是怎么来的?灵感来自 Roger Johansson 那篇著名的《Genetic Programming: Evolution of Mona Lisa》。作者的思路有意不同:它不是遗传算法,一次只处理一个形状,速度快得多,同时还支持多种形状类型。
什么样的输入图片效果最好?小图,大约 256x256 像素——反正用不到那么多细节,代码运行也更快。大图默认会先缩放到 256 再处理。
能不能突破普通随机形状的效果?可以,前提是你愿意折腾一下代码:你可以给形状加上创意约束,比如限制矩形的方向,让它们在一幅金字塔日落图中都指向太阳。
Creator
fogleman
Size
2.3 MB
Stars
13.5K
Updated
CommitMay 04
Age
10y
Commits · 90 Days