47

I'm working with PyOpenCV. How to convert cv2 image (numpy) to binary string for writing to MySQL db without a temporary file and imwrite?

I googled it but found nothing...

I'm trying imencode, but it doesn't work.

capture = cv2.VideoCapture(url.path)
capture.set(cv2.cv.CV_CAP_PROP_POS_MSEC, float(url.query))
self.wfile.write(cv2.imencode('png', capture.read()))

Error:

  File "server.py", line 16, in do_GET
  self.wfile.write(cv2.imencode('png', capture.read()))
  TypeError: img is not a numerical tuple

Help somebody!

1
  • question arose due to a TYPO. capture.read() returns a tuple (result, value), not just a numpy array. if OP had debugged this (not a minimal reproducible example...), they would have found this, and fixed it, and everything would have worked fine. Commented Jul 20 at 17:18

6 Answers 6

82

If you have an image img (which is a numpy array) you can convert it into string using:

>>> img_str = cv2.imencode('.jpg', img)[1].tostring()
>>> type(img_str)
 'str'

Now you can easily store the image inside your database, and then recover it by using:

>>> nparr = np.fromstring(STRING_FROM_DATABASE, np.uint8)
>>> img = cv2.imdecode(nparr, cv2.CV_LOAD_IMAGE_COLOR)

where you need to replace STRING_FROM_DATABASE with the variable that contains the result of your query to the database containing the image.

Sign up to request clarification or add additional context in comments.

2 Comments

have to use cv2.imdecode(nparr, cv2.IMREAD_COLOR) for opencv3.0+
isn't tobytes() better than tostring(), just as numpy recommends using frombuffer() instead of fromstring()?
14

It works in 2020 with numpy==1.19.4 and opencv==4.4.0:

import cv2

cam = cv2.VideoCapture(0)

# get image from web camera
ret, frame = cam.read()

# convert to jpeg and save in variable
image_bytes = cv2.imencode('.jpg', frame)[1].tobytes()

Comments

7

Here is an example:

def image_to_bts(frame):
    '''
    :param frame: WxHx3 ndarray
    '''
    _, bts = cv2.imencode('.webp', frame)
    bts = bts.tostring()
    return bts

def bts_to_img(bts):
    '''
    :param bts: results from image_to_bts
    '''
    buff = np.fromstring(bts, np.uint8)
    buff = buff.reshape(1, -1)
    img = cv2.imdecode(buff, cv2.IMREAD_COLOR)
    return img

Comments

6
im = cv2.imread('/tmp/sourcepic.jpeg')
res, im_png = cv2.imencode('.png', im)
with open('/tmp/pic.png', 'wb') as f:
    f.write(im_png.tobytes())

Comments

5

capture.read() returns a tuple, (err,img).

try splitting it up:

_,img = capture.read()
self.wfile.write(cv2.imencode('png', img))

3 Comments

it returns (True, array([[137], [ 80], [ 78], ..., [ 66], [ 96], [130]], dtype=uint8)), but not a byte string
How to convert that to byte string?
my solution is self.wfile.write(numpy.array(cv2.imencode('.png', img)[1]).tostring())
3

My code to use opencv with python cgi :

    im_data = form['image'].file.read()
    im = cv2.imdecode( np.asarray(bytearray(im_data), dtype=np.uint8), 1 )
    ret, im_thresh = cv2.threshold( im, 128, 255, cv2.THRESH_BINARY )
    self.send_response(200)
    self.send_header("Content-type", "image/jpg")
    self.end_headers()      
    ret, buf = cv2.imencode( '.jpg', im_thresh )
    self.wfile.write( np.array(buf).tostring() )

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.