domingo, 15 de septiembre de 2013

Fotos con webcam usando Django 1.5 y JpegCam

Hola nuevamente

Tenia un poco abandonado mi blog, debido a razones de trabajo, hoy vengo nuevamente a hablarles de Django, el framework de Python, esta vez, vamos a ver cosas interesantes como el tomar una instantánea o fotografía desde nuestra webcam utilizando una librería de Flash y Javascript.

Jpegcam es un interesante componente de Flash/JavaScript para capturar y guardar imágenes desde la webcam del usuario. Se puede utilizar por ejemplo para permitir a los usuarios hacer una imagen de sí mismos como avatares, o para completar su perfil.

Es un widget que a través de flash muestra una vista en vivo de la webcam y botones con funciones Javascript asociadas  que puede capturar y enviar una imagen a un servidor en modo POST.

¿Qué debemos hacer?
  1. Descargar la ultima versión de Jpegcam y agrégalo a tu carpeta de statics en tu proyecto Django, esta consta de archivos que son: shutter.mp3, webcam.js, webcam.swf
  2. Editamos el archivo webcam.js y buscamos para configurar los path de swf_url y shutter_url. En mi caso:
              swf_url: '/static/jpegcam/webcam.swf'
             shutter_url: '/static/jpegcam/shutter.mp3'
          Y mas abajo en el archivo, aproximadamente en la linea 166, agregar el path:
             this.shutter_url = url ? url : '/static/jpegcam/shutter.mp3';
Ahora nos vamos a Django, quiero manifestar que esta guía esta hecha para personas que han programado con Django y tienen conocimientos básicos del framework.

Primero creamos nuestro modelo de datos, donde vamos a almacenar los datos de la persona a registrar y su fotografía.
models.py
from django.db import models
import os
def get_image_name(instance, filename):
f, ext = os.path.splitext(filename)
archivo = '%s%s' % (instance.cedula, ext)
return os.path.join('webcamimages', archivo) 
class Persona(models.Model):
"""docstring for Personal"""
cedula = models.CharField(max_length=10)
nombres = models.CharField(max_length=60)
apellidos = models.CharField(max_length=60)
foto = models.ImageField(upload_to=get_image_name, blank=True, null=True) 
def __unicode__(self):
return self.cedula 
@models.permalink
def get_absolute_url(self):
return ('persona', [str(self.id)]) 
def _get_full_name(self):
"Retorna los nombres completos de Persona"
return '%s %s' % (self.nombres, self.apellidos) 
full_name = property(_get_full_name)
Les explico un poco el modelo, primero tenemos una función llamada get_image_name, esta función nos sirve para llamar los archivos que subamos por la opción file del formulario, siempre tendrán el nombre del campo cedula con su extensión, si mi cédula es 12345 y estoy cargando el archivo foto.jpg, esta función lo renombrada y lo guardara como 12345.jpg en la carpeta webcamimages dentro de media.
foto = models.ImageField(upload_to=get_image_name, blank=True, null=True) 
Ahora nos vamos a nuestro url.py, donde tenemos estas dos entradas:
url(regex=r'^persona/$',
     view= PersonaCreateView.as_view(),
         name='add_persona'
    ),
url(regex=r'^save_image/(?P<cedula>\d+)/$',
     view=SaveImage.as_view(),
      name='salvar_imagen'
),

La que nos interesa en este momento es la de save_image, ya que es la url que usaremos para tomar la fotografía, la otra es para que el formulario guarde la información dada.

Ahora crearemos nuestro views.py
from django.views.generic import TemplateView, CreateView, DetailView, ListView
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.conf import settings
from .models import Persona

class SaveImage(TemplateView): 
@csrf_exempt
def dispatch(self, *args, **kwargs):
self.filename = self.kwargs['cedula']+'.jpg'
return super(SaveImage, self).dispatch(*args, **kwargs) 
def post(self, request, *args, **kwargs): # save it somewhere
f = open(settings.MEDIA_ROOT + '/webcamimages/'+ self.filename, 'wb')
f.write(request.body)
f.close()
# return the URL
return HttpResponse("/media/webcamimages/" + self.filename) 
def get(self, request, *args, **kwargs):
return HttpResponse('No esta pasando el POST')

class PersonaCreateView(CreateView):
model = Persona
template_name = 'home/add_persona.html' 
def form_valid(self, form):
form.instance.foto = 'webcamimages/'+ form.instance.cedula + ".jpg"
return super(PersonaCreateView, self).form_valid(form)

Como ven, tenemos dos clases, la primera SaveImage, que es la que nos toma la instantánea y la guarda en la carpeta webcamimages con la cédula de la persona, la otra es la que guarda en base de datos y toma la dirección donde esta guardada la imagen y la agrega en el campo foto.

Ahora hacemos el html, llamado en nuestro caso add_persona.html
{% extends "base.html" %}
{% block extra_css %}
<!-- Primero, incluir la libreria de JpegCam -->
<script type="text/javascript" src="{{ STATIC_URL }}jpegcam/webcam.js"></script>
{% endblock extra_css %}
{% block contenido %}
<h1>Registrar Persona</h1>
<form class="span10" action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="row well">
<div class="span6">
<div class="control-group">
<label for="cedula" class="control-label">
Cedula:
</label>
<div class="controls">
<input name="cedula" type="text" value="" id="cedula">
<span class="help-inline">  Escriba su Cedula de Identidad</span>
</div>
</div>
<div class="control-group">
<label for="nombres" class="control-label">
Nombres:
</label>
<div class="controls">
<input name="nombres" type="text" value="" id="nombres">
</div>
</div>
<div class="control-group">
<label for="apellidos" class="control-label">
Apellidos:
</label>
<div class="controls">
<input name="apellidos" type="text" value="" id="apellidos">
</div>
</div>
<div class="control-group">
<label for="foto" class="control-label">
Foto:
</label>
<div class="controls">
<input name="foto" type="file" value="" id="foto">
<a href="#takephoto" role="button" data-toggle="modal" class="btn btn-warning">Tomar Foto</a>
</div>
</div>
</div>
<div class="span3" id="fotoview">
</div>
</div>
<button type="submit" class="btn btn-primary pull-right">Guardar</button>
</form>
<!-- Advanced Modal -->
<div id="takephoto" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
   <h3 id="myModalLabel">Camara</h3>
</div>
<div class="modal-body">
<!-- Configure a few settings -->
<script language="JavaScript">
document.write( webcam.get_html(320, 240) );
</script>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cerrar</button>
<button class="btn btn-primary" onClick="take_snapshot()" >Fotografíar</button>
</div>
</div>
{% endblock contenido %}

Lo primero es cargar la librería jpegcam.js, luego creamos nuestro formulario, aquí estoy usando bootstrap para ayudarme con los estilos, utilizo una ventana modal para activar la cámara y tomar la fotografía. Aquí algunos captura de pantalla de la aplicación final:



Y listo, quiero manifestar que hay formas de utilizar la cámara sin usar flash, el cual esta muy cuestionado por el tema de seguridad, mas esto les puede servir en un entorno empresarial, esta aplicación la pueden descargar desde github es este enlace, Espero sus recomendaciones y mejoras.

Saludos



No hay comentarios:

Publicar un comentario