lunes, 15 de julio de 2019

Gráficas de Maplotlib en Tkinter

He estado aprendiendo usar el módulo TKinter para hacer interfaces gráficas en Python y me está encantando. A pesar de no tener un asistente gráfico como pyQT, se me ha hecho bastante fácil de usar. Para incrustar gráficos de Matplotlib en un GUI de Tkinter pongo el siguiente ejemplo en donde cada botón manda a graficar una función diferente:

  
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Jul 13 15:08:30 2019
@author: Rodolfo E. Escobar U.
"""
import tkinter as tk
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
def B0f():
x = np.linspace(0,2*np.pi,100)
y = np.sin(4*x)
ax.clear()
ax.plot(x,y), ax.grid(True)
ax.set_xlabel('$x$'),ax.set_ylabel('$y(x)$')
ax.set_title('$y(x)=sin(4x)$')
line.draw()
def B1f():
x = np.linspace(0,2*np.pi,100)
y = np.cos(4*x)
ax.clear()
ax.plot(x,y), ax.grid(True)
ax.set_xlabel('$x$'),ax.set_ylabel('$y(x)$')
ax.set_title('$y(x)=cos(4x)$')
line.draw()
def B2f():
x = np.linspace(0,2*np.pi,100)
y = np.exp(-0.5*x)*np.sin(4*x)
ax.clear()
ax.plot(x,y), ax.grid(True)
ax.set_xlabel('$x$'),ax.set_ylabel('$y(x)$')
ax.set_title('$y(x)=e^{-0.5x}sin(4x)$')
line.draw()
def B3f():
x = np.linspace(0,10,100)
y = np.exp(x)
ax.clear()
ax.plot(x,y), ax.grid(True)
ax.set_xlabel('$x$'),ax.set_ylabel('y(x)')
ax.set_title('$y(x) = e^{x}$')
line.draw()
def B4f():
def gaussian(x, mu, sig):
return 1./(np.sqrt(2.*np.pi)*sig)*np.exp(-np.power((x - mu)/sig, 2.)/2)
x = np.linspace(0,10,100)
y = gaussian(x,5,1.3)
ax.clear()
ax.plot(x,y), ax.grid(True)
ax.set_xlabel('$x$'),ax.set_ylabel('y(x)')
ax.set_title('$y(x) = Gaussian(x,5,1.3)$')
line.draw()
#--- Raiz ---
root = tk.Tk()
root.geometry('940x450')
root.title("Tkinter + Matplotlib")
#------------
#-- Frames ---
left_frame = tk.Frame(root)
left_frame.place(relx=0.03, rely=0.05, relwidth=0.25, relheight=0.9)
right_frame = tk.Frame(root, bg='#C0C0C0', bd=1.5)
right_frame.place(relx=0.3, rely=0.05, relwidth=0.65, relheight=0.9)
#---------------
#--- Botones ---
RH = 0.19
B0 = tk.Button(left_frame,text="SIN(4x)",command = B0f)
B0.place(relheight=RH, relwidth=1)
B1 = tk.Button(left_frame,text="COS(4x)",command = B1f)
B1.place(rely=(0.1 + RH*0.54) ,relheight=RH, relwidth=1)
B2 = tk.Button(left_frame,text="EXP(-0.5x)SIN(x)",command = B2f)
B2.place(rely= 2*(0.1 + RH*0.54) ,relheight=RH, relwidth=1)
B3 = tk.Button(left_frame,text="EXP(x)",command = B3f)
B3.place(rely= 3*(0.1 + RH*0.54) ,relheight=RH, relwidth=1)
B4 = tk.Button(left_frame,text="Gaussian(x)",command = B4f)
B4.place(rely= 4*(0.1 + RH*0.54) ,relheight=RH, relwidth=1)
#------------
#--- Agregar figura ---
figure = plt.Figure(figsize=(5,6), dpi=100)
ax = figure.add_subplot(111)
ax.grid(True),ax.set_xlabel('$x$'),ax.set_ylabel('$y(x)$')
line = FigureCanvasTkAgg(figure, right_frame)
line.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH,expand=1)
#----------------------
root.mainloop()

martes, 9 de julio de 2019

martes, 2 de julio de 2019

Áreas, perímetros y centroides de imágenes binarias con scikit-image

Utilizando las funciones label() y regionprops() del submódulo measure de scikit-image podemos obtener varios parámetros muy útiles de regiones binarias contiguas (blobs binarios). En este ejemplo construiremos una imagen binaria con dos círculos de diferente tamaño de los cuales obtendremos sus propiedades.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Jul 2 22:15:13 2019
@author: Rodolfo E. Escobar U.
"""
import numpy as np
import matplotlib.pyplot as plt
from skimage import draw, measure
# Generación de una imagen binaria con dos objetos separados
Bim = np.zeros([300,300])
C1i,C1j = draw.circle(80,100,70)
Bim[C1i,C1j] = 1
C2i,C2j = draw.circle(220,220,50)
Bim[C2i,C2j] = 1
#Etiquetado
E = measure.label(Bim)
#Propiedades de regiones
PR = measure.regionprops(E)
#PR[i].area => área del objeto i
#PR[i].perimeter => Perímetro del objeto i
#PR[i].centroid => centroide del objeto i
plt.imshow(Bim,cmap='gray')
plt.show()
print(u"Región 1:")
print("Area (pixeles): " + str(PR[0].area))
print("Perimetro (pixeles): " + str(PR[0].perimeter))
print("Centroide: " + str(PR[0].centroid))
print('\n')
print(u"Región 2:")
print("Area (pixeles): " + str(PR[1].area))
print("Perimetro (pixeles): " + str(PR[1].perimeter))
print("Centroide: " + str(PR[1].centroid))
view raw etiquetas.py hosted with ❤ by GitHub
Las salidas del programa son:

Región 1:
Area (pixeles): 15361
Perimetro (pixeles): 458.2741699796952
Centroide: (80.0, 100.0)


Región 2:
Area (pixeles): 7825
Perimetro (pixeles): 326.3919189857866
Centroide: (220.0, 220.0)

Es posible  construir un dataframe de pandas a partir del diccionario de propiedades generado con la función regionprops_table(). Si están comenzando con scikit-image pueden revisar mis notas de mi curso introductorio aquí.