Image bit manipulation in Python
I have an application that receives a pointer to JPEG data from a camera API wrapped with ctypes, converts it to a wx.Image, and displays the images as a movie.
One of required features is to set two of the components of a pixel equal to the third. E.g, my pixel in RGB format is (100,200,255), I want to set the the R and B values equal to the G, or (200,200,200). I need to do t his for every pixel in the image whilst maintaining a decent framerate.
I can access the RGB values from my wx.Image by calling the Image.GetData, which returns a string containing the pixel values in the following format: RGBRGBRGB ... I have implemented the feature naively by iterating through this RGBRGBRGB string.
However, this naive approach is far too slow to achieve a decent FPS because (I think):
a) I am iterating through every pixel in the image.
b) I am doing too much data copying.
开发者_运维技巧I have considered converting my RGB data to numpy, performing the operation (I assume numpy would have a faster way of doing this sort of thing), and then converting back to wx.Image. Unfortunately I cannot convert straight from the raw data to numpy as the data comes as a JPEG, not in as a RGB bitmap. So I would need to go from data->wx.Image->numpy array->wx.Image.
I have also considered implementing my own python buffer which will return, for example, the G pixel value instead of the R and B values when being read. I think this would be the ideal solution, as it requires no data copying or excessive iterations, but I have no idea how to go about doing this. Will I need to write this buffer in C? Is it possible to implement buffers in pure python and still manipulate raw memory?
So SO, how do you think I should go about improving my performance? Should I attempt the numpy or buffer solution, or is there an easier solution that I am missing?
I am mainly looking for ideas/links to relevant documentation or examples, but if someones wants to write some code then that's fine :)
Thanks
You could try using the Python Imaging Library (PIL) - this is a library for manipulating images.
You can find information about converting between a wxPython image and a PIL image here, or you can load the jpeg directly into a PIL image.
Once you have converted your wx image into a PIL image I think this will do what you want (but I have not tested it):
r, g, b = im.split() # split the image into separate color planes
im = Image.merge("RGB", (g, g, g)) # merge them back, using the green plane for each
Then convert it back to a wxPython image.
This should be orders of magnitude faster than doing it in Python, since PIL is implemented in C and optimised for image processing.
If you need really fast processing of images I suggest writing GLSL pixel shader and interface it through OpenGL and PyGame. Nothing beats processing speed of pixel shaders, because every pixel is processed in parallel by GPU on video card. If you need to test code of pixel shaders (which is written with subset of C) it is better to do that with RenderMonkey - it is decent shader development IDE !
Good luck!
精彩评论