【Python】顔画像をPOST 、 顔検出 、 canvasで顔にお絵かき【JS】

2018-07-11
javascriptcanvaspython%E7%94%BB%E5%83%8F%E5%87%A6%E7%90%86opencv
    

目次

概要

「顔検出をして、顔に絵を描く」というもの。

具体的には、 顔写真の画像をAPIサーバへアップロードし、顔検出を行う。 サーバは顔座標を返し、それを元にcanvasでお絵かきする。

環境

フロント

html + JS + canvas axios.jsでAPIを叩く

サーバ
  • Ubutnu 16.04
  • Python + Flask
  • OpenCV 3.2 など

アプリケーション

app-demo

こんな感じになる。 とりあえず、顔に枠線を書いている。 画像の描画、顔へのお絵かきは全て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 

参考

【Python】顔画像をPOST 、 顔検出 、 canvasで顔にお絵かき【JS】

    
s-yoshiki
s-yoshiki
githubtwitterqiita
Web作ってますが、インタラクティブなプログラミングも好きです。
JavaScript / Vue / node.js / PHP / AWS / OpenCV

関連記事

10進数から2進数 2進数から10進数への変換 JavaScript
10進数から2進数 2進数から10進数 テスト 10進数から2進数、2進数から10進数への変換を行うJavaScriptのコードの紹介。 JSの場合、10進数から2進数への変換はメソッド。2進数から1…

JavaScriptの配列ショートハンド (AtCoder用)

JavaScriptでワーシャルフロイド法を実装
AtCoder ABC012 D問題 D - バスと避けられない運命 解説 実装 AtCoder ABC012 の D問題でワーシャルフロイド法が利用できる問題が出てきたので、 JavaScriptで実装しました。 AtCoder ABC012 D問題 D…

JavaScriptによる2分探索(バイナリサーチ) のサンプルコード
2分探索について ソース 参考 JavaScriptで2分探索(バイナリサーチ)を実装してみました。…

Firebase + Nuxt で認証付きページを作るときに参考にしたいところ
Webアプリケーションのセッション管理にJWT導入を検討する際の考え方 Service Worker によるセッション管理 ユーザー セッションの管理 Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する CookieとセッションとJWT SSR…

JavaScriptで幅優先探索 (bfs) を実装する
bfsソースコード 前提 bfs関数 テストコード JavaScriptで幅優先探索 (bfs) を実装し簡単な最短経路の探索問題を解いてみました。 AtCoderの問題を参考にしています bfsソースコード 前提 bfs 関数の定義について 引数 table…

JavaScriptでbig-integerでできること
定数 メソッド abs add, plus and bitLength compare compareTo compareAmb divide, over divmod equals, eq greater, gt greaterOrEquals, geq…

Selenium + Python でYahooのログインや検索・メールの操作を自動化する。
環境 Selenium環境の構築 Seleniumのインストール 検証 Yahoo検索する Yahooにログイン/ログアウトする Yahooメールの操作〜ゴミ箱を空にする サンプルソース 参考 Selenium + PythonでYahoo…

macOSにOpenCV4をインストール
パッケージの情報 インストール 試す with Python3 macOS (MacBook Pro 2018 13 inchi)にhomebrewを用いてOpenCVをインストールする方法。 パッケージの情報 まず、brew search と brew info…

エンジニアなMacBookのセットアップ 開発環境の構築
ブラウザ関連 Homebrewのインストール ターミナル環境系 Hyper エディタ VSCode typora CLIツール Git 言語系 Python node.js MacBookPro…

最新の投稿

SQL整形ツールを作成した
特徴 使い方 FW/ライブラリ等 nuxt sql-formatter-plus Monaco Editor おまけ ソース SQL整形ツールを作成しました。 URLはこちらです。 SQL…

ファイルの1行目を表示 Linuxコマンド head
head コマンド例 headコマンドでファイルの 1行目もしくは指定した行数だけ表示する方法。 head 利用できるオプション コマンド例 の 1行目だけを表示 の 5行目までを表示 カレントディレクトリ以下の全てのtxtファイルの1行目を表示

Amazon S3 と ローカルファイルのチェックサムの比較
s3apiでEtagを取得 検証 マルチアップロード時の注意点 Amazon S3 の Etagを使ってファイルの整合性チェックをする。 s3apiでEtagを取得 S3 APIを利用するとEtagを取得します。この値はmd5のハッシュ値になります。 検証 MD…

github.io / gitlab.ioで公開されている質の高い技術ドキュメント
AWSによるクラウド入門 Pythonプログラミング入門 普通の人が資産運用で99点をとる方法とその考え方 2018年の段階で私が知らないこと github.io / gitlab.io で無料で公開されている興味深いドキュメントのmemo AWS…

10進数から2進数 2進数から10進数への変換 JavaScript
10進数から2進数 2進数から10進数 テスト 10進数から2進数、2進数から10進数への変換を行うJavaScriptのコードの紹介。 JSの場合、10進数から2進数への変換はメソッド。2進数から1…

JavaScriptの配列ショートハンド (AtCoder用)

JavaScriptでワーシャルフロイド法を実装
AtCoder ABC012 D問題 D - バスと避けられない運命 解説 実装 AtCoder ABC012 の D問題でワーシャルフロイド法が利用できる問題が出てきたので、 JavaScriptで実装しました。 AtCoder ABC012 D問題 D…

GitHub Actions で Gatsby をビルドし Amazon S3 にデプロイする
GitHub Actions について あらかじめ準備しておくもの AWS IAM ユーザを環境変数にセットする workflowの記述 ビルド バッジを利用する 終わりに 参考にしたところ Gatsbyで作った静的サイトを、GitHub Actions…

cloudinaryによる画像ファイルの管理 はじめてみる
目的 cloudinary について 他のサービスとの比較 料金プラン アカウントの登録 利用してみる ダッシュボード 画像の編集 APIベースでのアクセス 感想 参考 画像の管理や配信、さらには加工といった事ができるsaas型のcloud…

JavaScriptによる2分探索(バイナリサーチ) のサンプルコード
2分探索について ソース 参考 JavaScriptで2分探索(バイナリサーチ)を実装してみました。…

Tags

Dates

© 2020   404 motivation not found