【Python】顔画像をPOST 、 顔検出 、 canvasで顔にお絵かき【JS】
2018-07-1114 min read
目次
概要
「顔検出をして、顔に絵を描く」というもの。
具体的には、 顔写真の画像をAPIサーバへアップロードし、顔検出を行う。 サーバは顔座標を返し、それを元にcanvasでお絵かきする。
環境
フロント
html + JS + canvas axios.jsでAPIを叩く
サーバ
- Ubutnu 16.04
- Python + Flask
- OpenCV 3.2 など
アプリケーション
こんな感じになる。 とりあえず、顔に枠線を書いている。 画像の描画、顔へのお絵かきは全てJSで実装。 サーバ側は顔検出するだけ。
下記にソース。
フロント
ファイルが選択されたら、canvasに画像を描画。 ボタン押下時にPOST。
html
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
</head>
<body>
<div class="container">
<canvas id="canvas"></canvas>
<label>
画像
<input type="file" class="form-control" id="image">
</label>
<button id="run">
submit
</button>
</div>
<script src="index.js">
</script>
</body>
</html>
js
(function() {
document.getElementById('run').addEventListener('click', function() {
var params = new FormData();
var file = document.getElementById('image').files[0];
params.append('image', file);
axios.post('/api', params).then(function(response) {
response.data.forEach((e) => {
var v = e.face;
drawRect(v.x, v.y, v.w, v.h);
e.eyes.forEach((eye) => {
eye.x += v.x;
eye.y += v.y;
drawRect(eye.x, eye.y, eye.w, eye.h);
});
});
}).catch(function(error) {
alert('error');
});
});
document.getElementById('image').addEventListener('change', function(e) {
var file = e.target.files;
var reader = new FileReader();
reader.readAsDataURL(file[0]);
reader.onload = function() {
var source = reader.result;
drawImage(reader.result);
};
}, false);
function drawImage(src) {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var image = new Image();
image.src = src;
image.onload = function() {
canvas.width = image.width;
canvas.height = image.height;
context.drawImage(image, 0, 0);
};
}
function drawRect(x, y, w, h) {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.rect(x, y, w, h);
context.stroke();
}
})();
サーバ
サーバはPython + Flaskで実装。 顔画像処理はOpenCV、numpyで実装。
サンプル index.py
import os,sys
from flask import Flask, render_template, request, jsonify
from jinja2 import FileSystemLoader
import base64
from face_detect import get_facepos
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024
app.config['UPLOAD_FOLDER'] = './tmp'
@app.route("/", methods=['GET'])
def get_index():
return render_template('index.html')
@app.route("/api", methods=['POST'])
def face_detect():
img = request.files['image']
name = img.filename
path = os.path.join(app.config['UPLOAD_FOLDER'], name)
img.save(path)
face_pos = get_facepos(path)
return jsonify(face_pos)
face_detect.py
import numpy as np
import cv2
def get_facepos(img_path):
face_cascade = cv2.CascadeClassifier('/path/to/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('/path/to/haarcascades/haarcascade_eye_tree_eyeglasses.xml')
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
result = []
for (x,y,w,h) in faces:
face_dst = {
"x": np.asscalar(x),
"y": np.asscalar(y),
"w": np.asscalar(w),
"h": np.asscalar(h)
}
eyes_dst = []
roi_gray = gray[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
for (ex,ey,ew,eh) in eyes:
eye_pos = {
"x": np.asscalar(ex),
"y": np.asscalar(ey),
"w": np.asscalar(ew),
"h": np.asscalar(eh)
}
eyes_dst.append(eye_pos)
result.append({
"face": face_dst,
"eyes": eyes_dst
})
return result
ディレクトリ構成
├── face_detect.py
├── index.py
├── templates
│ └── index.html
└── tmp
└── lenna.jpg
参考
Recommends
New Posts
Hot posts!
Date
Tags
(110)
(54)
(54)
(47)
(45)
(36)
(30)
(29)
(24)
(24)
(22)
(21)
(21)
(20)
(19)
(17)
(16)
(16)
(15)
(14)
(12)
(12)
(12)
(12)
(12)
(12)
(11)
(10)
(10)
(10)
(10)
(10)
(9)
(9)
(8)
(8)
(8)
(8)
(7)
(7)
(6)
(6)
(6)
(6)
(6)
(5)
(5)
(5)
(5)
(4)
Author