How to represent a numpy array to a pygame surface?

I am writing code, part of which reads the image source and displays it on the screen for user interaction. I also need pointy image data. To read data and display it in pyGame

I use the following:
 def image_and_sharpen_array(file_name): #read the image data and return it, with the sharpened image image = misc.imread(file_name) blurred = ndimage.gaussian_filter(image,3) edge = ndimage.gaussian_filter(blurred,1) alpha = 20 out = blurred + alpha*(blurred - edge) return image,out #get image data scan,sharpen = image_and_sharpen_array('foo.jpg') w,h,c = scan.shape #setting up pygame pygame.init() screen = pygame.display.set_mode((w,h)) pygame.surfarray.blit_array(screen,scan) pygame.display.update() 

And the image displayed on the screen only rotate and flip. Is this due to the differences between misc.imread and pyGame ? Or is it because of something wrong in my code?

Is there any other way to do this? Most of the solutions I read included saving the shape and then reading it with `` pyGame ''.

+7
python numpy pygame pygame-surface
source share
4 answers

Each lib has its own way of interpreting image arrays. By turning, I suppose you mean transposed. The way PyGame shows multiple arrays. There are many ways to make it look β€œright.” There are actually many ways to show an array that gives you full control over the presentation of channels, etc. In pygame version 1.9.2, this is the fastest array I could reach. (Note for an earlier version this will not work!). This function will fill the surface with an array:

 def put_array(surface, myarr): # put array into surface bv = surface.get_view("0") bv.write(myarr.tostring()) 

If this does not work, use this should work everywhere:

 # put array data into a pygame surface def put_arr(surface, myarr): bv = surface.get_buffer() bv.write(myarr.tostring(), 0) 

You probably still don't get what you want, so it wraps or changes color channels. The idea is to manage arrays in this form, which assigns this surface buffer. To find out what the correct order of the order and axis is, use the openCV library (cv2.imread (file name)). With openCV, you open images in the BGR standard as standard and has many conversion functions. If I remember correctly, when writing directly to a surface buffer, BGR is the correct order for 24 bits and BGRA for a 32-bit surface. Thus, you can try to put an array of images that you select from the file with this function and blit on the screen.

There are other ways to draw arrays, for example. there is a whole set of helper functions http://www.pygame.org/docs/ref/surfarray.html
But I would not recommend using it, since surfaces are not designed to manipulate pixels directly, you are likely to lose links. A little tip: to perform an "alarm test" use an image, for example. This way, you will immediately see that something is wrong, just load the array and try to do it.

enter image description here

+1
source share

My suggestion is to use the pygame.transform module. There are flip and rotate methods that you can use, however your conversion is. See the docs on this.

My recommendation is to save the output image in the new Surface , and then apply the transforms and go to the screen.

 temp_surf = pygame.Surface((w,h)) pygame.surfarray.blit(temp_surf, scan) '''transform temp_surf''' screen.blit(temp_surf, (0,0)) 

I have no idea why this is. This is probably due to the order in which the axes are transferred from the 2d array to pygame Surface .

+1
source share

I thought that technico provided a good solution - to rely a little on information. Assuming get_arr () is a function that returns an array of pixels:

 pixl_arr = get_arr() pixl_arr = numpy.swapaxes(pixl_arr, 0, 1) new_surf = pygame.pixelcopy.make_surface(pixl_arr) screen.blit(new_surf, (dest_x, dest_y)) 

Alternatively, if you know that the image will always have the same dimensions (as if iterating through frames of a video or gif file), it would be more efficient to use the same surface:

 pixl_arr = get_arr() pixl_arr = numpy.swapaxes(pixl_arr, 0, 1) pygame.pixelcopy.array_to_surface(old_surf, pixl_arr) screen.blit(old_surf, (dest_x, dest_y)) 

YMMV, but so far it works well for me.

+1
source share

I often use the numpy swapaxes() method: In this case, we only need to invert the x and y axes (0 and 1 axes) before displaying our array:

 return image.swapaxes(0,1),out 
0
source share

All Articles