Ich möchte Gesichter aus Bildern (Videos) erkennen, die mit einer Webkamera aufgenommen wurden, mit React und Django
Wenn Sie die Kamera gedrückt halten, kommt das Gesicht dort heraus, wo Sie es halten Es könnte für etwas Sicherheit nützlich sein
Letztes Mal Der abgelegte Teil wird durch die Webkamera ersetzt Aus diesem Grund sind einige Sicherheitseinstellungen erforderlich.
React
Letztes Mal ist nicht anders Ich habe den Prozess hinzugefügt, um mit dem Konstruktor auf die Kamera zuzugreifen Ein Bild von der Kamera bekommen? GetCameraImage ist ausgeschnitten Der Empfangsprozess von submitData wurde leicht geändert
create-react-app user
index.js
import React from "react";
import ReactDOM from "react-dom";
const SERVER = "https://192.168.139.140:8000/image/"; //Serverpost
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;
});
}
}
/**
*Holen Sie sich CSRF-Token von Cookies
*/
getCSRFtoken() {
for (const c of document.cookie.split(";")) {
const cArray = c.split("=");
if (cArray[0] === "csrftoken") return cArray[1];
}
}
/**
*Holen Sie sich ein Bild von der Kamera und konvertieren Sie es zum Senden und Empfangen in eine Zeichenfolge
* @return {str} base64
*/
getCameraImage() {
this.state.context.drawImage(
this.state.video,
0,
0,
this.state.width,
this.state.height
);
return this.state.canvas.toDataURL();
}
/**
*Daten an Server senden
*/
submitData() {
this.setState({ image: this.getCameraImage() });
this.render();
// console.log("Senden", this.state);
fetch(SERVER + "res/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": this.getCSRFtoken()
},
body: JSON.stringify({
image: this.state.image //← Bild senden
})
})
.then((res) => res.json())
.then((res) => {
console.log("Erhalten", res);
this.setState({ image: res.image, message: res.message }); //← Bild einstellen
this.render();
setTimeout(() => this.submitData(), 1000); //Nach 1 Sekunde senden
});
}
/**
*Schaltfläche und Senden / Empfangen von Datenwiedergabe
*/
render() {
return (
<div>
<div className="image-element">
{this.state.image ? <img src={this.state.image} alt="Bild" /> : ""}
</div>
</div>
);
}
}
ReactDOM.render(
<React.StrictMode>
<App message={"Image"} />
</React.StrictMode>,
document.getElementById("root")
);
Kopieren und Einfügen von JS, das ich vor fast langer Zeit geschrieben habe
index.js
constructor(props) {
super(props);
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
this.state = { //Legen Sie die Elemente Canvas (für Bildzeichnung) und Video (für Video) fest
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; //Holen Sie sich ein Video von der Kamera und fügen Sie es in das Videoelement ein
this.state.video.play(); //Wiedergabe(?)
this.state.video.onloadedmetadata = (e) => { //Sobald die Metadaten geladen werden können
this.setState({width: this.state.video.videoWidth, height: this.state.video.videoHeight}) //Größenerfassungssatz
this.state.canvas.width = this.state.width; //Geben Sie die Größe der Leinwand an
this.state.canvas.height = this.state.height;
this.submitData(); //An Server senden
};
})
.catch(function (error) {
console.error(error);
return;
});
}
}
Wenn es sich um Video handelt, video.onloadedmetadata oder etwas, das nach Mist riecht Ich litt zu Tode, als ich eine Video-App machte Wenn Sie das Laden von Metadaten durch diesen Vorgang nicht bestätigen, wird videoWidth usw. nicht für Video festgelegt Überraschenderweise bin ich immer verwirrt über die Größenangabe hier Video ist video.videoWidth und canvas ist canvas.width
Es scheint in diesen Tagen zu warten
Dies ist auch das gleiche wie das, das ich vor langer Zeit gemacht habe
index.js
getCameraImage() {
this.state.context.drawImage(this.state.video, 0, 0, this.state.width, this.state.height);
return this.state.canvas.toDataURL();
}
Ich habe das Gefühl, dass ich die horizontale Größe halbieren konnte, indem ich "this.state.width / 2" ausführte (denken Sie daran) Es machte keinen Sinn, es hier herauszuschneiden
Ich wollte das Antwortbild überprüfen, also machte ich die nächste Übertragung 1 Sekunde nach dem Zeichnen des Gesichtserkennungsbildes.
index.js
submitData() {
this.setState({ image: this.getCameraImage() });
this.render();
// console.log("Senden", this.state);
fetch(SERVER + "res/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": this.getCSRFtoken()
},
body: JSON.stringify({
image: this.state.image //← Bild senden
})
})
.then((res) => res.json())
.then((res) => {
console.log("Erhalten", res);
this.setState({ image: res.image, message: res.message }); //← Bild einstellen
this.render();
setTimeout(() => this.submitData(), 1000); //Nach 1 Sekunde senden
});
}
Ich habe über das Senden per Knopfdruck nachgedacht, aber ich habe nur den Knopf gerendert und das Ereignis gepostet.
Bauen Sie dies und wie gewohnt
{% csrf_token %}
{% load static %}
Am Anfang von index.html
und ersetzen Sie "/` `durch` `" {% static'image / '%} /
Als ich später nachgesehen habe, gab es im js-Prozess in index.html `` "/
, also möchte ich das vermeiden
Wenn ich dies auf den Server von previous schiebe, beschwert sich navigator.mediaDevices.getUserMedia
.
Aus Sicherheitsgründen können aktuelle Browser nur dann auf die Kamera zugreifen, wenn index.html mit der verschlüsselten Kommunikation bereitgestellt wird.
Daher muss SSL auf der Serverseite installiert werden
Django Führen Sie Entwicklungs-SSL auf dem Server ein
Pip django-sslserver
zu [previous] hinzugefügt (https://qiita.com/Pizarro/items/d2bcc60da10e32d05887)
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
Fast das gleiche wie Referenzen
Ändern Sie den Pfad, da der Pfad der letzten foobar.csr
und foobar.key
an derselben Stelle wie manage.py generiert wurde.
In der Entwicklungsphase könnten alle Eingaben nach "openssl genrsa -out foobar.key 2048" mit Enter erfolgen.
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', #SSL-Server hinzufügen
]
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = False
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Andere sind die gleichen wie beim letzten Mal Ich möchte diese eine Seite vervollständigen
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'),
]
Setzen Sie Sie in 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: #Schreiben Sie ein Rechteck in den Gesichtsbereich
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"})
Ich konnte mein launisches Gesicht erkennen
Die Kommunikation wird sofort problematisch, wenn die Serverumgebung eintritt
Es wird einige Zeit dauern, bis der echte Server vorbereitet ist. Spielen Sie also mit Heroku Ich kann React nicht dazu bringen, also möchte ich das nächste Mal so etwas wie ein Schwarzes Brett machen
@Syoitu, "Django https in wenigen Zeilen aktivieren", 7. November 2019