miércoles, 15 de mayo de 2013

Laboratorio 10 - Movimiento

Para esta entrada se pidió que detectáramos movimiento.


Primeramente se obtuvieron las imágenes que serian utilizadas para este laboratorio, yo en mi caso use desde la cámara web , se utilizo opencv solamente para esto pero no para ninguna otra función.
Aquí se puede observar el momento de ejecutar el programa, iré dejando las partes importantes del código.





El proceso era muy lento ya que mientras se tomaba captura de vídeo con la cámara se procesaba la imagen , a escala de grises y se le aplicaba un filtrado , aquí arriba  se muestran las dos imágenes con el filtrado aplicado y después se sacaba la convolución. Aquí dejo el código de eso.

import cv
import Image
import numpy as np
def detect_painting(image):
image = filtro(image)
#img = mascara(image)
def mascara(self,image):
inicio = time()
#Mascara Sobel
sobelx = ([-1,0,1],[-2,0,2],[-1,0,1]) #gradiente horizontal
sobely = ([1,2,1],[0,0,0],[-1,-2,-1]) # gradiente vertical
img=self.convolucion(sobelx,sobely,image)
fin=time()
tiempo_t = fin - inicio
#print "Tiempo que tardo en ejecutarse convolucion = "+str(tiempo_t)+" segundos"
return img
def convolucion(self,h1,h2,image):
pixels = image.load()
ancho,alto = image.size
a=len(h1[0])
self.conv = numpy.empty((ancho, alto))
self.gx=numpy.empty((ancho, alto))
self.gy=numpy.empty((ancho, alto))
self.minimo = 255
self.maximo = 0
for x in range(ancho):
for y in range(alto):
sumax = 0.0
sumay = 0.0
for i in range(a):
for j in range(a):
try:
sumax +=(pixels[x+i,y+j][0]*h1[i][j])
sumay +=(pixels[x+i,y+j][0]*h2[i][j])
except:
pass
gradiente = math.sqrt(pow(sumax,2)+pow(sumay,2))
self.conv[x,y]=gradiente
self.gx[x,y]=sumax
self.gy[x,y]=sumay
gradiente = int(gradiente)
pixels[x,y] = (gradiente,gradiente,gradiente)
p = gradiente
if p < self.minimo:
self.minimo = p
if p > self.maximo:
self.maximo = p
# print 'gx-------------',self.gx
# print 'gy-------------',self.gy
return image
def normalizar(self,image):
inicio=time()
pixels = image.load()
r = self.maximo-self.minimo
prop = 255.0/r
ancho,alto = image.size
for i in range(ancho):
for j in range(alto):
p =int(floor((self.conv[i,j]-self.minimo)*prop))
pixels[i,j]=(p,p,p);
# print 'TERMINO'
fin = time()
tiempo_t = fin - inicio
# print "Tiempo que tardo en ejecutarse normalizar = "+str(tiempo_t)+" segundos"
return image
def binarizar(self,img):
inicio = time()
pixels = img.load()
ancho,alto = img.size
minimo = int(argv[2])
for i in range(ancho):
for j in range(alto):
if pixels[i,j][1] < minimo:
p=0
else:
p= 255
pixels[i,j]=(p,p,p)
fin =time()
tiempo_t = fin - inicio
# print "Tiempo que tardo en ejecutarse binzarizar = "+str(tiempo_t)+" segundos"
return img
def filtro(image):
image,matriz = escala_grises(image)
pixels = image.load()
ancho, alto =image.size
lista = [-1,0,1]
for i in range(ancho):
for j in range(alto):
promedio = vecindad(i,j,lista,matriz)
pixels[i,j] = (promedio,promedio,promedio)
image.save('FILTRO.png')
return image
def escala_grises(image):
image = Image.open(image)
pixels = image.load()
ancho,alto = image.size
matriz = np.empty((ancho, alto))
for i in range(ancho):
for j in range(alto):
(r,g,b) = image.getpixel((i,j))
escala = (r+g+b)/3
pixels[i,j] = (escala,escala,escala)
matriz[i,j] = int(escala)
df = image.save('escala.png')
return image,matriz
def vecindad(i,j,lista,matriz):
promedio = 0
indice = 0
for x in lista:
for y in lista:
a = i+x
b = j+y
try:
if matriz[a,b] and (x!=a and y!=b):
promedio += matriz[a,b]
indice +=1
except IndexError:
pass
try:
promedio=int(promedio/indice)
return promedio
except ZeroDivisionError:
return 0
def main():
cam=cv.CaptureFromCAM(0)
while True:
im =cv.QueryFrame(cam)
snapshot = im
image_size = cv.GetSize(snapshot)
cv.SaveImage("test.png",im)
imagen=cv.CreateImage(image_size,cv.IPL_DEPTH_8U,3)
detect_painting("test.png")
cv.ShowImage('Camara', snapshot)
if cv.WaitKey(30)==27:
break
main()
view raw gistfile1.py hosted with ❤ by GitHub





