Transferência de estilo com GANs em imagens HD

Como gerar imagens HD com GANs e sem fantasia

Marco Pasini Segue 23 de jul · 11 min ler

Introdução

Uma série de estudos recentes explorou algumas formas e técnicas para gerar imagens de alta definição (1024×1024 pixels) usando GANs (Generative Adversarial Networks). É incrivelmente surpreendente ver imagens HD super realistas de rostos humanos, animais e outras coisas geradas por um algoritmo, especialmente lembrando as primeiras imagens GAN de alguns anos atrás. Passamos de imagens pixeladas de baixa qualidade para imagens próximas da realidade em pouco tempo: essa é uma prova muito clara da rapidez com que a pesquisa nesse campo avança.

Amostras de rosto StyleGAN HD

Mas lendo esses estudos recentes (o mais relevante é o artigo StyleGAN , da Nvidia, e o artigo BigGAN , do Google), sempre encontro um aspecto que reduz minha sensação de surpresa e excitação: o poder da computação. Descobrir os enormes recursos de computação usados para extrair essas imagens me faz perceber que entre mim e esses resultados está um obstáculo invaliável. Este pensamento só me faz sentir que toda a nova tecnologia explorada nos estudos está muito longe de mim e, portanto, menos surpreendente.

É por isso que neste artigo eu gostaria de explorar como fazer com que as GANs e imagens HD funcionem juntas sem a necessidade de hardware altamente caro, abrindo novas oportunidades para pessoas que não necessariamente têm acesso a GPUs de alto nível. Tudo o que foi explicado aqui pode ser obtido usando a plataforma de colaboração do Google disponível gratuitamente, que oferece uma GPU gratuita para todos os seus projetos de aprendizado profundo.

Nosso objetivo

Vamos tentar executar uma transferência de estilo entre dois domínios de imagens de alta definição, usando uma arquitetura GAN simples, mas especial, para executar nossa tarefa. Mais especificamente, vamos aplicar o estilo de pintura de Van Gogh a uma alta resolução de imagens de paisagens. É justo dizer que o Style Transfer tem sido um assunto moderno na Computer Vision nos últimos anos; o artigo original que iniciou a tendência é "Algoritmo Neural de Estilo Artístico" (Gatys et al.), que usou uma perda de Conteúdo e Estilo em uma rede convolucional pré-traçada para executar a tarefa. Enquanto este método pode trabalhar em imagens HD, ele só pode usar uma única imagem (digamos 'Starry Night') como a representação do estilo do pintor, que não é o que queremos.

Exemplos de transferência de estilo do documento original

Uma GAN, por outro lado, geralmente precisa de um domínio de imagens para treinar e, consequentemente, é capaz, no nosso caso, de capturar o estilo do pintor em sua totalidade (o artigo CycleGAN mostra resultados interessantes sobre transferência de estilo).

Exemplos de transferência de estilo CycleGAN

No entanto, o treinamento de GANs é extremamente computacionalmente caro : a geração de imagens de alta resolução só é possível com hardware de ponta e tempo de treinamento longo. Espero que os truques e técnicas explicadas neste artigo sejam capazes de ajudá-lo em suas aventuras de geração de imagem HD.

Pinturas de Van Gogh Imagens HD traduzidas para o estilo Van Gogh

Vamos começar!

A arquitetura

O que vamos tentar alcançar é chamado tradução de imagem para imagem (do domínio A para o domínio B). Existem diferentes formas e arquiteturas de rede para alcançá-lo: o mais famoso pode ser o CycleGAN, mas também existem vários outros trabalhos sobre o mesmo assunto.

Para meus experimentos, usei uma arquitetura personalizada que consiste em uma rede siamesa como Discriminadora e uma função de perda especial (mas super fácil). Escolhi esse método porque ele não depende de diferenças por pixel em nenhuma das perdas: isso significa simplesmente que a rede não segue nenhuma restrição geométrica na imagem gerada e, portanto, é capaz de criar traduções de imagem mais convincentes é válido no nosso caso).

Uma explicação profunda e completa deste tipo de arquitetura e como ela funciona pode ser encontrada neste outro artigo que escrevi aqui .

Aqui está uma breve introdução à arquitetura GAN siamesa.

Arquitetura Siamese GAN

É feito de um único gerador (G) e discriminador (D): G toma uma imagem como entrada e produz a imagem traduzida; D pega uma imagem como entrada e produz um vetor latente.

O Discriminador Siamês tem dois objetivos: dizer a G como gerar imagens mais realistas e manter nessas imagens falsas uma correlação (o mesmo 'conteúdo') com as originais.

Chamando A1, A2 e B1, B2 imagens aleatórias dos domínios A e B respectivamente, X uma imagem aleatória, e G (X) as imagens geradas pelo Gerador, o Discriminador deve codificar imagens em vetores D (X) tais como:

1. D (B1) deve estar próximo (distância euclidiana) a um ponto fixo (a origem, por exemplo), enquanto D (G (A1)) deve estar longe do mesmo ponto. Consequentemente, os vetores mais próximos dos pontos fixos representam imagens mais realistas. O Gerador, por outro lado, tenta minimizar a distância de D (G (A1)) ao ponto fixo, de um modo contraditório clássico.

2. (D (A1) -D (A2)) deve ser semelhante (semelhança de cosseno) a (D (G (A1)) – D (G (A2))) , para preservar 'conteúdo' entre A e G (A ) . Tanto o Gerador quanto o Discriminador participam desse objetivo.

Discriminador Siamês

Com estas 2 restrições (perdas) no lugar, o primeiro confiando na Magnitude dos vetores enquanto o segundo confiando no Ângulo entre os vetores, nosso objetivo completo é satisfeito e nós podemos alcançar nosso objetivo final de imagem para tradução de imagem do domínio A para o domínio B. Eu realmente sugiro que você leia este artigo onde eu dou uma explicação mais abrangente e profunda dessa arquitetura, enquanto mostro ilustrações e exemplos.

Agora que temos a arquitetura bloqueada, vamos explorar como e o que alimentar a rede para alcançar a geração de imagens HD.

Extração de Imagem

Precisamos de 2 conjuntos de imagens de imagens de alta definição: no nosso caso, vamos usar um conjunto de dados de paisagens (domínio A) e um conjunto de dados de pinturas de Van Gogh (domínio B). Tenha em mente que quanto maiores forem as imagens com as quais você escolher trabalhar, mais tempo levará para pré-processar (cortar, redimensionar) essas imagens (isso não aumentará o tempo gasto exclusivamente em treinar a rede!).

Agora precisamos escolher o tamanho das imagens que serão alimentadas no Generator: obviamente, não podemos usar o tamanho de todas as imagens HD dos conjuntos de dados, caso contrário, os tempos de treinamento e os tamanhos de rede seriam enormes e nenhum problema seria resolvido . Assim, escolhemos um SxS de tamanho pequeno o suficiente (por exemplo, 64×64 pixels) para que os tempos de treinamento possam ser mantidos sob controle e tudo continue computacionalmente viável até mesmo para as GPUs intermediárias (como as disponíveis gratuitamente no Google Colaboratory ).

Consequentemente, como você pode ter pensado, as imagens, antes de serem alimentadas ao Gerador, precisam ser cortadas (ou cortadas) em imagens SxS menores. Assim, depois de ler a imagem e transformá-la em um tensor, realizamos um corte SxS aleatório na imagem, adicionando-a a um lote e alimentando o lote para a Rede. Soa extremamente fácil e é realmente!

Agora, digamos que nós treinamos uma GAN usando este método até que cada pequena cultura SxS seja traduzida para o estilo Van Gogh pelo Generator de uma forma que nos satisfaça: como podemos agora traduzir uma imagem HD inteira do domínio A para o domínio B?

