jueves, 7 de marzo de 2013

Detección de círculos

Para esta tarea se hicieron unas pequeñas modificaciones al código hecho en la entrada pasada, lo primero que hice fue establecer una especie de rango de radios que voy a buscar en la imagen, pero esto no es suficiente ya que genera mucho ruido, y aparece círculos donde no hay. Se ve algo así:

Entonces lo que se me ocurrió hacer es primero en los radios que hice el "for" hacer como saltos, yo los hice de 2 en 2 me pareció que eso daba un mejor resultado.
Lo segundo fue sacar nuevamente los bordes de la imagen para esto yo use otra máscara la laplaciana y con esto si era posible obtener completamente el contorno del círculo de manera más fácil, entonces para saber cuales eran los bordes los cargue en una lista, esta lista es algo así [(x1,y1), (x2, y2), ...,(xN, yN)].
Una vez teniendo esto y todos los posibles centros de los círculos que son demasiados), hice otra lista que contuviera radio y posible centro, con esto me fue posible con un "for" recorrer toda esa lista y empezar a hacer cálculos de puntos de la circunferencia, con las siguientes formula:
 xc = int(round(x - radio * cosTheta))
 yc = int(round(y - radio * sinTheta))
Entonces estos eran puntos de la circunferencia, para la medida del angulo hice otra lista con 50 ángulos aleatorios.
Entonces para cada radio con centro posibles hice el calculo anterior, y sume en un contador cada que había más de 30 puntos que coincidían con los bordes obtenidos del laplaciano.
De esta manera los que si tenían al menos 30 puntos iguales a los bordes obtenidos anteriormente si pinta el círculo para comprobar en la imagen. Y es todo :) para sacar los círculos.
Algunos ejemplos:





      


Por último lo que falta es imprimir un listado que indica para cada ID el diámetro el círculo (como porcentaje del diagonal máxima de la imagen).



Otro ejemplo:





Código relevante


def dibuja_deteccion(imagen, radio, centros, DIA):
"""toma como parametros la imagen original, el radio
y los centros que se detectaron y regresa una imagen con
los circulos que se encontraron dibujados
"""
global CONT
draw = ImageDraw.Draw(imagen)
x_imagen, y_imagen = imagen.size
for i in range(len(centros)):
amarillo = (255, random.randint(120,255), random.randint(0, 40))
x = centros[i][0]
y = centros[i][1]
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill=None, outline=amarillo)
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill=None, outline=amarillo)
radio = radio + 1
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill=None, outline=amarillo)
radio = radio - 1
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill=None, outline=amarillo)
draw.ellipse((x-1,y-1, x+1,y+1),
fill=None, outline="green")
draw.text((x+2,y+2), str(CONT), fill="white")
dia = radio*2.0
p = (dia/DIA)*100
print "ID %s porcentaje %s" %(CONT, p)
CONT = CONT + 1
return imagen
def dibuja_circulo(num, imagen):
"""num es el numero de circulos aleatorios que se van a
dibujar, y la imagen es el canvas en el que se dibuja,
regresa la imagen con los circulos dibujados
"""
global CONT
draw = ImageDraw.Draw(imagen)
x_imagen, y_imagen = imagen.size
ruido = num
for i in range(ruido):
radio = random.randint(10, 30)
x = random.randint(radio, x_imagen-radio)
y = random.randint(radio, y_imagen-radio)
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill="black")
print "Ruido dibujado con centro en (%s, %s) y radio de %s" %(x,y, radio)
return imagen
def crea_imagen(dim):
"""crea una imagen con cierta dim, en blanco
"""
im = Image.new('RGB', (dim,dim), (255,255,255))
return im
def obtiene_votos(pix_x, pix_y, dim, radio):
"""se analiza la imagen, asi cada pixel detectado como
borde da lugar al circulo con el radio, las celdas que
pertenecen a ese circulo reciben un voto
"""
votos = []
for pos in xrange(dim):
votos.append([0] * dim)
for ym in xrange(dim):
y = dim / 2- ym
for xm in xrange(dim):
x = xm - dim / 2
gx = pix_x[ym, xm][0]
gy = pix_y[ym, xm][0]
g = sqrt(gx ** 2 + gy ** 2)
if fabs(g) > 0:
cosTheta = gx / g
sinTheta = gy / g
xc = int(round(x - radio * cosTheta))
yc = int(round(y - radio * sinTheta))
xcm = xc + dim / 2
ycm = dim / 2 - yc
if xcm >= 0 and xcm < dim and ycm >= 0 and ycm < dim:
votos[ycm][xcm] += 1
for rango in xrange (1, int(round(dim * 0.1))):
agregado = True
while agregado:
agregado = False
for y in xrange(dim):
for x in xrange(dim):
v = votos[y][x]
if v > 0:
for dx in xrange(-rango, rango):
for dy in xrange(-rango, rango):
if not (dx == 0 and dy == 0):
if y + dy >= 0 and y + dy < dim and x + dx >= 0 and x + dx < dim:
w = votos[y + dy][x + dx]
if w > 0:
if v - rango >= w:
votos[y][x] = v + w
votos[y + dy][x + dx] = 0
agregado = True
return votos
def detecta_centros(votos, dim):
"""se encarga de detectar los centros
"""
maximo = 0
suma = 0.0
for x in xrange(dim):
for y in xrange(dim):
v = votos[y][x]
suma += v
if v > maximo:
maximo = v
promedio = suma / (dim * dim)
umbral = (maximo + promedio) / 2.0
centros = []
for x in xrange(dim):
for y in xrange(dim):
v = votos[y][x]
if v > umbral:
#print 'Posible centro detectado en (%d, %d). ' % (y,x)
centros.append((y,x))
return centros
def main():
"""funcion principal
"""
try:
num = int(sys.argv[1])
except:
#print "recuerda escribe el radio y el numero de circulos"
return
dim = 200
im = crea_imagen(dim)
im = dibuja_circulo(num,im)
im.save("a.png")
mascara = [[0,1,0],[1,-4,1],[0,1,0]]
lap = filtros.convolucion(im, mascara)
lap = filtros.umbral(lap)
lap = filtros.umbral(lap)
lap.save("lap.png")
pix = lap.load()
bordes = []
#diagonal
dia = math.sqrt( math.pow((im.size[0]) , 2) + math.pow((im.size[1]) , 2))
for i in range(dim):
for j in range(dim):
if pix[j, i][0] == 255:
bordes.append((j,i))
im.save("original.png")
path = "circulos.png"
im.save(path)
im = filtros.abrir_imagen(path)
im = filtros.hacer_gris(im)
sobelx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
sobely = [[1, 2, 1], [0, 0, 0], [-1, -2, -1]]
Gx = filtros.convolucion(im, sobelx)
Gy = filtros.convolucion(im, sobely)
Gx.save("imagenx.png")
Gy.save("imageny.png")
votos = list()
pix_x = Gx.load()
pix_y = Gy.load()
combinaciones = []
for i in range(5, 45, 1):
votos = obtiene_votos(pix_x, pix_y, dim, i)
centros = detecta_centros(votos, dim)
centros.insert(0, i)
combinaciones.append(centros)
puntos = []
cen = []
#print combinaciones
for j in range(len(combinaciones)):
#print combinaciones[j]
cont = 0
radio = combinaciones[j][0]
for i in range(len(combinaciones[j])):
#print combinaciones[j][i]
if i == 0:
continue
cont = 0
angulos = []
for m in range(50):
angulos.append(random.randint(10, 360))
for a in range(len(angulos)):
x1 = int(radio*math.cos(math.degrees(angulos[a])))+combinaciones[j][i][0]
x2 = int(radio*math.sin(math.degrees(angulos[a])))+combinaciones[j][i][1]
s = (x1, x2)
s1 = (x1, x2+1)
s2 = (x1+1, x2)
s3 = (x1+1, x2+1)
s4 = (x1-1, x2-1)
s5 = (x1, x2-1)
s6 = (x1-1, x2)
if s in bordes or s2 in bordes or s1 in bordes or s3 in bordes or s4 in bordes or s5 in bordes or s6 in bordes:
cont = cont + 1
if cont >= 35:
print "CIRCULO CON CENTRO (%s, %s)" %(x1, x2)
im = dibuja_deteccion(im, radio, [(combinaciones[j][i][0], combinaciones[j][i][1])], dia)
im.save("final.png")
main()
view raw gistfile1.py hosted with ❤ by GitHub

 Repositorio