Posteriormente las imágenes se sometían a un binarizado y normalizado .

Después se procedía a sacarles una diferencia a estas imágenes eliminando un poco el ruido para comprobar los pixeles que sufrieron cambios de una imagen a otra.(cabe mencionar que salia mi dedo en una imagen la cambie por otra para evitar mas ruido)



Aun se puede apreciar que la imagen muestra ruido , pero claramente se observa también las lineas divisorias del movimiento.


import pygame
from pygame.locals import *
import Image
import math
#CONVOLUCION A ESCALA DE GRISES Y FILTRADA
image = Image.open("convo1.png")
pixeles = image.load()
ancho, altura =image.size
msobelX = ([-1, 0, 1], [-2, 0, 2], [-1, 0, 1]) #Para gradiente de x.
msobelY = ([1, 2, 1], [0, 0, 0], [-1, -2, -1]) #Para gradiente de y.
prewittX=([-1, 0, 1], [-1, 0, 1], [-1, 0, 1])#EJE X PREWITT
prewittY=([1, 1, 1], [0, 0, 0], [-1,-1,-1])#EJE Y PREWITT
tamanomatriz=3
sumatoriaX = 0
sumariaY = 0
seleccion=raw_input("INGRESA 1 PARA SOBEL y DOS PARA PREWITT ")
matrizagarrada=int(seleccion)
if matrizagarrada==1:
for x in range(altura):
for y in range(ancho):
sumatoriaX = 0
sumatoriaY = 0
if x != 0 and y != 0 and y != ancho and x != altura:
for i in range(tamanomatriz):
for j in range(tamanomatriz):
try:
gx = msobelX[i][j]*pixeles[y+j, x+i][1]
gy = msobelY[i][j]*pixeles[y+j, x+i][1]
except:
productosGX = 0
productosGY = 0
sumatoriaX = gx+sumatoriaX
sumatoriaY = gy+sumatoriaY
gxalcuadrado = pow(sumatoriaX, 2)
gyalcuadrado = pow(sumatoriaY, 2)
gradienteResultante = int(math.sqrt(gxalcuadrado+gyalcuadrado))
pixelNuevo=gradienteResultante
if pixelNuevo> 255:
pixelNuevo = 255
if pixelNuevo < 0:
pixelNuevo = 0
pixeles[y,x] = ( pixelNuevo, pixelNuevo, pixelNuevo)
image.save('convo1sal.png', 'png')
#image.show()
if matrizagarrada==2:
for x in range(altura):
for y in range(ancho):
sumatoriaX = 0
sumatoriaY = 0
if x != 0 and y != 0 and y != ancho and x != altura:
for i in range(tamanomatriz):
for j in range(tamanomatriz):
try:
gx = prewittX[i][j]*pixeles[y+j, x+i][1]
gy = prewittY[i][j]*pixeles[y+j, x+i][1]
except:
productosGX = 0
productosGY = 0
sumatoriaX = gx+sumatoriaX
sumatoriaY = gy+sumatoriaY
gxalcuadrado = pow(sumatoriaX, 2)
gyalcuadrado = pow(sumatoriaY, 2)
gradienteResultante = int(math.sqrt(gxalcuadrado+gyalcuadrado))
pixelNuevo=gradienteResultante
if pixelNuevo> 255:
pixelNuevo = 255
if pixelNuevo < 0:
pixelNuevo = 0
pixeles[y,x] = ( pixelNuevo, pixelNuevo, pixelNuevo)
# image.save('rayitas.png', 'png')
# image.show()
#FOTO BINARISARLA
image = Image.open("convo1sal.png")
pixeles = image.load()
ancho, altura =image.size
minimoo=34
for x in range(ancho):
for y in range(altura):
if pixeles[x,y][1] < minimoo:
prom=255
else:
prom= 0
pixeles[x,y] = (prom,prom,prom)
image.save('convo1convbinar.png', 'png')
#image.show()
# DIFERENCIA SE PEGO AQUI MISMO PARA EVITAR PONERMAS CUADROS DE CODIGO
import math
import sys
import os
import Image, ImageDraw, ImageFont
import random
import pygame
from pygame.locals import *
import Image
import math
import pygame
from pygame.locals import *
imagen1 = Image.open("convo1sal.png")
pixeles1 = imagen1.load()
ancho1, altura1 =imagen1.size
imagen2 = Image.open("convo2salcomparacion.png")
pixeles2 = imagen2.load()
ancho2, altura2 =imagen2.size
imagen3 = Image.new("RGB", (ancho1, altura1))
pixeles3 = imagen3.load()
for x in range(altura1):
for y in range(ancho1):
contador = 0
for i in range(-2,3):
for j in range(-2,3):
if y+a >= 0 and y+a < ancho1 and x+j >= 0 and x+j < altura1:
resta = abs(pixeles1[y+i,x+j][0] - pixeles2[y+i,x+j][0])
if resta == 0:
contador= 1
if contador == 1:
pixeles3[y,x] = (0,0,0)
else:
resta = abs(pixeles1[y,x][0] - pixeles2[y,x][0])
if resta != 0:
pixeles3[y,x] = (255,255,255)
nueva.save("diferencia.jpg")
view raw gistfile1.py hosted with ❤ by GitHub