Novamente, extremamente simples: a imagem é dividida em pequenos pedaços SxS (se o tamanho da imagem HD for BxB, então teremos (B / S) x (B / S) pequenas imagens SxS), cada imagem SxS será traduzida por o Gerador e, finalmente, tudo se junta novamente .

No entanto, se tentarmos treinar uma GAN usando essa idéia simples de extrair imagens menores de imagens maiores, durante o tempo de teste, logo perceberemos um problema bem chato: as pequenas imagens extraídas pela imagem grande que queremos traduzir, quando convertidas por o Generator para o domínio B, não se misturam organicamente . As bordas de cada imagem SxS são claramente visíveis na composição final, arruinando a 'mágica' do estilo bem-sucedido de transferência. Este é um problema relativamente pequeno que pode ser muito chato: mesmo usando métodos baseados em pixels, como o CycleGAN, o mesmo obstáculo ainda aparece .

As bordas são visíveis

Como podemos resolver isso?

A solução que usei é fácil de entender e bastante elegante na minha opinião, e representa a idéia central que espero que você se lembre (e talvez use) deste artigo.

Em primeiro lugar, precisamos revisitar nosso pipeline de dados: enquanto antes de cortar diretamente as colheitas SxS da imagem HD BxB, agora temos que obter culturas 2Sx2S (se S = 64, então precisamos de culturas 128×128). Então, depois de definir nosso Gerador, criamos um novo modelo , chamado Combo, que faz as seguintes operações:

1. Leve o lote de imagens 2Sx2S (do domínio A) como entrada ( INP );

2. Corte cada imagem no INP em 4 imagens SxS ( INPCUT );

3. Alimente cada uma das 4 imagens SxS de INPCUT ao Gerador e obtenha OUTCUT (mesma forma exata que INPCUT , mas com versão traduzida de cada imagem SxS);

4. Junte-se a cada grupo de 4 imagens SxS em OUTCUT e sair (mesma forma exata como INP, mas com versão traduzida de cada imagem 2Sx2S);

5. Saída OUT.

Modelo Combo: corte, tradução, junção

A saída de Combo é então passada como entrada para o Discriminador, que agora aceita entradas do dobro do tamanho anterior (2Sx2S). Este pequeno ajuste não requer muito mais tempo de computação e pode efetivamente resolver nosso problema anterior . Como?

O Gerador agora é forçado a gerar imagens que sejam coerentes com bordas e cores , porque o Discriminador não classificará as imagens unidas incoerentes como realistas e, portanto, notificará o Gerador sobre onde ele pode melhorar. Mergulhando um pouco mais fundo, o Generator é forçado a aprender como gerar bordas realistas em cada uma das 4 arestas da imagem SxS: na imagem final juntada 2×2 cada uma das 4 arestas está em contato com outra, e mesmo uma malfeita borda gerada arruinaria o realismo das imagens 2×2.

Amostras durante o treinamento: (da esquerda para a direita) imagens do domínio A, imagens traduzidas (AB), imagens do domínio B

Todas as coisas juntas

Para ter certeza de que tudo é claro e entendido, vamos resumir como toda a rede funciona.

O objetivo é aplicar o estilo de B às imagens em A. Imagens de tamanho 2Sx2S são cortadas de imagens de alta resolução nos domínios A e B. As imagens de A são a entrada de Combo; este modelo corta as imagens em 4 menores (SxS), depois usa o Generator G para convertê-las e, finalmente, as une. Nós chamamos essas imagens falsas de AB.

Agora vamos nos concentrar no Discriminador Siamês D : o tamanho de sua entrada é o dobro do tamanho da entrada do Gerador (2Sx2S), enquanto a saída é um vetor de tamanho LENVEC .

D codifica imagens em vetores D (X) como:

1. D (B) deve estar próximo da origem (vetor de zeros de tamanho VECLEN ):

LossD1 é o quadrado da distância euclidiana de D (B) a partir do ponto de origem, assim Eucl (D (A)) ² ;

2. D (AB) deve estar longe da origem:

LossD2 é ( max (0, custo – Eucl (D (AB)))) ²

3. Os vetores de transformação (D (A1) -D (A2)) e (D (AB1) -D (AB2)) devem ser vetores semelhantes, para preservar o 'conteúdo' de imagens:

LossD3 é a cosseno- similaridade (D (A1) -D (A2), D (AB1) -D (AB2))

Por outro lado, o Gerador deve gerar imagens (unidas) AB como:

1. D (AB) deve estar próximo da origem:

PerdaG1 é Eucl (D (AB)) ²

2. Os vetores de transformação (D (A1) -D (A2)) e (D (AB1) -D (AB2)) devem ser vetores semelhantes (mesmo objetivo do Discriminador):

PerdaG2 é cosseno- similaridade (D (A1) -D (A2), D (AB1) -D (AB2))

Uma explicação mais profunda sobre como cada uma dessas perdas funciona pode ser encontrada em meu artigo aqui , onde eu explico em detalhes como um Discriminador Siamês funciona (acho que vale a pena ler!).

É isso aí!

Seguindo este método, o Gerador é capaz de aprender como gerar pequenas imagens estilizadas que podem ser unidas sem qualquer discrepância de borda . Assim, ao traduzir uma imagem HD inteira, depois de cortá-la em imagens SxS menores separadas e alimentá-las ao Generator, podemos uni-las em uma imagem HD final, visualmente agradável e coerente .

Exemplos de tradução em imagens HD: embora não seja perfeito, são geradas pinceladas realistas e as imagens parecem bastante coerentes. Soluções podem ser redes de ajuste fino e maior capacidade

Conclusão

A técnica explicada neste artigo ainda apresenta alguns problemas que precisamos abordar.

Se imagens de alta definição são escolhidas, as culturas menores usadas para treinar a rede podem não conter informações relevantes (podem ser apenas cores sólidas, semelhantes a pixels únicos) e, portanto, o treinamento pode não ser bem-sucedido: tanto o Gerador quanto o Discriminador algum tipo de informação a processar (o Discriminador deve codificar imagens com base no seu 'conteúdo') e pode enfrentar alguns problemas se essa informação não estiver disponível.

Caso de falha: o gerador “alucina” cores e formas incoerentes em algumas áreas

Mesmo que o treinamento termine com sucesso, ao unir todas as diferentes culturas de uma imagem com resolução muito alta, a contribuição estilística de cada pequena imagem traduzida não é suficiente para toda a imagem HD, que muitas vezes parece similar à original com apenas um deslocamento em suas cores.

Em meus experimentos, acho que, para a fase de treinamento, usar uma versão redimensionada (baixa resolução) do conjunto de dados HD, enquanto alterna para as imagens HD completas ao traduzir, certamente ajuda no primeiro problema.

Essa técnica deixa muito a ser explorada : outros tipos de traduções de imagens diferentes de uma transferência de estilo tradicional podem ser possíveis. É importante lembrar que o Gerador no caso apresentado não tem idéia sobre o contexto de toda a imagem HD e apenas "vê" as culturas de baixa resolução. Assim, dar ao Gerador algum contexto (talvez na forma de um 'vetor de contexto' codificado?) Sobre as imagens como um todo pode certamente ampliar a gama de aplicações da técnica, abrindo possibilidades para tipos de traduções de imagem em HD muito mais complexas e sensíveis ao contexto. (objetos para outros objetos, rostos, animais).

Então, como você deve ter entendido, as possibilidades são infinitas e ainda não descobertas!

Eu gostaria de agradecer sinceramente pela atenção que você doou a este artigo, é muito apreciado, e espero que você saia com algo novo.

Diverta-se!

Texto original em inglês.