[LINUX] Ein Memo, das das Gesicht des mit Djangos OpenCV von der Webkamera aufgenommenen Bilds erkennt und zurückgibt.

Hintergrund

Ich möchte Gesichter aus Bildern (Videos) erkennen, die mit einer Webkamera aufgenommen wurden, mit React und Django

image.png 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

Methodik

Letztes Mal Der abgelegte Teil wird durch die Webkamera ersetzt Aus diesem Grund sind einige Sicherheitseinstellungen erforderlich. image.png

Implementierung

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")
);

Prozess zum Zugriff auf die Webkamera

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

Funktion zum Abrufen eines Bildes von der Kamera

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

Senden und Empfangen

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

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

Vorbereitung

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"})

Ergebnis

image.png Ich konnte mein launisches Gesicht erkennen

Fazit

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

Verweise

@Syoitu, "Django https in wenigen Zeilen aktivieren", 7. November 2019

Recommended Posts

Ein Memo, das das Gesicht des mit Djangos OpenCV von der Webkamera aufgenommenen Bilds erkennt und zurückgibt.
Holen Sie sich ein Bild von einer Webseite und ändern Sie die Größe
Ein Memo, das mit Python & Spark Daten aus dashDB liest
Ein Server, der mit Flasche.py und OpenCV die Anzahl der Personen vor der Kamera zurückgibt
Erstellen Sie mit turicreate eine API, die Daten aus einem Modell zurückgibt
Ich habe einen Linienbot erstellt, der das Geschlecht und das Alter einer Person anhand des Bildes errät
Versuchen Sie, mit Python3 eine Zeichenfolge aus einem Bild zu extrahieren
Gesichtserkennung aus mehreren Bilddateien mit openCV, ausschneiden und speichern
Ein Python-Programm, das die Größe eines Videos ändert und es in ein Bild verwandelt
Ein Memo mit Python2.7 und Python3 in CentOS
Ich habe versucht, die Strichzeichnung mit Deep Learning aus dem Bild zu extrahieren
Memo, mit dem ein Diagramm zum Plotten animiert wurde
Entwickeln Sie eine Web-API, die in DB gespeicherte Daten mit Django und SQLite zurückgibt
Konvertieren Sie Bilder aus dem FlyCapture SDK in ein Formular, das mit openCV verwendet werden kann
Erstellen Sie mit OpenCV und Python (Mertens, Robertson, Debevec) ein High Dynamic Range Image (HDR).
Beachten Sie, dass VSCode + Python einen interaktiven Anzeigemodus wie Jupyter Notebook verwendet
Ein Memo, dass ich den Datenspeicher mit Python berührt habe
"Ein Buch, das Flask von Grund auf versteht" Memo lesen
So nehmen Sie ein aufgenommenes Bild aus einem Video auf (OpenCV)
[Python] Webkamera-Rahmengröße und FPS-Einstellungen mit OpenCV
Lern-Roadmap, mit der Sie Services mit Python von Grund auf neu entwickeln und veröffentlichen können
Ein Beispiel für einen Mechanismus, der eine Vorhersage von HTTP aus dem Ergebnis des maschinellen Lernens zurückgibt
Schritte zum Erstellen eines Jobs, der ein Docker-Image abruft und mit Github-Aktionen testet