https://claudiovz.github.io/scipy-lecture-notes-ES/intro/scipy.html#transformada-rapida-de-fourier-scipy-fftpack
Python
Scipy: computación científica de alto nivel
1.5. Scipy: computación científica de alto nivel
Autores: | Adrien Chauve, Andre Espaze, Emmanuelle Gouillart, Gaël Varoquaux, Ralf Gommers |
---|
Scipy
El paquete scipy
contiene varias cajas de herramientas dedicadas a problemas comunes
problemas en computación científica. Sus diferentes submódulos
corresponden a diferentes aplicaciones, tales como interpolación,
integración, optimización, procesamiento de imágenes, estadística,
funciones especiales, etc.scipy se puede comparar con otras bibliotecas estándar de computación científica, como GSL (GNU Scientific Library para C y C++), o cajas de herramientas de Matlab. scipy es el paquete núcleo para rutinas científicas en Python; operando de manera eficiente los arreglos numpy, por tanto numpy y scipy trabajan mano a mano.
Antes de implementar una rutina, hay que comprobar si no está implementado en Scipy. Como programadores no profesionales, los científicos a menudo tienden a reinventar la rueda, lo que conduce a errores en el código, código no optimizado, código difícil de compartir e imposible de mantener. Por el contrario, las rutinas que contiene Scipy están optimizadas y probadas, por lo tanto se debe utilizar siempre que sea posible.
Contenido
- Entrada/salida de archivos: scipy.io
- Funciones especiales: scipy.special
- Operaciones de álgebra lineal: scipy.linalg
- Transformada rápida de Fourier: scipy.fftpack
- Optimización y ajuste: scipy.optimize
- Estadística y números aleatorios: scipy.stats
- Interpolación: scipy.interpolate
- Integración numérica: scipy.integrate
- Procesamiento de señales: scipy.signal
- Procesamiento de imágenes: scipy.ndimage
- Sumario de ejercicios para computación científica
Advertencia
Este tutorial está lejos de ser una introducción a
métodos numéricos. Enumerar los diferentes submódulos y funciones en
scipy seria muy aburrido, en cambio nos concentramos en algunos ejemplos
para dar una idea general de cómo utilizar scipy para computación científica.
scipy.cluster | Vector quantization / Kmeans |
scipy.constants | Constantes físicas y matemáticas |
scipy.fftpack | Transformadas de Fourier |
scipy.integrate | Rutinas para integración |
scipy.interpolate | Interpolación |
scipy.io | Entrada y salida |
scipy.linalg | Rutinas para algebra lineal |
scipy.ndimage | n-dimensional image package |
scipy.odr | Orthogonal distance regression |
scipy.optimize | Optimización |
scipy.signal | Procesamiento de señales |
scipy.sparse | Matrices dispersas |
scipy.spatial | estructuras de datos espaciales y algoritmos |
scipy.special | Funciones matemáticas especiales |
scipy.stats | Estadística |
>>> import numpy as np
>>> from scipy import stats # lo mismo para otros submódulos
1.5.1. Entrada/salida de archivos: scipy.io
- Cargar y guardar archivos de matlab
>>> from scipy import io as spio >>> a = np.ones((3, 3)) >>> spio.savemat('file.mat', {'a': a}) # savemat espera un diccionario >>> data = spio.loadmat('file.mat', struct_as_record=True) >>> data['a'] array([[ 1., 1., 1.], [ 1., 1., 1.], [ 1., 1., 1.]])
- Lectura de imágenes
>>> from scipy import misc >>> misc.imread('fname.png') >>> # Matplotlib tiene una función similar >>> import matplotlib.pyplot as plt >>> plt.imread('fname.png')
- Cargar archivos de texto: numpy.loadtxt()/numpy.savetxt()
- Cargar archivos de texto/csv de forma hábil: numpy.genfromtxt()/numpy.recfromcsv()
- Rápido y eficiente, formato propio de numpy en archivo binario: numpy.save()/numpy.load()
1.5.2. Funciones especiales: scipy.special
Las funciones especiales son funciones trascendentales. La cadena de documentación del módulo scipy.special está bien escrita, así que no vamos a enumerar todas las funciones aquí. Los frecuentemente utilizadas son:- Función de Bessel, tales como scipy.special.jn() (función de Bessel de enésimo orden)
- Función elíptica (scipy.special.ellipj() para la función elíptica jacobiana, ...)
- Función Gamma: scipy.special.gamma(), también tenga en cuenta scipy.special.gammaln() dará el registro de Gamma con una mayor precisión numérica.
- Erf, la función error o el área bajo la curva de Gauss: scipy.special.erf()
1.5.3. Operaciones de álgebra lineal: scipy.linalg
El módulo scipy.linalg ofrece operaciones estándar para álgebra lineal, basándose en una aplicación eficiente subyacente (BLAS, LAPACK).- El función scipy.linalg.det() calcula el determinante de una matriz cuadrada
>>> from scipy import linalg >>> arr = np.array([[1, 2], ... [3, 4]]) >>> linalg.det(arr) -2.0 >>> arr = np.array([[3, 2], ... [6, 4]]) >>> linalg.det(arr) 0.0 >>> linalg.det(np.ones((3, 4))) Traceback (most recent call last): ... ValueError: expected square matrix
- La función scipy.linalg.inv() calcula la inversa de una matriz cuadrada
>>> arr = np.array([[1, 2], ... [3, 4]]) >>> iarr = linalg.inv(arr) >>> iarr array([[-2. , 1. ], [ 1.5, -0.5]]) >>> np.allclose(np.dot(arr, iarr), np.eye(2)) True
>>> arr = np.array([[3, 2], ... [6, 4]]) >>> linalg.inv(arr) Traceback (most recent call last): ... LinAlgError: singular matrix
- Operaciones más avanzadas están disponibles, por ejemplo descomposición en valores singulares (SVD)
>>> arr = np.arange(9).reshape((3, 3)) + np.diag([1, 0, 1]) >>> uarr, spec, vharr = linalg.svd(arr)
>>> spec array([ 14.88982544, 0.45294236, 0.29654967])
>>> sarr = np.diag(spec) >>> svd_mat = uarr.dot(sarr).dot(vharr) >>> np.allclose(svd_mat, arr) True
1.5.4. Transformada rápida de Fourier: scipy.fftpack
El módulo scipy.fftpack permite calcular la transformada rápida de Fourier. A modo de ejemplo, una señal de entrada (con ruido) puede verse>>> time_step = 0.02
>>> period = 5.
>>> time_vec = np.arange(0, 20, time_step)
>>> sig = np.sin(2 * np.pi / period * time_vec) + \
... 0.5 * np.random.randn(time_vec.size)
>>> from scipy import fftpack
>>> sample_freq = fftpack.fftfreq(sig.size, d=time_step)
>>> sig_fft = fftpack.fft(sig)
>>> pidxs = np.where(sample_freq > 0)
>>> freqs = sample_freq[pidxs]
>>> power = np.abs(sig_fft)[pidxs]
La frecuencia de la señal se puede encontrar
>>> freq = freqs[power.argmax()]
>>> np.allclose(freq, 1./period) # check that correct freq is found
True
>>> sig_fft[np.abs(sample_freq) > freq] = 0
>>> main_sig = fftpack.ifft(sig_fft)
>>> import pylab as plt
>>> plt.figure()
>>> plt.plot(time_vec, sig)
>>> plt.plot(time_vec, main_sig, linewidth=3)
>>> plt.xlabel('Time [s]')
>>> plt.ylabel('Amplitude')
numpy.fft
Numpy también tiene una implementación de FFT (numpy.fft). Sin embargo, en general es preferible usar scipy.fftpack, ya que utiliza implementaciones subyacentes más eficientes.
Ejemplo práctico: Encontrar periodicidad cruda
[source code, hires.png, pdf][source code, hires.png, pdf]
Ejercicio: Imagen de alunizaje con ruido
- Examine la imagen moonlanding.png proporcionada, que está en gran medida contaminada con ruido periódico. En este ejercicio, nuestro objetivo es limpiar el ruido utilizando la transformada rápida de Fourier.
- Cargar la imagen usando pylab.imread().
- Encontrar y utilizar la función FFT 2-D en scipy.fftpack, y graficar el espectro de la imagen (de la transformada de Fourier). Tiene algún problema en visualizar el espectro? Si es así, porqué?
- El espectro consta de componentes de alta y baja frecuencia. El ruido está contenida en la parte de alta frecuencia del espectro, por lo que se debe establecer algunos de sus componentes a cero (use segmentado de arreglos o slicing).
- Aplicar la transformada inversa de Fourier para ver la imagen resultante.
1.5.5. Optimización y ajuste: scipy.optimize
Optimización es el problema de encontrar una solución numérica a un minimización o igualdad.El módulo scipy.optimize proporciona algoritmos útiles para la minimización de funciones (escalares o multidimensionales), ajuste de curvas y búsqueda de raices.
>>> from scipy import optimize
Vamos a definir la siguiente función:
>>> def f(x):
... return x**2 + 10*np.sin(x)
>>> x = np.arange(-10, 10, 0.1)
>>> plt.plot(x, f(x))
>>> plt.show()
Esta función tiene un mínimo global en torno a -1.3 y un mínimo local en torno a 3.8.
La forma general y eficiente para encontrar el mínimo de esta función es llevar a cabo un descenso de gradiente partiendo de un punto inicial dado. El algoritmo BFGS es una buena manera de hacer esto
>>> optimize.fmin_bfgs(f, 0)
Optimization terminated successfully.
Current function value: -7.945823
Iterations: 5
Function evaluations: 24
Gradient evaluations: 8
array([-1.30644003])
>>> optimize.fmin_bfgs(f, 3, disp=0)
array([ 3.83746663])
>>> grid = (-10, 10, 0.1)
>>> xmin_global = optimize.brute(f, (grid,))
>>> xmin_global
array([-1.30641113])
Para encontrar el mínimo local, vamos a restringir la variable en el intervalo (0, 10) usando scipy.optimize.fminbound():
>>> xmin_local = optimize.fminbound(f, 0, 10)
>>> xmin_local
3.8374671...
Nota
Encontrar los mínimos de una función se discute con más detalles en el capítulo avanzado: Mathematical optimization: finding minima of functions.
Para encontrar una raíz, o el punto donde f(x) = 0, de la función f de arriba podemos utilizar por ejemplo scipy.optimize.fsolve():
>>> root = optimize.fsolve(f, 1) # our initial guess is 1
>>> root
array([ 0.])
>>> root2 = optimize.fsolve(f, -2.5)
>>> root2
array([-2.47948183])
Supongamos que tenemos datos de una muestra de f con un poco de ruido:
>>> xdata = np.linspace(-10, 10, num=20)
>>> ydata = f(xdata) + np.random.randn(xdata.size)
>>> def f2(x, a, b):
... return a*x**2 + b*np.sin(x)
>>> guess = [2, 2]
>>> params, params_covariance = optimize.curve_fit(f2, xdata, ydata, guess)
>>> params
array([ 0.99925147, 9.76065551])
[source code, hires.png, pdf]
Nota
En scipy >= 0.11 se unificaron las interfaces para
todos los algoritmos de minimización y búsqueda de raices están
disponibles en scipy.optimize.minimize(), scipy.optimize.minimize_scalar() y scipy.optimize.root(). Se permite comparar fácilmente diferentes algoritmos a través de la palabra clave method.
Usted puede encontrar algoritmos con las mismas funcionalidades para problemas multi-dimensional en scipy.optimize.
Ejercicio: Ajuste de datos de temperatura
Las temperaturas extremas en Alaska para cada mes, a partir de enero (en grados centígrados)max: 17, 19, 21, 28, 33, 38, 37, 37, 31, 23, 19, 18
min: -62, -59, -56, -46, -32, -18, -9, -13, -25, -46, -52, -58
- Grafique las temperaturas extremas.
- Definir una función que puede describir las temperaturas min y máx. Sugerencia: esta función tiene un periodo de 1 año. Sugerencia: incluir un tiempo compensado.
- Ajuste esta función a los datos con scipy.optimize.curve_fit().
- Graficar el resultado. El ajuste es razonable? Si no, por qué?
- Si el tiempo no es compensado el ajuste de las temperaturas mínima y máxima tiene la misma exactitud?
Ejercicio: Minimización 2-D
[source code, hires.png, pdf]La función six-hump camelback
Sugerencia:
- Puede restringir las variables a -2 < x < 2 y -1 < y < 1.
- Use numpy.meshgrid() y pylab.imshow() para encontrar visualmente las regiones.
- Use scipy.optimize.fmin_bfgs() o otro minimizador multidimensional.
Ver el sumario de ejercicios en Non linear least squares curve fitting: application to point extraction in topographical lidar data para ejemplos más avanzados.
1.5.6. Estadística y números aleatorios: scipy.stats
El módulo scipy.stats contiene herramientas estadísticas y probabilísticas descripciones de procesos aleatorios. Generadores de números aleatorios para diferentes procesos aleatorios se puede encontrar en numpy.random .1.5.6.1. Histograma y la función de densidad de probabilidad
Mediante observaciones de un proceso aleatorio, su histograma es un estimador del proceso aleatorio PDF (probability density function):>>> a = np.random.normal(size=1000)
>>> bins = np.arange(-4, 5)
>>> bins
array([-4, -3, -2, -1, 0, 1, 2, 3, 4])
>>> histogram = np.histogram(a, bins=bins, normed=True)[0]
>>> bins = 0.5*(bins[1:] + bins[:-1])
>>> bins
array([-3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5])
>>> from scipy import stats
>>> b = stats.norm.pdf(bins) # norm is a distribution
In [1]: pl.plot(bins, histogram)
In [2]: pl.plot(bins, b)
Si sabemos que el proceso aleatorio pertenece a una determinada familia de procesos aleatorios, tales como procesos normales, podemos hacer un ajuste de máxima credibilidad de las observaciones para estimar los parámetros de la distribución subyacente. Aquí ajustamos a un proceso normal los datos observados
>>> loc, std = stats.norm.fit(a)
>>> loc
-0.045256707490...
>>> std
0.9870331586690...
Ejercicio: Distribuciones de probabilidad
Generar 1000 variables aleatorias desde una distribución gamma con un
parámetro de forma igual a 1, despues graficar el histograma de las
muestras. Puede graficar la pdf de arriba (debe coincidir)?Adicional: las distribuciones tienen una serie de métodos útiles. Explore la documentación o mediante la implementación del tabulador IPython. Puede encontrar el parámetro de forma de 1 vuelta usando el método fit para variables aleatorias?
1.5.6.2. Percentiles
La mediana es el valor situado al medio de las observaciones por debajo y arriba>>> np.median(a)
-0.058028034...
>>> stats.scoreatpercentile(a, 50)
-0.0580280347...
>>> stats.scoreatpercentile(a, 90)
1.231593551...
1.5.6.3. Pruebas estadísticas
Una prueba estadística es un indicador de decisión. Por ejemplo, si tenemos dos series de observaciones, que suponemos se generan a partir de una distribución normal, podemos utilizar la Prueba t de Student para decidir si los dos conjuntos de observaciones son significativamente diferentes>>> a = np.random.normal(0, 1, size=100)
>>> b = np.random.normal(1, 1, size=10)
>>> stats.ttest_ind(a, b)
(-3.75832707..., 0.00027786...)
- El valor estadístico T: es un número cuyo signo es proporcional a la diferencia entre los dos procesos aleatorios y la magnitud está relacionada a cuanto diferen.
- El valor p: la probabilidad de que ambos procesos sean idénticos. Si es cercano a 1, los dos procesos son casi con toda seguridad idénticos. Cuanto más cercano sea a cero, lo más probable es que los procesos tengan diferentes medias.
1.5.7. Interpolación: scipy.interpolate
El módulo scipy.interpolate es útil para ajustar una función a partir de datos experimental y evaluar los puntos que se requieren. El módulo se basa en FITPACK Fortran subroutines del proyecto netlib.Suponiendo que los datos experimentales son cercanos a una función seno
>>> measured_time = np.linspace(0, 1, 10)
>>> noise = (np.random.random(10)*2 - 1) * 1e-1
>>> measures = np.sin(2 * np.pi * measured_time) + noise
>>> from scipy.interpolate import interp1d
>>> linear_interp = interp1d(measured_time, measures)
>>> computed_time = np.linspace(0, 1, 50)
>>> linear_results = linear_interp(computed_time)
>>> cubic_interp = interp1d(measured_time, measures, kind='cubic')
>>> cubic_results = cubic_interp(computed_time)
[source code, hires.png, pdf]
scipy.interpolate.interp2d es similar a scipy.interpolate.interp1d, pero para arreglos 2-D. Tenga en cuenta que para los valores interp, el tiempo calculado debe permanecer dentro del intervalo de tiempo medido. Ver el sumario de ejercicios Maximum wind speed prediction at the Sprogø station para un ejemplo más avanzado de interpolación con splines.
1.5.8. Integración numérica: scipy.integrate
La rutina de integración más genérica es scipy.integrate.quad()>>> from scipy.integrate import quad
>>> res, err = quad(np.sin, 0, np.pi/2)
>>> np.allclose(res, 1)
True
>>> np.allclose(err, 1 - res)
True
scipy.integrate también cuenta con rutinas para integrar Ecuaciones Diferenciales Ordinarias (ODE). En particular, scipy.integrate.odeint() es un integrador de propósito general utilizando LSODA (Solucionador Livermore para Ecuaciones Diferenciales ordinarias con método Automático de conmutación para problemas rígidos y no rígidos), consulte ODEPACK Fortran library para más detalles.
odeint resuelve sistemas de ecuaciones diferenciales ordinarias de primer orden de la forma
dy/dt = rhs(y1, y2, .., t0,...)
>>> def calc_derivative(ypos, time, counter_arr):
... counter_arr += 1
... return -2 * ypos
...
>>> counter = np.zeros((1,), dtype=np.uint16)
>>> from scipy.integrate import odeint
>>> time_vec = np.linspace(0, 4, 40)
>>> yvec, info = odeint(calc_derivative, 1, time_vec,
... args=(counter,), full_output=True)
>>> counter
array([129], dtype=uint16)
>>> info['nfe'][:10]
array([31, 35, 43, 49, 53, 57, 59, 63, 65, 69], dtype=int32)
[source code, hires.png, pdf]
Otro ejemplo con scipy.integrate.odeint() será un oscilador amortiguado masa-resorte (oscilador de segundo orden). La posición de la masa unida a un resorte obedece la ecuación diferencial de segundo orden y'' + 2 eps wo y' + wo^2 y = 0 con wo^2 = k/m siendo k la constante del resorte , m la masa y eps = c/(2 m wo) siendo c el coeficiente de amortiguamiento. Para este ejemplo, elegimos los parámetros
>>> mass = 0.5 # kg
>>> kspring = 4 # N/m
>>> cviscous = 0.4 # N s/m
>>> eps = cviscous / (2 * mass * np.sqrt(kspring/mass))
>>> eps < 1
True
>>> nu_coef = cviscous / mass
>>> om_coef = kspring / mass
>>> def calc_deri(yvec, time, nuc, omc):
... return (yvec[1], -nuc * yvec[1] - omc * yvec[0])
...
>>> time_vec = np.linspace(0, 10, 100)
>>> yarr = odeint(calc_deri, (1, 0), time_vec, args=(nu_coef, om_coef))
[source code, hires.png, pdf]
Scipy no tiene solucionadores de ecuaciones diferenciales parciales (PDE). Algunos paquetes Python para la resolver PDE están disponibles, tales como fipy o SfePy.
1.5.9. Procesamiento de señales: scipy.signal
>>> from scipy import signal
- scipy.signal.detrend(): eliminar la tendencia lineal de la señal
t = np.linspace(0, 5, 100) x = t + np.random.normal(size=100) pl.plot(t, x, linewidth=3) pl.plot(t, signal.detrend(x), linewidth=3)
- scipy.signal.resample(): remuestrea una señal a n puntos usando FFT.
t = np.linspace(0, 5, 100) x = np.sin(t) pl.plot(t, x, linewidth=3) pl.plot(t[::2], signal.resample(x, 50), 'ko')
Note como en el lado de la ventana del remuestreo es menos precisa y tiene un efecto de ondulación.
- scipy.signal tiene muchas funciones como: scipy.signal.hamming(), scipy.signal.bartlett(), scipy.signal.blackman()...
- scipy.signal tiene filtros (median filter scipy.signal.medfilt(), Wiener scipy.signal.wiener()), discutiremos esto en la sección de imagen.
1.5.10. Procesamiento de imágenes: scipy.ndimage
El submódulo dedicada al procesamiento de imágenes en scipy es scipy.ndimage.>>> from scipy import ndimage
1.5.10.1. Transformaciones geométricas en imágenes
Cambio de orientación, resolución, ..>>> from scipy import misc
>>> lena = misc.lena()
>>> shifted_lena = ndimage.shift(lena, (50, 50))
>>> shifted_lena2 = ndimage.shift(lena, (50, 50), mode='nearest')
>>> rotated_lena = ndimage.rotate(lena, 30)
>>> cropped_lena = lena[50:-50, 50:-50]
>>> zoomed_lena = ndimage.zoom(lena, 2)
>>> zoomed_lena.shape
(1024, 1024)
In [35]: subplot(151)
Out[35]: <matplotlib.axes.AxesSubplot object at 0x925f46c>
In [36]: pl.imshow(shifted_lena, cmap=cm.gray)
Out[36]: <matplotlib.image.AxesImage object at 0x9593f6c>
In [37]: axis('off')
Out[37]: (-0.5, 511.5, 511.5, -0.5)
In [39]: # etc.
1.5.10.2. Filtrado de imágenes
>>> from scipy import misc
>>> lena = misc.lena()
>>> import numpy as np
>>> noisy_lena = np.copy(lena).astype(np.float)
>>> noisy_lena += lena.std()*0.5*np.random.standard_normal(lena.shape)
>>> blurred_lena = ndimage.gaussian_filter(noisy_lena, sigma=3)
>>> median_lena = ndimage.median_filter(blurred_lena, size=5)
>>> from scipy import signal
>>> wiener_lena = signal.wiener(blurred_lena, (5,5))
Ejercicio
Comparar histogramas para las diferentes imágenes filtradas.1.5.10.3. Morfología matemática
Morfología matemática es una teoría derivada de teória de conjuntos. Se caracterizan y transforman las estructuras geométricas. En particular las imágenes binarias (blanco y negro), se pueden transformar mediante esta teoría: los conjuntos para ser transformados son los grupos de píxeles vecinos de valor no cero. La teoría también se extendió a las imágenes en escala de grises.Operaciones elementales matemático-morfologícas usan un elemento estructurante con el fin de modificar otras estructuras geométricas.
Primero vamos a generar un elemento estructurante
>>> el = ndimage.generate_binary_structure(2, 1)
>>> el
array([[False, True, False],
[True, True, True],
[False, True, False]], dtype=bool)
>>> el.astype(np.int)
array([[0, 1, 0],
[1, 1, 1],
[0, 1, 0]])
- Erosion
>>> a = np.zeros((7,7), dtype=np.int) >>> a[1:6, 2:5] = 1 >>> a array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0]]) >>> ndimage.binary_erosion(a).astype(a.dtype) array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]]) >>> #Erosión elimina los objetos más pequeños que la estructura >>> ndimage.binary_erosion(a, structure=np.ones((5,5))).astype(a.dtype) array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]])
- Dilatación
>>> a = np.zeros((5, 5)) >>> a[2, 2] = 1 >>> a array([[ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 1., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.]]) >>> ndimage.binary_dilation(a).astype(a.dtype) array([[ 0., 0., 0., 0., 0.], [ 0., 0., 1., 0., 0.], [ 0., 1., 1., 1., 0.], [ 0., 0., 1., 0., 0.], [ 0., 0., 0., 0., 0.]])
- Apertura
>>> a = np.zeros((5,5), dtype=np.int) >>> a[1:4, 1:4] = 1; a[4, 4] = 1 >>> a array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 1]]) >>> #Apertura elimina objetos pequeños >>> ndimage.binary_opening(a, structure=np.ones((3,3))).astype(np.int) array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]]) >>> # Opening can also smooth corners >>> ndimage.binary_opening(a).astype(np.int) array([[0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 1, 1, 1, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0]])
- Cierre: ndimage.binary_closing
Ejercicio
Compruebe que las cantidades iniciales a erosionar, se dilataran.>>> a = np.zeros((50, 50))
>>> a[10:-10, 10:-10] = 1
>>> a += 0.25*np.random.standard_normal(a.shape)
>>> mask = a>=0.5
>>> opened_mask = ndimage.binary_opening(mask)
>>> closed_mask = ndimage.binary_closing(opened_mask)
Ejercicio
Compruebe que el área del cuadrado reconstruido es menor que el área
del cuadrado inicial. (Lo contrario ocurriría si la etapa de cierre se
realiza antes que la apertura).>>> a = np.zeros((7,7), dtype=np.int)
>>> a[1:6, 1:6] = 3
>>> a[4,4] = 2; a[2,3] = 1
>>> a
array([[0, 0, 0, 0, 0, 0, 0],
[0, 3, 3, 3, 3, 3, 0],
[0, 3, 3, 1, 3, 3, 0],
[0, 3, 3, 3, 3, 3, 0],
[0, 3, 3, 3, 2, 3, 0],
[0, 3, 3, 3, 3, 3, 0],
[0, 0, 0, 0, 0, 0, 0]])
>>> ndimage.grey_erosion(a, size=(3,3))
array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 0, 0],
[0, 0, 3, 2, 2, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]])
1.5.10.4. Mediciones en imágenes
Primero vamos a generar una imagen binaria sintética agradable.>>> x, y = np.indices((100, 100))
>>> sig = np.sin(2*np.pi*x/50.)*np.sin(2*np.pi*y/50.)*(1+x*y/50.**2)**2
>>> mask = sig > 1
>>> labels, nb = ndimage.label(mask)
>>> nb
8
>>> areas = ndimage.sum(mask, labels, xrange(1, labels.max()+1))
>>> areas
array([ 190., 45., 424., 278., 459., 190., 549., 424.])
>>> maxima = ndimage.maximum(sig, labels, xrange(1, labels.max()+1))
>>> maxima
array([ 1.80238238, 1.13527605, 5.51954079, 2.49611818,
6.71673619, 1.80238238, 16.76547217, 5.51954079])
>>> ndimage.find_objects(labels==4)
[(slice(30L, 48L, None), slice(30L, 48L, None))]
>>> sl = ndimage.find_objects(labels==4)
>>> import pylab as pl
>>> pl.imshow(sig[sl[0]])
<matplotlib.image.AxesImage object at ...>
1.5.11. Sumario de ejercicios para computación científica
El sumario de ejercicios utiliza principalmente Numpy, Scipy y Matplotlib. Se proporcionan algunos ejemplos de la vida real en computación científica con Python. Los fundamentos para trabajar con Numpy y Scipy fueron introducidos, se invita a el usuario interesado probar los ejercicios.Ejercicios:
- 1.5.11.25. Maximum wind speed prediction at the Sprogø station
- 1.5.11.26. Non linear least squares curve fitting: application to point extraction in topographical lidar data
- 1.5.11.27. Image processing application: counting bubbles and unmolten grains
- 1.5.11.28. Tránsito de avenidas en embalses
- 1.5.11.29. Tránsito de avenidas en cauces naturales
- 1.5.11.30. Ajuste de curva de caudales
No hay comentarios:
Publicar un comentario