Reproduzindo imagens com primitivas geométricas.
Uma imagem de destino é fornecida como entrada. O algoritmo tenta encontrar a forma mais ideal que pode ser desenhada para minimizar o erro entre a imagem de destino e a imagem desenhada. Ele repete esse processo, adicionando uma forma de cada vez . São necessárias cerca de 50 a 200 formas para alcançar um resultado reconhecível, mas artístico e abstrato.
Agora disponível como um aplicativo Mac nativo!
https://primitive.lol/
Siga @Primitivo no Twitter para ver uma nova imagem primitiva a cada 30 minutos!
O bot do Twitter procura fotos interessantes usando a API do Flickr, executa o algoritmo usando parâmetros randomizados e publica a imagem usando a API do Twitter.
Você pode twittar uma foto para o bot e ela a processará para você.
Execute suas próprias imagens! Primeiro, instale vá.
go get -u github.com/fogleman/primitive
primitive -i input.png -o output.png -n 100
As pequenas imagens de entrada devem ser usadas (como 256x256px). Você não precisa dos detalhes de qualquer maneira e o código será mais rápido.
Bandeira | Padrão | Descrição |
---|---|---|
i | n / D | arquivo de entrada |
o | n / D | arquivo de saída |
n | n / D | Número de formas |
m | 1 | Modo: 0 = combinação, 1 = triângulo, 2 = ret, 3 = elipse, 4 = círculo, 5 = rotado. |
rep | 0 | Adicione n formas extras cada iteração com pesquisa reduzida (principalmente boa para beziers) |
nth | 1 | Salve cada enésimo quadro (somente quando %d estiver no caminho de saída) |
r | 256 | redimensione imagens de entrada grandes para esse tamanho antes de processamento |
s | 1024 | Tamanho da imagem de saída |
a | 128 | color alfa (use 0 para permitir que o algoritmo escolha alfa para cada forma) |
bg | Avg | cor de fundo inicial (hexadecimal) |
j | 0 | Número de trabalhadores paralelos (o padrão usa todos os núcleos) |
v | desligado | saída detalhada |
vv | desligado | saída muito detalhada |
Dependendo da extensão do nome do arquivo de saída fornecida, você pode produzir diferentes tipos de saída.
PNG
: saída rasterJPG
: saída rasterSVG
: saída vetorialGIF
: saída animada mostrando formas sendo adicionadas - requer imageMagick (especificamente o comando convert
) Para saídas PNG e SVG, você também pode incluir %d
, %03d
, etc. no nome do arquivo. Nesse caso, cada quadro será salvo separadamente.
Você pode usar o sinalizador -o
várias vezes. Dessa forma, você pode salvar um PNG e um SVG, por exemplo.
Este GIF demonstra a natureza iterativa do algoritmo, tentando minimizar o erro quadrado médio adicionando uma forma de cada vez. (Use um arquivo de saída ".gif" para gerar um você mesmo!)
Como o algoritmo possui um componente aleatório, você pode executá -lo contra a mesma imagem de entrada várias vezes para trazer vida a uma imagem estática.
Se você estiver disposto a se envolver no código, pode aplicar restrições às formas para produzir resultados ainda mais interessantes. Aqui, os retângulos são restringidos a apontar para o sol nesta imagem de um pôr do sol da pirâmide.
A matriz abaixo mostra triângulos, elipses e retângulos a 50, 100 e 200 iterações cada.
Digamos que temos uma Target Image
. É isso que estamos trabalhando para recriar. Começamos com uma tela em branco, mas a preenchemos com uma única cor sólida. Atualmente, esta é a cor média da Target Image
. Chamamos isso de nova tela em branco de Current Image
. Agora, começamos a avaliar formas. Para avaliar uma forma, desenhamos -a sobre a Current Image
, produzindo uma New Image
. Esta New Image
é comparada à Target Image
para calcular uma pontuação. Utilizamos o erro raiz-quadrado médio para a pontuação.
Current Image + Shape => New Image
RMSE(New Image, Target Image) => Score
As formas são geradas aleatoriamente. Podemos gerar uma forma aleatória e pontuá -lo. Em seguida, podemos mudar a forma (ajustando um vértice do triângulo, ajustando um raio ou centro de elipse, etc.) e pontuá -lo novamente. Se a mutação melhorou a pontuação, nós a mantivemos. Caso contrário, revertemos o estado anterior. Repetir esse processo é conhecido como escalada. A escalada de montanhas é propensa a ficar presa nos mínimos locais, por isso fazemos muitas vezes diferentes vezes com várias formas iniciais diferentes. Também podemos gerar n formas aleatórias e escolher a melhor antes de começarmos a escalar. O recozimento simulado é outra boa opção, mas nos meus testes achei a técnica de escalada tão boa e rápida, pelo menos para esse problema em particular.
Depois de encontrarmos uma forma de boa pontuação, adicionamos-a à Current Image
, onde ela permanecerá inalterada. Em seguida, iniciamos o processo novamente para encontrar a próxima forma para desenhar. Esse processo é repetido quantas vezes o desejado.
Os seguintes primitivos são suportados:
Mais formas podem ser adicionadas implementando a seguinte interface:
type Shape interface {
Rasterize () [] Scanline
Copy () Shape
Mutate ()
Draw ( dc * gg. Context )
SVG ( attrs string ) string
}
Este projeto foi originalmente inspirado pelo trabalho popular e excelente de Roger Johansson - Programação Genética: Evolução de Mona Lisa. Desde que vi esse artigo quando era bastante novo, eu mexeu com esse problema aqui e ali ao longo dos anos. Mas só agora estou satisfeito com meus resultados.
Deve -se notar que existem diferenças significativas na minha implementação em comparação com o trabalho original de Roger. O meu não é um algoritmo genético. O meu opera apenas em uma forma de cada vez. O meu é muito mais rápido (AFAIK) e suporta muitos tipos de formas.
Aqui estão mais exemplos de fotos interessantes encontradas no Flickr.