Yo imágenes almacenadas leído a través cv2.imread
de una matriz masks
. La forma de la matriz es (10, 5248, 7936, 3) (10 images, image height, image width, 3 channels)
.
Ahora estoy tratando de copiar esta matriz, pero con cada imagen redimensionada a los valores monitor_h
y monitor_w
. Aquí es lo que tengo:
resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])
for i in range(masks.shape[0]):
resized_masks[i] = cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h))
Pero las imágenes que recibo de cv2.imshow
son en blanco y negro. Algo debe haber sucedido con los canales. ¿Alguna pista?
Para entender por qué sus imágenes están saliendo blanco y negro, vamos a paso a través del código.
resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])
Esta línea crea una matriz de tipo np.float
por defecto.
resized_masks[i] = cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h))
Esta línea asigna el resultado de cv2.resize
que una rebanada de resized_masks
.
Sus imágenes originales, y por lo tanto el resultado de cv2.resize
, presumiblemente, son de tipo np.uint8
. La asignación arroja los valores en float
s para ponerlos en el búfer. El elenco está bien en sí mismo: 5
conversos a 5.0
, 255
convertidos a 255.0
. El problema es que float
los valores se interpretan como siendo recortado a la gama [0.0, 1.0]
, no [0.0, 255.0]
. Por lo tanto, se termina con imágenes que son efectivamente todos los ceros y unos, a pesar de que contienen lo que parece a los valores correctos.
Puede comprobar que los valores son correctos, mostrando
resized_masks.astype(masks.dtype)
Esta no es una solución real. La verdadera solución es comenzar con el tipo de salida correcta:
resized_masks = np.empty((masks.shape[0], monitor_h, monitor_w, masks.shape[3]), dtype=masks.dtype)
Tenga en cuenta que es convencional usar tuplas para las formas y no constituyen listas, pero no importa funcionalmente.
Ahora vamos a ver por qué su parche funcionó.
resized_masks = list(resized_masks)
Esto crea una lista de Python de referencias a cada sub-serie. Puesto que usted está realmente cortado, que todavía se apuntan a una memoria intermedia contigua bajo el capó, pero lo importante es que cada uno resized_masks[i]
es una referencia por separado, no una rebanada en el mismo objeto de matriz.
resized_masks[i] = list(cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h)))
Desde resized_masks
es una lista que contiene referencias, esto es ahora asignando el resultado de cv2.resize
que el i
elemento de la lista XX, no asignar el contenido en una rebanada de tamaño apropiado. No es necesario el list
envoltorio aquí, ya que introduce una dimensión innecesaria.
resized_masks = np.asarray(resized_masks)
Esto sólo se recombina la lista en una matriz, ya que todos los elementos son del tamaño adecuado (aunque verá una dimensión unidad adicional, como se mencionó anteriormente). Como se puede imaginar esta solución es extremadamente ineficiente. En la parte superior del hecho de que usted va hacia y desde las listas y la asignación de múltiples memorias intermedias innecesarias, también se va a desechar el original np.empty
matriz sin usarlo.
El parche es más o menos lo mismo que hacer
resized_masks = np.array([cv2.resize(np.copy(mask), (monitor_w, monitor_h)) for mask in masks])
No recomiendo hacerlo así.