Numpy 与精神病不一致的对比处理

Numpy 与精神病不一致的对比处理,numpy,pillow,psychopy,Numpy,Pillow,Psychopy,我找不到版本1.75.01和1.82在对比度处理方面的差异的来源。这里有两张图片显示了它过去的样子(1.75), 它现在看起来是什么样子: 不幸的是,回滚并不是一件小事,因为我遇到了依赖项的问题(尤其是PIL v PILLOW)。这些图像是从一个numpy数组创建的,我怀疑当从数组到图像的转换发生时,数字是如何处理的(?type,rounding)与此有关,但我找不到错误。任何帮助都将不胜感激 已编辑-新的最小示例 这就产生了: 在转换为图像之前生成阵列时,沿水平方向的三块棋盘格会改变阵列中

我找不到版本1.75.01和1.82在对比度处理方面的差异的来源。这里有两张图片显示了它过去的样子(1.75), 它现在看起来是什么样子:

不幸的是,回滚并不是一件小事,因为我遇到了依赖项的问题(尤其是PIL v PILLOW)。这些图像是从一个numpy数组创建的,我怀疑当从数组到图像的转换发生时,数字是如何处理的(?type,rounding)与此有关,但我找不到错误。任何帮助都将不胜感激

已编辑-新的最小示例

这就产生了:

在转换为图像之前生成阵列时,沿水平方向的三块棋盘格会改变阵列中的对比度。左上角显示,之后更改图像对比度效果良好。我不能使用它的原因是a)我收集了上一个版本的大量数据,b)我想通过编程将一个数组与另一个数组相乘(例如,使用对数刻度或其他函数)来对中间那些大的长条的对比度进行评分,并且在numpy中做数学比较容易


我仍然怀疑问题出在从np.array->pil.image的转换中。这些数组的
dtype
为float64,但即使强制为float32,也不会有任何更改。如果在转换前以半对比度检查数组,则该数组将填充0.5和-0.5个数字,但是所有的负数都变成了黑色,在转换时,psychopy.tools.imagetools.array2image将黑色设置为零,我想。

代码太长,我无法通读并解决实际问题

问题可能是零应该在哪里。我认为有一段时间,numpy数组被视为VAL为0:1,而PsychoPy的其他人期望值为-1:1,因此可能需要使用
array=array*2-1
重新缩放值,以恢复到原来的状态(不良行为)。或者也检查不透明度,这可能会有类似的问题。如果你写一个最小的例子,我会正确地阅读/测试它


谢谢

好的,是的,问题在于数组值的比例问题。基本上,你已经发现了一个心理变态无法正确处理的角落案例(即一个bug)

说明: PsychoPy有一套处理图像/纹理的复杂变换规则;它试图推断您将对该图像执行什么操作,以及该图像是否应以支持颜色操作(带符号浮点)的方式存储(可以是无符号字节)。在你的例子中,精神病患者把这个理解错了;数组中填充了浮点数这一事实让PsychoPy认为它可以进行颜色变换,但它是NX3这一事实表明它不应该这样做(我们不想为已经为每个像素指定了颜色作为rgb VAL的东西指定“颜色”)

解决方法(其中任何一种):

  • 只需将您的阵列提供为NxN,而不是NX3。无论如何,这是正确的做法;这意味着计算/存储的工作量减少,通过提供“强度”值,可以动态地重新存储这些值。这大致上是您在仅提供NX3阵列的一个切片时发现的,但问题是您首先只能/应该创建一个切片

  • 使用GratingStim,它可以将所有内容转换为有符号浮点值,而不是试图找出最好的内容(但可能需要找出空间频率)

  • 您可以通过重新缩放数组(*0.5+0.5)来添加一行来修复它,但您必须设置一些内容,使其仅在该版本中发生(我们将在下一版本之前修复)

  • 基本上,我建议您这样做(1),因为这已经适用于过去、现在和将来的版本,而且更高效。但是谢谢你让我们知道-我会尽力确保我们在将来抓住这个

    祝福
    Jon

    为了补充这一点,使用psychopy.useVersion,这种行为出现在1.81版本,但1.80年代的行为更为怪异。由于一些导入问题,我无法运行之前的版本,但您可以试一试。在脚本顶部,运行
    import psychopy
    ,然后在下一行
    psychopy.useVersion(1.76.00')
    。这就是它可以倒退的程度。顺便说一句,这不是一个很小的例子,因为它导入了很多东西并定义了几个从未使用过的变量。我找到了一个解决方法,但它并不能真正回答为什么的问题。您只需获取NX3阵列的第一个“层”。显然,图像转换将正确处理浮动,例如
    partCon_i_FIXED=visual.ImageStim(w,image=partCon_np[:,:,1],size=partCon_np.shape[0:2][:::-1],pos=(0100),colorSpace='rgb')
    。但这看起来仍然与使用完整数组并在之后调整对比度时不完全相同。@Jonas当然,关于最小示例,你们都是对的。我想在一天的沮丧结束后,就我对自己的工作量而言,这是“最小的”。我会根据你的建议做更多的工作,如果问题仍然存在,我会给出一个更好的例子。
    #! /bin/bash
    
    import numpy as np
    from psychopy import visual,core
    
    def makeRow (n,c):
        cp = np.tile(c,[n,n,3])
        cm = np.tile(-c,[n,n,3])
        cpm = np.hstack((cp,cm))
        return(cpm)
    
    def makeCB (r1,r2,nr=99):
        #nr is repeat number
        (x,y,z) = r1.shape
        if nr == 99:
            nr = x/2
        else:
            hnr = nr/2
        rr = np.vstack((r1,r2))
        cb=np.tile(rr,[hnr,hnr/2,1])
        return(cb)
    
    def makeTarg(sqsz,targsz,con):
        wr = makeRow(sqsz,1)
        br = makeRow(sqsz,-1)
        cb = makeCB(wr,br,targsz)
        t = cb*con
        return(t)
    
    def main():
        w = visual.Window(size = (400,400),units = "pix", winType = 'pyglet',colorSpace = 'rgb')
        fullCon_np = makeTarg(8,8,1.0)
        fullCon_i  = visual.ImageStim(w, image = fullCon_np,size = fullCon_np.shape[0:2][::-1],pos = (-100,0),colorSpace = 'rgb')
        fullCon_ih = visual.ImageStim(w, image = fullCon_np,size = fullCon_np.shape[0:2][::-1],pos = (-100,0),colorSpace = 'rgb')
        fullCon_iz = visual.ImageStim(w, image = fullCon_np,size = fullCon_np.shape[0:2][::-1],pos = (-100,0),colorSpace = 'rgb')
        fullCon_ih.contrast = 0.5
        fullCon_ih.setPos((-100,100))
        fullCon_iz.setPos((-100,-100))
        fullCon_iz.contrast = 0.1
        partCon_np = makeTarg(8,8,0.1)
        partCon_i  = visual.ImageStim(w, image = partCon_np,pos = (0,0), size = partCon_np.shape[0:2][::-1],colorSpace = 'rgb')
        zeroCon_np = makeTarg(8,8,0.0)
        zeroCon_i  = visual.ImageStim(w, image = zeroCon_np,pos=(100,0), size = zeroCon_np.shape[0:2][::-1],colorSpace = 'rgb')
        fullCon_i.draw()
        partCon_i.draw()
        fullCon_ih.draw()
        fullCon_iz.draw()
        zeroCon_i.draw()
        w.flip()
        core.wait(15)
        core.quit()
    
    if __name__ == "__main__":
        main()