Gerando paletas de cores de filmes com o Python

Andris Gauracs Blocked Desbloquear Seguir Seguindo 10 de janeiro

Como podemos usar o Python para gerar automaticamente imagens de paleta de cores no estilo do Pinterest a partir de cenas icônicas de nossos filmes favoritos

Se você for ao Pinterest e digitar “paletas de cores do filme”, poderá encontrar muitos exemplos excelentes de paletas de cores em cenas icônicas de vários filmes conhecidos. Eu pensei que seria uma boa ideia criar um programa, que pode gerar automaticamente essas paletas de cores.

Neste tutorial, irei guiá-lo pelas etapas para criar um programa desse tipo. O programa é simplesmente um único script baseado em Python, que lança uma instância do player VLC e foi complementado com vários botões e outros elementos GUI para que possamos criar nossas paletas de cores. As próprias paletas de cores são criadas usando um método de agrupamento de cores com um algoritmo chamado K-means. Vamos mergulhar!

O código completo do projeto está disponível na minha página do github .

Observação: você também pode conferir a versão em vídeo deste tutorial no meu canal:

1. Instalando os pré-requisitos

Para este projeto, precisaremos de três pacotes essenciais:

  1. Python VLC – uma ligação do Python para o framework VLC Player. Vamos usar isso para criar uma instância de um player VLC em nosso programa.
  2. PyQt4 – Um pacote GUI, que nos fornece ótimas ferramentas, que podemos usar para criar programas em funcionamento reais com janelas, botões e outros elementos gráficos da interface do usuário.
  3. OpenCV – Uma estrutura de manipulação de imagens muito poderosa, que usaremos para gerar as imagens de saída final com as paletas de cores.

Nós usaremos pip para instalar nosso primeiro pacote, o Python VLC. Abra o seu Terminal e execute o seguinte comando:

 $ pip instalar o python-vlc 

Para obter o PyQt, precisamos instalá-lo usando o Homebrew. Nota: Precisamos especificamente instalar a versão 4 para este tutorial, portanto, especificaremos ao escrever nosso comando de instalação:

 $ brew instalar pyqt @ 4 

Por fim, precisamos instalar o framework OpenCV. Nós podemos fazer isso facilmente através do pip, mas este pacote também depende muito de pacotes – matplotlib e numpy , então vamos instalar os primeiros:

 $ pip instalar o matplotlib 
$ pip install numpy
$ pip instalar scikit-learn
$ pip instalar o opencv-python

Nota: No momento de escrever este tutorial, estou instalando a segunda versão do OpenCV, portanto, em Python, ele será importado como módulo cv2. No futuro, no entanto, a versão pode ser atualizada.

Antes de chegarmos à parte de codificação real, precisamos verificar se todos os pacotes estão realmente instalados, então, depois que todas as instalações estiverem feitas, é sempre uma boa idéia abrir o Python através da linha de comando e tentar importar cada pacote por 1. Se nenhum erro aparecer na interface da linha de comando após cada importação, é seguro dizer que tudo está funcionando e podemos sair do Python e fechar a janela do Terminal. Veja como é o processo. Primeiro abra o Python simplesmente executando o seguinte comando: $ python

Agora vamos importar cada módulo sequencialmente:

 importar vlc 
importar PyQt4
importar cv2

Se o interpretador nos permite ir para a próxima linha, tudo está funcionando bem e podemos sair da interface do Python executando o seguinte comando exit() Isso fechará o Python na linha de comando. Nós também podemos fechar o próprio Terminal neste momento.

2. Obtendo a instância do VLC Player para o nosso projeto

O repositório Python VLC tem ótimos exemplos prontos para usar como incorporar a instância do VLC Player em várias configurações de projeto do Python. Para este projeto, vamos copiar o código de exemplo, que mostra um Python VLC Player pronto para usar combinado com uma interface GUI do PyQt. Esta será a espinha dorsal do nosso programa de paleta de cores. Vamos para o arquivo qtvlc.py e copiar o conteúdo do arquivo para usar em nosso próprio projeto.

Podemos então criar um novo arquivo em nosso diretório de projeto raiz e chamá-lo: vlc_player.py

Agora podemos verificar como o arquivo realmente funciona. Abra a janela do Terminal, use o comando cd para $ python vlc_player.py a pasta do nosso projeto e execute o seguinte comando: $ python vlc_player.py Quando executamos o comando, devemos ver a seguinte janela sendo lançada:

Até aí tudo bem, agora temos uma instância de trabalho de um player VLC. Agora precisamos criar nosso arquivo principal, onde faremos toda a nossa codificação personalizada. Crie um novo arquivo e nomeie como main.py ou use o comando Terminal para fazer isso: $ touch main.py

3. Modificando a interface do usuário

Antes de começarmos a trabalhar no main.py, devemos ir ao arquivo vlc_player.py e comentar a última parte do arquivo, que atua como o iniciador do programa. Como não usaremos esse arquivo como um script autônomo e o usaremos como um arquivo de classe auxiliar, devemos mover essa parte para o nosso arquivo principal. Em vlc_player.py, comente esta parte ou apague-a completamente:

No nosso arquivo main.py, vamos importar todos os pacotes necessários:

 de vlc_player import Player 
import sys
importar os
de PyQt4 import QtGui, QtCore

Então vamos configurar nossas variáveis globais, que usaremos mais tarde em nosso projeto:

Agora a parte divertida começa. Vamos criar uma subclasse de nossa classe existente encontrada no arquivo vlc_player.py, que herdará todos os atributos originais desta classe. Em seguida, adicionaremos nossas próprias funções personalizadas sobre ele para criar nosso programa personalizado. Vamos começar definindo nossa classe herdada:

Nós voltaremos a esta classe mais tarde, mas a próxima coisa que temos que fazer é configurar o nosso código principal de inicialização do programa, que nós previamente deletamos da classe vlc_player.py. Vamos deixar tudo igual ao original, exceto pelas dimensões da janela. Usaremos um novo tamanho, só porque isso criará um layout de interface de usuário mais atraente para nosso projeto específico.

Agora vamos rodar o python main.py Nós devemos ver a mesma janela de antes. Nada mudou ainda – acabamos de criar nossa classe personalizada, que faz a mesma coisa que a classe vlc_player original. Por enquanto, tudo bem. Vamos começar adicionando nosso código personalizado.

Vamos voltar para a nossa função init para a classe Custom_VLC_Player e vamos adicionar o seguinte código, que adicionará novos elementos personalizados da interface do usuário à janela do player. Modifique a função init para corresponder ao seguinte código:

Se executarmos o código novamente, veremos um layout atualizado em nossa janela principal:

4. Definindo as funções

Agora vamos definir uma função valuechange, que irá apenas atualizar o estado de nossos elementos de UI ao longo do processo de captura de quadros. Logo após a função init, vamos definir uma nova função:

Neste ponto, podemos voltar para a função init e descomentar a seguinte linha:

 self.sp.valueChanged.connect (self.valuechange) 

Isso acionará nossa função valuechange todas as vezes, quando um usuário alterar o valor do spinbox.

Agora que temos uma instância funcional do VLC Player em nosso programa, podemos acessar suas principais funções, e a função mais importante que precisamos aproveitar neste projeto é a função video_take_snapshot. Ele nos permite tirar uma foto do quadro, que está atualmente visível no player, e salvá-lo em um diretório de nossa escolha. Então, primeiro vamos encaixar o quadro, salvá-lo em nosso diretório e usá-lo em nossa etapa de processamento de imagens. Vamos em frente e escreva a função para o nosso botão "Tirar foto":

Nós também precisamos descomentar o código em nossa função init, que conecta esta função ao nosso botão:

 self.connect (self.snapbutton, QtCore.SIGNAL ("clicked ()"), self.take_snapshot) 

Agora, se executarmos o programa e começarmos a reproduzir o vídeo, poderemos ver que uma nova imagem png é salva no diretório raiz do projeto toda vez que pressionamos o botão. É exatamente assim que deve funcionar até este ponto. Em seguida, vamos verificar como podemos gerar as paletas de cores para os quadros extraídos.

5. A função de geração de paleta de cores

O nome real para este método é chamado de cluster de cores e se você fosse para o Google este termo, você certamente poderia encontrar bons tutoriais sobre como fazer este processo. Eu encontrei este tutorial muito incrível de Adrian Rosebrock sobre agrupamento de cores que usaremos como base para nosso próprio programa: https://www.pyimagesearch.com/2014/05/26/opencv-python-k-means-color -clustering /

Em uma nota lateral: Você deve definitivamente verificar o blog de Adrian https://www.pyimagesearch.com se você quiser aprender um pouco de visão de computador e tutoriais de aprendizagem profunda. Ele é um mestre nisso e tem excelentes tutoriais gratuitos em seu site sobre outros assuntos interessantes como reconhecimento de faces e detecção de objetos.

