iPadで顔認証し、人数を数えるpythonスクリプトを作りましたので紹介します。carnetsという無料アプリを使ってpythonを実行しています。
色々制約があるようでなんちゃってpythonですが参考に。
以下はマークダウン形式です。
```python
# ipad+python(carnets)を用いて
# ipadのカメラで
# 顔認証し、人数を数える(カメラマンを含む)
# ただし、顔に手がついていたり、傾いた顔、横顔は認識出来ない
# ipadpro11 ios17.4 carnets with Scipy
# carnets はAppstoreで入手して下さい(いちおう無料)
```
```python
# pip list
```
```python
import cv2
# from cv2 import dnn # deep neural networks
from PIL import Image
import matplotlib.pyplot as plt # carnetsでは画像表示に必須のよう
import time
import numpy as np
import random
```
```python
device = 0 # back camera
# device = 1 # front camera
cap = cv2.VideoCapture(device) # camera shot
```
```python
time.sleep(0.1) # 直ぐには読みこめない
```
```python
# カメラ設定を確認する どういうわけか解像度しか読みこめない
# カメラを横向きにしてもだめ
camera_parameters = ['CAP_PROP_FRAME_WIDTH', # 4 解像度(幅)
'CAP_PROP_FRAME_HEIGHT', # 3 解像度(高さ)
'CAP_PROP_FOURCC', # 圧縮フォーマット
'CAP_PROP_BRIGHTNESS', # 明るさ
'CAP_PROP_CONTRAST', # コントラスト
'CAP_PROP_SATURATION', # 彩度
'CAP_PROP_HUE', # 色相
'CAP_PROP_GAIN', # ゲイン
'CAP_PROP_EXPOSURE'] # 露出
print('CAP_PROP_FRAME_WIDTH = ', cap.get(4))
print('CAP_PROP_FRAME_HEIGHT= ', cap.get(3))
```
CAP_PROP_FRAME_WIDTH = 360.0
CAP_PROP_FRAME_HEIGHT= 480.0
```python
cap.set(3, 1080) # どうも設定変更ができないようです
```
True
```python
print('CAP_PROP_FRAME_WIDTH = ', cap.get(4))
print('CAP_PROP_FRAME_HEIGHT= ', cap.get(3))
```
CAP_PROP_FRAME_WIDTH = 360.0
CAP_PROP_FRAME_HEIGHT= 480.0
```python
ret, frame = cap.read()
```
```python
print(ret)
```
True
```python
print(type(frame)) # 正常に読み込めたかの確認 numpy.ndarray形式ならOK
```
<class 'numpy.ndarray'>
```python
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # グレースケール変換
```
```python
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # RGB変換
```
```python
# plt.figure(figsize=(6,5)) # 画面サイズが変更できない
```
```python
plt.imshow(gray) # matplotlibの色なのでグレーには見えませんが、気にしないでください
```
![png](output_14_1.png)
```python
# plt.imshow(rgb)
```
```python
# ハール識別器の設定
# 見かけ上ファイル名は...xmlですが、情報を見ると.txtがついていた
# メガネをかけていると検知できないことがあります
# 横顔は検知できません
# clf = cv2.CascadeClassifier("haarcascade_frontalface_default.xml.txt")
# clf = cv2.CascadeClassifier("haarcascade_upperbody.xml")
clf = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml.txt")
```
```python
faces = clf.detectMultiScale(gray,
scaleFactor=1.1,
minNeighbors=2,
minSize=(15,15))
```
```python
faces # 検出した顔の配列を確認のため出力 ex, ey, ew, eh
```
array([[120, 281, 25, 25],
[ 90, 284, 23, 23],
[240, 90, 25, 25],
[289, 87, 26, 26],
[332, 86, 26, 26],
[236, 138, 28, 28],
[286, 238, 26, 26],
[235, 191, 26, 26],
[332, 188, 27, 27],
[ 88, 175, 34, 34],
[118, 178, 31, 31],
[150, 176, 32, 32]], dtype=int32)
```python
maxid = len(faces)
print(maxid)
```
12
```python
rnd = random.sample(range(1,maxid+2),maxid+1) # カメラマン含む
print(rnd)
```
[8, 13, 6, 10, 2, 9, 3, 5, 1, 12, 4, 7, 11]
```python
id = 0 # detected id
```
```python
# 顔を四角で囲み、ランダムな番号をふる
for (ex,ey,ew,eh) in faces:
cv2.rectangle(rgb, # image
(ex,ey), # box
(ex+ew,ey+eh),
(255,255,255), # color
2, # thickness
# cv2.FILLED) # linetype 塗りつぶし
cv2.LINE_AA)
text = "{0}".format(rnd[id])
id = id + 1
# text = "{0}".format(id)
scale = 0.6
cv2.putText(rgb, # 描画対象のimage
text, # text
(ex+3,ey-5), # right bottom
cv2.FONT_HERSHEY_SIMPLEX, # font style
scale, # fontScale
(255,255,255), # color
2, # thickness
cv2.LINE_AA) # lineTyp
cv2.rectangle(rgb,(ex,ey-25),(ex+30,ey),(255,255,255),1) # rectangle on id
```
```python
# cameraman
bg = cv2.rectangle(rgb,(45,475),(300,450),(255,255,255),cv2.FILLED)
cameraman = cv2.putText(rgb,
'total: '+"{0}".format(maxid+1)+
' cameraman: '+"{0}".format(rnd[maxid]),
(50,470),
cv2.FONT_HERSHEY_SIMPLEX,
scale,
(0,0,0),
1,
cv2.LINE_AA)
```
```python
plt.imshow(rgb)
```
![png](output_24_1.png)
```python
cap.release()
```
```python
```
```python
```