Algoritmos para fazer mosaicos de imagens - existe uma maneira mais rápida do que isso?


9

Eu tenho brincado fazendo mosaicos de imagens. Meu script captura um grande número de imagens, reduz ao tamanho das miniaturas e as usa como blocos para aproximar uma imagem de destino.

A abordagem é realmente bastante agradável:

Calculo o erro quadrático médio para cada polegar em cada posição do bloco.

No começo, acabei de usar um posicionamento ganancioso: coloque o polegar com o menor erro no ladrilho que melhor se encaixa e depois no próximo e assim por diante.

O problema com o ganancioso é que, eventualmente, você coloca os polegares mais diferentes nos ladrilhos menos populares, combinando-os de perto ou não. Eu mostro exemplos aqui: http://williamedwardscoder.tumblr.com/post/84505278488/making-image-mosaics

Então, faço trocas aleatórias até que o script seja interrompido. Os resultados são bastante bons.

Uma troca aleatória de dois blocos nem sempre é uma melhoria, mas às vezes uma rotação de três ou mais blocos resulta em uma melhoria global, ou seja, A <-> Bpode não melhorar, mas A -> B -> C -> A1pode ..

Por esse motivo, depois de escolher duas peças aleatórias e descobrir que elas não melhoram, eu escolho várias peças para avaliar se elas podem ser a terceira peça dessa rotação. Não exploro se qualquer conjunto de quatro peças pode ser rotacionado com lucro, e assim por diante; isso seria super caro em breve.

Mas isso leva tempo .. Muito tempo!

Existe uma abordagem melhor e mais rápida?


Atualização de recompensa

Testei várias implementações e ligações do Python do método húngaro .

De longe o mais rápido foi o https://github.com/xtof-durr/makeSimple/blob/master/Munkres/kuhnMunkres.py

Meu palpite é que isso se aproxima da resposta ideal; quando executadas em uma imagem de teste, todas as outras bibliotecas concordaram com o resultado, mas esse kuhnMunkres.py, apesar de ter ordens de magnitude mais rápidas, ficou muito, muito, muito próximo da pontuação que as outras implementações concordaram.

A velocidade depende muito dos dados; Mona Lisa correu pelo kuhnMunkres.py em 13 minutos, mas o Periquito-de-peito-escarlate levou 16 minutos.

Os resultados foram os mesmos que os swaps e rotações aleatórias para o periquito:

insira a descrição da imagem aquiinsira a descrição da imagem aqui

(kuhnMunkres.py à esquerda, trocas aleatórias à direita; imagem original para comparação )

No entanto, para a imagem da Mona Lisa com a qual eu testei, os resultados foram visivelmente aprimorados e ela realmente teve seu 'sorriso' definido brilhando:

insira a descrição da imagem aquiinsira a descrição da imagem aqui

(kuhnMunkres.py à esquerda, trocas aleatórias à direita)


11
Relacionado ... ish. No Codegolf palate, a transformação teve problemas semelhantes.

11
E outro conjunto de imagens relacionado é allRGB, onde cada imagem (embora isso não lhe dê muita dica de como fazê-lo ... apenas que há outra área em que esse problema foi abordado).

11
Eu me deparei com esse problema com um fabricante de mosaicos há alguns anos atrás. Minha linha de raciocínio agora e agora é que o problema não está muito no seu algoritmo (a parte MSE), mas no tamanho limitado da sua paleta de imagens de entrada. Não tendo um bilhão de imagens para trabalhar, eu a falsifiquei, permitindo que uma imagem fosse reutilizada após algum tempo. No entanto, se você quiser continuar com sua abordagem, pode ser bom fazer uma primeira passagem para ajustes "bons" e, em seguida, tratar o restante das imagens como aleatórias (ou aleatórias) - com uma entrada limitada definida, você só tem tantas escolhas.
J Trana

@ MichaelT obrigado por esse excelente link :) O codegolf é particularmente fascinante. Acho que a votou-melhores soluções estão usando swaps aleatórios (rotações não aleatórios) e são presumivelmente correndo por um bom tempo ...
Will

