HOME/Articles/

pil example deteccionMovimiento (snippet)

Article Outline

Python pil example 'deteccionMovimiento'

Functions in program:

  • def main(): # rutina principal
  • def colstr(r, g, b):
  • def colhex(v):
  • def convolucion(imagen, h):
  • def getObjectInfo(grupo, imagen, id):
  • def deteccionObjetos(imagen, objts):
  • def asignColor(grupo):
  • def bfs(imagen, cola, ancho, altura, grupo):
  • def box(x, y, w, h, color):
  • def assignColor(grupo):

Modules used in program:

  • import time, PIL.Image, ImageDraw, ImageFont
  • import numpy as np

python deteccionMovimiento

Python pil example: deteccionMovimiento

import numpy as np
import time, PIL.Image, ImageDraw, ImageFont
from PIL import ImageDraw
from math import fabs
from subprocess import call
from Tkinter import * # ventanas
from random import random # pseudoaleatorio
from random import randint
from math import sqrt, log # evidente
from time import sleep # retraso
from sys import argv # parametros de linea de instr.
from threading import Thread # hilos (paralelismo)

def assignColor(grupo):
    return colstr((13 * grupo * 5 + 23) % 256, (3 * grupo * 7 + 31) % 256, (9 * grupo * 13 + 41) % 256)

class Objeto:
    def __init__(self, id, w, h, xc, yc, area, es):
        self.id = id
        self.w = w
        self.h = h
        self.xc = xc
        self.yc = yc
        self.area = area
        self.es = es
        self.direccion = ''


class Cuadrado:
    def __init__(self, id, x, y, t, v, d): # constructor
        self.x = x
        self.y = y
        self.t = t
        self.v = v
        self.d = d
        self.dx = 0
        self.dy = 0
        self.dz = 0
        self.counter = 0
        self.color = assignColor(id)
        self.drawing = None

    def step(self): # metodo de instancia
        if self.counter == 0:
            seleccion = randint(0, 3)
            self.dx = 0
            self.dy = 0
            self.dz = 0
            if seleccion == 0:
                self.dx = randint(-self.v, self.v+1)
            elif seleccion == 1:
                self.dy = randint(-self.v, self.v+1)
            else:
                self.dz = randint(-self.v, self.v+1)

        self.counter += 1
        if self.counter >= self.d:
            self.counter = 0

        self.x += self.dx
        self.y += self.dy
        self.t += self.dz

        if self.t < 1:
            self.t = 1
        elif self.t > 100:
            self.t = 100
        if self.x < 0:
            self.x = 0
        elif self.x > ( 700 - self.t ):
            self.x = 700 - self.t
        if self.y < 0:
            self.y = 0
        elif self.y > ( 700 - self.t ):
            self.y = 700 - self.t
        return

    def repaint(self):
        global canvas
        if self.drawing is not None:
            canvas.delete(self.drawing) # quito el viejo
        self.drawing = box(self.x, self.y, self.t, self.t, self.color)
        return

dim = 300
tk = Tk() # controlador
canvas = Canvas(tk, width = dim, height = dim) # ventana
speed = 1

def box(x, y, w, h, color): 
    return canvas.create_rectangle( x+w, y+h, x, y, outline= '#000000', fill = color, width = 1)

class Simulacion(Thread): # clase hijo de la clase hilo (paralelismo)
    def __init__(self, n):
        Thread.__init__(self)
        self.nodes = n
        return

    def run(self):
        global canvas, speed
        objetos = None
        while True:
            for n in self.nodes:
                n.repaint()
            sleep(speed)
            for n in self.nodes:
                n.step()
            canvas.update()
            canvas.postscript(file="image.ps", colormode='color')
            call(["convert","image.ps","image.png"])

            t1 = time.time()

            imagen = PIL.Image.open('image.png')
            original = imagen

            px = np.array([[-1,0,1],[-1,0,1],[-1,0,1]])
            py = np.array([[1,1,1],[0,0,0], [-1,-1,-1]])

            g = (convolucion(original, px)**2 + convolucion(original, py) **2) ** 0.5

            prom = np.average(g)
            ancho, altura = imagen.size
            imagen = imagen.convert('L')
            im = imagen.load()
            for x in xrange(ancho):
                for y in xrange(altura):
                    if g[x, y] < 4 * prom / 3:
                        im[x, y] = 0
                    else:
                        im[x, y] = 255
            resultado, objetos = deteccionObjetos(PIL.Image.fromarray(np.array(imagen)), objetos)
            t2 = time.time()
            print("Tiempo total: ",t2 -t1)


#metodo breath first search
#toma como parametro la matriz de la imagen, una copia de la matriz
#el color asignado RGB, la cola que es una lista, el ancho y la
#altura de la imagen original
def bfs(imagen, cola, ancho, altura, grupo):
    #toma el primer elemento de la cola y lo saca
    (x, y) = cola.pop(0)
    #si imagen no es color negro nos regresa un false
    if not imagen[x, y] == 0:
        return False
    #toma como blanco el pixel en la cola
    imagen[x, y] = 255 # ignora por poner en blanco
    grupo.append((x, y))
    for dx in [-1, 0, 1]:
        for dy in [-1, 0, 1]:
            (px, py) = (x + dx, y + dy)
            if px >= 0 and px < ancho and py >= 0 and py < altura:
                if imagen[px, py] == 0: # solo los negros entran en la cola
                    if (px, py) not in cola:
                        cola.append((px, py))
    return True

def asignColor(grupo):
    return ((grupo * 5 + 7) % 256, (grupo * 13 + 41) % 256, (grupo * 29 + 13) % 256)

