Hello group, I've been redicted from usenet ("Convert numpy.ndarray into "normal" array", <75dgm1F16hqntU1@mid.dfncis.de>) here and hope this is the right place. Basically, what I have is a numpy-Array which I got from a FITS-file (it's black/white). I want to display that using GTK. Therefore every color needs to appear three times (to make it look gray R = G = B). The basic framework looks like [...] pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, width, height) pb_pixels = pb.get_pixels_array() print(type(pb_pixels), pb_pixels.shape, pb_pixels.typecode()) print(type(fits_pixels), fits_pixels.shape, fits_pixels.dtype) which gives (<type 'array'>, (480, 640, 3), 'b') (<type 'numpy.ndarray'>, (480, 640), dtype('uint8')) so now I need to assign values. Naively I started out with for x in range(width): for y in range(height): pb_pixels[y, x] = fits_pixels[y, x] which was horribly slow (around 3 seconds). Thanks to the usenet help, I now got somewhat better: fits_colors = numpy.zeros((height, width, 3), dtype="uint8") for y in range(height): for x in range(width): fits_colors[height - y - 1, x] = fits_pixels[y, x] pb_pixels[:, :] = fits_colors This also works, and is a lot faster (around 0.7 seconds). However, there seems to be a better way to do it. I played around with fits_colors = numpy.fromfunction(lambda y, x, z: fits_pixels[y, x], (height, width, 3), dtype="uint8") pb_pixels[:, :] = fits_colors Which worked somewhat - but gives weird results: The picture is rotatated 90° to the right and the lower left part is displayed repeatedly after 256 pixels... (I can make a screenshot if that's easier). The fromfunction Function is quite fast in my context (around 0.2 second). How should I solve this problem the right way? Kind regards, Johannes
Hi Johannes, According to http://www.pygtk.org/pygtk2reference/class- gdkpixbuf.html , the pixels_array is a numeric python array (a predecessor to numpy). The upshot is that perhaps the nice broadcasting machinery will work fine: pb_pixels[...] = fits_pixels[..., numpy.newaxis] This might not work, though. But perhaps it would be possible to make a numpy array that's really just a view onto the memory of pb_pixels, or perhaps one could convert fits_pixels into a numeric array... Hopefully someone on the list can make a suggestion about dealing with numeric arrays. Alternately, there are pixbuf methods for reading image data from strings. You'd just need to get fits_pixels set up properly, then call tostring() on it, and pass that to the pixbuf. The trick is in setting up fits_pixels so that its memory layout corresponds to what gtk wants. Usually, images are stored in memory as (r,g,b) tuples packed by rows and then columns; this is I assume what GTK wants. So you'd do something like: fits_color = numpy.empty((height, width, 3), dtype=numpy.uint8) fits_color[...] = fits_pixels[..., numpy.newaxis] fits_string = fits_color.tostring() pb = gtk.gdk.pixbuf_new_from_data(fits_string, gtk.gdk.COLORSPACE_RGB, False, 8, 640, 480, 3*640) Zach On Apr 28, 2009, at 2:36 AM, Johannes Bauer wrote:
Hello group,
I've been redicted from usenet ("Convert numpy.ndarray into "normal" array", <75dgm1F16hqntU1@mid.dfncis.de>) here and hope this is the right place.
Basically, what I have is a numpy-Array which I got from a FITS-file (it's black/white). I want to display that using GTK. Therefore every color needs to appear three times (to make it look gray R = G = B).
The basic framework looks like
[...] pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, width, height) pb_pixels = pb.get_pixels_array()
print(type(pb_pixels), pb_pixels.shape, pb_pixels.typecode()) print(type(fits_pixels), fits_pixels.shape, fits_pixels.dtype)
which gives
(<type 'array'>, (480, 640, 3), 'b') (<type 'numpy.ndarray'>, (480, 640), dtype('uint8'))
so now I need to assign values. Naively I started out with
for x in range(width): for y in range(height): pb_pixels[y, x] = fits_pixels[y, x]
which was horribly slow (around 3 seconds). Thanks to the usenet help, I now got somewhat better:
fits_colors = numpy.zeros((height, width, 3), dtype="uint8") for y in range(height): for x in range(width): fits_colors[height - y - 1, x] = fits_pixels[y, x] pb_pixels[:, :] = fits_colors
This also works, and is a lot faster (around 0.7 seconds). However, there seems to be a better way to do it. I played around with
fits_colors = numpy.fromfunction(lambda y, x, z: fits_pixels[y, x], (height, width, 3), dtype="uint8") pb_pixels[:, :] = fits_colors
Which worked somewhat - but gives weird results: The picture is rotatated 90° to the right and the lower left part is displayed repeatedly after 256 pixels... (I can make a screenshot if that's easier). The fromfunction Function is quite fast in my context (around 0.2 second).
How should I solve this problem the right way?
Kind regards, Johannes _______________________________________________ Numpy-discussion mailing list Numpy-discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Hi Zach, Zachary Pincus schrieb:
According to http://www.pygtk.org/pygtk2reference/class- gdkpixbuf.html , the pixels_array is a numeric python array (a predecessor to numpy). The upshot is that perhaps the nice broadcasting machinery will work fine:
pb_pixels[...] = fits_pixels[..., numpy.newaxis]
Ayyyyyyyyyyyyyyyy! *jump* That does what I want so fast that my current implementation can't even measure it. You're a genius! Thanks so much! Kind regards, Johannes
participants (2)
-
Johannes Bauer
-
Zachary Pincus