11
Chegando a isso depois que você selecionou uma resposta e concedeu uma recompensa. Uma abordagem diferente seria tratar isso como um problema de recozimento simulado . Você pode usar o SA como um dos estágios do seu pipeline de soluções.
precisa saber é o seguinte

Respostas:


3

Sim, existem duas abordagens melhores e mais rápidas.

  • Problema mais simples: para cada bloco, escolha o melhor polegar (com possível duplicação). Ok, isso é trapaça, mas só pode levar a melhores resultados visuais.
  • Sua opinião é algoritmicamente mais interessante e resume-se a "problema de atribuição linear", supondo que você tome MSE como custos de correspondência cuja soma deve ser mínima. Esse problema pode ser resolvido em tempo polinomial, via, por exemplo, o "Método Húngaro"

Em seguida, você pode ajustar seus custos substituindo o MSE por uma distância visualmente mais precisa, sem alterar o algoritmo subjacente.


THX! O LAP e o Método Húngaro foram os leads que eu precisava! Atualize com os resultados em questão.
Will

3

Estou razoavelmente certo de que é um problema difícil de NP. Para encontrar uma solução 'perfeita', você deve tentar todas as possibilidades exaustivamente, e isso é exponencial.

Uma abordagem seria usar o ajuste ganancioso e tentar melhorá-lo. Isso pode ser feito com uma imagem mal posicionada (uma das últimas) e encontrando outro lugar para colocá-la, depois pegando essa imagem e movendo-a e assim por diante. Você termina quando (a) fica sem tempo (b) o ajuste é 'bom o suficiente'.

Se você introduzir um elemento probabilístico, ele poderá render uma abordagem simulada de recozimento ou um algoritmo genético. Talvez tudo o que você está tentando alcançar seja espalhar os erros uniformemente. Eu suspeito que isso esteja se aproximando do que você já está fazendo, então a resposta é: com o algoritmo certo, você pode obter um resultado melhor mais rapidamente, mas não há atalho mágico para o Nirvana.


Sim, isso é semelhante ao que você já está fazendo. O objetivo é esquecer uma resposta mágica e pensar em termos de 2 algoritmos: primeiro preencha e depois otimize.

O preenchimento pode ser: aleatório, melhor disponível, primeiro melhor, bom o suficiente, algum tipo de hot spot.

A otimização pode ser aleatória, corrigir o pior ou (como sugeri) o recozimento simulado ou o algoritmo genético.

Você precisa de uma métrica de 'bondade' e de uma quantidade de tempo que esteja preparado para gastar nela e apenas experimentar. Ou encontre alguém que realmente tenha feito isso.


Você descreve exatamente a abordagem descrita na pergunta ...?
Will

1

Se os últimos blocos forem o seu problema, tente colocá-los desde o início, de alguma forma;)

Uma abordagem seria olhar para o bloco que está mais distante do x% superior de suas correspondências (intuitivamente, eu usaria 33%) e colocá-lo na sua melhor correspondência. Essa é a melhor combinação possível de qualquer maneira.

Além disso, você pode optar por não usar a melhor correspondência para o pior bloco, mas aquele que introduz o menor erro em comparação com a melhor correspondência para esse espaço, para que você não jogue completamente fora suas melhores correspondências por causa de " controle de dano".

Outra coisa a ter em mente é que, no final, você está produzindo uma imagem a ser processada pelo olho. Então, o que você realmente deseja é usar alguma detecção de borda para determinar quais posições na sua imagem são mais importantes. Da mesma forma, o que acontece na periferia da imagem tem pouco valor para a qualidade do efeito. Sobreponha esses dois pesos e inclua-os no cálculo da distância. Qualquer tremulação que você receber deve, portanto, gravitar em direção à borda e afastá-la, perturbando muito menos.

Além disso, com a detecção de arestas no lugar, convém colocar os primeiros y% avidamente (talvez até cair abaixo de um certo limite de "nervosismo" nos ladrilhos restantes), para que os "pontos quentes" sejam tratados muito bem, e depois mude para "controle de danos" nos demais.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.