Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scipy imsave saves wrong values

I'm trying to write code that will produce disparity maps using numpy and scipy, but the values that I store in my numpy array for my images are completely different from the values that are actually showing up in my output images, saved with misc.imsave. For example, in the array, none of the values are greater than 22, but in the image, I have a full range of values from 0 to 255. I thought that perhaps imsave was stretching the values so that the max value showed up as 255 in the image, but I have other images created with imsave that have a max below 255.

These are the functions I'm using to create my disparity maps, given two pgm images that have been shifted along the x axis:

def disp(i, j, winSize, leftIm, rightIm): #calculate disparity for a given point
    width = leftIm.shape[1]
    height = leftIm.shape[0]
    w = winSize / 2
    minSAD = 9223372036854775807 #max int
    for d in range(23):
        SAD = 0.0 #SAD
        k = i - w
        v = i + w
        m = j - w
        n = j + w
        for p in range(k, v+1): #window - x
            for q in range(m, n+1): #window y
                if(p - d > 0 and p < width and q < height):
                    SAD += abs((int(leftIm[q][p]) - int(rightIm[q][p - d])))
        if(SAD < minSAD):
            minSAD = SAD
            disp = d
    #       print "%d, %d" % (i, j)
    return (disp, SAD)

def dispMap(winSize, leftIm, rightIm):
    width = leftIm.shape[1]
    height = leftIm.shape[0]
    outIm = np.zeros((height, width)) 
    SADstore = np.zeros((height, width))
    w = winSize / 2
    for i in range(w, width-w):
        for j in range(w, height/3-w):
            dispout =  disp(i, j, winSize, leftIm, rightIm)
            outIm[j][i] = 1 * dispout[0] #should normally multiply by 4
            SADstore[j][i] = dispout[1]
    return (outIm, SADstore)

Ignore the SAD/SADstore return values, I have ensured that these are not effecting my current process.

This is the code I'm using to get my output:

disp12 = dispMap(9, view1, view2)
disp12im = disp12[0]
misc.imsave('disp121.pgm', disp12im)

As it current is, nothing in disp12im should be > 23. If I run a for loop to check this on the array, this remains true. However, if I load the saved image and run that same for loop on the values, I get tons of numbers over 23. What am I doing wrong?

like image 676
jackwise Avatar asked Nov 04 '15 18:11

jackwise


1 Answers

The data gets rescaled when the dtype of the array is changed from np.float64 (the data type of disp12im) to the 8 bit values stored in the image.

To avoid this, convert your image to data type np.uint8 before giving it to imsave:

misc.imsave('disp121.pgm', disp12im.astype(np.uint8))

For example, I'll save this x as a PGM image:

In [13]: x
Out[13]: 
array([[  1.,   3.,   5.],
       [ 21.,  23.,  25.]])

In [14]: x.dtype
Out[14]: dtype('float64')

Save x unaltered, and then read it back:

In [15]: imsave('foo.pgm', x)

In [16]: imread('foo.pgm')
Out[16]: 
array([[  0,  21,  42],
       [212, 234, 255]], dtype=uint8)

The values have been scaled up to the full 8-bit range.

Instead, convert x to np.uint8 before saving, and then read it back:

In [17]: imsave('foo.pgm', x.astype(np.uint8))

In [18]: imread('foo.pgm')
Out[18]: 
array([[ 1,  3,  5],
       [21, 23, 25]], dtype=uint8)
like image 62
Warren Weckesser Avatar answered Sep 29 '22 13:09

Warren Weckesser