@eiki828

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Djangoの機能追加

解決したいこと

DjangoのコードにJavaScriptの追加をするとエラーが発生する

Djangoで、クイズのアプリを作成しています。
その過程で、JavaScriptの顔認識機能を作成しましたが作動しません

発生している問題・エラー

Failed to load resource: the server responded with a status of 404 (Not Found)
face-api.min.js:1 
        
        
       Failed to load resource: the server responded with a status of 404 (Not Found)
1/:1 Refused to execute script from 'http://127.0.0.1:8000/students/quiz/1/js/face-api.min.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
1/:1 Refused to execute script from 'http://127.0.0.1:8000/students/quiz/1/js/script.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
31/:89 Uncaught ReferenceError: OnButtonClick is not defined
    at HTMLInputElement.onclick (1/:89:63)

または、問題・エラーが起きている画像をここにドラッグアンドドロップ

該当するソースコード

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  <div class="progress mb-3">
    <div class="progress-bar" role="progressbar" aria-valuenow="{{ progress }}" aria-valuemin="0" aria-valuemax="100" style="width: {{ progress }}%"></div>
  </div>
  <h2 class="mb-3">{{ quiz.name }}</h2>
  <p class="lead">{{ question.text }}</p>
  <form method="post" novalidate>
    {% csrf_token %}
    {{ form|crispy }}
    <button type="submit" class="btn btn-primary">Next →</button>
  </form>
{% endblock %}

上記のコードに、以下のコードを追加しようと試みています

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>media element</title>
  <script src="js/face-api.min.js" type="text/javascript"></script>
  <script src="js/script.js" type="text/javascript"></script>
  <style>
    div.wait{
      margin:0;
      padding:0;
      box-sizing:border-box;
      position:fixed;
      width:100vw;
      height:100vh;
      left:0;
      top:0;
      right:0;
      bottom:0;
      display:none;
      background:rgba(255,255,255,0.8);
      z-index:30000;
      font-size:18px;
    }
    div.wait>img{
      position:relative;
      display:block;
      left:50%;
      top:50%;
      transform:translate(-50%,-50%);
    }
    #preview{
      max-width:100%;
      width:640px;
      height:auto;
    }
    #back{
      max-width:100%;
      width:800px;
      height:auto;
      background:rgba(255,255,255,0.8);
    }
  </style>
</head>
<body>
  <div class="wait"><img src="./img/loading.gif"></div>
  <input type="button" value="開始" onclick="OnButtonClick();"/><br />
  <div style="position: relative;">
    <canvas id="back" width="800" height="600" style="position: absolute; top: 0px; left: 0px;"></canvas>
    <video id="video" width="640" height="480" style="position: absolute; top: 60px; left: 80px; transform: scaleX(-1);"></video>
    <canvas id="preview" width="640" height="480" style="position: absolute; top: 60px; left: 80px; transform: scaleX(-1);"></canvas>
  </div>
</body>
</html>
var video,prev,prev_ctx,prevW,prevH;
var detect;
var irisC = [];
let nowBlinking = false;
let blinkCount = 0;

async function loadImage(src){
  return new Promise(function(resolve,reject){
    let img=new Image();
    img.onload=function(){resolve(img);}
    img.onerror=function(e){reject(e);}
    img.src=src;
  });
}

