2011-08-12 53 views
6

Por lo tanto, esto debería ser un comentario a this thread, pero aparentemente está cerrado, así que aquí va. He estado jugando con bastante éxito con matplotlib, numpy y mencoder, como se ha sugerido por aquí. Desde entonces adopté Voki Codder buffer to stdin solution, lo que acelera considerablemente todo el proceso. El caso es que no pude encontrar ninguna documentación sobre la parte de -format = "bgra" del comando. Esto significa que los bytes son de derecha a izquierda, azul, verde, rojo, alfa, derecha. ¿Tienen que estar mal o algo por el estilo? El problema es que estoy trazando mapas de color de flotadores, así que estoy tratando de convertirlos a escala de grises, pero estoy recibiendo muchos patrones extraños que me hacen creer firmemente que estoy haciendo algo mal. Escribí esta función para convertir de flotantes a uint32 dentro de un rango. Pero el resultado no es el porque esperaba, ¿estoy haciendo algo terriblemente estúpido?Trazando directamente a película con numpy y mencoder

def grayscale(x, min, max): 
    return np.uint32((x-min)/(max-min)*0xffffff) 

Respuesta

5

Creo que estás confundiendo en lo que el uint32 representa. Son 4 bandas de uint8 enteros.

Si tiene datos de punto flotante y desea representarlo en escala de grises, no desea volver a escalarlo a un rango completo de 32 bits, desea volver a escalarlo a un rango de 8 bits, y repita eso para las bandas roja, verde y azul (y presumiblemente poner en una banda alfa constante).

También podría usar un byteorizador diferente. Y8 es solo una escala de grises, banda de 8 bits, y Y16 es una única banda de 16 bits en escala de grises. (Echa un vistazo a la salida del mencoder -rawvideo format=help para obtener una lista completa (aunque algo confuso).)

Sólo para ilustrar el uso de numpy de vista de un entero de 32 bits como cuatro bandas de enteros de 8 bits:

import numpy as np 
height, width = 20,20 

# Make an array with 4 bands of uint8 integers 
image = np.zeros((height, width, 4), dtype=np.uint8) 

# Filling a single band (red) 
b,g,r,a = image.T 
r.fill(255) 

# Fill the image with yellow and leave alpha alone 
image[...,:3] = (255, 255, 0) 

# Then when we want to view it as a single, 32-bit band: 
image32bit = image.reshape(-1).view(np.uint32).reshape(height, width) 
# (Note that this is a view. In other words, we could change "b" above 
# and it would change "image32bit") 

En su caso, sin embargo, es probable que quieren hacer algo más parecido a esto:

import numpy as np 
from videosink import VideoSink 

height, width = 20,20 
numframes = 1000 
data = np.random.random((height, width, numframes)) 

# Rescale your data into 0-255, 8-bit integers 
# (This could be done in-place if you need to conserve memory) 
d ata_rescaled = 255.0/(data.max() - data.min()) * (data - data.min()) 
data_rescaled = data_rescaled.astype(np.uint8) 

# The key here is the "Y8" format. It's 8-bit grayscale. 
video = VideoSink((height,width), "test", rate=20, byteorder="Y8") 

# Iterate over last axis 
for frame in data.T: 
    video.run(frame.T) 
video.close() 
+0

frío, por lo que lo mejor sería hacer algo como escala de grises def (x, min, max): t = INT_MAX * (x-min)/(max-min) return np.uint8 (t) * 0x1 + np.uint8 (t) * 0x100 + np.uint8 (x) * 0x10000 + 0x0f000000, donde int_max woul d sea el valor máximo de 8 bits ints. –

+0

@Alex - Ver las ediciones. Espero que aclare las cosas un poco! –

+0

Genial Joe, estoy haciendo la prueba en este momento, pero creo que ya lo tengo, ¡el byteorizador probablemente haga el truco! ¡Gracias una tonelada! Alex. –