es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Encuentra el área en una imagen con Python y OpenCV.

Me gustaría encontrar un área en aproximadamente 1,5K imágenes que todas tengan un formato similar. Todas son escaneos de imágenes pintadas o fotografiadas de personas. Todas incluyen la misma tarjeta de color. La tarjeta de color puede estar colocada en cualquier lado de la imagen (ver imagen de muestra a continuación).

El resultado debe ser una imagen que solo contenga el retrato de la persona.

Soy capaz de encontrar la tarjeta de color con la coincidencia de plantilla de OpenCV:

import cv2
import numpy as np

method = cv2.TM_SQDIFF_NORMED

# Leer las imágenes desde el archivo
img_rgb = cv2.imread('./imgs/test_portrait.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)

template = cv2.imread('./portraet_color_card.png', 0)
w, h = template.shape[::-1]

result = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)

threshold = .97
loc = np.where(result >= threshold)
for pt in zip(*loc[::-1]):
   print("Encontrado:", pt)
   cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,255,255), 2)

cv2.imwrite('result.png',img_rgb)

Salida:

Encontrado: (17, 303)
Encontrado: (18, 303)
Encontrado: (17, 304)
Encontrado: (18, 304)

Con las coordenadas y las dimensiones de la imagen, puedo determinar si la imagen está a la izquierda o a la derecha, y puedo recortar la imagen. El resultado está lejos de ser perfecto, ya que los bordes siguen presentes.

¿Hay una mejor manera de extraer los retratos de las imágenes? Preferiría trabajar con Python y OpenCV, pero estoy abierto a otras sugerencias sobre cómo resolver este problema para un mayor número de imágenes.

Muestras:
Sample image 1
Sample image 2
Sample image 3
Sample image 4

Plantilla:
Template

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Una posible solución para extraer los retratos de las imágenes es utilizar algoritmos de detección de rostros. OpenCV tiene un algoritmo de detección de rostros incorporado que se puede utilizar para este propósito. Aquí tienes un ejemplo de código para la detección de rostros utilizando OpenCV:

    import cv2
    
    # Cargar la imagen
    img = cv2.imread('imagen.jpg')
    
    # Convertir a escala de grises
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # Cargar el modelo de detección de rostros
    face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    
    # Detectar los rostros en la imagen
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
    
    # Dibujar rectángulos alrededor de los rostros detectados y guardarlos como nuevas imágenes
    for i, (x, y, w, h) in enumerate(faces):
        roi = img[y:y+h, x:x+w]
        cv2.imwrite(f'resultado_{i}.jpg', roi)
    

    Ten en cuenta que la detección de rostros no es perfecta y puede omitir algunos rostros o detectar falsos positivos. Sin embargo, podría ser un buen punto de partida para extraer los retratos de las imágenes.

    Otro enfoque que se podría utilizar es la segmentación. Un método posible para la segmentación es aplicar un algoritmo de umbralización a la imagen, que separa el primer plano del fondo. Aquí tienes un ejemplo de código para la umbralización utilizando OpenCV:

    import cv2
    
    # Cargar la imagen
    img = cv2.imread('imagen.jpg')
    
    # Convertir a escala de grises
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # Aplicar umbralización para separar el primer plano del fondo
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    
    # Obtener los contornos de los objetos del primer plano
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    # Obtener los cuadros delimitadores alrededor de los contornos y guardarlos como nuevas imágenes
    for i, contour in enumerate(contours):
        (x, y, w, h) = cv2.boundingRect(contour)
        roi = img[y:y+h, x:x+w]
        cv2.imwrite(f'resultado_{i}.jpg', roi)
    

    La umbralización puede funcionar bien si el primer plano y el fondo tienen buen contraste y son relativamente fáciles de separar. Sin embargo, es posible que no funcione bien si hay colores o texturas similares en el primer plano y el fondo. En ese caso, podrían ser necesarios algoritmos de segmentación más avanzados, como la segmentación de instancias o la segmentación semántica.

Comments are closed.