matchifang
matchifang

Reputation: 5450

How to convert array values 0 and 255 to corresponding 0 and 1 array

I have an image represented as numpy array which has values of 0 and 255 (no other value within the range). What is the best way to convert it to 0 and 1 array.

Upvotes: 7

Views: 14662

Answers (4)

Ofer Sadan
Ofer Sadan

Reputation: 11922

my_array = np.array([255,255,0,0])
my_array = my_array / 255

Will output

array([ 1., 1., 0., 0.])

In other words, it will work to normalize all values in the range of 0-255 (even though you said it's the only 2 values, it will work for everything in between as well, while keeping the ratios)

Upvotes: 8

Alejandro
Alejandro

Reputation: 3392

Because there are so many answers that give the right answer, I just wanted to test the different approaches and decide which is the best in terms of computational cost. I wrote the following code that creates a given data set, which is an image of 0 and 255 values, placed at random, and then I study the mean elapsed time for each proposed algorithm, varying the number of pixels of the image (note that I use the mean to reduce the noise in the measurement):

import numpy as np
import time

times1_all = [] 
times2_all = []
times3_all = []


for i in xrange(20):
    times1 = []
    times2 = []
    times3 = []

    xsizes = np.arange(100,10000,500)
    print len(xsizes)
    for xsize in xsizes:
        #Create the dataset                                                                                                                                                                                                                                                     
        ysize = xsize
        xrand = np.random.randint(0,xsize, xsize)
        yrand = np.random.randint(0,ysize, xsize)
        a = np.zeros([xsize,ysize])
        a[xrand, yrand] = 255

        start = time.time()
        b = (a == 255).astype('int')
        stop = time.time()
        time1 = stop-start

        start = time.time()
        b = a/255
        stop = time.time()
        time2 = stop-start

        start = time.time()
        b = a.clip(max=1)
        stop = time.time()
        time3 = stop-start
        print time3

        times1.append(time1)
        times2.append(time2)
        times3.append(time3)
        print 'Elapsed times --> (1)/(1)=%.2f, (2)/(1)=%.2f, (3)/(1)=%.2f' %(time1/time1,time2/time1,time3/time1)

    times1_all.append(times1)
    times2_all.append(times2)
    times3_all.append(times3)

times1_mean = np.mean(times1_all, axis=0)
times2_mean = np.mean(times2_all, axis=0)
times3_mean = np.mean(times3_all, axis=0)

The results of this test are shown in the image below, which shows the elapsed time of different algorithms as a function of the image pixel number (I only quote the side number of pixels in the x-axis). As expected, the bigger the image, the longer it takes to do the job. However, it is clear that there are systematic differences amongst the algorithms. For any number of pixels, the algorithms proposed by @randomir and @Ofer perform better than that proposed by @user1717828. So, According to this metric, @Ofer and $randomir are equivalent.

Comparison of algorithms

Upvotes: 2

randomir
randomir

Reputation: 18687

Sounds like a job for numpy.clip:

>>> a = np.array([0, 255, 0, 255, 255, 0])
>>> a.clip(max=1)
array([0, 1, 0, 1, 1, 0])

From the docs:

Given an interval, values outside the interval are clipped to the interval edges. For example, if an interval of [0, 1] is specified, values smaller than 0 become 0, and values larger than 1 become 1.

Upvotes: 5

user1717828
user1717828

Reputation: 7225

You can mask (either with >0 or ==255 or really anything else) then convert to type int:

npa = np.array([0,255,0,255,255,255,0])
npa
array([  0, 255,   0, 255, 255, 255,   0])


(npa>0).astype('int')
array([0, 1, 0, 1, 1, 1, 0])

Upvotes: 1

Related Questions