Traducciones

Páginas 4-5 y 28-31.

martes, 5 de marzo de 2013

Simulación NS-3

Para realizar la simulación lo que utilice es ns-3, es un simulador de redes que se basa en eventos discretos, se pueden simular protocolos unicast y multicast, se utiliza mucho en la investigación de redes móviles ad-hoc. Implementa muchos protocolos tanto de redes alámbricas como inalámbricas , la versión que yo uso la ns-3 se usa para soportar el flujo de trabajo de una simulación desde configuración hasta recolección y análisis de tramas.

La finalidad de esta entrada es diseñar y ejecutar una simulación de prueba, además incluir algunas medidas de desempeño.
Lo importante es que haya nodos, tráfico y algunas medidas de desempeño. Lo primero que yo hice es comenzar a correr los ejemplos que ya vienen, es difícil ya que todos están C++ y no hay una API completa de Python, entonces hay que investigar bastante.

Yo diseñé la siguiente red:


Lo primero que se hace es crear los nodos, yo cree los nodos de las terminales en un arreglo, luego los de los switches. Después se tenía que definir los links y marcar los nodos que de hicieron con la finalidad de ser switches como tales. Aquí la parte del código:

print "Crea nodos"
terminals = ns.network.NodeContainer()
terminals.Create(5)
csmaSwitch = ns.network.NodeContainer()
csmaSwitch.Create(1)
csmaSwitch2 = ns.network.NodeContainer()
csmaSwitch2.Create(1)
print "Construye la topologia"
csma = ns.csma.CsmaHelper()
csma.SetChannelAttribute("DataRate", ns.network.DataRateValue(ns.network.DataRate(5000000)))
csma.SetChannelAttribute("Delay", ns.core.TimeValue(ns.core.MilliSeconds(2)))
# Crea los links de cada terminal al switch
terminalDevices = ns.network.NetDeviceContainer()
switchDevices = ns.network.NetDeviceContainer()
switchDevices2 = ns.network.NetDeviceContainer()
#se unen los cuatro nodos al primer switch
for i in range(4):
link = csma.Install(ns.network.NodeContainer(ns.network.NodeContainer(terminals.Get(i)), csmaSwitch))
terminalDevices.Add(link.Get(0))
switchDevices.Add(link.Get(1))
#se une un nodo al segundo switch
link = csma.Install(ns.network.NodeContainer(ns.network.NodeContainer(terminals.Get(2)), csmaSwitch2))
terminalDevices.Add(link.Get(0))
switchDevices2.Add(link.Get(1))
link = csma.Install(ns.network.NodeContainer(ns.network.NodeContainer(terminals.Get(4)), csmaSwitch2))
terminalDevices.Add(link.Get(0))
switchDevices2.Add(link.Get(1))
#se crean los puentes para enviar los paquetes
switchNode = csmaSwitch.Get(0)
bridgeDevice = ns.bridge.BridgeNetDevice()
switchNode.AddDevice(bridgeDevice)
switchNode2 = csmaSwitch2.Get(0)
bridgeDevice2 = ns.bridge.BridgeNetDevice()
switchNode2.AddDevice(bridgeDevice2)
for portIter in range(switchDevices.GetN()):
bridgeDevice.AddBridgePort(switchDevices.Get(portIter))
for portIter in range(switchDevices2.GetN()):
bridgeDevice2.AddBridgePort(switchDevices2.Get(portIter))
view raw gistfile1.py hosted with ❤ by GitHub


Despues se asignan las direcciones IP a las terminales:

# se agrega el internet a las terminales
internet = ns.internet.InternetStackHelper()
internet.Install(terminals)
# Se agregan las direcciones iP
print "Se asignan direcciones IP"
ipv4 = ns.internet.Ipv4AddressHelper()
ipv4.SetBase(ns.network.Ipv4Address("10.1.1.0"), ns.network.Ipv4Mask("255.255.255.0"))
ipv4.Assign(terminalDevices)
view raw gistfile1.py hosted with ❤ by GitHub


Enseguida se empieza a agregar el tráfico, en esta parte del código muestro como se envían datos del nodo 0 al 1, ademas de indicar que es UDP:

print "Create Applications."
port = 9
onoff = ns.applications.OnOffHelper("ns3::UdpSocketFactory",
ns.network.Address(ns.network.InetSocketAddress(ns.network.Ipv4Address("10.1.1.2"), port)))
onoff.SetConstantRate (ns.network.DataRate ("500kb/s"))
app = onoff.Install(ns.network.NodeContainer(terminals.Get(0)))
# empieza la aplicacion
app.Start(ns.core.Seconds(1.0))
sink = ns.applications.PacketSinkHelper("ns3::UdpSocketFactory",
ns.network.Address(ns.network.InetSocketAddress(ns.network.Ipv4Address.GetAny(), port)))
app = sink.Install(ns.network.NodeContainer(terminals.Get(1)))
app.Start(ns.core.Seconds(0.0))
view raw gistfile1.py hosted with ❤ by GitHub


En donde se estableció la velocidad de transferencia en 500kb/s y se establece la dirección IP del destino en este caso 10.1.1.2 corresponde al nodo 1.

En las demás transferencias también se establecieron cada una de esas características, aquí esta el resto de los nodos en los que varié la velocidad de transferencia:

# se envian paquetes del nodo 3 al 0
onoff.SetConstantRate (ns.network.DataRate ("100kb/s"))
onoff.SetAttribute("Remote",
ns.network.AddressValue(ns.network.InetSocketAddress(ns.network.Ipv4Address("10.1.1.1"), port)))
app = onoff.Install(ns.network.NodeContainer(terminals.Get(3)))
app.Start(ns.core.Seconds(1.1))
app = sink.Install(ns.network.NodeContainer(terminals.Get(0)))
app.Start(ns.core.Seconds(2.0))
#se envian paquetes del nodo 2 al 4
onoff.SetConstantRate (ns.network.DataRate ("300kb/s"))
onoff.SetAttribute("Remote",
ns.network.AddressValue(ns.network.InetSocketAddress(ns.network.Ipv4Address("10.1.1.6"), port)))
app = onoff.Install(ns.network.NodeContainer(terminals.Get(2)))
app.Start(ns.core.Seconds(1.1))
app = sink.Install(ns.network.NodeContainer(terminals.Get(4)))
app.Start(ns.core.Seconds(0.0))
#se envian paquetes del nodo 1 al 2
onoff.SetConstantRate (ns.network.DataRate ("160kb/s"))
onoff.SetAttribute("Remote",
ns.network.AddressValue(ns.network.InetSocketAddress(ns.network.Ipv4Address("10.1.1.3"), port)))
app = onoff.Install(ns.network.NodeContainer(terminals.Get(1)))
app.Start(ns.core.Seconds(1.1))
app = sink.Install(ns.network.NodeContainer(terminals.Get(2)))
app.Start(ns.core.Seconds(0.0))
csma.EnablePcapAll("csma-bridge", False)
#se envian paquetes del nodo 3 al 2
onoff.SetConstantRate (ns.network.DataRate ("800kb/s"))
onoff.SetAttribute("Remote",
ns.network.AddressValue(ns.network.InetSocketAddress(ns.network.Ipv4Address("10.1.1.3"), port)))
app = onoff.Install(ns.network.NodeContainer(terminals.Get(3)))
app.Start(ns.core.Seconds(1.1))
app = sink.Install(ns.network.NodeContainer(terminals.Get(2)))
app.Start(ns.core.Seconds(0.0))
csma.EnablePcapAll("csma-bridge", False)
#se envian paquetes del 4 al 2
onoff.SetAttribute("Remote",
ns.network.AddressValue(ns.network.InetSocketAddress(ns.network.Ipv4Address("10.1.1.5"), port)))
app = onoff.Install(ns.network.NodeContainer(terminals.Get(4)))
app.Start(ns.core.Seconds(1.1))
app = sink.Install(ns.network.NodeContainer(terminals.Get(2)))
app.Start(ns.core.Seconds(0.0))
view raw gistfile1.py hosted with ❤ by GitHub


