Flask：リアルタイムなカメラ撮影画像ラベリングWebアプリ♬

![camra_category.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/3145e5e6-2a06-984b-228d-9c8f5ff5e515.jpeg)

**ここまで来ました！**
早速、解説したいと思います。
###全体のコードは以下に置きました。
[Video-Stream / sampling.py ](https://github.com/MuAuan/Video-Stream/blob/master/sampling.py)
[Video-Stream / templates / index2.html ](https://github.com/MuAuan/Video-Stream/blob/master/templates/index2.html)
###Dir構成

```
flask_PJ
├── sampling.py
|── templates
|   └── index2.html 
└── static
    └── sample 
    |   └── gazo....jpg  #撮影画像格納
    └── labeled　　　　　 #分類用Dir〇✖などを配下に作る
        └── 〇 
        |    └── gazo....jpg 
        |    ... 
        |    └── ....jpg
        └── ✖ 
            └── gazo....jpg 
            ... 
            └── ....jpg
```
###実行時の流れ
１．上記の絵のように、画像を分類して下さい。
２．下のラジオボタンをクリックして、送信ボタンを押す
３．画像が選んだDirに移動しています
４．再びカメラ画像が表れて、１に戻る
流れは、参考サイトの通り、異なるのはカメラ撮影画像を格納しているところだけです。

【参考】
[Flaskでデータのラベリングサイトを作成する](https://qiita.com/habakan/items/45410cb0ce479c3a709d)

以下、上記流れをコードレベルで説明します。
###１．上記の絵のように、画像を分類して下さい。
まずは、表示用Html

```
<!DOCTYPE html>
<html lang="jp">
<head>
    <meta charset="UTF-8">
    <title>カメラ撮影画像ラベリングサイト</title>
</head>
<body>
    <h1>画像を分類してください</h1>
    <img src="{{ img }}" style="width: 300px;">
      <form action="{{ url_for('sampling')  }}" method="POST">
         <input type="hidden" name="img_path" value="{{ img }}">
           {% if category_list %}
              {% for category in category_list %}
                 <input type="radio" name="category" value="{{ category }}">
                 {{ category }}
                 <br/>
              {% endfor %}
           {% else %}
              static/labeledにカテゴリーフォルダを作成してください。
           {% endif %}
         <input type="submit" value="送信">
      </form>
</body>
</html>
```
```<img src="{{ img }}" style="width: 300px;">```　：imgを表示します。中身無いとき（最初の呼び出し）は表示されません
```<form action="{{ url_for('sampling')  }}" method="POST">```　：後で示す、sampling.py内の関数samplingに向けてPostしている。
```<input type="hidden" name="img_path" value="{{ img }}">```　：以下のラジオボタンで選ばれたimg_pathにimgを上記のform actionの操作でPostしている。

      {% if category_list %}
：category_listがあれば、以下実行

      {% for category in category_list %}
      <input type="radio" name="category" value="{{ category }}">
      {{ category }}
      <br/>
      {% endfor %}
：category_listがなくなるまで、ラジオボタンを表示

      {% else %}
      static/labeledにカテゴリーフォルダを作成してください。
      {% endif %}

：categoryがなければ、以下の「static/labeledにカテゴリーフォルダを作成してください。」を表示してif文終了
###２．下のラジオボタンをクリックして、送信ボタンを押す
      <input type="submit" value="送信">
：送信を押すと上記アクションを実行
そして、これを受けるsampling.py

```sampling.py
from flask import Flask, render_template, request, redirect, url_for
import glob
import os
import shutil
import time
import numpy as np
import cv2
```
必要なものを呼んでいます。
ここで、[shutilは、いろいろできる優れものです](https://docs.python.jp/3/library/shutil.html)。

```
app = Flask(__name__)
start_time=time.time()
```
次にFlask、時刻をGlobal変数として取得しておきます。

```
@app.route("/")
def index():
    # 画像ファイルパスを取得
    img_path = glob.glob("static/sample/*.jpg")
    # 分類するフォルダ名を取得
    category_path = [os.path.basename(path) for path in glob.glob("static/labeled/*")]    
    return render_template('index2.html', img=img_path[len(img_path)-1], category_list=category_path) 
```
次に、index()で
①撮影画像を格納しているstatic/sample/からjpgファイルを取得します。
②static/labeled/配下のディレクトリ名称を取得しcategory_pathに格納します。
③```render_template```でindex2.htmlを描画しています。引数としてimgとcategory_listを渡しています。
④```@app.route("/")```：実行後、ルートで表示することを意味します。

```
@app.route("/sampling", methods=['POST'])
def sampling():
    # 分類するフォルダパスを取得
    category_path = os.path.join("static", os.path.join("labeled", request.form['category']))
    # ファイルの移動
    shutil.move(request.form['img_path'], category_path)
```
①```@app.route("/sampling", methods=['POST'])```
：```<form action="{{ url_for('sampling')  }}" method="POST">```からPOSTで取得します。配置は/samplingです。
②category_pathに取得したPathとcategory（ディレクトリの名前）を入力します。
③```shutil.move```で②のディレクトリに```request.form['img_path']```で受け取ったimgを移動します。

```
    cap = cv2.VideoCapture(0)
    FRAME_RATE=1
    ret, frame = cap.read()
    i=0
    while ret == True:
        ret, frame = cap.read()
        i+=1
        cv2.imwrite("static/sample/gazo"+str(int(10*(time.time()-start_time)))+".jpg",frame)
        #なんかKey押せば止まる
        if cv2.waitKey(1000*FRAME_RATE) >= 0:  
            break
        elif i>=1:
            break
    cap.release()
    cv2.destroyAllWindows()
　　return redirect("/")
```
①```cap = cv2.VideoCapture(0)```
：いよいよカメラの準備
②```ret, frame = cap.read()```
：とりあえず、一度読み込みます。これで起動させる。⇒だいたい黒い画像しか得られない
③

```
    while ret == True:
        ret, frame = cap.read()
        i+=1
        cv2.imwrite("static/sample/gazo"+str(int(10*(time.time()-start_time)))+".jpg",frame)
```
：二度目の```cap.read()```でframeに画像読込し、```cap.imwrite```でstatic/sample/ホルダーに保管。ここでファイル名は時刻.jpgとしました。
④ 

```
       #なんかKey押せば止まる
        if cv2.waitKey(1000*FRAME_RATE) >= 0:  
            break
        elif i>=1:
            break
```
：何かKeyを押せばとりあえず、その回のsamplingは止まる仕様です。
　また、繰り返しは１度限りにしています。つまり、一つだけ画像ファイルが取り込まれます。いろいろやってみましたが、目的が異なりますが、連続動画を作成する場合や長時間コマ撮り取得するような場合は、数を増やすと画像がたまります。

```
    cap.release()
    cv2.destroyAllWindows()
　　return redirect("/")
```
：最後にcapを解除して、Windowsも削除して終了し、"/"にredirectします。
　つまり、index()が起動し、index2.htmlが再描画されます。

###最後にもう一回
![camra_category2.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/12ea1f80-33f2-fcb8-73e8-8af8ba0572d4.jpeg)
###まとめ
・カメラ撮影画像ラベリングWebアプリを作成した
・これは基本RasPiでも動くはず
⇒以下のようにidle2環境（Python 2.7.9）でできました。

・利用はいろいろできそうだが、やはりStreaming配信作ろう。。
・物体認識や物体検出Webアプリを作ろう
###**RasPi遠隔監視で撮影画像ラベリング実行**

```
Python 2.7.9 (default, Sep 17 2016, 20:26:04) 
[GCC 4.9.2] on linux2
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>> 
 * Running on http://192.168.0.15:5000/
192.168.0.15 - - [24/May/2018 22:23:06] "GET / HTTP/1.1" 500 -
192.168.0.15 - - [24/May/2018 22:23:32] "GET / HTTP/1.1" 200 -
192.168.0.15 - - [24/May/2018 22:23:32] "GET /static/sample/2.jpg HTTP/1.1" 200 -
192.168.0.15 - - [24/May/2018 22:23:39] "POST /sampling HTTP/1.1" 302 -
192.168.0.15 - - [24/May/2018 22:23:39] "GET / HTTP/1.1" 200 -
192.168.0.15 - - [24/May/2018 22:23:39] "GET /static/sample/gazo401.jpg HTTP/1.1" 200 -
192.168.0.15 - - [24/May/2018 22:23:46] "POST /sampling HTTP/1.1" 400 -
192.168.0.15 - - [24/May/2018 22:24:03] "GET / HTTP/1.1" 200 -
192.168.0.15 - - [24/May/2018 22:24:10] "POST /sampling HTTP/1.1" 302 -
192.168.0.15 - - [24/May/2018 22:24:10] "GET / HTTP/1.1" 200 -
192.168.0.15 - - [24/May/2018 22:24:10] "GET /static/sample/gazo709.jpg HTTP/1.1" 200 -
192.168.0.15 - - [24/May/2018 22:24:18] "POST /sampling HTTP/1.1" 302 -
192.168.0.15 - - [24/May/2018 22:24:18] "GET / HTTP/1.1" 200 -
192.168.0.15 - - [24/May/2018 22:24:18] "GET /static/sample/gazo783.jpg HTTP/1.1" 200 -
192.168.0.15 - - [24/May/2018 22:24:27] "POST /sampling HTTP/1.1" 302 -
192.168.0.15 - - [24/May/2018 22:24:27] "GET / HTTP/1.1" 200 -
192.168.0.15 - - [24/May/2018 22:24:28] "GET /static/sample/gazo876.jpg HTTP/1.1" 200 -
```
![camra_category3.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/479b13ab-cae8-ba4d-c4ca-d54e93b8d155.jpeg)