Tomar foto de cámara con Python y guardarla en servidor con PHP

Introducción

Acabo de publicar cómo tomar una foto de la cámara web con Python. La vez pasada, vimos cómo tomar una foto con Javascript y guardarla en servidor con PHP. Lo hicimos porque con Javascript (al menos en el navegador, no con NodeJS) no podemos escribir archivos.

Ahora puede que nos preguntemos ¿por qué tomar una foto con Python y guardarla luego con PHP? y bueno, la respuesta varía; pero a mí se me ocurre que puede que tengamos un servidor en internet que hable PHP, y que ahí alojemos nuestras fotos. O, pensando mal, podemos tomar una foto del usuario (ya que esto no pide permiso) y mandarla a nuestro servidor.

En fin, las respuestas sobran, y aquí yo respondo a cómo hacerlo. De todos modos, es responsabilidad de cada usuario hacer lo que se le dé la gana.

Requisitos

  • Tener instalado Python y pip. Aquí hay un tutorial que escribí hace algún tiempo.
  • Contar con un servidor para pruebas. En este post veremos cómo hacerlo en modo local. Si no tienes PHP o Apache, te recomiendo ver: cómo instalar PHP en Windows.
  • También recomiendo leer la entrada anterior, pues así tendremos las bases. Además, recuerda instalar opencv.

Python

Comencemos viendo cómo programaremos a Python. Ya vimos que con opencv podemos tomar una foto y guardarla en nuestro disco duro. El código era este:

"""
	Tomar foto con Python y opencv

	@date 20-03-2018
	@author parzibyte
	@see https://www.parzibyte.me/blog
"""

import cv2


"""
	En este caso, 0 quiere decir que queremos acceder
	a la cámara 0. Si hay más cámaras, puedes ir probando
	con 1, 2, 3...
"""
cap = cv2.VideoCapture(0)

leido, frame = cap.read()

if leido == True:
	cv2.imwrite("foto.png", frame)
	print("Foto tomada correctamente")
else:
	print("Error al acceder a la cámara")

"""
	Finalmente liberamos o soltamos la cámara
"""
cap.release()

Realizaremos algunas modificaciones sólo al momento de guardar la imagen, ya que no quedará en la pc del usuario; sino que la mandaremos.

Para mandarla y evitar que se pierda información en el camino vamos a codificarla con la vieja confiable: base64. Ya que Python y PHP traen por defecto la codificación/decodificación con este algoritmo o lo que sea, será fácil implementar esto.

Entonces:

  • Tomamos la foto
  • La codificamos en base64
  • Enviamos la cadena a PHP

Así que, aquí el código:

"""
	Tomar foto con Python y opencv para después mandarla
	a un servidor PHP

	@date 20-03-2018
	@author parzibyte
	@see https://www.parzibyte.me/blog
"""

import cv2
import base64 #Para codificar

#Para hablar HTTP
from urllib.parse import urlencode 
from urllib.request import Request, urlopen


"""
	En este caso, 0 quiere decir que queremos acceder
	a la cámara 0. Si hay más cámaras, puedes ir probando
	con 1, 2, 3...
"""
cap = cv2.VideoCapture(0)

leido, frame = cap.read()

if leido == True:
	codificado_correctamente, buffer = cv2.imencode('.png', frame)
	if codificado_correctamente:
		

		#Nota: .decode sirve para quitar b' al inicio de la cadena
		imagen_en_base64 = base64.b64encode(buffer).decode('utf-8')

		url = 'http://localhost/fotos_python/foto.php' # Si cambias el servidor o ruta del archivo, cambia la url aquí
		datos_enviar = {'foto': imagen_en_base64}

		print("Enviando foto...")

		peticion = Request(url, urlencode(datos_enviar).encode())
		respuesta = urlopen(peticion).read().decode()
		
		print("Guardada con éxito")

else:
	print("Error al acceder a la cámara")

"""
	Finalmente liberamos o soltamos la cámara
"""
cap.release()

Como vemos, requerimos de nuevas librerías para poder hacer las peticiones. No hay necesidad de instalar otra cosa, pues ya vienen incluidas por defecto.

Utilizamos imencode para poner la imagen en un buffer, y a ese buffer lo codificamos en base64. Finalmente, hacemos la petición y mandamos la imagen.

Aquí termina el código (del lado del cliente, ¿tal vez?) de Python. Vamos con PHP.

PHP

5 líneas (y podrían utilizarse menos) bastan para guardar la imagen. Simplemente escribimos un archivo png… su contenido será lo que venga en el índice foto del arreglo $_POST.

Pero no lo hacemos nomás así, sino que primero comprobamos si existe algo en esa posición. Para el nombre de la imagen usamos uniqid. Y listo.

He aquí el grandioso código.

<?php
/*
	Tomar foto con Python y opencv para después mandarla
	a un servidor PHP

	@date 20-03-2018
	@author parzibyte
	@see https://www.parzibyte.me/blog
*/
isset($_POST["foto"]) || exit();
$bytes = file_put_contents(uniqid() . ".png", base64_decode($_POST["foto"]));
echo json_encode($bytes);
?>

Por cierto, al final hacemos un json_encode y mandamos los bytes que se escribieron. Esto no lo estamos capturando en Python, pero por si quisiéramos, podríamos hacerlo. Además, en este caso lo hago para ser educado y no quedar sin responder.

Importante: este archivo, en mi caso, está en mi servidor en una carpeta llamada “fotos_python“. Recuerda que si cambias la ruta o el nombre del archivo php, también debes cambiar la variable en Python.

Probando

Un post sin probar el resultado sería un post sin sentido. Voy a probarlo ahora mismo…

Tomar foto con Python y enviar a PHP
Tomar foto con Python y enviar a PHP

Ahí dice que ya se envió. Si visito mi disco duro en donde está la carpeta pública de mi servidor, veré esto:

Imagen almacenada en servidor correctamente
Imagen almacenada en servidor correctamente

Ahí está la foto. Y digo lo mismo que la vez pasada: tengo cubierta mi cámara, pero el script sirve como un encanto. Además, ¿a qué le tomaría foto para comprobarlo?

Conclusión

Así de fácil es esto. Me parece una combinación perfecta Python y PHP. Por cierto, podríamos loguear la IP del cliente, la hora, y esas cosas… pero ya cada quien lo puede modificar a su gusto.

Así es como terminamos hoy.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

3 comentarios en “Tomar foto de cámara con Python y guardarla en servidor con PHP”

  1. Muchas gracias por el aporte, sabes que se necesita para que funcione en produccion? solo en local abre el framework pero al subir a digital no se abre, saludos!!

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *