Acceda a los valores de píxeles dentro de un límite de contorno utilizando OpenCV en Python

Estoy usando OpenCV 3.0.0 en Python 2.7.9. Estoy tratando de rastrear un objeto en un video con un fondo fijo y estimar algunas de sus propiedades. Como puede haber múltiples objetos en movimiento en una imagen, quiero poder diferenciarlos y seguirlos individualmente a lo largo de los cuadros restantes del video.

Una forma en que pensé que podía hacer eso fue convirtiendo la imagen a binario, obteniendo los contornos de las manchas (objeto rastreado, en este caso) y obteniendo las coordenadas del límite del objeto. Luego puedo ir a estas coordenadas de límite en la imagen en escala de grises, obtener las intensidades de píxel rodeadas por ese límite y rastrear las intensidades de gradiente / píxel de color en los otros marcos. De esta manera, podría mantener dos objetos separados entre sí, para que no se consideren como nuevos objetos en el siguiente cuadro.

Tengo las coordenadas de contorno del contorno, pero no sé cómo recuperar las intensidades de píxeles dentro de ese límite. ¿Podría alguien ayudarme con eso por favor?

¡Gracias!

Siguiendo con nuestros comentarios, lo que puede hacer es crear una lista de matrices numpy , donde cada elemento es la intensidad que describe el interior del contorno de cada objeto. Específicamente, para cada contorno, cree una máscara binaria que rellene el interior del contorno, encuentre las coordenadas (x,y) del objeto relleno, luego indexe en su imagen y capture las intensidades.

No sé exactamente cómo configura su código, pero supongamos que tiene una imagen en escala de grises llamada img . Es posible que deba convertir la imagen a escala de grises porque cv2.findContours funciona en imágenes en escala de grises. Con esto, llame a cv2.findContours normalmente:

 import cv2 import numpy as np #... Put your other code here.... #.... # Call if necessary #img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Call cv2.findContours contours,_ = cv2.findContours(img, cv2.RETR_LIST, cv2.cv.CV_CHAIN_APPROX_NONE) 

contours ahora es una lista de matrices de numpy 3D donde cada una es de tamaño N x 1 x 2 donde N es el número total de puntos de contorno para cada objeto.

Como tal, puedes crear nuestra lista así:

 # Initialize empty list lst_intensities = [] # For each list of contour points... for i in range(len(contours)): # Create a mask image that contains the contour filled in cimg = np.zeros_like(img) cv2.drawContours(cimg, contours, i, color=255, thickness=-1) # Access the image pixels and create a 1D numpy array then add to list pts = np.where(cimg == 255) lst_intensities.append(img[pts[0], pts[1]]) 

Para cada contorno, creamos una imagen en blanco y luego dibujamos el contorno relleno en esta imagen en blanco. Puede rellenar el área que ocupa el contorno especificando que el parámetro de thickness sea ​​-1. Establecí el interior del contorno en 255. Después, usamos numpy.where para encontrar todas las ubicaciones de filas y columnas en una matriz que coinciden con una determinada condición. En nuestro caso, queremos encontrar los valores que son iguales a 255. Después, usamos estos puntos para indexar en nuestra imagen para capturar las intensidades de píxeles que están dentro del contorno.

lst_intensities contiene esa lista de matrices numpy 1D donde cada elemento le proporciona las intensidades que pertenecen al interior del contorno de cada objeto. Para acceder a cada matriz, simplemente haga lst_intensities[i] donde i es el contorno al que desea acceder.

¡La respuesta de @rayryeng es excelente!

Una pequeña cosa de mi implementación es: np.where() devuelve una tupla, que contiene una matriz de índices de fila y una matriz de índices de columna. Entonces, pts[0] incluye una lista de row indices de row indices , que corresponden a la altura de la imagen, pts[1] incluye una lista de column indices de column indices , que corresponden al ancho de la imagen. El img.shape devuelve (rows, cols, channels) . Así que creo que debería ser img[pts[0], pts[1]] para cortar el ndarray detrás del img.