En el código se puede ver que hay transferencia de los nodos:

3 al 0: Pasando por el switch0, y con una velocidad de transferencia de 100kb/s
2 al 4: Pasando por el switch1, y con una velocidad de transferencia de 300kb/s.
1 al 2: Pasando por el switch0, y con una velocidad de transferencia de 160kb/s.
3 al 2: Pasando por el switch0, y con una velocidad de transferencia de 800kb/s.
4 al 2: Pasando por el switch1, y con una velocidad de transferencia de 800kb/s

Este es el resultado de correr la simulación:

Empieza la simulacion
scanning topology: 7 nodes...
scanning topology: calling graphviz layout
scanning topology: all done.
FlowID: 1 (UDP 10.1.1.1/49153 --> 10.1.1.2/9)
Tx Bytes: 2267460
Rx Bytes: 2266920
Tx Packets: 4199
Rx Packets: 4198
Lost Packets: 0
Mean{Delay}: 0.00604608194188
Mean{Jitter}: 0.000512220537527
Mean{Hop Count}: 1.0
FlowID: 2 (UDP 10.1.1.4/49154 --> 10.1.1.3/9)
Tx Bytes: 3617460
Rx Bytes: 3616920
Tx Packets: 6699
Rx Packets: 6698
Lost Packets: 0
Mean{Delay}: 0.00701732511406
Mean{Jitter}: 0.0015147514075
Mean{Hop Count}: 1.0
FlowID: 3 (UDP 10.1.1.6/49153 --> 10.1.1.5/9)
Tx Bytes: 3617460
Rx Bytes: 3616920
Tx Packets: 6699
Rx Packets: 6698
Lost Packets: 0
Mean{Delay}: 0.00782599346073
Mean{Jitter}: 0.00141445805674
Mean{Hop Count}: 1.0
FlowID: 4 (UDP 10.1.1.5/49153 --> 10.1.1.6/9)
Tx Bytes: 1356480
Rx Bytes: 1355940
Tx Packets: 2512
Rx Packets: 2511
Lost Packets: 0
Mean{Delay}: 0.00860451551254
Mean{Jitter}: 0.00213814440797
Mean{Hop Count}: 1.0
FlowID: 5 (UDP 10.1.1.2/49153 --> 10.1.1.3/9)
Tx Bytes: 723060
Rx Bytes: 723060
Tx Packets: 1339
Rx Packets: 1339
Lost Packets: 0
Mean{Delay}: 0.00675767407991
Mean{Jitter}: 0.00117281030942
Mean{Hop Count}: 1.0
FlowID: 6 (UDP 10.1.1.4/49153 --> 10.1.1.1/9)
Tx Bytes: 451980
Rx Bytes: 451980
Tx Packets: 837
Rx Packets: 837
Lost Packets: 0
Mean{Delay}: 0.00580386284229
Mean{Jitter}: 1.8284687799e-05
Mean{Hop Count}: 1.0
Finaliza
view raw gistfile1.sh hosted with ❤ by GitHub


Este resultado muestra estadísticas para cada transferencia de datos que hicieron los nodos, por ejemplo del nodo 0 al 1, la transferencia es de la IP 10.1.1.1 a la 10.1.1.2, con sus cantidades de bytes de paquetes transmitidos y recibidos, ademas de el número de paquetes, indica que se perdieron 0 paquetes.

FlowID: 1 (UDP 10.1.1.1/49153 --> 10.1.1.2/9)

  Tx Bytes:  2267460
  Rx Bytes:  2266920
  Tx Packets:  4199
  Rx Packets:  4198
  Lost Packets:  0
  Mean{Delay}:  0.00604608194188
  Mean{Jitter}:  0.000512220537527
  Mean{Hop Count}:  1.0

