SacreD
SacreD

Reputation: 373

Numpy 8-bits images conversion to 16/32-bits images before cvtColor() in opencv

I was doing some testing based on my understanding from reading the documentation but stumble upon this.

Source: NumPy convert 8-bit to 16/32-bit image

 i = cv2.imread(imgNameIn, cv2.CV_LOAD_IMAGE_COLOR) # Need to be sure to have a 8-bit input
 img = np.array(i, dtype=np.uint16) # This line only change the type, not values
 img *= 256 # Now we get the good values in 16 bit format

But from what I read here http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html

To scale down from 32bits to 8 bits one have to divide by 255 instead of 256 mentioned above which I got from the other post? This code below is what I am trying to play around with.

Would appreciate if anyone able to check if I have done the scaling correctly. I am asking this question mainly to confirm whether the supposed casting value is 255 or 256?

Upvotes: 2

Views: 3060

Answers (1)

Eskapp
Eskapp

Reputation: 3645

I have to disagree with the answer to the question you link. Format uint8 can represent 256 values of integers i.e., integers from 0 to 255 (2^8 - 1). 256 cannot be represented as uint8. uint16 will range from 0 to (2^16 - 1) = 65535.

Therefore, if you want a 16-bit, images with 65535 color levels and if the intensity values of the images are in the range [0, 1] when you read the image and in format float, you need to multiply the values by 65535 and to and then to convert the array to uint16.

It is good practice to cast the type of your end result as the very last step of the operations you perform. This is mainly for two reasons: - If you perform divisions or multiplications by float, the result will return a float and you will need to change the type again. - In general (in the mathematical sense of the term), a transformation from float to integer introduces errors. Casting the type at the very end of the operations prevents error propagation.

To go back to 8-bit i.e., 256 color levels, you need to multiply all values by 255 / 65535.

The same reasoning holds for 32-bit images with 2^32 = 4,294,967,296 possible intensity values, i.e, values in the range [0, 4294967295]. These number becoming big, you will rather work with 32-bit images in the float format where values are contained in the range [0, 1].

PS: I found your code quite confusing and did not go through in detail. Understanding that the 8/16/32/64-bit format is a representation of the number of possible intensity levels in the image is the key that should allow you to understand the transformations you are doing on the images.

Upvotes: 3

Related Questions