2011-01-26 18 views
16

Estoy tratando con arreglos creados a través de numpy.array(), y necesito dibujar puntos en un lienzo que simula una imagen. Como hay una gran cantidad de valores cero alrededor de la parte central de la matriz que contiene datos significativos, me gustaría "recortar" la matriz, borrando columnas que solo contienen ceros y filas que solo contienen ceros.¿Hay una función de "cuadro delimitador" (división con valores distintos de cero) para un ndarray en NumPy?

Entonces, me gustaría saber si hay alguna función numpy nativa o incluso un fragmento de código para "recortar" o encontrar un "cuadro delimitador" para cortar solo la parte que contiene datos de la matriz.

(., Ya que es una cuestión conceptual, no puse ningún código, lo siento si yo debería, yo soy muy fresco a publicar en SO)

Gracias por leer

+0

http://stackoverflow.com/questions/31400769/bounding-box-of-numpy-array ver la función bbox2 ... MUCHO más rápido, si hay muchas filas/columnas completamente llenas de ceros y solo una pequeña cantidad de datos agrupados – Benjamin

Respuesta

6

El código de abajo, desde this answer corre más rápido en mis pruebas:

def bbox2(img): 
    rows = np.any(img, axis=1) 
    cols = np.any(img, axis=0) 
    ymin, ymax = np.where(rows)[0][[0, -1]] 
    xmin, xmax = np.where(cols)[0][[0, -1]] 
    return img[ymin:ymax+1, xmin:xmax+1] 

La respuesta aceptada utilizando argwhere funcionó, pero corrió más lento. Mi suposición es que es porque argwhere asigna una matriz de salida gigante de índices. Probé en una gran matriz 2D (una imagen de 1024 x 1024, con aproximadamente una región distinta de cero de 50x100).

+0

¡Encontré esta respuesta mucho más pitonica! ¡Gracias! – heltonbiker

+0

Atención, este código puede generar un error en el borde de una imagen completamente negra. Debe verificar que ninguna de las dos llamadas 'np.where()' devuelve una matriz vacía. – Delgan

0

algo como:

empty_cols = sp.all(array == 0, axis=0) 
empty_rows = sp.all(array == 0, axis=1) 

Las matrices resultantes serán 1D matrices boolianas. Bucle en ambos extremos para encontrar el 'cuadro delimitador'.

+1

se debe evitar el bucle en matrices numpy – Paul

+0

El bucle es solo 1D, por lo tanto, solicite n, no n^2. No es gran cosa. – kiyo

+1

Tiene razón sobre el pedido y ni siquiera necesita un bucle en todo el ancho de la matriz, pero el bucle de Python contiene todo tipo de pasos adicionales, como la comprobación de tipos. En este ejemplo de 1D: http://www.scipy.org/Getting_Started#head-9aed725bd569d40f625240b2b6ec710550ff14b9 ¡El bucle python funciona 25 veces más lento para realizar la misma tarea! Sin saber el tamaño o la cantidad de las imágenes o la aplicación del algoritmo (¿visión artificial?), No puedo decir qué tan grande es ese tipo de aceleración. – Paul

20

Esto debe hacerlo:

from numpy import array, argwhere 

A = array([[0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 1, 0, 0, 0, 0], 
      [0, 0, 1, 1, 0, 0, 0], 
      [0, 0, 0, 0, 1, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0]]) 

B = argwhere(A) 
(ystart, xstart), (ystop, xstop) = B.min(0), B.max(0) + 1 
Atrim = A[ystart:ystop, xstart:xstop] 
+1

¡Agradable! Solo en una nota de legibilidad, podrías hacer '(ystart, xstart), (ystop, xstop) = B.min (0), B.max (0) + 1' y luego simplemente indexar' A' con 'Atrim = a [ystart: ystop, xstart: xstop] '. Por supuesto, es totalmente equivalente, pero me parece más legible, en cualquier caso. –

+0

Hecho. Gracias, Joe. – Paul

+0

Este estaba bien, el ejemplo que usaste es exactamente el arreglo típico que usaría (solo más grande). No sabía la función en ese lugar, haré mi tarea ahora. ¡Gracias! – heltonbiker

Cuestiones relacionadas