También se muestra por ejemplo el Jitter de .0005 que de acuerdo a lo visto en la entrada pasada, es un valor bastante bueno para la comunicación. 
Las demás transmisiones muestran las mismas estadísticas.
Las medidas se obtuvieron así:

print " Mean{Delay}: ", (st.delaySum.GetSeconds() / st.rxPackets)
print " Mean{Jitter}: ", (st.jitterSum.GetSeconds() / (st.rxPackets-1))
print " Mean{Hop Count}: ", float(st.timesForwarded) / st.rxPackets + 1
view raw gistfile1.py hosted with ❤ by GitHub


Visualización

Para este último paso lo que había que hacer ya es importar la librería de visualizer y dibujar los nodos si es que queremos que aparezcan en alguna posición determinada, si no se dibujan solos, yo si establecí las posiciones:

#para dibujar los nodos
mobility = ns.mobility.ConstantPositionMobilityModel()
mobility.SetPosition(ns.core.Vector(95, 5, 0))
terminals.Get(0).AggregateObject(mobility)
mobility = ns.mobility.ConstantPositionMobilityModel()
mobility.SetPosition(ns.core.Vector(120,35, 0))
terminals.Get(1).AggregateObject(mobility)
mobility = ns.mobility.ConstantPositionMobilityModel()
mobility.SetPosition(ns.core.Vector(60,35, 0))
terminals.Get(2).AggregateObject(mobility)
mobility = ns.mobility.ConstantPositionMobilityModel()
mobility.SetPosition(ns.core.Vector(100,65, 0))
terminals.Get(3).AggregateObject(mobility)
mobility = ns.mobility.ConstantPositionMobilityModel()
mobility.SetPosition(ns.core.Vector(10,35, 0))
terminals.Get(4).AggregateObject(mobility)
mobility1 = ns.mobility.ConstantPositionMobilityModel()
mobility1.SetPosition(ns.core.Vector(90,45, 0))
csmaSwitch.Get(0).AggregateObject(mobility1)
mobility2 = ns.mobility.ConstantPositionMobilityModel()
mobility2.SetPosition(ns.core.Vector(40,40, 0))
csmaSwitch2.Get(0).AggregateObject(mobility2)
view raw gistfile1.py hosted with ❤ by GitHub


Resultados

Funcionando todos juntos



Nodo 5 (SWITCH)



Nodo 6 (SWITCH)



Código completo

Referencias

Ejemplo NS-3 Python
Instalación python

Tiendas útiles para hacer implementar sistemas inteligentes

En esta entrada muestran proveedores de software y/o hardware para hacer sistemas inteligentes.

Cosas de Ingeniería
Link al sitio principal

Esta es una empresa mexicana. Ofrecen al mercado nuevos y atractivos productos electrónicos  además de capacitar de los especialistas en tecnología y generan proyectos de ingeniería que pidan los clientes. Su especialidad es desarrollar proyectos que específicos que la gente les pida algunos ejemplos son:
  • Control Para prótesis de brazo.
  • Sistema de entrenamiento en microcontroladores para control PID.
  • Sistema para terapia Médica con diatermia.
  • Sistemas de control para calentadores solares
  • Diseño de mini-robots educativos.
En esta tienda se puede pagar con tarjetas de crédito o por depósito en el banco, hay entrega en todo México.
Algunos productos sobresalientes que ofrecen son:



Steren
Link al sitio oficial

Es una tienda en donde según mi experiencia no se va a encontrar nada muy especializado, pero si las cosas básicas que se ocupan en los proyectos, su especialidad es vender productos electrónicos que son útiles no solamente para pequeños proyectos electrónicos si no también para reponer piezas de algún aparato electrónico.
Para obtener los productos aquí basta con ir a la tienda por ellos, o también es posible hacer las compras en línea.
Algunos productos típicos son:
  • Drivers para los mismos dispositivos que ellos venden
  • Leds
  • Resistencias
  • Microcontroladores

Advancer Technologies
Link al Sitio Oficial

