psychopy.org | Reference | Downloads | Github

[Solved] Gap the color value to 255


#1

Hello everybody !

I am actually running a color changing experiment :

A subject will modify the color using arrows on one dimension (red/blue/green)

My actual problem is that after getting to the value 255, it starts over 0

  • Color being 250, the subject add +10 with arrows it gets to 250 +10 %255 so it goes to 5

What I would like it’s that it stays to 255.

If i had only one pixel it would be easy to restrain it to 255, the problem is that pictures have many pixel with different values for red/green/blue.

The difficulty of what I’m trying to do :
illustration : case of 2 pixels : one pixel (250, x, y) the other (150, x, y)
the subject increase twice +10 : pixel one gapped to 255, pixel 2 turned into 170
the subject decrease -10 : pixel one should stay to 255, pixel 2 should turn into 160
the subject decrease -10 : pixel one should return to 250, pixel 2 should return into 150

Begin experiment

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm      
from matplotlib.widgets import Slider, Button
import copy
import random

def f(x,b):
    
    x[:,:,1] =x[:,:,1]+ b 
    
    return x
b=random.randint(50,150)

Begin routine

### Take a picture and transform it into data

def f(x,b):
    
    x[:,:,ColorDimension] =x[:,:,ColorDimension]+ b 
    
    return x
b=random.randint(50,150)


## conversion image into data
imgpil = Image.open(ItemFile)
img = np.asarray(imgpil) # Transformation de l'image en tableau numpy
img=np.array(img)


## keys initialisation
theseKeys=""
option_incdec="10"
inputText=""
#couleurajouter=0
#graphique=f(img,b)
#valeurb=np.mean(graphique[:,:,ColorDimension]-img[:,:,ColorDimension])
## plot
fig=plt.imshow(graphique)
plt.axis('off')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)

## save plot to a picture
plt.savefig('image.png',dpi='figure',transparent=True)

## setup default changing range
self = 10

each frame

n= len(theseKeys)
i = 0
while i < n:

    if theseKeys[i] == 'return':
        ## pressing RETURN means time to stop
        continueRoutine = False
        break

    elif theseKeys[i] == 'backspace':
        inputText = inputText[:-1]  ## lose the final character
        i = i + 1

        ## decrease color level
    elif theseKeys[i] == 'left':
        y = self
        img[:,:,ColorDimension] = img[:,:,ColorDimension] - y
        a=img[:]
        fig.set_data(a)
        plt.savefig('image.png',dpi='figure',transparent=True)
        inputText=str (self)+"-"
        couleurajouter=couleurajouter-y
        i = i + 1

        ## increase color level
    elif theseKeys[i] == 'right':
        y= self
        img[:,:,ColorDimension] = img[:,:,ColorDimension] + y
        a=img[:]
        fig.set_data(a)
        plt.savefig('image.png',dpi='figure',transparent=True)
        inputText=str (self)+"+"
        couleurajouter=couleurajouter+y
        i = i + 1

        ## setup changing range 

    elif theseKeys[i] == 'up':
        if self == 1 : 
            self = 10
            option_incdec=str(10)
            i = i + 1
        elif self == 10:
            self = 100
            option_incdec=str(100)
            i = i + 1
        elif self == 100 : 
            i = i + 1

    elif theseKeys[i] == 'down':
        if self ==100:
            self = 10
            option_incdec=str(10)
            i = i + 1
        elif self == 10 :
            self = 1
            option_incdec=str(1)
            i = i + 1

End Routine

#to clear the plot and not having stimulis one over the other
plt.clf()

Does anybody have a hint on how I should proceed?


#2

@alextremz, this is because your numpy array is type int8. To keep track of your additions etc, you could change your array to one that allows numbers to be greater than 255 using

img = img.astype(np.int16)

#3

But also, why are you presenting your colors/images in a matplotlib window?


#4

@dvdbridges Thank you, I didn’t thought about that, but sounds logical, I will try this this afternoon.

@jon it’s the only method I found to make the subject “play” with colors and have an instant update : I turn the picture into data, turn it into a plot, apply the change from the user, turn the plot into a png and display it via the image component of psychopy.
In the experiment, the subject see a picture and then a desaturated version of same picture in one dimension, and has to accomodate the colors to retrive the previous picture’s colors.


#5

I solved my problem using numpy.clip() that takes a matrix A where you then set a minimal value (Min) and a maximal value (Max) and export it to a matrix B where all below Min will take the value Min and all above Max will take the value Max

The Matrix A was set in np.int16 and the Matrix B in np.uint8

Thanks again to dvbridges