domingo, 20 de setembro de 2015

Criando um Mosaico de Imagens

Um mosaico de imagens é a organização de um conjunto de imagens que resulte em uma nova imagem. Para essa implementação serão utilizados a linguagem Python, as bibliotecas cv2 (OpenCV) e Numpy, um banco de imagens e uma imagem principal.

A ideia principal do algoritmo consiste em:
  • Segmentar a imagem original em pequenas partes;
  • Comparar cada parte com as imagens contidas no banco de imagens;
  • Montar uma imagem final com as imagens mais compatíveis às partes correspondentes na imagem principal.

O banco de imagens utilizado possui 1223 imagens de mesmas dimensões, desse modo, ao serem lidas e redimensionadas pelo programa de maneira padronizada, não perdem suas proporções. A função principal de comparação das imagens foi implementada utilizando análises de histograma.
Para cada parte da imagem principal, as seguintes operações são realizadas:

  • É calculado o histograma de cada banda ("b","g" e "r") da parte considerada:

 hist1_b = cv2.calcHist([img],[0],None,[256],[0,256])   
 hist1_g = cv2.calcHist([img],[1],None,[256],[0,256])   
 hist1_r = cv2.calcHist([img],[2],None,[256],[0,256])  

  • O banco de imagens é percorrido imagem a imagem realizando as devidas comparações.

Para cada comparação:

  • É verificado se a imagem já foi utilizada e quantas vezes (para controle de repetição de imagens). 
  •  São calculados os histogramas das bandas "b", "g" e "r" .

 hist2_b = cv2.calcHist([imagens[i]],[0],None,[256],[0,256])   
 hist2_g = cv2.calcHist([imagens[i]],[1],None,[256],[0,256])   
 hist2_r = cv2.calcHist([imagens[i]],[2],None,[256],[0,256])  

  • Os histogramas da parte da imagem principal e de cada imagem do banco são comparados de acordo com a banda. Essa comparação é realizada por meio da operação "compareHist" e o método da comparação pode um dos quatro: CV_COMP_CORREL, CV_COMP_CHISQR, CV_COMP_INTERSECT, CV_COMP_BHATTACHARYYA.

 comp_b = cv2.compareHist(hist1_b, hist2_b, metodo)   
 comp_g = cv2.compareHist(hist1_g, hist2_g, metodo)   
 comp_r = cv2.compareHist(hist1_r, hist2_r, metodo)  

O valor final de comparação foi composto de duas formas diferentes para os testes: soma das três comparações e menor valor entre os três.

 comp = comp_b+comp_g+comp_r  ou comp = min(comp_b,comp_g,comp_r)

As variáveis avaliadas durantes os testes foram: tamanho das partes da imagem principal a serem comparadas (grande, médio e pequeno), número de repetições de cada imagem do banco (variando entre 1 e 300, dependendo do teste), método de comparação de histograma (CV_COMP_CORREL, CV_COMP_CHISQR, CV_COMP_INTERSECT, CV_COMP_BHATTACHARYYA.) e modelo de análise dos resultados das comparações (soma dos três ou mínimo).

A imagem utilizada para os testes foi a seguinte:



Teste 1 - Tamanho das partes: Grande (sem repetição das imagens do banco)

As imagens a seguir descrevem o resultado do algoritmo testado selecionando partes de tamanho 45px por 30px.

Método BHATTACHARYYA

Retorno do Valor Mínimo
Retorno da Soma













Método CHISQR

Retorno do Valor Mínimo
Retorno da Soma













Método CORREL (correlação)

Retorno do Valor Mínimo
Retorno da Soma














Método INTERSEC

Retorno do Valor Mínimo
Retorno da Soma














Observou-se que os métodos CV_COMP_CORREL e CV_COMP_INTERSECT oferecem os melhores resultados e os testes seguintes foram realizados através deles.

Teste 2 - Tamanho das partes: Grande (com até 10 e 50 repetições)

Os métodos escolhidos foram testados novamente com a possibilidade de cada imagem do banco repetir 10 vezes. Os resultados obtidos foram os seguintes:

Método CORREL (máximo 10 repetições)

Retorno do Valor Mínimo
Retorno da Soma














Método INTERSEC (máximo 10 repetições)

Retorno do Valor Mínimo
Retorno da Soma














Os métodos escolhidos foram testados novamente com a possibilidade de cada imagem do banco repetir 50 vezes. Os resultados obtidos foram os seguintes:

Método CORREL (máximo 50 repetições)

Retorno do Valor Mínimo
Retorno da Soma













Método INTERSEC (máximo 50 repetições)

Retorno do Valor Mínimo
Retorno da Soma














Realizaram-se testes com valores maiores de repetição, mas estes não apresentaram diferenças significativas.


Teste 3 - Tamanho das partes: Médio (com possibilidade de 3, 5, 10, 50, 100 e 200 repetições)

As imagens a seguir descrevem o resultado do algoritmo testado selecionando partes de tamanho 23px por 15px. Como o banco de imagens possui apenas 1223 imagens, foi preciso permitir no mínimo 3 repetições para alcançar um número suficiente de imagens para cobrir toda a imagem.

Método CORREL (máximo 3 repetições)

