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.

¿Cómo encuentro el rango superior y el rango inferior del espacio de color en las coordenadas dadas?

Entonces estoy trabajando en un proyecto en el que especifico 4 coordenadas como un área rectangular y necesito encontrar cuál es el rango de color superior e inferior en esa área.
Esta es la imagen de prueba:
Imagen de prueba en RGB

Y esta es el área rectangular en la cual necesito predecir el rango superior e inferior de color – (351, 467), (505, 467), (505, 538), (351, 538)

Pensé que convertir la imagen a HSV sería un poco más preciso.

Imagen HSV con coordenadas

Actualmente estoy usando este código

def upper_range(x1, x2, y1, y2, hsv):
    for i in range(hsv[y1:y2,x1:x2,0].shape[0]):
        H_upper = np.amax(hsv[y1:y2,x1:x2,0][i])
    for i in range(hsv[y1:y2,x1:x2,0].shape[0]):
        S_upper = np.amax(hsv[y1:y2,x1:x2,1][i])
    for i in range(hsv[y1:y2,x1:x2,0].shape[0]):
        V_upper = np.amax(hsv[y1:y2,x1:x2,2][i])
    range_upper = np.array([int(H_upper), int(S_upper), int(V_upper)])
    return range_upper
def lower_range(x1, x2, y1, y2, hsv):
    for i in range(hsv[y1:y2,x1:x2,0].shape[0]):
        H_lower = np.amin(hsv[y1:y2,x1:x2,0][i])
    for i in range(hsv[y1:y2,x1:x2,0].shape[0]):
        S_lower = np.amin(hsv[y1:y2,x1:x2,1][i])
    for i in range(hsv[y1:y2,x1:x2,0].shape[0]):
        V_lower = np.amin(hsv[y1:y2,x1:x2,2][i])
    range_lower = np.array([int(H_lower),int(S_lower),int(V_lower)])
    return range_lower

image = cv2.imread('test_image.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower_range = lower_range(351, 505, 467, 538, hsv)
upper_range = upper_range(351, 505, 467, 538, hsv)

Pero el rango superior e inferior que estoy obteniendo no es perfecto, y supongo que tiene sentido por qué está mal porque actualmente solo estoy obteniendo el valor máximo y mínimo en cada canal utilizando np.amax y combinando esos valores de canal haciendo un arreglo de rango.

Pero no es necesario que el arreglo de valores máximos y mínimos que obtenemos ACTUALMENTE SEA UN VALOR EXISTENTE EN EL ÁREA DE LA IMAGEN.

Por ejemplo, si consideramos cuatro valores [(220, 3 ,4), (180, 73, 29), (121, 120, 45), (2, 5,89)]

Mi código devolvería [(220, 120, 89)] como rango superior y [(2, 3, 4)] como rango inferior, pero eso no es perfectamente correcto.

¿Alguna sugerencia de cómo puedo mejorar mi código?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Una idea para mejorar el código es utilizar algoritmos de agrupación como K-Means o DBSCAN para encontrar los colores dominantes en el área rectangular. Estos algoritmos pueden agrupar píxeles similares y identificar los valores de color más comunes en el área.

    Aquí tienes un código de ejemplo utilizando la agrupación K-Means:

    import cv2
    import numpy as np
    from sklearn.cluster import KMeans
    
    def obtener_rango_de_color(x1, x2, y1, y2, imagen):
        # recortar la imagen al área rectangular
        recorte = imagen[y1:y2, x1:x2]
    
        # remodelar los píxeles en una matriz 2D
        píxeles = recorte.reshape(-1, 3)
    
        # utilizar el algoritmo K-Means para agrupar los píxeles en k grupos
        k = 5 # puedes ajustar este número para obtener resultados diferentes
        kmeans = KMeans(n_clusters=k).fit(píxeles)
    
        # obtener los valores de color promedio para cada grupo
        colores = np.array(kmeans.cluster_centers_, dtype=np.uint8)
    
        # ordenar los colores por brillo (componente V en HSV)
        colores_hsv = cv2.cvtColor(colores, cv2.COLOR_BGR2HSV)
        brillo = colores_hsv[:, 2]
        índices_ordenados = np.argsort(brillo)
        colores_ordenados = colores[índices_ordenados]
    
        # obtener el rango de color superior e inferior basado en los colores más claros y más oscuros
        rango_superior = colores_ordenados[-1]
        rango_inferior = colores_ordenados[0]
    
        return rango_superior, rango_inferior
    
    # cargar la imagen y convertirla a HSV
    imagen = cv2.imread('imagen_de_prueba.png')
    hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV)
    
    # obtener el rango de color para el área rectangular
    x1, x2, y1, y2 = 351, 505, 467, 538
    rango_superior, rango_inferior = obtener_rango_de_color(x1, x2, y1, y2, hsv)
    
    print('Rango superior:', rango_superior)
    print('Rango inferior:', rango_inferior)
    

    Este código utiliza el algoritmo sklearn.cluster.KMeans para agrupar los píxeles en el área rectangular en 5 grupos. Luego calcula los valores de color promedio para cada grupo y los ordena según el brillo. Finalmente, selecciona los colores más claros y más oscuros como el rango de color superior e inferior.

    Puedes ajustar el número de grupos (k) para obtener resultados diferentes. Un valor de k más pequeño dará como resultado un rango de colores más reducido, mientras que un valor de k más grande capturará más variaciones en el color.

Comments are closed.