異なる顔を区別する
動画チュートリアル 19 - 異なる顔を区別する:https://singtown.com/learn/50033/
このセクションでは、LBP特徴量を使用して異なる顔を区別する方法を紹介します。
まず、独自の画像ライブラリを構築する必要があります。まずOpenMVのUディスク内に新しいフォルダを作成し(SDカードを挿入している必要があることに注意してください)、singtownという名前を付けます。次に、singtownフォルダ内にs1、s2、s3...snという名前のn個のサブフォルダを作成します。ここでnは画像ライブラリ全体の人数です。以下に示す通りです:

次に、以下のコードを実行してさまざまな顔のサンプルを収集します。収集する際は、背景をできるだけ均一にし、顔ができるだけ画面全体を占めるようにしてください。表情は笑顔、無表情、正面、傾き、メガネあり、メガネなしなど、さまざまなものを用意します。1人あたり10〜20枚程度の写真を選ぶとよいでしょう。
# スナップショットの例
#
# 注記: この例を実行するにはSDカードが必要です。
#
# OpenMV Camを使用して画像ファイルを保存できます。
import csi, image, machine
csi0 = csi.CSI()
#import pyb
RED_LED_PIN = 1
BLUE_LED_PIN = 3
csi0.reset() # カメラセンサーを初期化。
csi0.pixformat(csi.GRAYSCALE) # またはcsi.GRAYSCALE
csi0.framesize(csi.QQVGA) # またはcsi.QQVGA(その他も可)
csi0.window((92,112))
csi0.snapshot(frames=10) # 新しい設定を反映させる。
csi0.snapshot(time = 2000)
num = 1 # 撮影対象者の番号を設定します。1人目の写真はs1フォルダに、2人目の写真はs2フォルダに、というように保存されます。撮影対象者を変更するたびにnumの値を変更してください。
n = 20 # 1人あたりの撮影枚数を設定します。
# n枚の写真を連続して撮影します。3秒間隔で1枚撮影します。
while(n):
# 赤色LEDを点灯
machine.LED("LED_RED").on()
#pyb.LED(RED_LED_PIN).on()
csi0.snapshot(time = 3000) # ユーザーに準備する時間を与える。3秒待って、表情を整えます。
# 赤色LEDを消灯し、青色LEDを点灯
machine.LED("LED_RED").off()
machine.LED("LED_BLUE").on()
#pyb.LED(RED_LED_PIN).off()
#pyb.LED(BLUE_LED_PIN).on()
# 撮影した画像をSDカードに保存
print(n)
csi0.snapshot().save("singtown/s%s/%s.pgm" % (num, n) ) # または"example.bmp"(その他も可)
n -= 1
#pyb.LED(BLUE_LED_PIN).off()
machine.LED("LED_BLUE").off()
print("Done! Reset the camera to see the saved image.")
撮影後、OpenMVのUディスク内の画像は次のようになります(OpenMVのUディスクに新しい画像/ファイルが書き込まれるたびに、それを確認するにはOpenMVをリセットする必要があることに注意してください):


最後に、以下のコードを実行して現在のカメラ視野内の顔を識別し、現在の対象に最も一致する人物を出力します。
# LBP記述子を用いた顔認識。
# Timo Ahonen の論文「Face Recognition with Local Binary Patterns」を参照。
#
# この例を実行する前に:
# 1) AT&T顔データベースをダウンロードする http://www.cl.cam.ac.uk/Research/DTG/attarchive/pub/data/att_faces.zip
# 2) orl_facesディレクトリを展開し、SDカードのルートにコピーする。
import csi, time, image
csi0 = csi.CSI()
csi0.reset() # カメラセンサーを初期化。
csi0.pixformat(csi.GRAYSCALE) # またはcsi.GRAYSCALE
csi0.framesize(csi.QQVGA) # またはcsi.QQVGA(その他も可)
csi0.window((92,112))
csi0.snapshot(frames=10) # 新しい設定を反映させる。
csi0.snapshot(time = 5000) # 5秒待つ
#SUB = "s1"
NUM_SUBJECTS = 6 # 画像ライブラリ内の人数、合計6人
NUM_SUBJECTS_IMGS = 20 # 1人あたり20枚のサンプル画像
# 現在の顔を撮影。
img = csi0.snapshot()
#img = image.Image("singtown/%s/1.pgm"%(SUB))
d0 = img.find_lbp((0, 0, img.width(), img.height()))
# d0は現在の顔のLBP特徴量
img = None
pmin = 999999
num=0
def min(pmin, a, s):
global num
if a<pmin:
pmin=a
num=s
return pmin
for s in range(1, NUM_SUBJECTS+1):
dist = 0
for i in range(2, NUM_SUBJECTS_IMGS+1):
img = image.Image("singtown/s%d/%d.pgm"%(s, i))
d1 = img.find_lbp((0, 0, img.width(), img.height()))
# d1はsフォルダ内のi番目の画像のLBP特徴量
dist += image.match_descriptor(d0, d1) # d0とd1、つまりサンプル画像と検出された顔との特徴量の差異度を計算する。
print("Average dist for subject %d: %d"%(s, dist/NUM_SUBJECTS_IMGS))
pmin = min(pmin, dist/NUM_SUBJECTS_IMGS, s) # 特徴量の差異度が小さいほど、検出された顔はこのサンプルに類似しており、より一致度が高い。
print(pmin)
print(num) # numは現在最も一致する人物の番号。
実行結果は図に示す通りです:
