Imshow() and imwrite() outputs are different and normalization is not preserving original image

I’m using the CUDA functions to calculate optical flow. I want to save the images to disk but the original array has float values ranging around -5 to 5, which gives black images when using imwrite.

Normalization to 0-255 is changing the output, although it manages to give the same output for imshow and imwrite.

Is it possible to write the image I originally viewed through imshow (the float array)?

Thanks.

Code:

#FLOW COMPUTATION
gpu_flow = brox_of.calc(gpu_prev, gpu_frame, None) #2 vectors

#splitting flow into 2
gpu_flow_x = cv2.cuda_GpuMat(gpu_flow.size(), cv2.CV_32FC1)
gpu_flow_y = cv2.cuda_GpuMat(gpu_flow.size(), cv2.CV_32FC1)
temp = cv2.cuda_GpuMat(gpu_flow.size(), cv2.CV_8U)
cv2.cuda.split(gpu_flow, [gpu_flow_x, gpu_flow_y], cv2.cuda.Stream_Null())

# set value to normalized magnitude from 0 to 255
#gpu_flow_x = cv2.cuda.normalize(gpu_flow_x, 0, 1, cv2.NORM_MINMAX, -1)
#print(gpu_flow_x.type())
#gpu_flow_y = cv2.cuda.normalize(gpu_flow_y, 0, 255, cv2.NORM_MINMAX, -1)

#help(cv2.cuda_GpuMat.convertTo)
gpu_flow_x.convertTo(cv2.CV_8U, temp)
x = gpu_flow_x.download()
y = gpu_flow_y.download()
#x3d = np.expand_dims(x, axis=2)
#x = x.astype(np.uint8)
cv2.imshow('temp', x)

This is just a small snippet that won’t make sense but should provide some context for what I’ve tried.

imwrite and imshow indeed handle floats differently.

scale your values as needed.

I think these are the full scale value ranges (but check docs to be sure):

  • imshow: floats: 0.0 to 1.0
  • imwrite: floats: 0 to 255

there may be image file formats that store floating point values as is.

you can always dump the floating point data as binary data.

OpenCV has a FileStorage class. it’s text-based (XML), so not the most efficient, and I don’t know if that’ll be exactly lossless for floats but it probably is.

I tried several combinations and now I have come to a conclusion as to why my output is bad when I’m trying to normalise it.

Optical flow vectors contain signed values, but when I normalise them to 0 to 1 for imshow, the negative values somehow clip back to the upper interval i.e -1 corresponds to 255 and so on.

How do I scale a signed array (values ranging from around -6 to 6 based on what I’ve seen) to 0 to 1?

For context,
when I tried normalising using standard methods, the black parts of my image flashed white for a few moments. So thus my conclusion that negative numbers in when fed to the 0-255 constraint results in it taking values from the upper interval.