How to convert 16 bit to 8 bit image in OpenCV?

I have a 16-bit grayscale image and I want to convert it to an 8-bit grayscale image in OpenCV for using python with various functions (e.g. findContours, etc.). Is it possible to do this in python or do I need to switch to C ++?

+10
source share
5 answers

You can use numpy conversion methods since the OpenCV layout is a numpy array.

It works:

img8 = (img16/256).astype('uint8') 
+11
source

You can do this in Python using NumPy by matching an image through a lookup table.

 import numpy as np def map_uint16_to_uint8(img, lower_bound=None, upper_bound=None): ''' Map a 16-bit image trough a lookup table to convert it to 8-bit. Parameters ---------- img: numpy.ndarray[np.uint16] image that should be mapped lower_bound: int, optional lower bound of the range that should be mapped to ``[0, 255]``, value must be in the range ``[0, 65535]`` and smaller than `upper_bound` (defaults to ``numpy.min(img)``) upper_bound: int, optional upper bound of the range that should be mapped to ``[0, 255]``, value must be in the range ``[0, 65535]`` and larger than `lower_bound` (defaults to ``numpy.max(img)``) Returns ------- numpy.ndarray[uint8] ''' if not(0 <= lower_bound < 2**16) and lower_bound is not None: raise ValueError( '"lower_bound" must be in the range [0, 65535]') if not(0 <= upper_bound < 2**16) and upper_bound is not None: raise ValueError( '"upper_bound" must be in the range [0, 65535]') if lower_bound is None: lower_bound = np.min(img) if upper_bound is None: upper_bound = np.max(img) if lower_bound >= upper_bound: raise ValueError( '"lower_bound" must be smaller than "upper_bound"') lut = np.concatenate([ np.zeros(lower_bound, dtype=np.uint16), np.linspace(0, 255, upper_bound - lower_bound).astype(np.uint16), np.ones(2**16 - upper_bound, dtype=np.uint16) * 255 ]) return lut[img].astype(np.uint8) # Let generate an example image (normally you would load the 16-bit image: cv2.imread(filename, cv2.IMREAD_UNCHANGED)) img = (np.random.random((100, 100)) * 2**16).astype(np.uint16) # Convert it to 8-bit map_uint16_to_uint8(img) 
+2
source

It is really easy to convert to 8-bit using scipy.misc.bytescale. The OpenCV matrix is ​​a simple array, so bytescale will do exactly what you want.

 from scipy.misc import bytescale img8 = bytescale(img16) 
+2
source

To convert from 16 bits to 8 bits using python openCV:

 import numpy as np import cv2 imagePath = "--" img_8bit = cv2.imread(imagePath).astype(np.uint8) 
+1
source

Code from scipy (not recommended now):

 def bytescaling(data, cmin=None, cmax=None, high=255, low=0): """ Converting the input image to uint8 dtype and scaling the range to ''(low, high)'' (default 0-255). If the input image already has dtype uint8, no scaling is done. :param data: 16-bit image data array :param cmin: bias scaling of small values (def: data.min()) :param cmax: bias scaling of large values (def: data.max()) :param high: scale max value to high. (def: 255) :param low: scale min value to low. (def: 0) :return: 8-bit image data array """ if data.dtype == np.uint8: return data if high > 255: high = 255 if low < 0: low = 0 if high < low: raise ValueError("'high' should be greater than or equal to 'low'.") if cmin is None: cmin = data.min() if cmax is None: cmax = data.max() cscale = cmax - cmin if cscale == 0: cscale = 1 scale = float(high - low) / cscale bytedata = (data - cmin) * scale + low return (bytedata.clip(low, high) + 0.5).astype(np.uint8) 
0
source

Source: https://habr.com/ru/post/1201071/


All Articles