Drawing—shapes

这篇博客介绍了如何使用PsychoPy库在Python中绘制基本图形,包括从屏幕底部左角到顶部右角的直线、自定义颜色和宽度的线条、不同尺寸和位置的矩形以及平滑边缘的圆形。此外,还展示了如何通过简单的线条排列创建视觉错觉,如Ponzo和Ebbinghaus illusion。文章提供了详细的代码示例,演示了如何生成和控制这些图形的属性。

Objectives

Be able to generate and display stimuli formed from a variety of shapes (lines, rectangles, circles).

Using psychopy, we can also easily draw a variety of shapes.

Lines

Perhaps the most simple “shape” stimulus is a line, which we can create in psychopy using Line. The two critical arguments to create a line are start and end, which are each two-item lists that specify the x and y coordinates of the start and end points of the line, respectively.

For example, to draw a line from the bottom left to the top right of our screen, we could do:

import psychopy.visual
import psychopy.event

win = psychopy.visual.Window(
    size=[400, 400],
    units="pix",
    fullscr=False,
    color=[1, 1, 1]
)

line = psychopy.visual.Line(
    win=win,
    units="pix",
    lineColor=[-1, -1, -1]
)

line.start = [-200, -200]
line.end = [+200, +200]

line.draw()

win.flip()

psychopy.event.waitKeys()

win.close()

We can also change the colour of the line using lineColor and its width using lineWidth:

import psychopy.visual
import psychopy.event

win = psychopy.visual.Window(
    size=[400, 400],
    units="pix",
    fullscr=False,
    color=[1, 1, 1]
)

line = psychopy.visual.Line(
    win=win,
    units="pix",
    lineColor=[-1, -1, -1]
)

line.start = [-200, -200]
line.end = [+200, +200]

line.lineColor = [-1, -1, 1]
line.lineWidth = 5

line.draw()

win.flip()

psychopy.event.waitKeys()

win.close()

 Many visual illusions can be created using simple line arrangements. For example, by drawing a few lines we can create a Ponzo illusion, where the upper horizontal bar looks a bit bigger than the lower horizontal bar:

import psychopy.visual
import psychopy.event

win = psychopy.visual.Window(
    size=[400, 400],
    units="pix",
    fullscr=False,
    color=[1, 1, 1]
)

line = psychopy.visual.Line(
    win=win,
    units="pix",
    lineColor=[-1, -1, -1]
)

bar_horiz_offset = 20
bar_vert_offset = 80

for bar_offset in [-1, +1]:

    line.start = [-bar_horiz_offset, bar_vert_offset * bar_offset]
    line.end = [+bar_horiz_offset, bar_vert_offset * bar_offset]

    line.draw()

pers_far_horiz_offset = 150
pers_near_horiz_offset = 10
pers_vert_offset = 140

for pers_offset in [-1, +1]:

    line.start = [pers_far_horiz_offset * pers_offset, -pers_vert_offset]
    line.end = [pers_near_horiz_offset * pers_offset, +pers_vert_offset]

    line.draw()

win.flip()

win.getMovieFrame()
psychopy.event.waitKeys()

win.close()

Rectangles

We can also create rectangles, using psychopy’s Rect. The two critical arguments are the height and width of the rectangle. We can also set a fillColor.

import psychopy.visual
import psychopy.event

win = psychopy.visual.Window(
    size=[400, 400],
    units="pix",
    fullscr=False,
    color=[1, 1, 1]
)

rect = psychopy.visual.Rect(
    win=win,
    units="pix",
    width=200,
    height=100,
    fillColor=[1, -1, -1],
    lineColor=[-1, -1, 1]
)

rect.draw()

win.flip()

psychopy.event.waitKeys()

win.close()

 A class of visual stimuli that makes heavy use of rectangles are the so-called Mondrian patterns. In such a stimulus, a large number of rectangles of varying widths and heights are drawn at random positions—which ends up producing a pleasant variegated stimulus:

import random

import psychopy.visual
import psychopy.event

win = psychopy.visual.Window(
    size=[400, 400],
    units="pix",
    fullscr=False,
    color=[1, 1, 1]
)

rect = psychopy.visual.Rect(win=win, units="pix")

n_rect = 500

for i_rect in range(n_rect):

    rect.width = random.uniform(10, 100)
    rect.height = random.uniform(10, 100)

    rect_color = random.uniform(-1, 1)
    rect.fillColor = rect_color
    rect.lineColor = rect_color

    rect.pos = [
        random.uniform(-200, 200),
        random.uniform(-200, 200)
    ]

    rect.draw()

win.flip()

psychopy.event.waitKeys()

win.close()

Circles

Circles can also be useful, and are created by psychopy’s Circle. The critical parameter for a circle is its radius.

import psychopy.visual
import psychopy.event

win = psychopy.visual.Window(
    size=[400, 400],
    units="pix",
    fullscr=False,
    color=[1, 1, 1]
)

circle = psychopy.visual.Circle(
    win=win,
    units="pix",
    radius=150,
    fillColor=[0, 0, 0],
    lineColor=[-1, -1, -1]
)

circle.draw()

win.flip()

psychopy.event.waitKeys()

win.close()

 Notice though that the edges of the circle are not all that smooth. That is because the circle needs to be approximated with a set of points, and psychopy uses 32 by default. We can increase that a bit to give smoother circles (at the cost of more computation and storage requirements):

import psychopy.visual
import psychopy.event

win = psychopy.visual.Window(
    size=[400, 400],
    units="pix",
    fullscr=False,
    color=[1, 1, 1]
)

circle = psychopy.visual.Circle(
    win=win,
    units="pix",
    radius=150,
    fillColor=[0, 0, 0],
    lineColor=[-1, -1, -1],
    edges=128
)

circle.draw()

win.flip()

psychopy.event.waitKeys()

win.close()

That looks nicer. Keeping up with the tradition of this lesson, we can create a compelling size illusion (called the Ebbinghaus illusion) using a few circles:

 

import psychopy.visual
import psychopy.event
import psychopy.misc

win = psychopy.visual.Window(
    size=[400, 400],
    units="pix",
    fullscr=False,
    color=[1, 1, 1]
)

circle = psychopy.visual.Circle(
    win=win,
    units="pix",
    fillColor=[-1] * 3,
    lineColor=[-1] * 3,
    edges=128
)

# 'test' circles
circle.radius = 12

test_offset = 100

for offset in [-1, +1]:

    circle.pos = [test_offset * offset, 0]

    circle.draw()

# 'surround' circles
surr_thetas = [0, 72, 144,  216,  288]
surr_r = 50

for i_surr in range(len(surr_thetas)):

    [surr_pos_x, surr_pos_y] = psychopy.misc.pol2cart(
        surr_thetas[i_surr],
        surr_r
    )
    surr_pos_x = surr_pos_x + test_offset

    circle.pos = [surr_pos_x, surr_pos_y]
    circle.radius = 25
    circle.draw()

win.flip()

win.getMovieFrame()
psychopy.event.waitKeys()

win.close()

Tip

Note the use of a new function in the above code, psychopy.misc.pol2cart. Often when creating visual stimuli it can be more intuitive to work in polar coordinates (polar angle, radius) than cartesian coordinates (x, y). We can use this function to easily convert from polar to cartesian. 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值