Je souhaite détecter des visages à partir d'images (vidéos) prises avec une caméra Web, avec React et Django
Lorsque vous tenez l'appareil photo, le visage sort de l'endroit où vous le tenez Cela peut être utile pour quelque chose de sécurité
Dernière fois La pièce déposée est remplacée par la caméra Web Pour cette raison, certains paramètres de sécurité sont nécessaires.
React
Dernière fois n'est pas différent J'ai ajouté le processus pour accéder à la caméra avec le constructeur Obtenir une image de la caméra? GetCameraImage est coupé Légèrement modifié le processus de réception de submitData
create-react-app user
index.js
import React from "react";
import ReactDOM from "react-dom";
const SERVER = "https://192.168.139.140:8000/image/"; //Poste de serveur
class App extends React.Component {
/**
* @param {json} props
*/
constructor(props) {
super(props);
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
this.state = {
video: document.createElement("video"),
canvas: canvas,
context: context
};
if (navigator.mediaDevices){
navigator.mediaDevices
.getUserMedia({ video: true, audio: false })
.then((stream) => {
this.state.video.srcObject = stream;
this.state.video.play();
this.state.video.onloadedmetadata = (e) => {
this.setState({width: this.state.video.videoWidth, height: this.state.video.videoHeight})
this.state.canvas.width = this.state.width;
this.state.canvas.height = this.state.height;
this.submitData();
};
})
.catch(function (error) {
console.error(error);
return;
});
}
}
/**
*Obtenir des jetons CSRF à partir des cookies
*/
getCSRFtoken() {
for (const c of document.cookie.split(";")) {
const cArray = c.split("=");
if (cArray[0] === "csrftoken") return cArray[1];
}
}
/**
*Obtenez une image de la caméra et convertissez-la en une chaîne de caractères pour l'envoi et la réception
* @return {str} base64
*/
getCameraImage() {
this.state.context.drawImage(
this.state.video,
0,
0,
this.state.width,
this.state.height
);
return this.state.canvas.toDataURL();
}
/**
*Envoyer des données au serveur
*/
submitData() {
this.setState({ image: this.getCameraImage() });
this.render();
// console.log("Envoyer", this.state);
fetch(SERVER + "res/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": this.getCSRFtoken()
},
body: JSON.stringify({
image: this.state.image //← Envoyer l'image
})
})
.then((res) => res.json())
.then((res) => {
console.log("Recevoir", res);
this.setState({ image: res.image, message: res.message }); //← Définir l'image
this.render();
setTimeout(() => this.submitData(), 1000); //Envoyer après 1 seconde
});
}
/**
*Bouton et envoyer / recevoir le rendu des données
*/
render() {
return (
<div>
<div className="image-element">
{this.state.image ? <img src={this.state.image} alt="image" /> : ""}
</div>
</div>
);
}
}
ReactDOM.render(
<React.StrictMode>
<App message={"Image"} />
</React.StrictMode>,
document.getElementById("root")
);
Copiez et collez du JS que j'ai écrit il y a presque longtemps
index.js
constructor(props) {
super(props);
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
this.state = { //Définir des éléments de canevas (pour le dessin d'image) et vidéo (pour la vidéo)
video: document.createElement("video"),
canvas: canvas,
context: context
};
if (navigator.mediaDevices){
navigator.mediaDevices
.getUserMedia({ video: true, audio: false })
.then((stream) => {
this.state.video.srcObject = stream; //Obtenez la vidéo de la caméra et mettez-la dans l'élément vidéo
this.state.video.play(); //Régénération(?)
this.state.video.onloadedmetadata = (e) => { //Une fois que les métadonnées peuvent être chargées
this.setState({width: this.state.video.videoWidth, height: this.state.video.videoHeight}) //Kit d'acquisition de taille
this.state.canvas.width = this.state.width; //Spécifiez la taille du canevas
this.state.canvas.height = this.state.height;
this.submitData(); //Envoyer au serveur
};
})
.catch(function (error) {
console.error(error);
return;
});
}
}
Si c'est lié à la vidéo, à la vidéo, aux métadonnées téléchargées ou à quelque chose qui sent la merde Je souffrais à mort en créant une application de visionnage de vidéos Si vous ne confirmez pas le chargement des métadonnées par ce processus, videoWidth etc. ne sera pas défini pour la vidéo Étonnamment, je suis toujours confus quant aux spécifications de taille ici la vidéo est video.videoWidth et canvas est canvas.width
Il semble y avoir attendre ces jours-ci
C'est aussi le même que celui que j'ai fait il y a longtemps
index.js
getCameraImage() {
this.state.context.drawImage(this.state.video, 0, 0, this.state.width, this.state.height);
return this.state.canvas.toDataURL();
}
Je pense que j'ai pu réduire de moitié la taille horizontale en faisant `` this.state.width / 2 '' (rappelez-vous) Ça n'avait pas de sens de le couper ici
Je voulais vérifier l'image de réponse, j'ai donc effectué la transmission suivante 1 seconde après avoir dessiné l'image de détection de visage.
index.js
submitData() {
this.setState({ image: this.getCameraImage() });
this.render();
// console.log("Envoyer", this.state);
fetch(SERVER + "res/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": this.getCSRFtoken()
},
body: JSON.stringify({
image: this.state.image //← Envoyer l'image
})
})
.then((res) => res.json())
.then((res) => {
console.log("Recevoir", res);
this.setState({ image: res.image, message: res.message }); //← Définir l'image
this.render();
setTimeout(() => this.submitData(), 1000); //Envoyer après 1 seconde
});
}
J'ai pensé à envoyer en appuyant sur un bouton, mais je viens de rendre le bouton et de poster l'événement.
Construisez ceci et comme d'habitude
{% csrf_token %}
{% load static %}
Au début de ʻindex.html`` et remplacez
" / `` par `` "{% static'image / '%} /
Quand j'ai vérifié plus tard, il y avait `` "/
`dans le processus js dans index.html, donc je veux éviter cela
Quand je mets ceci dans le serveur de précédent, `` navigator.mediaDevices.getUserMedia '' se plaint. Pour des raisons de sécurité, les navigateurs actuels ne peuvent pas accéder à la caméra à moins que index.html ne soit fourni avec la communication cryptée. Il est donc nécessaire d'installer SSL côté serveur
Django Introduire le SSL de développement sur le serveur
Ajout de pip django-sslserver
à précédent
python -m venv test
cd test
source bin/activate
pip install -U pip
pip install django opencv-python django-sslserver
django-admin startproject server
cd server
python manage.py startapp image
python manage.py migrate
openssl genrsa -out foobar.key 2048
openssl req -new -key foobar.key -out foobar.csr
openssl x509 -req -days 365 -in foobar.csr -signkey foobar.key -out foobar.crt
Presque identique à References
Changez le chemin car le chemin du dernier foobar.csr '' et
foobar.key '' a été généré au même endroit que manage.py.
De plus, au stade du développement, toutes les entrées après `ʻopenssl genrsa -out foobar.key 2048`` peuvent être effectuées avec Enter.
server/setting.py
ALLOWED_HOSTS = ["127.0.0.1"]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'image.apps.ImageConfig',
'sslserver', #Ajouter un serveur SSL
]
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = False
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
D'autres sont les mêmes que la dernière fois Je veux compléter cette page
server/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('image/', include('image.urls')),
]
image/urls.py
from django.urls import path
from . import views
app_name = 'urls'
urlpatterns = [
path('', views.Index, name='index'),
path('res/', views.Res, name='res'),
]
Mettez-vous dans `ʻimage / static`` haarcascade_frontalface_default.xml
views.py
from django.shortcuts import render
from django.http.response import JsonResponse
from django.http import HttpResponse
import json, base64
import numpy as np
import cv2
def Index(request):
return render(request, 'image/index.html')
def Res(request):
data = request.body.decode('utf-8')
jsondata = json.loads(data)
image_base64 = jsondata["image"]
encoded_data = image_base64.split(',')[1]
nparr = np.fromstring(base64.b64decode(encoded_data), np.uint8)
image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
face_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
face_cascade = cv2.CascadeClassifier("image/static/haarcascade_frontalface_default.xml")
faces = face_cascade.detectMultiScale(face_gray)
for x, y, w, h in faces: #Ecrire un rectangle dans la zone du visage
cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2)
result, dst_data = cv2.imencode('.png', image)
dst_base64 = base64.b64encode(dst_data).decode()
return JsonResponse({"image": "data:image/png;base64,"+dst_base64, "message": "Django"})
J'ai pu détecter mon visage maussade
La communication devient immédiatement gênante lorsque l'environnement du serveur entre
Il faudra du temps pour préparer le vrai serveur, alors commencez à jouer avec Heroku Je ne peux pas laisser React le faire, alors la prochaine fois, je veux créer quelque chose comme un babillard
@Syoitu, «Activez Django https en quelques lignes», 7 novembre 2019
Recommended Posts