8

I have an image with data type int16. So when I have to convert its range to 0-255, I got two ways to do that in Python.

1) Use numpy.uint8 function directly

2) Use OpenCV cv2.normalize function with 0-255 range and then use numpy.uint8.

In Matlab, we directly get the conversion using uint8 function. In

Also in second case, I used NORM_MINMAX and the range of intensity values gets changed to 0-4.

What is the correct way to do the conversion?

Reti43
  • 9,656
  • 3
  • 28
  • 44
Gunjan naik
  • 501
  • 1
  • 7
  • 18

2 Answers2

18

All of these do different things.

np.uint8 considers only the lowest byte of your number. It's like doing value & 0xff.

>>> img = np.array([2000, -150, 11], dtype=np.int16)
>>> np.uint8(img)
array([208, 106,  11], dtype=uint8)

cv2.normalize with the cv2.NORM_MINMAX norm type normalises your values according to the normalisation function

img_new = (img - img.min()) * ((max_new - min_new) / (img.max() - img.min())) + min_new

It effectively changes one range to another and all the values in the between are scaled accordingly. By definition the original min/max values become the targetted min/max values.

>>> cv2.normalize(img, out, 0, 255, cv2.NORM_MINMAX)
array([255,   0,  19], dtype=int16)

uint8 in Matlab simply saturates your values. Everything above 255 becomes 255 and everything below 0 becomes 0.

>> uint8([2000 -150 11])

ans =

  255    0   11

If you want to replicate Matlab's functionality, you can do

>>> img[img > 255] = 255
>>> img[img < 0] = 0

Which one you want to use depends on what you're trying to do. If your int16 covers the range of your pixel values and you want to rescale those to uint8, then cv2.normalize is the answer.

Reti43
  • 9,656
  • 3
  • 28
  • 44
  • Thanks for clearing that up... I want to scaled the intensities. So first I have to use cv2.normalize then np.uint8. Right? – Gunjan naik Oct 22 '17 at 06:30
  • @user3515225 Yes, though you can do it in one step if you pass the argument `dtype=cv2.CV_8U` in `cv2.normalize`. – Reti43 Oct 22 '17 at 07:34
  • [`np.clip()`](https://numpy.org/doc/stable/reference/generated/numpy.clip.html#numpy-clip) performs the Matlab saturating behavior your mention. Also worth checking out for converting to `uint8` is [`cv2.convertScaleAbs()`](https://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html?highlight=convertscale#convertscaleabs). – ryanjdillon Nov 25 '21 at 15:16
2

the simply way to convert data format is to use the following formula. In this case it is possible to convert any array to a new custom format.

# In the case of image, or matrix/array conversion to the uint8 [0, 255] 
# range

Import numpy as np

new_data = (newd_ata - np.min(new_data)) * ((255 - 0) / (np.max(new_data) - 
np.new_data))) + 0
vittorio
  • 143
  • 3
  • 14