Я пишу библиотеку для обработки отслеживания пристального взгляда в 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)
Вы изучали Tkinter ?
Библиотека изображений Python тоже может помочь.
Вам действительно стоит заглянуть в 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
, first_col
, last_col
, чтобы обрезать кисть (обычно устанавливайте их на 0 и # rows/cols - 1, но настраивайте, когда вы находитесь достаточно близко к границе изображения, чтобы закрасить только часть кисти).
Надеюсь, это поможет.
.Немного математики в пространстве Фурье может помочь: перевод (свертка дираком) равна простому умножению на фазу в Фурье... это заставляет вашу кисть перемещаться в точное место (аналогичное решение, чем 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))