Você já admirou como as câmeras dos celulares isolam o assunto principal do fundo, adicionando um desfoque sutil ao fundo com base na profundidade? Este efeito de “modo retrato” dá às fotos uma aparência profissional, simulando uma profundidade de campo rasa semelhante às câmeras DSLR. Neste tutorial, recriaremos esse efeito programaticamente usando modelos de visão computacional de código aberto, como SAM2 da Meta e MiDaS da Intel ISL.
Para construir nosso pipeline, usaremos:
- Segmentar qualquer modelo (SAM2): Para separar objetos de interesse e separar primeiro e segundo plano.
- Modelo de estimativa de profundidade: Calculando o mapa de profundidade, permite desfoque baseado em profundidade.
- Desfoque gaussiano: desfoque o fundo com intensidade variável com base na profundidade.
Etapa 1: Configurando o Ambiente
Para começar, instale as seguintes dependências:
pip install matplotlib samv2 pytest opencv-python timm pillow
Etapa 2: carrega a imagem de destino
Selecione uma imagem para usar este efeito e carregue-a em Python usando o Um travesseiro a biblioteca.
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
image_path = ".jpg"
img = Image.open(image_path)
img_array = np.array(img)
# Display the image
plt.imshow(img)
plt.axis("off")
plt.show()
Etapa 3: iniciar o SAM2
Para executar o modelo, baixe um ambiente de teste pré-treinado. O SAM2 oferece quatro variantes baseadas no desempenho e na velocidade de decisão: mínimo, mínimo, base_plus e grande. Neste tutorial, usaremos um pouco para um rápido entendimento.
Baixe o ponto de verificação do modelo em: https://dl.fbaipublicfiles.com/segment_anything_2/072824/sam2_hiera_
Substitua
from sam2.build_sam import build_sam2
from sam2.sam2_image_predictor import SAM2ImagePredictor
from sam2.utils.misc import variant_to_config_mapping
from sam2.utils.visualization import show_masks
model = build_sam2(
variant_to_config_mapping["tiny"],
"sam2_hiera_tiny.pt",
)
image_predictor = SAM2ImagePredictor(model)
Passo 4: Insira a imagem no SAM e selecione um título
Defina a imagem no SAM e atribua pontos que estejam no assunto que você deseja segmentar. SAM prevê uma máscara binária para o sujeito e o domínio.
image_predictor.set_image(img_array)
input_point = np.array([[2500, 1200], [2500, 1500], [2500, 2000]])
input_label = np.array([1, 1, 1])
masks, scores, logits = image_predictor.predict(
point_coords=input_point,
point_labels=input_label,
box=None,
multimask_output=True,
)
output_mask = show_masks(img_array, masks, scores)
sorted_ind = np.argsort(scores)[::-1]
Etapa 5: execute o modelo de estimativa de profundidade
Para medir a profundidade, usamos MiDaS pela Intel ISL. Semelhante ao SAM, você pode escolher variantes com base na precisão e velocidade.Tome cuidado: O mapa de profundidade previsto é invertido, o que significa que valores maiores correspondem a objetos mais próximos. Iremos convertê-lo na próxima etapa para melhor compreensão.
import torch
import torchvision.transforms as transforms
model_type = "DPT_Large" # MiDaS v3 - Large (highest accuracy)
# Load MiDaS model
model = torch.hub.load("intel-isl/MiDaS", model_type)
model.eval()
# Load and preprocess image
transform = torch.hub.load("intel-isl/MiDaS", "transforms").dpt_transform
input_batch = transform(img_array)
# Perform depth estimation
with torch.no_grad():
prediction = model(input_batch)
prediction = torch.nn.functional.interpolate(
prediction.unsqueeze(1),
size=img_array.shape[:2],
mode="bicubic",
align_corners=False,
).squeeze()
prediction = prediction.cpu().numpy()
# Visualize the depth map
plt.imshow(prediction, cmap="plasma")
plt.colorbar(label="Relative Depth")
plt.title("Depth Map Visualization")
plt.show()
Etapa 6: aplicar desfoque gaussiano baseado em profundidade
Aqui implementamos o desfoque baseado em profundidade usando um método iterativo de desfoque gaussiano. Em vez de usar um kernel grande, usamos um kernel pequeno várias vezes para pixels com valores de profundidade altos.
import cv2
def apply_depth_based_blur_iterative(image, depth_map, base_kernel_size=7, max_repeats=10):
if base_kernel_size % 2 == 0:
base_kernel_size += 1
# Invert depth map
depth_map = np.max(depth_map) - depth_map
# Normalize depth to range [0, max_repeats]
depth_normalized = cv2.normalize(depth_map, None, 0, max_repeats, cv2.NORM_MINMAX).astype(np.uint8)
blurred_image = image.copy()
for repeat in range(1, max_repeats + 1):
mask = (depth_normalized == repeat)
if np.any(mask):
blurred_temp = cv2.GaussianBlur(blurred_image, (base_kernel_size, base_kernel_size), 0)
for c in range(image.shape[2]):
blurred_image[..., c][mask] = blurred_temp[..., c][mask]
return blurred_image
blurred_image = apply_depth_based_blur_iterative(img_array, prediction, base_kernel_size=35, max_repeats=20)
# Visualize the result
plt.figure(figsize=(20, 10))
plt.subplot(1, 2, 1)
plt.imshow(img)
plt.title("Original Image")
plt.axis("off")
plt.subplot(1, 2, 2)
plt.imshow(blurred_image)
plt.title("Depth-based Blurred Image")
plt.axis("off")
plt.show()
Etapa 7: junte o plano de fundo ao plano de fundo
Finalmente, use uma máscara SAM para remover o primeiro plano nítido e misturá-lo com o fundo desfocado.
def combine_foreground_background(foreground, background, mask):
if mask.ndim == 2:
mask = np.expand_dims(mask, axis=-1)
return np.where(mask, foreground, background)
mask = masks[sorted_ind[0]].astype(np.uint8)
mask = cv2.resize(mask, (img_array.shape[1], img_array.shape[0]))
foreground = img_array
background = blurred_image
combined_image = combine_foreground_background(foreground, background, mask)
plt.figure(figsize=(20, 10))
plt.subplot(1, 2, 1)
plt.imshow(img)
plt.title("Original Image")
plt.axis("off")
plt.subplot(1, 2, 2)
plt.imshow(combined_image)
plt.title("Final Portrait Mode Effect")
plt.axis("off")
plt.show()
A conclusão
Com apenas algumas ferramentas, recriamos o efeito do modo retrato de forma programática. Essa técnica pode ser estendida a aplicativos de edição de fotos, simulação de efeitos de câmera ou projetos criativos.
Melhorias Futuras:
- Use algoritmos de detecção de bordas para aprimorar melhor as bordas do assunto.
- Experimente o tamanho do kernel para melhorar o efeito de desfoque.
- Crie uma interface de usuário para fazer upload de imagens e selecionar tópicos dinamicamente.
Recursos:
- Segmente qualquer modelo com META (
- Uma implementação compatível com CPU do SAM 2 (
- O modelo de estimativa de profundidade MIDAs (
Vineet Kumar é estagiário de consultoria na MarktechPost. Atualmente, ele está cursando seu bacharelado no Instituto Indiano de Tecnologia (IIT), Kanpur. Ele é um entusiasta do aprendizado de máquina. Ele está interessado em pesquisas e desenvolvimentos recentes em Deep Learning, Visão Computacional e áreas afins.
📄 Conheça 'Height': ferramenta independente de gerenciamento de projetos (patrocinado)