3

I converted an image into a gray scale numpy array using opencv:

im_g=cv2.imread("smallgray.png",0)
print(im_g)

[[187 158 104 121 143]
 [198 125 255 255 147]
 [209 134 255  97 182]]

I want to darken the image for those values that are higher than 200 for example, being 255 white and 0 black. If I do this I get the correct result:

im_g[im_g>200] = 150
print(im_g)

[[187 158 104 121 143]
 [198 125 150 150 147]
 [150 134 150  97 182]]

But my question is, if I don't want to use a constant (like 150 in the example) and instead perform some calculation on the current element, how do I refer to that element??

Thanks in advance

7
  • Something like im_g[im_g>(255-im_g)]? Commented Aug 16, 2019 at 7:40
  • no, that wouldn't be it. If I have to describe it, it would be "for each element, if it's greater than 200 for example, replace the element with the current value multiplied by the result of some function that returns a number"... Commented Aug 16, 2019 at 7:44
  • I meant it as an example; you can replace 255 - im_g with any vectorized numpy function that performs the computation you need. Commented Aug 16, 2019 at 7:46
  • 1
    Maybe have a look here and here and here. Commented Aug 16, 2019 at 7:50
  • 1
    np.where in combination with a lambda function should do what you want Commented Aug 16, 2019 at 7:58

4 Answers 4

2

You can easily vectorize your operation using where:

im_g = np.where(im_g < 150, im_g, np.random.randint(1, 40, size=im_g.shape))
Sign up to request clarification or add additional context in comments.

1 Comment

thanks!! it's nice to have another solution. Could you explain what's happening on that 3rd parameter?. I tested in jupyter and it works wonders. Is this more performant than the np,vectorize method?
0

You could just loop through the list of lists with a list comprehension and use an if and else statement. For example

t=[[187, 158, 104, 121, 143],
 [198, 125, 255, 255, 147],
 [209, 134, 255,  97, 182]]

new=[[x*2-50 if x>190 else x for x in y] for y in t]

returns this

[[187, 158, 104, 121, 143],
 [3910, 125, 5050, 5050, 147],
 [4130, 134, 5050, 97, 182]]

Is this what you're looking for? You could presumably add any function into the the list comprehension to get the exact conditional that you want

Comments

0

Assuming you want to use some function on it

def some_func(x):
    return x/10.

Convert the array to a numpy array:

import numpy as np
im_g = np.asarray(im_g)

and use

im_g[im_g>200] = some_func(im_g[im_g>200])

1 Comment

OP only wants to perform a function on selected indices
0

I ended up using the vectorize function as stated in the documentation along with a lambda function(thanks @hilberts_drinking_problem for pointing me in the right direction). If I replace that random function with a custom function I get the functionality I need, I just wanted to leave a template for future reference:

=================
import random
import cv2
import numpy as np

#loading image as a numpy array(grayscale)
im_g=cv2.imread("smallgray.png",0)
print(im_g)    

=================

[[187 158 104 121 143]
 [198 125 255 255 147]
 [209 134 255  97 182]]

=================

#applying function conditionally to each element
index = lambda x: x if x < 150 else random.randint(1,40)
vfunc = np.vectorize(index)
vectorized_im=vfunc(im_g)
print(vectorized_im)  
cv2.imwrite("darkened.png",vectorized_im)

=================

array([[ 37,  38, 104, 121, 143],
       [ 34, 125,  40,   6, 147],
       [ 10, 134,   9,  97,  24]])

3 Comments

Also from the docs on np.vectorize, it's noted - The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop.. You might want to add that too for future reference.
thanks for your contribution!! I read about that, how would you achieve the same with better performance? Just curious
For that we need to know the exact function you are working with.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.