Can't decode jpg buffer back to image

I’m trying to send a compressed image slice from Python to C++

image = cv2.cvtColor(abs(sliced), cv2.COLOR_GRAY2BGR)
encoded, buf = cv2.imencode('.jpg', image)

in C++ :

// Receive the message here, excluded from code

cv::Mat data(samplerOutVideoIn->message.size(), 1, CV_8U, (uchar*)samplerOutVideoIn>;
Mat img = imdecode(data, IMREAD_UNCHANGED);

The size of the resulting frame seems to be right, but it’s filled with zeros ( black frame )

What I’m missing ? The message is getting transported correctly, so it’s not a transport issue

The original array gets printed just fine with imshow in Python ( when I mean the original array I mean before processing it with cvtColor )


sockets do not guarantee that you can send everything in one call.

nor do they guarantee that you can receive “everything” in a single call.

in fact, that is regularly (not) happening.

[mre] please

Hi thanks for answering, but I thin I’m missing something else that is not related to socket transport. When I do this conversion in Python, simulating encoding and decoding I have the same problem. This is what I do on python and I also get the shape of the image, but it’s all filled with zeros. I know I’m missing something, maybe reshaping the array ? But I don’t know what it is exactly :

    image_bytes = cv2.imencode('.jpg', last_column)[1].tobytes()
    nparr = np.frombuffer(image_bytes,np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
[[[0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]]

 [[0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]]

 [[0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]]


what makes you think those border pixels represent the entire image? numpy’s abbreviated output only shows you the first/last few elements of each dimension.

I can’t reproduce what you claim is happening, in fact, I can reproduce it working.

im = cv.imread(cv.samples.findFile("lena.jpg"))
rv, imbytes = cv.imencode('.jpg', im); assert rv
imbytes2 = np.frombuffer(imbytes.tobytes(), np.uint8)
im2 = cv.imdecode(imbytes2, cv.IMREAD_COLOR)

because I am comparing it with printing the same image slice via imshow, which works, and when I change the index of the slices it is the same shape.

you talk of slices. what are you doing? [mre] please. do click on that link please.

    slice = abs(x[:, 18:])
    image_bytes = cv2.imencode('.jpg', slice)[1].tobytes()
    nparr = np.frombuffer(image_bytes,np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)


This is the entire test, there is nothing else besides the original image. What I’m doing is slicing it to get chunks of the image. This is why I’m wondering if I need to do something else after slicing, since imshow prints the slice in black and white correctly if I print it before processing it

what is abs?

I still can’t reproduce what you’re describing. works perfectly fine here.

It’s the resulting image of a computed histogram. You do abs to get floats because it’s complex otherwise. If I print this with imshow like

cv2.imshow('image',slice) The slice gets printed in black and white correctly. Comparing arrays :

slice = abs(Wxo[:, 5:])
(44, 17)
image_bytes = cv2.imencode('.jpg', slice)[1].tobytes()
nparr = np.frombuffer(image_bytes,np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_UNCHANGED)
(44, 17)

But if you print cv2.imshow('image',img) you get a black frame, since the array is filled with zeros … I have no idea what’s happening

ok so what range do your values have, what’s min and max of the array you pass to imencode?

We get last step of x index of the histogram:
slice = abs(Wx[:, 21:])
(44, 1)

 [0.1188442 ]
 [0.4942981 ]
 [0.6087264 ]
 [0.5708605 ]
 [0.5613081 ]
 [0.6002452 ]
 [0.5419052 ]
 [0.3428418 ]

as I said, this gets printed correctly by imshow, so I wonder how imshow does it internally to print the image and if it has something to do with encoding it to a certain format, but I’m totally lost here. thanks

Ok so it’s a matter of the format, since the ranges are not within the standards. Tiff is capable of such float ranges and it works, but I guess I need to transform those values to the accepted ranges for PNG or JPG. Thanks for your time

imshow and imwrite differ in how they interpret floats.

  • imshow shows the range 0.0 to 1.0
  • imwrite just converts to uint8, expecting a range of 0 to 255

scale your data before giving it to imwrite

yes, I’m on my way to do it :slight_smile: Thank you