How to Convert a 16-Bit to an 8-Bit Image in Opencv

How to convert 16 bit image to 8 bit in OpenCV C++

Solved it by using another function.

Mat image_grayscale = image.clone();
image_grayscale.convertTo(image_grayscale, CV_8U, 1 / 256.0);

guess there was a problem with cloning

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

Thanks to @moarningsun, problem resolved:

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

Python and OpenCV: convert 16 bit image to gray image

It works with
img.astype(np.uint16)

and to check the documentation first is a very good hint!

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

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.

OpenCV BGR image to 16 bit gray scale

What you could do is create your custom function to convert BGR in uint16 to a GRAYSCALE in uint16. Fore example as follows:

def bgr2gray(img):
weights = [0.11, 0.59, 0.3]
return np.uint16(np.dot(img, weight))

Where the weights are the standard weights used to convert from RGB/BGR to grayscale (https://www.tutorialspoint.com/dip/grayscale_to_rgb_conversion.htm#:~:text=Since%20its%20an%20RGB%20image,Its%20done%20in%20this%20way.&text=If%20you%20have%20an%20color,into%20grayscale%20using%20average%20method.).

Then you would apply this function to the BGR image that you previously converted to uint16. However, this should in general not give you more information than converting the 8-bit BGR image to a 8-bit grayscale image. It would be different if the original BGR image was 16-bit.

To convert from uint8 to uint16, you should use the following formula:

img16 = np.uint16(img8)*256

OpenCV: cvLoadImage opens 16-bit image as 8-bit

Hmm... you could write your own code to load the image. Its uncompressed TIFF, so shouldn't be much trouble.



Related Topics



Leave a reply



Submit