Então, no tutorial de Adrian, há duas funções principais, que precisamos emprestar e ajustar um pouco – histograma centróide e plot_colors.

Nossa versão do plot_colors será um pouco diferente. Nós usaremos o código original do centroid_histogram. Vá em frente e cole essa função dentro do nosso arquivo main.py como uma função independente. (fora da classe de jogadores VLC)

E agora vá em frente e cole nossa função plot_colors abaixo:

Nossa versão será um pouco diferente, porque em vez de plotar as cores com uma largura relativa a sua porcentagem de quanto essa cor está presente no quadro, queremos exibir todas as n cores em uma barra uniformemente, porque é assim que essas cores paletas geralmente parecem, mais eu acho que é mais visualmente atraente.

No código acima, primeiro encontramos os centróides que representam as cores com a maior freqüência, então classificamos esses centróides em uma matéria ascendente para formar uma espécie de gradiente, da cor mais escura até a mais brilhante. Mais uma vez, isso é apenas para torná-lo mais visualmente atraente. Também adicionamos uma margem definida em nossas variáveis globais, apenas para adicionar algum espaçamento entre os blocos de cores para uma melhor aparência geral.

Note que aqui nós usamos o parâmetro global offset que definimos no começo deste tutorial. Depois de mexer com a execução deste programa, notei que a primeira ou as primeiras duas cores da paleta de cores eram quase sempre completamente pretas, porque os vídeos geralmente têm uma alta frequência de tons pretos. É por isso que decidi não incluir esses primeiros tons negros no cluster. É por isso que especificamos o parâmetro-offset, que nos informa quantas cores excluir a partir do início. Isso nos permite produzir uma paleta de cores mais colorida e, portanto, mais interessante.

6. Colocar a função de geração de cores para usar

Nós temos nossa função de gerador de cor pronta, agora só temos que colocá-la em uso em nossa função de tirar fotos. Vamos voltar para a função take_snapshot e acrescentar o seguinte código a ela:

Começamos recuperando a imagem que capturamos e salvamos em nosso diretório raiz. Em seguida, transformamos essa imagem em um formato legível para OpenCV e fazemos uma cópia dessa imagem para usar em nossa paleta de cores. Como o algoritmo K-means é muito trabalhoso, nós o executamos em uma versão reduzida da imagem. Não afeta qualquer qualidade no nosso caso, porque mesmo que reduzamos a imagem, ainda podemos ter uma boa compreensão de quais cores são as dominantes.

Nós executamos as duas funções de paleta de cores que definimos anteriormente e acabamos com uma nova imagem, que é a nossa barra de paleta de cores. Nossa tarefa final é anexar essa imagem de barra à original, adicionando uma margem branca entre as duas apenas para uma melhor aparência, e a paleta de cores está pronta!

7. Complementando a UI com miniaturas

Para fornecer uma melhor visão geral de como os instantâneos tomados se parecem com sua paleta de cores acompanhada, e para acompanhar o progresso de quantos instantâneos foram tirados até agora, podemos adicionar uma lista de elementos de rótulo, que contém uma miniatura da imagem. acabado de criar. Para fazer isso no PyQt4, precisamos criar um elemento pixmap, que pode conter imagens dentro dele:

Anteriormente, criamos uma grade de dez caixas de imagem como rótulos. Agora podemos inserir o pixmap dentro desses rótulos. Por fim, queremos manter a imagem final da paleta de cores na memória, enquanto continuamos o processo de captura de instantâneos, para que possamos juntar tudo no final. É por isso que precisamos adicionar a imagem a framesTakenList – uma matriz que contém todas as nossas imagens tiradas até agora.

8. Costurando a imagem final juntos

Vamos continuar anexando o código à função take_snapshot. O próximo passo é verificar se obtivemos todos os nossos instantâneos necessários. Se for esse o caso, estamos prontos para juntá-los para formar a última imagem:

O código acima nos permite combinar todas as imagens e finalizar a tarefa salvando a entrada final em nosso diretório raiz. Nós então automaticamente saímos do programa, não para confundir o usuário. Também podemos ajustar o parâmetro global borderSize para especificar a espessura que queremos que a borda esteja ao redor de nossa imagem e da paleta de cores. Isso é apenas por preferência pessoal.

9. O exemplo completo

Sucesso! Agora, criamos nosso próprio programa gerador de paleta de cores. O código está disponível na minha página github e é completamente open source, então você pode brincar com ele, ajustá-lo ou melhorá-lo para suas próprias preferências.