Tecnologías Advancer se dedica al desarrollo de tecnologías biomédicas y biomecánica y ciencias aplicadas. También se venden una variedades de sensores de músculo y kits de circuitos para incorporar las tecnologías biomédicas en cualquier proyecto.
Se dedican a vender  sensores de músculos como este entre otros artículos relacionados.
En esta tienda se puede comprar en línea y envían el paquete al domicilio indicado.


Smarthome
Link al sitio oficial

En esta tienda se venden todo tipo de artículos o componentes para poder automatizar el hogar,
El sitio vende controles remotos, sistemas de seguridad, iluminación, altavoces, cámaras y equipos de vigilancia, entre otras cosas.
Algunos productos que venden son:


También aquí las compras se pueden hacer en línea y envían el producto a domicilio o directamente en la tienda.

Mouser Electronics
Link al sitio oficial

Esta tienda se dedica a la venta de todo tipo de componentes electrónicos, componentes para los diseños de ingenieros, y cumplir con alguna funcionalidad inteligente.
Algunos componentes interesantes son:

  • Sensor de calidad del aire

  • Sensores ópticos

También cuenta con servició de compra en línea y entrega a domicilio, además de poder comprar directamente en la tienda.

Newark
Link al sitio oficial

Es una tienda que vende principalmente arduinos, microcontroladores, micropocesadores, así como otros productos para computo integrado y sistemas inteligentes.
Se puede comprar en línea y hay envío a domicilio.
Algunos productos que venden en la tienda son:

  • Sensor fotoeléctrico
  • Sensor de posición

Además al igual que "Cosas de Ingeniería" también venden software, esta es una lista de librerías que manejan.



Es todo espero sea útil mi mini-catálogo.

Detección de círculos

La detección de círculos es muy importante en aplicaciones como la inspección
automática de productos que son manufacturados, la vectorización asistida de dibujos, la detección de
objetivos, etc. La detección de círculos en imágenes se hace con el método de la transformada circular de Hough.
Lo malo de este método es que es computacionalmente muy pesado.


http://sathyakumar-spark.blogspot.mx/2011/10/circle-detection-using-opencv.html

Para hacer el algoritmo se modifico el código de las líneas, pero en este código se usan los gradientes para poder calcular el angulo y poder usar ese punto como si ya fuera del circulo. Entones se obtiene un centro para cada punto, y luego se dice que es circulo cuando hay muchos píxeles que coinciden que se centro es ese mismo punto.
Usaremos otra vez el gradiente:


Luego se usa cos(Θ) = gx / g y sin(Θ) = gy / g, y con eso podemos después encontrar los posibles centros del circulo con las formulas: 
xc = int(round(x - radio * cos(Θ)))

yc = int(round(y - radio * sin(Θ)))

Aquí algunos resultados:

radio 30, tiempo 50 segundos


radio 50, tiempo 54 segundos 



radio 90, tiempo 1 minuto y 22 segundos


Código:

