Capa de invisibilidade usando OpenCV

Uma das abilidades indispensável para um projetista de visão computacional é sobre o uso máscaras. A capa de invisibilidade é um excelente exercício para compreensão dessa técnica.

Para repetir esse experimento você vai precisar dos seguintes itens.

  • Python3
  • Opencv-python ou opencv-contrib-python
  • numpy
  • Video de fundo
  • Uma toalha ou lençou de cor vermelho (com edição pode ser outra cor)

Podemos dividir esse propblemas nos seguintes tópicos:

  • Obtenção do fundo
  • mascaras para cor vermelha
  • Operações lógicas
import cv2
import numpy as np

cap=cv2.VideoCapture("input.mp4")
cap_fundo=cv2.VideoCapture("fundo.mp4")
mean_fundo=[]

# calcula mediana de de 10 frame
for i in range(10):
    fundo=cap_fundo.read()[1]
    mean_fundo.append(fundo)

fundo = np.median(np.array(mean_fundo),axis=0)
fundo=fundo.astype(np.uint8)

#gravar resultado
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
h, w, _ =fundo.shape
out = cv2.VideoWriter('my_saida.mp4', fourcc, 30, (h, w))

while(cap.isOpened()):
    ret,frame=cap.read()
    if not ret:
        break
    print(frame.shape)

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    lower_red = np.array([0, 120, 70])
    upper_red = np.array([30, 255, 255])
    mask1 = cv2.inRange(hsv, lower_red, upper_red)

    lower_red = np.array([120, 120, 70])
    upper_red = np.array([180, 255, 255])

    mask2 = cv2.inRange(hsv, lower_red, upper_red)

    mask1 = mask1 + mask2

    mask1 = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
    mask1 = cv2.morphologyEx(mask1, cv2.MORPH_DILATE, np.ones((3, 3), np.uint8))
    mask2 = cv2.bitwise_not(mask1)

    res1 = cv2.bitwise_and(frame, frame, mask=mask2)

    res2 = cv2.bitwise_and(fundo, fundo, mask=mask1)

    saida = cv2.addWeighted(res1, 1, res2, 1, 0)

    cv2.imshow("janela", saida)
    k = cv2.waitKey(3)
    #out.write(frame)
    if k == ord("q"):
        break

cv2.destroyAllWindows()

Das linhas 8 à 14 pegamos os 10 primeiros frames do fundo e criamos um fundo usando a mediana. Isso pode ser útil caso tenha alguma variação luminosa durante a gravação do video.

for i in range(10):
    fundo=cap_fundo.read()[1]
    mean_fundo.append(fundo)

fundo = np.median(np.array(mean_fundo),axis=0)
fundo=fundo.astype(np.uint8)

Das linhas 27 à 38 criamos as máscaras para detectar nossa capa

A segmentação realizada aqui segue os passos desse artigo link. Com excessão de que a cor vermelho esta entre 120 a 30 do canal H. Assim precisamos definir duas mascas porque o OpenCV mapear o canal H até 180.

Ou seja, uma mascara pega a região de 0 a 30 e a outra de 120 a 180.

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    lower_red = np.array([0, 120, 70])
    upper_red = np.array([30, 255, 255])
    mask1 = cv2.inRange(hsv, lower_red, upper_red)

    lower_red = np.array([120, 120, 70])
    upper_red = np.array([180, 255, 255])

    mask2 = cv2.inRange(hsv, lower_red, upper_red)

    mask1 = mask1 + mask2

Linhas 40 e 41 Aplicamos duas operações morfológica para remover ruídos e preencher buracos na máscara.

    mask1 = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
    mask1 = cv2.morphologyEx(mask1, cv2.MORPH_DILATE, np.ones((3, 3), np.uint8))

A mask1 tem valor 1 para a capa e 0 para o restante. A operação cv2.bitwise_not inverte criando a mask2. Assim quando aplicamos na imagem original, apenas a capa é removida.

a) mask1. b) mask2. d) res1. d) res2
 mask2 = cv2.bitwise_not(mask1)

    res1 = cv2.bitwise_and(frame, frame, mask=mask2)

    res2 = cv2.bitwise_and(fundo, fundo, mask=mask1)

    saida = cv2.addWeighted(res1, 1, res2, 1, 0)

Na saída combinamos res1 e res2.

Se ficou com alguma dúvida deixe um comentário abaixo.

Creditos: learnopencv

15 Replies to “Capa de invisibilidade usando OpenCV”

  1. We are a group of volunteers and opening a new scheme in our community.

    Your web site provided us with valuable info to work on. You have done a formidable job and our entire community will be grateful to you.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *