How to read raw png from an array in python opencv?
I figured it out:
# Read rawImage from a file, but in reality will have it from TCPServer
f = open('frame.png', "rb")
rawImage = f.read()
f.close()
# Convert rawImage to Mat
pilImage = Image.open(StringIO(rawImage));
npImage = np.array(pilImage)
matImage = cv.fromarray(npImage)
#show it
cv.NamedWindow('display')
cv.MoveWindow('display', 10, 10)
cv.ShowImage('display', matImage)
cv. WaitKey(0)
another way,
also in the case of a reading an actual file this will work for a unicode path (tested on windows)with open(image_full_path, 'rb') as img_stream:
file_bytes = numpy.asarray(bytearray(img_stream.read()), dtype=numpy.uint8)
img_data_ndarray = cv2.imdecode(file_bytes, cv2.CV_LOAD_IMAGE_UNCHANGED)
img_data_cvmat = cv.fromarray(img_data_ndarray) # convert to old cvmat if needed
@Andy Rosenblum's works, and it might be the best solution if using the outdated cv python API (vs. cv2).
However, because this question is equally interesting for users of the latest versions, I suggest the following solution. The sample code below may be better than the accepted solution because:
- It is compatible with newer OpenCV python API (cv2 vs. cv). This solution is tested under opencv 3.0 and python 3.0. I believe only trivial modifications would be required for opencv 2.x and/or python 2.7x.
- Fewer imports. This can all be done with numpy and opencv directly, no need for StringIO and PIL.
Here is how I create an opencv image decoded directly from a file object, or from a byte buffer read from a file object.
import cv2
import numpy as np
#read the data from the file
with open(somefile, 'rb') as infile:
buf = infile.read()
#use numpy to construct an array from the bytes
x = np.fromstring(buf, dtype='uint8')
#decode the array into an image
img = cv2.imdecode(x, cv2.IMREAD_UNCHANGED)
#show it
cv2.imshow("some window", img)
cv2.waitKey(0)
Note that in opencv 3.0, the naming convention for the various constants/flags changed, so if using opencv 2.x, you will need to change the flag cv2.IMREAD_UNCHANGED. This code sample also assumes you are loading in a standard 8-bit image, but if not, you can play with the dtype='...' flag in np.fromstring.