使用python / numpy将一个数组“绘制”到另一个数组上

时间:2009-12-22 21:17:03

标签: python image-processing numpy scipy

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

我想到的操作与在Photoshop中使用画笔工具或多或少完全相同。

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

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

5 个答案:

答案 0 :(得分:7)

在你的问题中,你描述了一个高斯滤波器,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)

答案 1 :(得分:2)

你应该真正关注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_row first_br_collast_br_col以解决要添加画笔的子图像first_row,{{1} },last_rowfirst_col剪辑画笔(通常将它们设置为0和#rows / cols - 1,但是当你足够接近图像边界时调整它只想要绘制部分刷子)。

希望这一切都有所帮助。

答案 2 :(得分:2)

在傅立叶空间中做一些数学运算可能会有所帮助:翻译(通过狄拉克语进行卷积)等于傅立叶中相位的简单乘法...这使得您的画笔移动到准确的位置(类似于解决方案) 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))

答案 3 :(得分:1)

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

要绘制一条线,您可以调用

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

每次获得鼠标事件。

答案 4 :(得分:0)

你有没有看过Tkinter

Python Image Library也可能有所帮助。