Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent im2double function in OpenCV Python

In MATLAB, the following code reads in an image and normalizes the values between [0.0,1.0]:

img=im2double(imread('image.jpg')) 

I would like to perform this in OpenCV Python. Is there an equivalent function to do this?

I have tried the following code, but its asking for source IplImage. Also, what would be the equivalent to imread in Python?

def im2double(im):
    mat = cvGetMat(im);
    if CV_MAT_DEPTH(mat.type)==CV_64F:
       return mat
    im64f = array(size(im), 'double')
    cvConvertScale(im, im64f, 1.0, 0.0)
    return im64f
like image 583
Naveen Raja Avatar asked Mar 17 '15 13:03

Naveen Raja


1 Answers

I would avoid using the old cv module and use cv2 instead as these use numpy arrays. numpy arrays operate very similar to arrays and matrices in MATLAB.

In any case, im2double in MATLAB normalizes an image such that the minimum intensity is 0 and the maximum intensity is 1. You can achieve that by the following relationship, given a pixel in from the image img:

out = (in - min(img)) / (max(img) - min(img))

Therefore, you would need to find the minimum and maximum of the image and apply the above operation to every pixel in the image. In the case of multi-channel images, we would find the global minimum and maximum over all channels and apply the same operation to all channels independently.

The short answer to your question is to use cv2.normalize like so:

out = cv2.normalize(img.astype('float'), None, 0.0, 1.0, cv2.NORM_MINMAX)

The first input is the source image, which we convert to float. The second input is the output image, but we'll set that to None as we want the function call to return that for us. The third and fourth parameters specify the minimum and maximum values you want to appear in the output, which is 0 and 1 respectively, and the last output specifies how you want to normalize the image. What I described falls under the NORM_MINMAX flag.

Your other question is with regards to reading in an image. To read in an image with cv2, use cv2.imread. The input into this function is a string that contains the file you want to load in. Therefore, you'd call the above function like so:

img = cv2.imread('....') # Read image here
out = cv2.normalize(img.astype('float'), None, 0.0, 1.0, cv2.NORM_MINMAX) # Convert to normalized floating point

However, if you'd like to write something yourself, we can very easily do that using numpy operations.

As such, write your function like so:

import cv2
import numpy as np

def im2double(im):
    min_val = np.min(im.ravel())
    max_val = np.max(im.ravel())
    out = (im.astype('float') - min_val) / (max_val - min_val)
    return out

You'd then use the code like so:

img = cv2.imread('...') # Read in your image
out = im2double(img) # Convert to normalized floating point

Edit - September 29, 2016

More recent versions of MATLAB now simply divide all of the numbers by the largest value supported by that datatype. For example, for uint8 the largest value is 255 while for uint16 the largest value is 65535.

If you wanted to reimplement this for more recent versions of MATLAB, you can use the numpy.iinfo function to infer what the smallest and largest values of the datatype are and convert accordingly. Simply access the largest value and divide all elements in your image by this number. Make sure you convert the image to a floating-point representation first:

import cv2
import numpy as np

def im2double(im):
    info = np.iinfo(im.dtype) # Get the data type of the input image
    return im.astype(np.float) / info.max # Divide all values by the largest possible value in the datatype
like image 140
rayryeng Avatar answered Nov 07 '22 18:11

rayryeng