Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adapted cornsweet illusion and added mask
- Loading branch information
1 parent
1387f2c
commit 821263d
Showing
1 changed file
with
38 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,68 @@ | ||
import numpy as np | ||
from stimuli.Stimulus import Stimulus | ||
|
||
|
||
def cornsweet(size=(10,10), ppd=10, contrast=0.5, ramp_width=2, exponent=2.75, | ||
mean_lum=.5): | ||
#TODO: the parameters aren't analogous to the other stimuli | ||
def cornsweet(size=(10.,10.), ppd=10., vmax=1., vmin=0., vtarget=0.5, ramp_width=2., exponent=2.75): | ||
""" | ||
Create a matrix containing a rectangular Cornsweet edge stimulus. | ||
The 2D luminance profile of the stimulus is defined as | ||
L = L_mean +/- (1 - X / w) ** a * L_mean * C/2 for the ramp and | ||
L = L_mean for the area beyond the ramp. | ||
Left side: | ||
v = vtarget + (1 - X / w) ** a * (vmax-vtarget) for the ramp and v = vtarget beyond. | ||
Right side: | ||
v = vtarget - (1 - X / w) ** a * (vmin-vtarget) for the ramp and v = vtarget beyond. | ||
X is the distance to the edge, w is the width of the ramp, a is a variable | ||
determining the steepness of the ramp, and C is the contrast at the edge, | ||
defined as C = (L_max-L_min) / L_mean. | ||
determining the steepness of the ramp, vtarget is the luminance of the targets and | ||
vmax/vmin are the max/min luminances. | ||
Parameters | ||
---------- | ||
size : tuple of 2 numbers | ||
the size of the matrix in degrees of visual angle | ||
ppd : number | ||
the number of pixels in one degree of visual angle | ||
contrast : float, in [0,1] | ||
the contrast at the Cornsweet edge, defined as Michelson contrast | ||
(max_luminance - min_luminance) / (max_luminance + min_luminance) | ||
ramp_width : number (optional) | ||
the width of the luminance ramp in degrees of visual angle. | ||
Default is 3. | ||
exponent : number (optional) | ||
Determines the steepness of the ramp. Default is 2.75. An | ||
exponent value of 0 leads to a stimulus with uniform flanks. | ||
mean_lum : number | ||
The mean luminance of the stimulus, i.e. the value outside of | ||
the ramp area. | ||
size in degrees of visual angle | ||
ppd : float | ||
number of pixels in one degree of visual angle | ||
vmax : float | ||
maximum luminance value | ||
vmin : float | ||
minimum luminance value | ||
vtarget : float | ||
luminance value of targets (=plateaus) | ||
ramp_width : float | ||
width of luminance ramp in degrees of visual angle | ||
exponent : float | ||
determines steepness of ramp (default is 2.75. 1 would be linear) | ||
Returns | ||
------- | ||
Dictionary with img: ndarray (2D) and empty mask | ||
Dictionary with img: ndarray (2D) and mask | ||
References | ||
---------- | ||
The formula and default values are taken from Boyaci, H., Fang, F., Murray, | ||
The formula and default values are adapted from Boyaci, H., Fang, F., Murray, | ||
S.O., Kersten, D. (2007). Responses to Lightness Variations in Early Human | ||
Visual Cortex. Current Biology 17, 989-993. | ||
""" | ||
|
||
size = [int(size[0]*ppd), int(size[1]*ppd)] | ||
img = np.ones(size) * mean_lum | ||
ramp_width = int(ramp_width*ppd) | ||
img = np.ones(size) * vtarget | ||
mask = np.zeros(size) | ||
|
||
# Create ramp profiles individually for left and right side | ||
dist = np.arange(size[1] / 2.) | ||
dist = dist / (ramp_width*ppd) | ||
dist = dist / ramp_width | ||
dist[dist > 1.] = 1. | ||
profile = (1. - dist) ** exponent * mean_lum * contrast | ||
img[:, :int(np.ceil(size[1]/2.))] += profile[::-1] | ||
img[:, size[1] // 2:] -= profile | ||
mask = None | ||
profile1 = (1. - dist) ** exponent * (vmax-vtarget) | ||
profile2 = (1. - dist) ** exponent * (vmin-vtarget) | ||
img[:, :int(size[1]/2.)] += profile1[::-1] | ||
img[:, size[1] // 2:] += profile2 | ||
|
||
# Generate the target mask | ||
mask[:, 0:int(size[1]/2. - ramp_width - 1)] = 1 | ||
mask[:, int(size[1]/2. + ramp_width+1)::] = 2 | ||
return {"img": img, "mask": mask} | ||
|
||
|
||
if __name__ == '__main__': | ||
import matplotlib.pyplot as plt | ||
stim = cornsweet() | ||
plt.imshow(stim, cmap='gray') | ||
plt.imshow(stim['img'], cmap='gray') | ||
plt.show() |