#Metodo para hacer deteccion de objetos
#toma como parametro el nombre de la imagen
def deteccionObjetos(imagen, objts):
    #Toma las proporciones de la imagen
    ancho, altura = imagen.size
    #toma es escala de grises la imagen
    imagen = imagen.convert('L')
    #carga la imagen para manipularla
    im = imagen.load()

    porAsignar = list()
    for x in xrange(ancho):
        for y in xrange(altura):
            if im[x, y] == 255: # blanco
                porAsignar.append((x, y))

    grupos = list()
    while True:
        grupo = list()
        # se coloca como false un marcador
        listo = False
        #Se recorre segun las proporciones
        for y in xrange(altura):
            for x in xrange(ancho):
                # si el pixel actual es negro
                #el marcador se coloca en true
                # y se sale del ciclo
                if im[x, y] == 0: # negro
                    listo = True
                    break
            if listo:
                break
        #si el marcador es falso sale del ciclo infinito
        if not listo:
            break
        #se crea la cola
        cola = list()
        # agrega la coordenada donde se encuentra nuestro pixel
        cola.append((x, y))
        #este ciclo seguira hasta que la cola no tenga nada
        while len(cola) > 0:
            #se hace breath first search
            #tomando como parametro matriz de la imagen, la matriz creada en rgb
            #la cola, el ancho y la altura de la imagen
            bfs(im, cola, ancho, altura, grupo)
        grupos.append(grupo)

    mayor = 0
    fondoPos = None
    objetos = list()
    copia = PIL.Image.new(mode = 'RGB', size = (ancho, altura))
    cp = copia.load()
    for pos in xrange(len(grupos)):
        tam = len(grupos[pos])
        if tam > mayor:
            fondoPos = pos
            mayor = tam
    del grupos[fondoPos]
    print('Cantidad de objetos:',len(grupos))
    print('Fondo pos', fondoPos)
    for pos in xrange(len(grupos)):
           print('Crea objeto')
           objetos.append(getObjectInfo(grupos[pos], cp, pos))

    if objts != None and len(objts) == len(objetos):
        f = ImageFont.load_default()
        i = ImageDraw.Draw(copia)
        print('objts :',len(objts),' objetos:', len(objetos))
        for objeto in xrange(len(objts)):
            direccion = 'ID %s '%objts[objeto].id
            dx = objts[objeto].xc - objetos[objeto].xc
            dy = objts[objeto].yc - objetos[objeto].yc
            if objts[objeto].w < objetos[objeto].w:
                print('Objeto %s se acerca'%(objts[objeto].id))
                direccion+=' + '
            elif objts[objeto].w > objetos[objeto].w:
                print('Objeto %s se aleja'%(objts[objeto].id))
                direccion+=' - '
            elif dx > 0:
                print('Objeto %s se mueve a la izquierda'%(objts[objeto].id))
                direccion+=' <- '
            else:
                print('Objeto %s se mueve a la derecha'%(objts[objeto].id))
                direccion+=' -> '
            if dy > 0:
                print('Objeto %s se mueve hacia arriba'%(objts[objeto].id))
                direccion+=' arriba '
            else:
                print('Objeto %s se mueve hacia abajo'%(objts[objeto].id))
                direccion+=' abajo '
            i.text((objetos[objeto].xc, objetos[objeto].yc), direccion, font=f, fill = '#FFFFFF')
    copia.save('objetos.png', option='optimize')

    return PIL.Image.fromarray(np.array(copia)), objetos


def getObjectInfo(grupo, imagen, id):
    global dim
    minX = dim
    maxX = 0
    minY = dim
    maxY = 0
    for (x, y) in grupo:
        imagen[x, y] = asignColor(id)
        if x < minX:
            minX = x
        if x > maxX:
            maxX = x
        if y < minY:
            minY = y
        if y > maxY:
            maxY = y
    ancho = maxX - minX
    altura = maxY - minY
    xc = minX + ancho / 2
    yc = minY + altura / 2
    es = (minX, minY)
    print('Objeto %s esquina superior %s  %s dimensiones ancho %s altura %s centro %s %s '%(id, minX, minY, ancho, altura, xc, yc))
    return Objeto(id, ancho, altura, xc, yc, ancho * altura, es)




def convolucion(imagen, h):
    iancho, ialtura = imagen.size
    imagen = imagen.convert('L')
    im = imagen.load()
    maltura, mancho = h.shape
    g = np.zeros(shape = (iancho, ialtura))

    for x in xrange(iancho):
        for y in xrange(ialtura):

            sum = 0.0
            c = 0.0001

            for i in xrange(mancho):
                zi = ( i - ( mancho / 2 )) 
                for j in xrange(maltura):
                    zj = ( j - ( maltura / 2 ) )

                    if x + zi >= 0 and x + zi < iancho and \
                            y + zj >= 0 and y + zj < ialtura:
                        sum += im[x + zi, y + zj] * h[i, j]
                        c += 1.0

            g[x, y] = sum / c

    return g



def colhex(v):
    s = '%x' % v
    while len(s) < 2:
        s = '0%s' % s
    return s

def colstr(r, g, b):
    return '#%s%s%s' % (colhex(r), colhex(g), colhex(b))

def main(): # rutina principal
    global canvas, dim, speed
    canvas.pack() # crear la ventana en su tamano
    nodes = list()
    try:
        count = int(argv[1])
    except:
        count = 15
    try:
        speed = float(argv[2])
    except:
        speed = 0.2

    for c in xrange(count):
        t = randint(20, 50)
        x = randint(0,dim - t)
        y = randint(0,dim - t)
        v = randint(1, 4)
        d = randint(1, 15)
        nodes.append(Cuadrado(c, x, y, t, v, d))

    s = Simulacion(nodes)
    s.start()
    mainloop()

    return

main()