window.addEventListener('DOMContentLoaded',async function(event){
  //ロード中画像の表示
  ShowWait();

  detect=0;
  prev=document.querySelector("#preview");
  prev_ctx=prev.getContext("2d" ,{willReadFrequently:false});

  back=document.querySelector("#back");
  back_ctx=back.getContext("2d" ,{willReadFrequently:false});

  //alert=document.querySelector("#alert");
  //alert_ctx=back.getContext("2d" ,{willReadFrequently:false});

  // 画像読み込み
  mAlertImage = new Image();
  if(mAlertImage){
    mAlertImage.src = "/img/alert.png";
  }

  // 音声読み込み
  mBlinkSound = new Audio("/sound/alert.mp3");

  await Promise.all([
    //顔認識とランドマーク用の学習モデルを読み込む
    faceapi.nets.tinyFaceDetector.loadFromUri('./models'),
    faceapi.nets.faceLandmark68TinyNet.loadFromUri("./models"),
  ]);

  //<video>エレメントの取得と設定
  video = document.getElementById("video");
  video.setAttribute("autoplay","");
  video.setAttribute("muted","");
  video.setAttribute("playsinline","");
  video.onloadedmetadata = function(e){video.play();};

  prev=document.getElementById("preview");
  prev_ctx=prev.getContext("2d", {willReadFrequently:true,alpha:false});

  //左右反転表示させる
  prev.style.transform="scaleX(-1)";

  //ロード中画像の非表示
  HideWait();
});

function OnButtonClick() {
  //カメラ使用の許可ダイアログが表示される
  navigator.mediaDevices.getUserMedia(
    //マイクはオフ, カメラの設定   前面カメラを希望する 640×480を希望する
    //参考:背面は"environment"、全面は"user"
    {"audio":false,"video":{"facingMode":"user","width":{"ideal":640},"height":{"ideal":480}}}
  ).then( //許可された場合
    function(stream){
      video.srcObject = stream;
      //0.5秒後にスキャンする
      setTimeout(Scan,500,true);
    }
  ).catch(
    //許可されなかった場合
    function(){
      //ロード中画像の非表示
      HideWait();
    }
  );
}

async function Scan(first){
  if(first){
    //初回のみ設定を行う(最終的に選択されたカメラ映像のサイズが不明の為)
    //選択された幅高さ
    prevW=video.videoWidth;
    prevH=video.videoHeight;
    //内部のサイズ
    prev.setAttribute("width",prevW);
    prev.setAttribute("height",prevH);
    //ロード中画像の非表示
    HideWait();
  }

  //  webカメラの映像から顔検出を行う
  const useTinyModel = true;
  const detection = await faceapi.detectSingleFace(
      video , 
      new faceapi.TinyFaceDetectorOptions({
        inputSize:160,      //検出する最大ピクセル数、32だと最大で32x32ピクセルの顔まで検出する
      })
  ).withFaceLandmarks(true);

    prev_ctx.clearRect(0, 0, prevW, prevH);
    prev_ctx.drawImage(video,0,0,prevW,prevH);
    var frame = prev_ctx.getImageData(0,0,prevW,prevH);

  if(detection){
    //アラート非表示
    HideAlert();
    detect=0;
    // 背景を青にする
    document.getElementById('back').style.backgroundColor = "blue";

    // 認識データをリサイズ
    const resizedDetection = faceapi.resizeResults(detection, {
      width: video.width,
      height: video.height,
    });
    // ランドマークをキャンバスに描画
    faceapi.draw.drawFaceLandmarks(prev, resizedDetection);

    // 以後使用するランドマーク座標
    const landmarks = resizedDetection.landmarks;

    //const nose = landmarks.getNose()[3];
    //const leftEye = landmarks.getLeftEye()[0];
    //const rightEye = landmarks.getRightEye()[3];
    //const jaw = landmarks.getJawOutline()[8];
    //const leftMouth = landmarks.getMouth()[0];
    //const rightMouth = landmarks.getMouth()[6];
    //const leftOutline = landmarks.getJawOutline()[0];
    //const rightOutline = landmarks.getJawOutline()[16];

    const landmarkPositions = landmarks.positions;

    //--- Iric mark ---//
    //ctx_bg.clearRect(0, 0, canvas_bg.width, canvas_bg.height)
    var x_ = landmarkPositions[38-1].x
    var y_ = landmarkPositions[38-1].y
    var w_ = landmarkPositions[39-1].x - landmarkPositions[38-1].x
    var h_ = landmarkPositions[42-1].y - landmarkPositions[38-1].y
    //ctx_bg.fillStyle = "rgb(255,0,0)";
    //ctx_bg.fillRect(x_, y_, w_, h_)

    x_ = landmarkPositions[44-1].x
    y_ = landmarkPositions[44-1].y
    w_ = landmarkPositions[45-1].x - landmarkPositions[44-1].x
    h_ = landmarkPositions[48-1].y - landmarkPositions[44-1].y
    //ctx_bg.fillRect(x_, y_, w_, h_)

    //--- Iris value ---//
    var p_ = Math.floor(x_+w_/2) + Math.floor(y_+h_/2) * video.width
    //console.log("eye_RGB:"+[frame.data[p_*4+0], frame.data[p_*4+1], frame.data[p_*4+2]]);
    var v_ = Math.floor( (frame.data[p_*4+0] + frame.data[p_*4+1] + frame.data[p_*4+2])/3 );
    //console.log("irisC:"+v_);

    irisC.push(v_);
    if(irisC.length>100){
        irisC.shift();
    }//

    let meanIrisC = irisC.reduce(function(sum, element){
      return sum + element;
    }, 0);
    meanIrisC = meanIrisC / irisC.length;
    let vThreshold = 1.5;

    let currentIrisC = irisC[irisC.length-1];
    if(irisC.length==100){
       if(nowBlinking==false){
          if(currentIrisC>=meanIrisC*vThreshold){
              nowBlinking = true;
              if(mBlinkSound){
                mBlinkSound.pause();
              }
              // 背景を青にする
              document.getElementById('back').style.backgroundColor = "blue";
          }//
       }//
       else{
          if(currentIrisC<meanIrisC*vThreshold){
              nowBlinking = false;
              blinkCount += 1;
              if(mBlinkSound){
                if(mBlinkSound.paused){
                  mBlinkSound.currentTime = 0;
                  mBlinkSound.play();
                }
              }
              // 背景を紫にする
              document.getElementById('back').style.backgroundColor = "purple";
          }//
       }//

    }//


  }else{
    detect=detect+1;

    if(detect>50){
      // 背景色を赤にする
      document.getElementById('back').style.backgroundColor = 'red';
      //アラート表示
      ShowAlert();
    }else if(detect>10){
      // 背景色を黄にする
      document.getElementById('back').style.backgroundColor = 'yellow';
    }
  }
  setTimeout(Scan,50,false);
}

