前提・実現したいこと
pythonプログラムでaxios.jsのWebAPIで画像をアップロードしてレスポンスしたい。
参考URL:https://qiita.com/s-yoshiki/items/d4a460b2ab56e72220b9
環境
作業PC:windows10 64bit
サーバー:Windows10上、できればさくらVPS(Linux)上でも試したい。
python:3.7(Anaconda仮想環境)
ディレクトリ構成
index.html
html
1./ 2├── face_detect.py # 顔検出の処理 3├── index.py # リクエスト処理 4├── templates # html(テンプレート) 5│ └── index.html 6└── tmp # アップロードされた画像格納ディレクトリ 7 └── sample.jpg
該当のソースコード
html
1<html> 2 <head> 3 <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script> 4 </head> 5 <body> 6 <div class="container"> 7 <canvas id="canvas"></canvas> 8 <hr> 9 <label> 10 画像 11 <input type="file" class="form-control" id="image"> 12 </label> 13 <button id="run"> 14 submit 15 </button> 16 </div> 17 <script src="index.js"> 18 </script> 19 </body> 20</html>
index.js
js
1(function(){ 2 3 document.getElementById("run").addEventListener("click", function(){ 4 var params = new FormData(); 5 var file = document.getElementById("image").files[0] 6 7 params.append('image', file) 8 axios.post('/api', params).then(function(response) { 9 response.data.forEach((e) => { 10 var v = e.face 11 drawRect(v.x, v.y, v.w, v.h) 12 e.eyes.forEach((eye) => { 13 eye.x += v.x 14 eye.y += v.y 15 drawRect(eye.x, eye.y, eye.w, eye.h) 16 }) 17 }) 18 }).catch(function(error) { 19 alert("error") 20 }); 21 }) 22 23 document.getElementById("image").addEventListener("change", function(e) { 24 var file = e.target.files; 25 var reader = new FileReader(); 26 reader.readAsDataURL(file[0]); 27 reader.onload = function() { 28 var source = reader.result; 29 drawImage(reader.result) 30 } 31 }, false); 32 33 function drawImage(src) { 34 var canvas = document.getElementById("canvas") 35 var context = canvas.getContext('2d') 36 var image = new Image() 37 image.src = src; 38 image.onload = function() { 39 canvas.width = image.width 40 canvas.height = image.height 41 context.drawImage(image, 0, 0) 42 } 43 } 44 45 function drawRect(x, y, w, h) { 46 var canvas = document.getElementById("canvas") 47 var context = canvas.getContext('2d') 48 context.rect(x, y, w, h); 49 context.stroke(); 50 } 51})()
index.py
python
1import os,sys 2from flask import Flask, render_template, request, jsonify 3from jinja2 import FileSystemLoader 4import base64 5 6from face_detect import get_facepos 7 8app = Flask(__name__) 9 10app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024 11app.config['UPLOAD_FOLDER'] = './tmp' 12 13@app.route("/", methods=['GET']) 14def get_index(): 15 return render_template('index.html') 16 17@app.route("/api", methods=['POST']) 18def face_detect(): 19 img = request.files['image'] 20 name = img.filename 21 path = os.path.join(app.config['UPLOAD_FOLDER'], name) 22 img.save(path) 23 face_pos = get_facepos(path) 24 return jsonify(face_pos)
face_detect.py
python
1import numpy as np 2import cv2 3 4def get_facepos(img_path): 5 face_cascade = cv2.CascadeClassifier('/path/to/haarcascade_frontalface_default.xml') 6 eye_cascade = cv2.CascadeClassifier('/path/to/haarcascades/haarcascade_eye_tree_eyeglasses.xml') 7 8 img = cv2.imread(img_path) 9 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 10 faces = face_cascade.detectMultiScale(gray, 1.3, 5) 11 12 result = [] 13 for (x,y,w,h) in faces: 14 face_dst = { 15 "x": np.asscalar(x), 16 "y": np.asscalar(y), 17 "w": np.asscalar(w), 18 "h": np.asscalar(h) 19 } 20 eyes_dst = [] 21 roi_gray = gray[y:y+h, x:x+w] 22 eyes = eye_cascade.detectMultiScale(roi_gray) 23 for (ex,ey,ew,eh) in eyes: 24 eye_pos = { 25 "x": np.asscalar(ex), 26 "y": np.asscalar(ey), 27 "w": np.asscalar(ew), 28 "h": np.asscalar(eh) 29 } 30 eyes_dst.append(eye_pos) 31 result.append({ 32 "face": face_dst, 33 "eyes": eyes_dst 34 }) 35 return result
試したこと
①haarcascade_eye_tree_eyeglasses.xmlら2つのpathは自身の環境のcv2の中のどこに存在しているかチェックし記載しなおしました。
②
index.py
python
1if __name__ == "__main__": 2 app.run(port=8888)
上記をindex.pyの下部に追記して、
$ python index.py を実行しhttp://localhost:8888をブラウザ実行しました。
cmd
1 * Serving Flask app "index" (lazy loading) 2 * Environment: production 3 WARNING: This is a development server. Do not use it in a production deployment. 4 Use a production WSGI server instead. 5 * Debug mode: off 6 * Running on http://127.0.0.1:8888/ (Press CTRL+C to quit)
しかし、画面は出るものの、画像をアップロードすることができませんでした。
③この他、jsの場所をjsフォルダに変えることも行いましたが、結果は同じでした。
どのポイントを調べれば原因がわかりますでしょうか。どのようにしたら実現できるか教えて頂けないでしょうか。
また、さくらVPSなどのLinuxに配置する場合、このディレクトリ構造ではなく、/var/www/html/にindex.htmlを配置することにあるかと思うのですが、その際のディレクトリはどういった形態になるものなのでしょうか。
よろしくお願い致します。
2020/05/06 21:58追記
ローカル実行についてその後アドバイス頂いたstaticフォルダの中にindex.jsを置いて
js
1<script src="{{url_for('static', filename = 'index.js')}}">
に変更し以下コマンドを実行したところ、
cmd
1D:\work\unittest\face>python index.py
以下結果に変わりました。
ブラウザはEdge。
F12キーを使用し要求と応答ヘッダーやコンソールを確認しました。
2020/05/06 22:39
申し訳ありません。face_detect.pyを少し変えてしまった結果を追記してしまいました。正しくは以下になります。
500エラーはないのですが、errorとサイトからメッセージダイアログが出ている状態になります。
2020/05/06 追記
ローカルでの実行では解決できました。原因が以下でした。
①上記指摘頂いたjsの置き場やhtmlのコード
②face_detect.pyにreturnがなかったこと
face_detect.pyの最後の行に以下を追加。
python
1return result
あとはLinuxでの実行方法は別質問にさせて一度完了とします。
ありがとうございました。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/06 11:35
2020/05/06 11:59 編集
2020/05/06 12:33
2020/05/06 13:25
2020/05/06 13:38
2020/05/06 14:07
2020/05/06 21:24 編集
2020/05/07 02:06