Mosaico de imagens com OpenCV e Python

Um mosaico ou panorama de imagens (em inglês, image stitching) consiste em uma composição a partir de algoritmos de alinhamento, os quais estão entre os mais antigos e usados na área de Visão Computacional.

São muito úteis, por exemplo, na construção de mapas, fotos de satélite e na criação de panoramas de imagens nos smartphones.

image

Fig. 1 - Exemplo de mosaico utilizando a função panorama de um celular


Passos para a criar um mosaico:


Passo 1 - Encontrar pontos-chave em todas as fotos

Consiste na identificação de pontos semelhantes nas imagens, para que haja o alinhamento correto dos objetos.

image

Fig. 2 - Pontos-chave entre duas imagens


Passo 2 - Encontrar correspondências paralelas (pairwise correspondences)

Para que haja a construção de um único objeto identificado, é necessário encontrar correspondências entre elas.

Como diria Fábio Jr, encontrar as metades da laranja.

image

Fig. 3 - Correspondências entre as imagens


Passo 3 e 4 - Estimar homografias semelhantes e refiná-las (pairwise homographies)

O processo de homografia (em inglês, homography) corresponde ao mapeamento de duas projeções, onde há ângulos diferentes em planos 2D ou 3D. Ao refinar esse mapeamento, é possível encontrar pontos em comum e mapear suas posições combinadas em uma única perspectiva.

image

Fig. 4 - Exemplo de um processo de homografia


Passo 5 - Junção das imagens

Por fim, para realizar o panorama é preciso juntá-las usando os conceitos anteriores. Abaixo há um exemplo de mosaico:

image

Fig. 5 - Resultado da junção das imagens

A fim de reproduzir esse resultado, utilizaremos a biblioteca open-source OpenCV e a linguagem de programação Python para construir um mosaico de múltiplas fotos.

Para criar mosaicos de imagens usando OpenCV, é indispensável usar a classe stitcher.


Passo 1 - Importação das bibliotecas

Usaremos as bibliotecas cv2 (OpenCV), glob (para retornar todos os arquivos em um diretório), matplotlib.pyplot (uma coleção de funções que simulam o MATLAB) e math (funções matemáticas).

import cv2
import glob
import matplotlib.pyplot as plt
import math


Passo 2 - Leitura das imagens

Neste passo, glob.glob identificará todas as imagens do diretório informado : ("diretorio/") e a realização da leitura será feita com o apoio da função **imread* do OpenCV.
As imagens são convertidas de BGR para RGB para facilitar a identificação dos pontos-chave das imagens.

imagefiles = glob.glob("diretorio/*")
imagefiles.sort()

images = []
for filename in imagefiles:
  img = cv2.imread(filename)
  img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  images.append(img)

num_images = len(images)


Passo 3 - Exibição das imagens

Para que haja a exibição prévia das imagens a serem utilizadas, serão plotadas linhas e colunas de acordo com num_images.

plt.figure(figsize=[30,10]) 
num_cols = 3
num_rows = math.ceil(num_images / num_cols)
for i in range(0, num_images):
  plt.subplot(num_rows, num_cols, i+1) 
  plt.axis('off')
  plt.imshow(images[i])

image

Fig. 6 - Exibição das imagens


Passo 4 - Construção do mosaico e exibição do resultado

Por fim, usaremos a classe stitcher para realizar o panorama das imagens selecionadas:

stitcher = cv2.Stitcher_create()
status, result = stitcher.stitch(images)
if status == 0:
  plt.figure(figsize=[30, 10])
  plt.imshow(result)
  plt.show()

image

Fig. 7 - Resultado do panorama de imagens

Código completo: Link no Github

import cv2
import glob
import matplotlib.pyplot as plt
import math

# Read Images

imagefiles = glob.glob("diretorio/*")
imagefiles.sort()

images = []
for filename in imagefiles:
  img = cv2.imread(filename)
  img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  images.append(img)

num_images = len(images)

# Display Images
plt.figure(figsize=[30, 10])
num_cols = 3
num_rows = math.ceil(num_images / num_cols)
for i in range(0, num_images):
  plt.subplot(num_rows, num_cols, i+1)
  plt.axis('off')
  plt.imshow(images[i])

# Stitch Images
stitcher = cv2.Stitcher_create()
status, result = stitcher.stitch(images)
if status == 0:
  plt.figure(figsize=[30, 10])
  plt.imshow(result)
  plt.show()

Referências

GARTIA, Anisha. Project 2: Local Feature Matching. Disponível em: https://www.cc.gatech.edu/classes/AY2016/cs4476_fall/results/proj2/html/agartia3/.
SZELISKI, Richard. Computer Vision: Algorithms and Applications. 2021. Disponível em: https://szeliski.org/Book/.
MILGRAM, D. L.. Computer Methods for Creating Photomosaics, in IEEE Transactions on Computers, vol. C-24, no. 11, pp. 1113-1119, Nov. 1975, doi: 10.1109/T-C.1975.224142.
OPENCV. Basic concepts of the homography explained with code. Disponível em: https://docs.opencv.org/3.4/d9/dab/tutorial_homography.html.
OPENCV. OpenCV Python Course. Disponível em: https://opencv.org/opencv-python-free-course/.
PULLI, Kari. Stitching and Blending. Disponível em: https://web.stanford.edu/class/cs231m/lectures/lecture-5-stitching-blending.pdf. Acesso em: 14 jul. 2021.
TARALLO, André de Souza. Construção Automática De Mosaicos De Imagens Digitais Aéreas Agrícolas Utilizando Transformada SIFT E Processamento Paralelo. 2013.
Wu, Mengmeng & Wang, J.. (2018). Reassembling fractured sand particles using fracture-region matching algorithm. Powder Technology. 338. 10.1016/j.powtec.2018.06.045.

17