XXX




 




vv



import math
import sys
import os
import Image, ImageDraw, ImageFont
import random
import pygame
from pygame.locals import *
import Image
import math
import pygame
from pygame.locals import *
fuente =ImageFont.truetype("/usr/share/fonts/truetype/freefont/FreeSansBold.ttf", 20)
imagen1 = Image.open("convo1sal.png")
pixeles = imagen1.load()
ancho, altura =imagen1.size
imagen2 = Image.open("convo2salcomparacion.png")
pixeles2 = imagen2.load()
ancho2, altura2 =imagen2.size
imagen3 = Image.new("RGB", (ancho, altura))
pixeles3 = imagen3.load()
for i in range(altura):
for j in range(ancho):
if pixeles2[j,i][0] != 0:
if pixeles[j,i] == pixeles2[j,i]:
pixeles3[j,i] = (0,0,0)
else:
pixeles3[j,i] = (255,255,255)
else:
pixeles3[j,i] = (0,0,0)
imagen3.save("deteccion.jpg")
imagen1 = Image.open("deteccion.jpg")
pixeles = imagen1.load()
ancho, altura =imagen1.size
imagen2 = Image.open("difer.jpg")
pixeles2 = imagen2.load()
ancho2, altura2 =imagen2.size
imagen3 = Image.new("RGB", (ancho, altura))
pixeles3 = imagen3.load()
draw = ImageDraw.Draw(imagen3)
for x in range(altura2):
for y in range(ancho2):
i = 1
j = 0
exit = 0
if pixeles2[y,x][0] == 255:
while i < ancho2:
if y+i >= 0 and y+i < ancho-10 and x+j >= 0 and x+j < altura-10:
if pixeles[y+i,x][0] != 0:
exit = i
pixeles[y+i,x] = (0,0,0)
i = ancho2
break
if y-i >= 0 and y-i < ancho-10 and x+j >= 0 and x+j < altura-10:
if pixeles[y-i,x][0] != 0:
exit = i
pixeles[y-i,x] = (0,0,0)
i = ancho2
break
i += 1
if exit != 0:
draw.line((y, x, y+ exit, x), fill=255)
imagen3.save("salida.jpg")
view raw gistfile1.py hosted with ❤ by GitHub

Se divide la imagen en cuadrantes 


def cuadrante(image, movimient, tamano = 15):
enX = ancho / tamano
enY = altura / tamano
cuadrado = tamano*tamano
pixeles = cv2_array(movimiento).copy()
color, h=None,1
for x in range(enX):
for y in range(enY):
primerp1 = x*tamano, y*tamano
segundop2 = (x + 1)*tamano, (y + 1)*tamano
tmp = ocupados(pixeles, primerp1, segundop2)
Rect = (primerp1[0], primerp1[1], segundop2[0], segundop2[1])
if tmp > 0:
h = 2
color = (0, 255, 0)
else:
h = 1
color = (128, 128, 128)
draw.line((primerp1, (segundop2[0], primerp1[1])), color, width = h)
draw.line(((segundop2[0], primerp1[1]), segundop2), color, width = h)
draw.line((segundop2, (primerp1[0], segundop2[1])), color, width = h)
draw.line(((primerp1[0], segundop2[1]), primerp1), color, width = h)
pygame.display.update()
return image, centrar(pixeles, (255))
view raw gistfile1.py hosted with ❤ by GitHub


Lo siguiente es que ya teniendo donde hubo movimiento regresamos a la segunda imagen donde ocurrió movimiento 

Una ves que se conoce los pixeles donde hubo cambio y su posición , regresamos a la imagen esa
y se pinta el cuadrante de verde donde hubo movimiento de el pixel inicial al pixel final en cada frame.



 

Aquí arriba se muestran los resultados obtenidos, por cuestiones técnicas no se pudo descargar algún programa para grabar la pantalla ya que en FIME no lo permitía , y la que se empezó a descargar eran 11 MB pero duro cerca de media hora y aun no pasaba de la mitad de carga, mas tarde si se puede conseguir este programa se pondrá aquí abajo el vídeo.

Aqui ya se agrego el video ,por falta de tiempo se decidió saltarse algunos frames pero este es el video.


Gracias



1 comentario: