【问题标题】:"painting" one array onto another using python / numpy使用 python / numpy 将一个数组“绘制”到另一个数组
【发布时间】:2010-12-29 06:50:55
【问题描述】:

我正在编写一个库来处理 Python 中的凝视跟踪,而且我对整个 numpy / scipy 世界还是很陌生。本质上,我希望及时获取一组 (x,y) 值,并在这些坐标处将一些形状“绘制”到画布上。例如,形状可能是一个模糊的圆圈。

我想到的操作和在Photoshop中使用画笔工具差不多。

我有一个交互式算法,可以将我的“画笔”修剪到我的图像范围内,并将每个点添加到一个累加器图像中,但它很慢(!),而且似乎有一种从根本上更简单的方法这样做。

关于从哪里开始寻找的任何指针?

【问题讨论】:

  • 听起来你想要某种形式的快速 blit。但是我缺乏关于 python 的知识来提出一个好的答案。

标签: python image-processing numpy scipy


【解决方案1】:

OpenCV 使用 numpy 数组并具有基本的绘图功能:圆、椭圆、折线...

要画一条线,你可以调用

cv.line(array,previous_point,new_point,colour,thickness=x)

每次获得鼠标事件。

【讨论】:

    【解决方案2】:

    在您的问题中,您描述了一个高斯过滤器,scipy 通过package 支持该过滤器。 例如:

    from scipy import * # rand
    from pylab import * # figure, imshow
    from scipy.ndimage import gaussian_filter
    
    # random "image"
    I = rand(100, 100)
    figure(1)
    imshow(I)
    
    # gaussian filter
    J = gaussian_filter(I, sigma=10)
    figure(2)
    imshow(J)
    

    当然,您可以使用切片将其应用于整个图像,或仅应用于补丁:

    J = array(I) # copy image
    J[30:70, 30:70] = gaussian_filter(I[30:70, 30:70], sigma=1) # apply filter to subregion
    figure(2)
    imshow(2)
    

    对于基本的图像处理,Python 图像库 (PIL) 可能是您想要的。

    注意: 对于用“画笔”“绘画”,我认为你可以用你的画笔创建一个布尔蒙版数组。例如:

    # 7x7 boolean mask with the "brush" (example: a _crude_ circle)
    mask = array([[0, 0, 1, 1, 1, 0, 0],
                  [0, 1, 1, 1, 1, 1, 0],
                  [1, 1, 1, 1, 1, 1, 1],
                  [1, 1, 1, 1, 1, 1, 1],
                  [1, 1, 1, 1, 1, 1, 1],
                  [0, 1, 1, 1, 1, 1, 0],
                  [0, 0, 1, 1, 1, 0, 0]], dtype=bool)
    
    # random image
    I = rand(100, 100)
    # apply filter only on mask
    # compute the gauss. filter only on the 7x7 subregion, not the whole image
    I[40:47, 40:47][mask] = gaussian_filter(I[40:47, 40:47][mask], sigma=1)
    

    【讨论】:

    • 嗯,这可能会让我走上正轨——我认为一些切片魔法会帮助我做我需要的事情。
    • 我添加了一个带有布尔掩码的示例,也许这就是您所需要的。
    【解决方案3】:

    在傅里叶空间中做一些数学运算可能会有所帮助:平移(通过狄拉克进行卷积)等于简单地乘以傅里叶中的相位...这会使您的画笔移动到确切的位置(类似于catchmeifyoutry & dwf,但这允许翻译比像素更精细,比如 2.5,唉,有一些振铃)。那么,这些笔画的总和就是这些操作的总和。

    在代码中:

    import numpy
    import pylab
    from scipy import mgrid
    
    def FTfilter(image, FTfilter):
        from scipy.fftpack import fftn, fftshift, ifftn, ifftshift
        from scipy import real
        FTimage = fftshift(fftn(image)) * FTfilter
        return real(ifftn(ifftshift(FTimage)))
    
    def translate(image, vec):
        """
        Translate image by vec (in pixels)
    
        """
        u = ((vec[0]+image.shape[0]/2) % image.shape[0]) - image.shape[0]/2
        v = ((vec[1]+image.shape[1]/2) % image.shape[1]) - image.shape[1]/2
        f_x, f_y = mgrid[-1:1:1j*image.shape[0], -1:1:1j*image.shape[1]]
        trans = numpy.exp(-1j*numpy.pi*(u*f_x + v*f_y))
        return FTfilter(image, trans)
    
    def occlude(image, mask):
        # combine in oclusive mode
        return  numpy.max(numpy.dstack((image, mask)), axis=2)
    
    if __name__ == '__main__':
        Image = numpy.random.rand(100, 100)
        X, Y = mgrid[-1:1:1j*Image.shape[0], -1:1:1j*Image.shape[1]]
        brush = X**2 + Y**2 < .05 # relative size of the brush
        # shows the brush
        pylab.imshow(brush)
    
        # move it to some other position  / use a threshold to avoid ringing
        brushed = translate(brush, [20, -10.51]) > .6
        pylab.imshow(brushed)
    
        pylab.imshow(occlude(Image, brushed))
    
        more_strokes = [[40, -15.1], [-40, -15.1], [-25, 15.1], [20, 10], [0, -10], [25, -10.51]]
        for stroke in more_strokes:
            brushed = brushed + translate(brush, stroke) > .6
    
        pylab.imshow(occlude(Image, brushed))
    

    【讨论】:

      【解决方案4】:

      你真的应该看看 Andrew Straw 的 motmotlibcamiface。他将它用于飞行行为实验,但它是一个灵活的库,用于进行我认为您正在做的那种图像采集和处理。他在 SciPy2009 上的演讲有一个video

      至于你提到的画笔场景,我会使用 .copy() 方法制作图像的副本,将画笔图像保存在数组中,然后简单地添加它

      arr[first_br_row:last_br_row, first_br_col:last_br_col] += brush[first_row:last_row, first_col:last_col]
      

      你设置first_br_rowlast_br_rowfirst_br_collast_br_col来处理你要添加画笔的子图像和first_rowlast_rowfirst_collast_col来剪辑画笔(通常将它们设置为 0 和 # rows/cols - 1,但是当您足够靠近图像边界时进行调整,以便只绘制画笔的一部分)。

      希望对您有所帮助。

      【讨论】:

      • 谢谢!事实证明,是的,切片和索引技巧会有所帮助。然而!正确的答案可能是绘制单个点并应用画笔和模糊作为内核。感谢图书馆的碰撞;但是,这实际上是一项后处理任务:数据已经收集完毕。
      【解决方案5】:

      你看过Tkinter吗?

      Python Image Library 也可能有一些帮助。

      【讨论】:

      • Tkinter 让我有点警觉——我真的很怀疑使用 GUI takelit 来做数组数学。而且我对 PIL 很熟悉,但并没有真正看到它如何解决 numpy 无法解决的任何问题。我仍然需要做一些奇怪的游戏来将数组添加在一起......?
      猜你喜欢
      • 2012-04-04
      • 2017-04-03
      • 2021-12-10
      • 2022-07-05
      • 1970-01-01
      • 2021-07-17
      • 1970-01-01
      • 2016-03-09
      相关资源
      最近更新 更多