transpuesta - "Pintar" una matriz en otra usando python/numpy
multiplicar matrices python numpy (5)
Estoy escribiendo una biblioteca para procesar el seguimiento de la mirada en Python, y soy bastante nuevo en el mundo numpy / scipy. Esencialmente, estoy buscando tomar una matriz de valores (x, y) en el tiempo y "pintar" alguna forma en un lienzo en esas coordenadas. Por ejemplo, la forma puede ser un círculo borroso.
La operación que tengo en mente es más o menos idéntica a usar la herramienta Pincel en Photoshop.
Tengo un algoritmo de intención que recorta mi "pincel" para que esté dentro de los límites de mi imagen y agrega cada punto a una imagen de acumulador, pero es lento (!), Y parece que probablemente haya una forma fundamentalmente más fácil de hacerlo. .
¿Alguna sugerencia sobre dónde empezar a buscar?
¿Has mirado a Tkinter ?
La biblioteca de imágenes de Python también puede ser de ayuda.
Deberías echarle un vistazo al motmot y a la libcamiface de Andrew Straw. Lo usa para experimentos de comportamiento de moscas pero creo que es una biblioteca flexible para hacer el tipo de adquisición y procesamiento de imágenes que estás haciendo. Hay un video de su presentación en SciPy2009.
En cuanto al escenario del pincel que mencionas, haré una copia de la imagen con el método .copy (), mantendré la imagen del pincel en una matriz y simplemente lo añadiré con
arr[first_br_row:last_br_row, first_br_col:last_br_col] += brush[first_row:last_row, first_col:last_col]
donde establece first_br_row
, last_br_row
first_br_col
, last_br_col
para direccionar la subimagen donde desea agregar el pincel y first_row
, last_row
, first_col
, last_col
para recortar el pincel (normalmente los establece en 0 y # rows / cols - 1, pero ajusta cuando está lo suficientemente cerca del límite de la imagen para solo querer pintar parte del pincel).
Espero que todo eso ayude
Hacer un poco de matemática en el espacio de Fourier puede ayudar: una traducción (convolución por dirac) es igual a una simple multiplicación por una fase en Fourier ... esto hace que su pincel se mueva al lugar exacto (una solución similar a catchmeifyoutry & dwf , pero esto permite una traducción más fina que el píxel, como 2.5, por desgracia con un poco de timbre). Entonces, una suma de tales golpes es la suma de estas operaciones.
En codigo:
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))
En su pregunta, describe un filtro gaussiano, para el cual scipy tiene soporte a través de un paquete . Por ejemplo:
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)
Por supuesto, puedes aplicar esto en toda la imagen, o solo en un parche, usando slicing:
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)
Para la manipulación básica de imágenes, la biblioteca de imágenes de Python ( PIL ) es probablemente lo que desea.
NOTA: para "pintar" con un "pincel", creo que podrías simplemente crear una matriz de máscara booleana con tu pincel. Por ejemplo:
# 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)
OpenCV utiliza matrices numpy y tiene funciones básicas de dibujo: círculos, elipses, polilíneas ...
Para dibujar una línea puedes llamar
cv.line(array,previous_point,new_point,colour,thickness=x)
cada vez que obtienes un evento de mouse.