#!/usr/bin/python
from PIL import Image, ImageDraw
import random
import filtros
import time
from math import sqrt, fabs
import sys
def dibuja_deteccion(imagen, radio, centros):
"""toma como parametros la imagen original, el radio
y los centros que se detectaron y regresa una imagen con
los circulos que se encontraron dibujados
"""
draw = ImageDraw.Draw(imagen)
x_imagen, y_imagen = imagen.size
for i in range(len(centros)):
amarillo = (255, random.randint(120,255), random.randint(0, 40))
x = centros[i][0]
y = centros[i][1]
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill=None, outline=amarillo)
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill=None, outline=amarillo)
radio = radio + 1
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill=None, outline=amarillo)
radio = radio - 1
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill=None, outline=amarillo)
draw.ellipse((x-1,y-1, x+1,y+1),
fill=None, outline="green")
draw.text((x+2,y+2), str(i), fill="white")
print "ID %s " %i
return imagen
def dibuja_circulo(num, radio, imagen):
"""num es el numero de circulos aleatorios que se van a
dibujar, y la imagen es el canvas en el que se dibuja,
regresa la imagen con los circulos dibujados
"""
draw = ImageDraw.Draw(imagen)
x_imagen, y_imagen = imagen.size
for i in range(num):
x = random.randint(radio, x_imagen-radio)
y = random.randint(radio, y_imagen-radio)
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill="black")
print "Circulo dibujado con centro en (%s, %s) y radio de %s" %(x,y, radio)
ruido = 1
for i in range(ruido):
radio = random.randint(10, 50)
x = random.randint(radio, x_imagen-radio)
y = random.randint(radio, y_imagen-radio)
draw.ellipse((x-radio,y-radio, x+radio,y+radio),
fill="black")
print "Ruido dibujado con centro en (%s, %s) y radio de %s" %(x,y, radio)
draw.rectangle((10, 10, 90, 90), fill="black", outline="red")
draw.rectangle((120, 100, 200, 200), fill="black", outline="red")
return imagen
def crea_imagen():
"""crea una imagen con cierta dim, en blanco
"""
im = Image.new('RGB', (500,500), (255,255,255))
return im
def obtiene_votos(pix_x, pix_y, dim, radio):
"""se analiza la imagen, asi cada pixel detectado como
borde da lugar al circulo con el radio, las celdas que
pertenecen a ese circulo reciben un voto
"""
votos = []
for pos in xrange(dim):
votos.append([0] * dim)
for ym in xrange(dim):
y = dim / 2- ym
for xm in xrange(dim):
x = xm - dim / 2
gx = pix_x[ym, xm][0]
gy = pix_y[ym, xm][0]
g = sqrt(gx ** 2 + gy ** 2)
if fabs(g) > 0:
cosTheta = gx / g
sinTheta = gy / g
xc = int(round(x - radio * cosTheta))
yc = int(round(y - radio * sinTheta))
xcm = xc + dim / 2
ycm = dim / 2 - yc
if xcm >= 0 and xcm < dim and ycm >= 0 and ycm < dim:
votos[ycm][xcm] += 1
for rango in xrange (1, int(round(dim * 0.1))):
agregado = True
while agregado:
agregado = False
for y in xrange(dim):
for x in xrange(dim):
v = votos[y][x]
if v > 0:
for dx in xrange(-rango, rango):
for dy in xrange(-rango, rango):
if not (dx == 0 and dy == 0):
if y + dy >= 0 and y + dy < dim and x + dx >= 0 and x + dx < dim:
w = votos[y + dy][x + dx]
if w > 0:
if v - rango >= w:
votos[y][x] = v + w
votos[y + dy][x + dx] = 0
agregado = True
return votos
def detecta_centros(votos, dim):
"""se encarga de detectar los centros
"""
maximo = 0
suma = 0.0
for x in xrange(dim):
for y in xrange(dim):
v = votos[y][x]
suma += v
if v > maximo:
maximo = v
promedio = suma / (dim * dim)
umbral = (maximo + promedio) / 2.0
centros = []
for x in xrange(dim):
for y in xrange(dim):
v = votos[y][x]
if v > umbral:
print 'Posible centro detectado en (%d, %d). ' % (y,x)
centros.append((y,x))
return centros
def main():
"""funcion principal
"""
try:
radio = int(sys.argv[1])
num = int(sys.argv[2])
except:
print "recuerda escribe el radio y el numero de circulos"
return
dim = 500
im = crea_imagen()
im = dibuja_circulo(num, radio, im)
im.save("original.png")
path = "circulos.png"
im.save(path)
im = filtros.abrir_imagen(path)
im = filtros.hacer_gris(im)
sobelx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
sobely = [[1, 2, 1], [0, 0, 0], [-1, -2, -1]]
Gx = filtros.convolucion(im, sobelx)
Gy = filtros.convolucion(im, sobely)
Gx.save("imagenx.png")
Gy.save("imageny.png")
votos = list()
pix_x = Gx.load()
pix_y = Gy.load()
votos = obtiene_votos(pix_x, pix_y, dim, radio)
centros = detecta_centros(votos, dim)
im = dibuja_deteccion(im, radio, centros)
im.save("final.png")
main()
view raw gistfile1.py hosted with ❤ by GitHub


Referencias

Diapositivas y ejemplo