Retorno do Valor Mínimo
Retorno da Soma













Método INTERSEC (máximo 3 repetições)

Retorno do Valor Mínimo
Retorno da Soma














Método CORREL (máximo 5 repetições)

Retorno do Valor Mínimo
Retorno da Soma














Método INTERSEC (máximo 5 repetições)

Retorno do Valor Mínimo
Retorno da Soma














Método CORREL (máximo 10 repetições)

Retorno do Valor Mínimo
Retorno da Soma













Método INTERSEC (máximo 10 repetições)

Retorno do Valor Mínimo
Retorno da Soma













Método CORREL (máximo 50 repetições)

Retorno do Valor Mínimo
Retorno da Soma














Método INTERSEC (máximo 50 repetições)

Retorno do Valor Mínimo
Retorno da Soma













Método CORREL (máximo 100 repetições)

Retorno do Valor Mínimo
Retorno da Soma














Método INTERSEC (máximo 100 repetições)

Retorno do Valor Mínimo
Retorno da Soma














Método CORREL (máximo 200 repetições)

Retorno do Valor Mínimo
Retorno da Soma













Método INTERSEC (máximo 200 repetições)

Retorno do Valor Mínimo
Retorno da Soma














Realizaram-se outros testes com outros valores de repetição, mas os citados foram os que melhor exibem as diferenças entre eles.

Para a continuidade dos testes, foi elegida a estratégia de retorno da soma dos histogramas (das três bandas) como mais adequado.

Teste 4 - Tamanho das partes: Pequeno (com possibilidade de 6, 20, 100, 200 e 300 repetições)

As imagens a seguir descrevem o resultado do algoritmo testado selecionando partes de tamanho 14px por 10px. Como o banco de imagens possui apenas 1223 imagens, foi preciso permitir no mínimo 6 repetições para alcançar um número suficiente de imagens para cobrir toda a imagem.

Métodos CORREL e INTERSEC (máximo 6 repetições)

Método CORREL
Método INTERSEC

Métodos CORREL e INTERSEC (máximo 20 repetições)

Método CORREL
Método INTERSEC

Métodos CORREL e INTERSEC (máximo 100 repetições)

Método CORREL
Método INTERSEC

Métodos CORREL e INTERSEC (máximo 200 repetições)

Método CORREL
Método INTERSEC

Métodos CORREL e INTERSEC (máximo 300 repetições)

Método CORREL
Método INTERSEC

Esses foram os resultados obtidos por meio da imagem:



Segue o código completo utilizado:


 import cv2  
 import numpy as np  
   
 def maiorCorrelacao(img,imagens,usadas,numero_imagens):  
     
   hist1_b = cv2.calcHist([img],[0],None,[256],[0,256])  
   hist1_g = cv2.calcHist([img],[1],None,[256],[0,256])  
   hist1_r = cv2.calcHist([img],[2],None,[256],[0,256])  
     
   valor_maior = -2  
   img_comp = []  
   pos_maior = 0  
   for i in range(numero_imagens):  
     metodo = cv2.cv.CV_COMP_INTERSECT       
       
     if usadas[i] < 300:  
       hist2_b = cv2.calcHist([imagens[i]],[0],None,[256],[0,256])  
       hist2_g = cv2.calcHist([imagens[i]],[1],None,[256],[0,256])  
       hist2_r = cv2.calcHist([imagens[i]],[2],None,[256],[0,256])  
   
       comp_b = cv2.compareHist(hist1_b, hist2_b, metodo)  
       comp_g = cv2.compareHist(hist1_g, hist2_g, metodo)  
       comp_r = cv2.compareHist(hist1_r, hist2_r, metodo)  
   
       comp = comp_b+comp_g+comp_r  
         
       if comp > valor_maior:  
         valor_maior = comp  
         img_comp = imagens[i]  
         pos_maior = i  
   return (img_comp,pos_maior)  
   
   
 def criarMosaico(imagem_principal_name):  
   imagem_principal = cv2.imread(imagem_principal_name,-1)   
   linhas,colunas,cores = np.shape(imagem_principal)  
     
   numero_imagens = 1223  
   imagens = []  
   ci = 10  
   li = 15  
   for i in range(numero_imagens):  
     nome = "banco_capas\\img ({0}).jpg".format(i)  
     imagens.append(cv2.imread(nome,-1))  
     imagens[i] = cv2.resize(imagens[i], (ci,li), interpolation = cv2.INTER_AREA)  
     
   usadas = np.zeros(numero_imagens)  
   mosaico = np.copy(imagem_principal)  
   
   c = 0  
   l = 0  
   while (l+li) <= linhas:  
     while (c+ci) <= colunas:  
       (parte,pos) = maiorCorrelacao(imagem_principal[l:(l+li):1,c:(c+ci):1,::],imagens,usadas,numero_imagens)  
       mosaico[l:(l+li):1,c:(c+ci):1,::] = parte  
       usadas[pos] += 1  
       c += ci  
     c = 0  
     l += li  
   
   return mosaico  
   
 mosaico = criarMosaico("p (6).jpg");  
   
 cv2.imshow("saida1",mosaico)    
 cv2.waitKey(0)  
 cv2.destroyAllWindows()  

0 comentários:

Postar um comentário