6

I am trying to perform the following operation on an array in python:

if true then a else b

I am trying to perform it on one channel of an image. Basically I want to check if a value is greater than 255, if so, return 255 else return the value that is being checked.

here is what I'm trying:

imfinal[:,:,1] = imfinal[:,:,1] if imfinal[:,:,1] <= 255 else 255

I get the following error: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Is there a better way to perform this operation?

shaveenk
  • 1,983
  • 7
  • 25
  • 37

4 Answers4

6

Use np.where:

imfinal[:,:,1] = np.where(imfinal[:,:,1] <= 255, imfinal[:,:,1], 255)

As to why you get that error see this: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().

Essentially it becomes ambiguous when you compare arrays using and, or because what if 1 value in the array matches? To compare arrays you should use bitwise operators &, |, ~ for and, or, not respectively.

np.where uses the boolean condition to assign the value in the second param when true, else assigns the 3rd param, see the docs

Community
  • 1
  • 1
EdChum
  • 376,765
  • 198
  • 813
  • 562
2

in your expression:

if imfinal[:,:,1] <= 255

you're trying to compare a scalar with a vector, so it's unlikely to work.

What you actually want is to use map() to do the check on each element of the array:

map(lambda x: x if x <= 255 else 255, imfinal[:,:,1])
zmo
  • 24,463
  • 4
  • 54
  • 90
  • Looks like map works a lot like the point function. I was curious if it would work anyway when comparing a scalar with a vector because certain operations of that sort are possible for e.g. imfinal = 1 * (imfinal < 128) – shaveenk Mar 28 '15 at 22:36
2

While the other answers cover the general case well, the best solution in your case is probably to use numpy.minimum that does the expansion of the scalar for you:

imfinal[:,:,1] = numpy.minimum(imfinal[:,:,1], 255)
Henrik
  • 4,254
  • 15
  • 28
0

As alternative to using np.where

mask = imfinal[:,:,1] > 255
imfinal[:,:,1][mask] = 255

Or for this specific circumstance (assuming the minimum value allowed is 0).

np.clip(imfinal[:,:,1], 0, 255, out=imfinal[:,:,1]) 
Dunes
  • 37,291
  • 7
  • 81
  • 97