我正在编写一个库来处理 Python 中的凝视跟踪,而且我对整个 numpy / scipy 世界还是很陌生。本质上,我希望及时获取一组 (x,y) 值,并在这些坐标处将一些形状“绘制”到画布上。例如,形状可能是一个模糊的圆圈。
我想到的操作或多或少与在 Photoshop 中使用画笔工具相同。
我有一个交互式算法,可以将我的“画笔”修剪到我的图像范围内,并将每个点添加到一个累加器图像中,但它很慢(!),而且似乎有一种从根本上更简单的方法来做到这一点.
关于从哪里开始寻找的任何指示?
我正在编写一个库来处理 Python 中的凝视跟踪,而且我对整个 numpy / scipy 世界还是很陌生。本质上,我希望及时获取一组 (x,y) 值,并在这些坐标处将一些形状“绘制”到画布上。例如,形状可能是一个模糊的圆圈。
我想到的操作或多或少与在 Photoshop 中使用画笔工具相同。
我有一个交互式算法,可以将我的“画笔”修剪到我的图像范围内,并将每个点添加到一个累加器图像中,但它很慢(!),而且似乎有一种从根本上更简单的方法来做到这一点.
关于从哪里开始寻找的任何指示?
在您的问题中,您描述了一个高斯滤波器,scipy 通过一个包支持它。例如:
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)
你真的应该看看 Andrew Straw 的motmot和libcamiface。他将它用于飞行行为实验,但它是一个灵活的库,仅用于我认为您正在做的那种图像采集和处理。有一段他在 SciPy2009 上的演讲视频。
至于你提到的画笔场景,我会使用 .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_row
, last_br_row
first_br_col
,last_br_col
来处理要添加画笔的子图像,以及, ,first_row
来last_row
剪辑画笔(通常将它们设置为 0 和 # rows/cols - 1,但是当你足够接近图像边界时进行调整只想绘制画笔的一部分)。first_col
last_col
希望所有这些都有帮助。
在傅立叶空间中做一些数学运算可能会有所帮助:平移(狄拉克卷积)等于傅立叶相位的简单乘法......这使您的画笔移动到确切的位置(与 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))
OpenCV 使用 numpy 数组并具有基本的绘图功能:圆、椭圆、折线...
要画一条线,您可以调用
cv.line(array,previous_point,new_point,colour,thickness=x)
每次你得到一个鼠标事件。
你看过Tkinter吗?
Python 图像库也可能会有所帮助。