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.

Detectar mesa rectangular a partir de la imagen IR de ASUS Xtion Live Pro.

Tengo una imagen de IR con una resolución de (240 x 320), de tipo de dato: float32, como se puede ver aquí:
ir
La imagen “npy” cruda está aquí.

Mi objetivo es detectar la mesa (contorno marrón) para recortar esta región como una ROI.

Lo que he intentado hasta ahora es lo siguiente:
1. Ecualización del histograma para aumentar el contraste,
2. Desenfoque gaussiano para reducir el ruido, y
3. Detección de contornos para encontrar la mesa rectangular en el centro de la imagen.

Tenga en cuenta que la mesa en mi caso está instalada sobre ruedas, por lo que podría moverse ligeramente, por lo que quiero detectarla dinámicamente y no utilizar su posición fija dentro de la imagen.

El código que he utilizado es:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
import cv2
import random as rng

path = ""

# Leer el arreglo numpy
ir_raw = np.load(path+"ir.npy") # (240, 320) float32

ir = np.uint8((ir_raw/ir_raw.max()) * 255)

# Ecualización del histograma (ajuste de contraste)
heq_ir = cv2.equalizeHist(ir)

# Suavizado gaussiano (eliminación de ruido)
g_blur_ir = cv2.GaussianBlur(heq_ir, (5,5), 0)

# Umbralización de Otsu
_, thresh_ir = cv2.threshold(g_blur_ir, 120, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# Encontrar contornos
contours, hierarchy = cv2.findContours(thresh_ir, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Dibujar contornos
rng.seed(12345)
drawing = np.zeros((thresh_ir.shape[0], thresh_ir.shape[1], 3), dtype=np.uint8)

for i in range(len(contours)):
    color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
    cv2.drawContours(drawing, contours, i, color, 2, cv2.LINE_8, hierarchy, 0)

plt.subplot(121)
plt.imshow(heq_ir)
plt.title("IR")

plt.subplot(122)
plt.imshow(drawing)
plt.title("Contornos IR")

plt.show()

¿Puede decirme cómo puedo detectar la mesa rectangular para recortarla como una ROI? Gracias de antemano.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para detectar la mesa rectangular en la imagen de infrarrojos (IR) y recortarla como una ROI, puedes seguir los siguientes pasos:

    1. Utiliza técnicas de detección de bordes como la detección de bordes de Canny para detectar los bordes de la mesa. Puedes experimentar con diferentes umbrales hasta obtener los bordes deseados.
    2. Utiliza la transformada de Hough para detectar líneas rectas en la imagen. En particular, utiliza la transformada de Hough probabilística (cv2.HoughLinesP) para detectar los cuatro lados de la mesa rectangular. Esto te dará una lista de segmentos de línea que aproximan los lados de la mesa.

    3. Agrupa los segmentos de línea en cuatro grupos, correspondientes a los cuatro lados de la mesa. Puedes hacer esto calculando el ángulo de cada segmento de línea y agrupándolos en base a sus ángulos relativos.

    4. Encuentra los puntos de intersección de los cuatro grupos de segmentos de línea, lo cual te dará las cuatro esquinas de la mesa. Puedes hacer esto encontrando la intersección de cada par de líneas que pertenezcan a diferentes grupos.

    5. Recorta la región de interés (ROI) basada en las cuatro esquinas de la mesa. Para hacer esto, puedes utilizar las funciones cv2.getPerspectiveTransform y cv2.warpPerspective para realizar una transformación perspectiva en la imagen, lo cual mapeará la mesa a una forma rectangular.

    Aquí tienes un ejemplo de código que demuestra estos pasos:

    import numpy as np
    import cv2
    
    # Carga la imagen de infrarrojos (IR)
    ir = np.load("ir.npy")
    
    # Conviértela a uint8 y normalízala
    ir = np.uint8(ir / np.max(ir) * 255)
    
    # Aplica ecualización de histograma y desenfoque gaussiano
    ir = cv2.equalizeHist(ir)
    ir = cv2.GaussianBlur(ir, (5, 5), 0)
    
    # Aplica detección de bordes de Canny para encontrar los bordes
    bordes = cv2.Canny(ir, 50, 150)
    
    # Aplica transformada de Hough probabilística para encontrar segmentos de línea
    lineas = cv2.HoughLinesP(bordes, 1, np.pi/180, 50, minLineLength=50, maxLineGap=10)
    
    # Agrupa los segmentos de línea en base a sus ángulos
    grupos = [[], [], [], []]
    for linea in lineas:
        x1, y1, x2, y2 = linea[0]
        angulo = np.arctan2(y2 - y1, x2 - x1) * 180 / np.pi
        if -45 <= angulo <= 45:
            grupos[0].append(linea)
        elif 45 < angulo <= 135:
            grupos[1].append(linea)
        elif -135 <= angulo < -45:
            grupos[2].append(linea)
        else:
            grupos[3].append(linea)
    
    # Encuentra las intersecciones de los segmentos de línea para obtener las esquinas
    esquinas = []
    for i in range(4):
        for j in range(i+1, 4):
            for linea1 in grupos[i]:
                for linea2 in grupos[j]:
                    x1, y1, x2, y2 = linea1[0]
                    x3, y3, x4, y4 = linea2[0]
                    d = (x1-x2) * (y3-y4) - (y1-y2) * (x3-x4)
                    if d != 0:
                        pt = ((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4)) / d, \
                             ((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4)) / d
                        if 0 <= pt[0] < ir.shape[1] and 0 <= pt[1] < ir.shape[0]:
                            esquinas.append(pt)
    
    # Recorta la ROI basada en las esquinas
    if len(esquinas) == 4:
        # Ordena las esquinas en sentido horario comenzando desde arriba a la izquierda
        esquinas = np.array(sorted(esquinas, key=lambda x: x[0]+x[1]))[[0, 2, 3, 1]]
        # Calcula la matriz de transformación perspectiva
        src = np.float32(esquinas)
        dst = np.float32([[0, 0], [400, 0], [400, 200], [0, 200]])
        M = cv2.getPerspectiveTransform(src, dst)
        # Aplica la transformación perspectiva
        roi = cv2.warpPerspective(ir, M, (400, 200))
        # Muestra el resultado
        cv2.imshow("ROI", roi)
        cv2.waitKey(0)
    else:
        print("No se encontraron las esquinas de la mesa")
    

    Ten en cuenta que este código asume que la mesa es rectangular y que tiene cuatro lados que son aproximadamente paralelos a los bordes de la imagen. Si la mesa tiene una forma irregular o no está alineada con la imagen, entonces pueden ser necesarios pasos de procesamiento adicionales para detectarla con precisión.

Comments are closed.