简体   繁体   中英

How do I get a TIFF bytestream from an OpenCV image, rather than a numpy array?

In python, I want to convert an image that has been processed using OpenCV for transmission in a certain image format ( TIFF in this case, but could be: BMP, JPEG, PNG, .....).

For this purpose it will suffice to encode the OpenCV image into a memory buffer. The problem is that when I use cv2.imencode() to do this the returned object still looks like a numpy array:

import cv2
img_cv2_aka_nparr = cv2.imread('test.jpg')
my_format = '.tiff'
retval, im_buffer = cv2.imencode(my_format, img_cv2_aka_nparr)
print type(im_buffer)

im_buffer is just another numpy array - it is not at all a TIFF-encoded bytestream! As far as I can tell, OpenCV images in python always behave like numpy arrays, and even look like numpy arrays via type() .

In fact, if you want to create a dummy "OpenCV image", you have to use numpy - see eg https://stackoverflow.com/a/22921648/1021819

Why is this, and how do I fix it? That is, how do I obtain an actual TIFF-encoded bytestream rather than another numpy array?

Now I love numpy , but in this case I need the image to be readable by non-python services, so it needs to be in a commonly-available (preferably lossless) format (see list above).

(I've gone round the houses of embedding numpy within JSON and decided against it.)

I could use PIL /pillow, scipy , and some, but I am trying to minimize dependencies (ie so far only cv2 , numpy and intrinsics).

Thanks!

Following https://stackoverflow.com/a/50630390/1021819 and building (but not very much) on the comment by Dan Masek, the required extra step is simply to use im_buffer.tobytes() , which returns a bytestring that can be sent through a stream.

Python OpenCV images do seem to be represented as pure numpy arrays. As pointed out by Dan Masek, the arrays can be transformed using cv2.imencode() into TIFF, PNG, BMP, JPG etc.

There is obviously some debate around choice of formats and compression. In the case above there was a preference for lossless compression, implying TIFF, BMP or PNG (still there will be debate). The python bindings to OpenCV have no tunable parameters for TIFF compression (unlike(?) the C++ bindings?), so it's not very easy to discover what is being done there. The compression level could apparently be better using other libraries but my aim was to minimize dependencies (see above).

A BMP-encoded image was no smaller than a TIFF one. PNG compression is tunable in python OpenCV, and setting

cv2.imencode('.png', nparr, [int(cv2.IMWRITE_PNG_COMPRESSION),1])

has given the best size-speed trade-off so far. Thanks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM