ひょっこりはんした画像を返してくれるLINEbotを作ってみる～前半編～

#画像認識技術の勉強のため、ひょっこりはん
画像処理の勉強をするモチベーションのため、最終目標となるサービスを考えてみた。
事例紹介をする場が、プログラムについて興味ない人でもとっつきやすいネタであることを踏まえた。

遊戯王や、ピカチュウなどいろいろ考えた結果「ひょっこりはん」
##ひょっこりはんを選定した理由
①ひょこりはんを題材でやっている方がいなさそうだった。
②顔認識する。画像にペイントする。という技術が身につく題材として初心者の私にとってもハードルが低い

#Pythonで画像認識環境を構築(Docker利用)

画像処理を利用するのにお手軽な　OpenCV　

OpenCV環境をDocker上で構築します。Dockerfileを作成してimage作成

##Dockerfile （＊webApiとし利用することを想定し、Flaskも導入）
```
FROM ubuntu:16.04

RUN apt-get update -y && apt-get install -yq make cmake gcc g++ unzip wget build-essential gcc zlib1g-dev

# Python3のインストール
WORKDIR /root/
RUN wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tgz \
        && tar zxf Python-3.6.0.tgz \
        && cd Python-3.6.0 \
        && ./configure \
        && make altinstall
ENV PYTHONIOENCODING "utf-8"
RUN apt-get install -y python3-pip python-qt4

# Opencvのインストール
RUN apt-get -y install build-essential pkg-config libjpeg-dev libpng12-dev libtiff5-dev libopenexr-dev libavcodec-dev libavformat-dev yasm libfaac-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev libx264-dev libswscale-dev libjasper-dev libdc1394-22-dev libv4l-dev libgstreamer1.0-dev libgstreamer-plugins-base0.10-dev libgstreamer-plugins-base1.0-dev libtbb2 libtbb-dev libeigen3-dev
RUN ln -s /usr/include/libv4l1-videodev.h /usr/include/linux/videodev.h

RUN mkdir ~/tmp
RUN cd ~/tmp && wget https://github.com/Itseez/opencv/archive/3.1.0.zip && unzip 3.1.0.zip
RUN cd ~/tmp/opencv-3.1.0 && cmake CMakeLists.txt -DWITH_TBB=ON -DINSTALL_CREATE_DISTRIB=ON -DWITH_FFMPEG=OFF -DCMAKE_INSTALL_PREFIX=/usr/local
RUN cd ~/tmp/opencv-3.1.0 && make -j3 && make install

# Opencvのインストール
RUN pip3 install numpy opencv-python

# flaskのインストール
RUN pip3 install flask


ENV APP_NAME opencv-docker
WORKDIR /home/$APP_NAME

CMD [ '/bin/bash'  ]
```

＜参考文献＞
https://qiita.com/sey323/items/8cb10f90889a6d911cd4

##Opencv Docker環境立ち上げ
*Docker環境が立ち上がっていることを前提

```
# コンテナをビルド
$ docker build -t opencv-docker:0.1 .

# コンテナを起動し内容確認
$ docker run --rm -it　opencv-docker /bin/bash　

```

#OpenCVでひょっこりはん

OpenCVは目や鼻などの特徴量をもった定義ファイルがあります。
それを利用することで簡単に顔認識を利用することできます。(精度は無視)
識別ができるファイルがサイトにあります。
【URL】https://github.com/opencv/opencv/tree/master/data/haarcascades

今回は、人の顔（正面）の認識ができる
haarcascade_frontalface_default　を利用してひょっこりはんを実装しました。

サクッと作ってみたので、ロジックはしょぼいです。

##ひょっこりはん.py

```
import cv2

cascade_path = "./models/haarcascade_frontalface_default.xml"

image_file = "test.jpg"
image_path = "./inputs/" + image_file
output_path = "./outputs/" + image_file

image = cv2.imread(image_path)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cascade = cv2.CascadeClassifier(cascade_path)

facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=2, minSize=(30, 30))
facecolor=(196,226,252)
color = (255, 255, 255)
if len(facerect) > 0:

    for rect in facerect:
        a=rect[0];
        b=rect[1]
        c=int(rect[2]/2)
        d=int(rect[3]/2)
        cv2.rectangle(image, (a+int(c/2),b-d),(a-2*c,b+3*d), color, thickness=-1) 
        cv2.circle(image, (a+int(c/2),b+int(2.15*d)),int(d/2), facecolor, thickness=-1) 
        cv2.circle(image, (a+int(c/2),b+int(2.75*d)),int(d/2), facecolor, thickness=-1)
#画像を切り取り
    y=(b-d)
    yend=(b+3*d)
    x=(a-2*c)
    xend=(a+2*c)
    if y < 0 :
        y=0
        yend=3*d
    if x < 0 :
        x=0
        xend=2*c
#画像を切り取る場合は、一つだけ顔を認識したとき        
    if len(facerect) == 1:
        image=image[y:yend,x:xend];

#画像処理した結果を保存する
    cv2.imwrite(output_path, image)
```


##実際に画像処理をしてみた結果
今回利用した画像はこちら
1人の女性を利用してみました

###＜Input画像＞
![00_input.jpg](https://qiita-image-store.s3.amazonaws.com/0/213995/349f5e3a-f221-e45c-fa82-346028253a0b.jpeg)


###＜OutPut画像＞　ひょっこり変換
画像処理をした結果がこちら　ちゃんとひょっこりしてくれてます。

![01_output.jpg](https://qiita-image-store.s3.amazonaws.com/0/213995/0c7ce886-1c3a-24ad-4d5a-26791edad943.jpeg)



#LINEと連携して画像処理結果をリアルタイムで確認

別の記事としてまとめます。
<概要>
FlaskでLineのエンドポイント作成
LINEで画像送信するために、必要なhttps化を実装する。