function drawPath(arr,ctx,lineWidth,color){
  ctx.lineWidth=lineWidth;
  ctx.strokeStyle=color;
  ctx.beginPath();
  ctx.moveTo(arr[0].x,arr[0].y);
  for(let i=1;i<arr.length;i++){
    ctx.lineTo(arr[i].x,arr[i].y);
  }
  ctx.stroke();
}



function ShowWait(){
  document.querySelector(".wait").style.display="block";
}
function HideWait(interval){
  setTimeout(function(){
    document.querySelector(".wait").style.display="none";
  },interval);
}

function ShowAlert(){
  //alert.style.visibility="visible";
  //alert_ctx.drawImage(mAlertImage, 0, 0, 800, 600);
  if(mAlertImage){
    prev_ctx.drawImage(mAlertImage, 0, 0, 640, 480);
  }
  if(mBlinkSound.paused){
    mBlinkSound.currentTime = 0;
    mBlinkSound.play();
  }
}
function HideAlert(interval){
  //alert.style.visibility="hidden";
  //alert_ctx.clearRect(0, 0, 800, 600);
  prev_ctx.clearRect(0, 0, 640, 480);
  mBlinkSound.pause();
}

自分で試したこと

コードをDjangoに対応できるように、{% extends 'base.html' %}{% load crispy_forms_tags %}{% block content %}を追加しました。
また、対応するJavaScriptのフォルダを追加しました

0 likes

2Answer

Comments

  1. @eiki828

    Questioner

    すみません、解決したかったので複数の掲示板に載せました

Failed to load resource: the server responded with a status of 404 (Not Found)
face-api.min.js:1

<script src="js/face-api.min.js" type="text/javascript"></script>

find / -name face-api.min.js
でファイルの有無を確認しては?

0Like

Your answer might help someone💌