ラズパイのカメラで撮った画像から顔検出する

前回ラズパイ4に付けたカメラモジュールV2.1で画像取り込みをしたので、今回はその画像から顔とかの検出をやってみます。

#顔検出
openCVにある顔検出プログラムを使ってみました。正面を向いている顔のみ検出するので横顔は検出できません。また、画像取り込みのプログラムについては前回と同じなので説明は省略します。

```python:face.py
import cv2
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH,640)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT,480)
cascade = cv2.CascadeClassifier('/home/pi/.local/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_alt.xml')
while True:
    _,image = camera.read()
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    face = cascade.detectMultiScale(gray,minSize=(50,50))
    for x,y,w,h in face:
        cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
    cv2.imshow('camera',image)
    key = cv2.waitKey(1)
    if key != -1:
        break
camera.release()
cv2.destroyAllWindows()
```

* 顔検出部分の説明

顔検出の部分を下に記載します。

```python:
cascade = cv2.CascadeClassifier('/home/pi/.local/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_alt.xml')
...
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    face = cascade.detectMultiScale(gray,minSize=(50,50))
```

`CascadeClassifier`に入れているxmlのファイルは顔認識用のファイルで、このファイルを変えることにより検出対象（顔、目、鼻など）を変えることができます。パスはopenCVをインストールした環境によって変わると思いますが、私の場合は（pip3でopenCVをインストールした）、ここのパスにファイルが置かれていました。
検出対象の画像を`cvtColor`で白黒に変換してから`detectMultiScale`で顔の検出をしています。

* 枠描写プログラムの説明

検出した顔を緑の枠で囲む部分を下に記載します。

```python:
    for x,y,w,h in face:
        cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
```

`detectMultiScale`で検出した顔座標はリスト形式で受け取っています。なお、最後の2は線の太さを示しています。

#人物検出

これもopenCVにある検出プログラムを使ってみました。残念ながら検出精度は思ったより高くありませんでした。

```python:person.py
import cv2
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH,640)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT,480)
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
while True:
    _,image = camera.read()
    person,_ = hog.detectMultiScale(image)
    for x,y,w,h in person:
        cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
    cv2.imshow('camera',image)
    key = cv2.waitKey(1)
    if key != -1:
        break
camera.release()
cv2.destroyAllWindows()
```

* 人物検出部分の説明

人物検出の部分を下に記載します。

```python:
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
...
    person,_ = hog.detectMultiScale(image)
```

顔検出と違いカラー画像をそのまま渡しています。

#QRコードのデコード

ついでにQRコードのデコードプログラムも作ってみました。

```python:qr.py
import cv2
from pyzbar.pyzbar import decode
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH,640)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT,480)
while True:
    _,image = camera.read()
    qrdata = decode(image)
    for qr in qrdata:
        cv2.rectangle(image,(qr.rect.left,qr.rect.top),(qr.rect.left+qr.rect.width,qr.rect.top+qr.rect.height),(0,255,0),2)
        cv2.putText(image,qr.data.decode('utf-8'),(0,20),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0))
    cv2.imshow('camera',image)
    key = cv2.waitKey(1)
    if key != -1:
        break
camera.release()
cv2.destroyAllWindows()
```

* デコード部分の説明

デコードの部分を下に記載します。

```python:
    qrdata = decode(image)
```

* 文字表示の説明

文字表示部分を下に記載します。

```python:
        cv2.putText(image,qr.data.decode('utf-8'),(0,20),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0))
```

`data`は文字列、`(0,20)`は表示座標、`1`は文字の大きさ、`(0,255,0)`はBGRを示しています。