Convert signed float to uint8 image opencv

11,763

why this doesn't work:

I don't think this function is doing the rescaling you are hoping for. Consider the example from the reference manual below:

>>> image = np.array([-10, 0, 10], dtype=np.int8)
>>> rescale_intensity(image, out_range=(0, 127))
array([  0,  63, 127], dtype=int8)

It maps the minimum number in the input array to 0 and the largest number to 1. If you don't have the exact values of -1, and 1 in your input array then using this function will not work.


what you can do instead:

I recommend writing a simple function to rescale the values from -1 to 1 into 0 to 255:

>>> image = np.random.uniform(-1,1,(3,3))
>>> scaled = (image + 1)*255/2.
>>> image
array([[ 0.59057256,  0.01683666, -0.24498247],
       [-0.25144806, -0.32312655, -0.02319944],
       [ 0.50878506, -0.04102033,  0.3094886 ]])
>>> scaled
array([[ 202.79800129,  129.64667417,   96.26473544],
       [  95.44037187,   86.3013643 ,  124.54207199],
       [ 192.37009459,  122.26990741,  166.95979601]])

How it works:

  • image + 1 shifts all numbers to the [0,2] range
  • (image +1)/2. scales all numbers to [0,1]
  • (image +1)*255/2. scales the numbers from [0,1] to [0,255]
Share:
11,763

Related videos on Youtube

dpetrini
Author by

dpetrini

More than 15 years of professional experience as developer and tech team lead. Technology stack with moderate to expert level of experience and understanding: Python PyTorch/Deep Learning OpenCV/Machine Learning Linux embedded systems and drivers Linux/Unix administration C/C++ Javascript NodeJs Blockchain - Insight, explorer, web wallets React (Components) & Redux JS Libraries FullStack web development

Updated on May 25, 2022

Comments

  • dpetrini
    dpetrini almost 2 years

    I have an image from cv2.matchTemplate that is float range -1,1:

    res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
    

    res has values like: [[ 0.00730964 -0.00275442 -0.02477949 ... -0.16014284 -0.13686109 -0.13015044]

    I can see graycale map of pattern matching with:

    cv2.imshow("Match", res)
    

    However I want to see in colormap, using:

    resC = cv2.applyColorMap(res, cv2.COLORMAP_JET)
    

    Using this I immediately have issues like: "cv::ColorMap only supports source images of type CV_8UC1 or CV_8UC3 in function 'operator()'"

    So I try skimage convertion:

    from skimage import img_as_ubyte
    res = img_as_ubyte(res)
    

    or

    from skimage import exposure
    res = exposure.rescale_intensity(res, out_range=(0, 255))
    

    With them I get outputs like: [[48 46 42 ... 14 19 20] [52 56 54 ... 22 28 30]

    Better now, integers. However, something is wrong cause I get only (blue) monochrome colormaps, not the nice ones from cv2.COLORMAP_JET range. It seems is shifted somehow.

    Any hints on how to convert from -1,1 to 0,255 properly?

  • dpetrini
    dpetrini over 5 years
    Great. Worked very fine, Thank you!
  • dpetrini
    dpetrini over 5 years
    I only added "scaled = np.uint8(scaled)" to truncate decimals. So that I can use standard opencv image manipulations.