Visionによる「人間」の検出
オンデバイスで「人間」を検出する
iOSでは古くはCore Imageの CIDetector
で顔の検出ができたし、最近ではVisionフレームワークでディープラーニングベースの顔検出もできる。
しかし顔検出は、顔しか検出できない。画像内における顔領域の大きさが小さかったり、顔が横や後ろを向いているときには画像内に人間がいることを検出できない。
そういう場合、YOLOのCore MLモデル(公式でも配布されている)を利用して、personクラスを検出する方法があった。
YOLO で person を検出する際の問題
まず、YOLOによる一般物体検出(Object Detection)はiOSにビルトインされているモデルではないので、Core MLモデルをアプリに同梱する必要がある[2]。
この場合、一番小さい YOLOv3Int8LUT.mlmodel
を利用しても62.2MBもある。
YOLOv3-Tiny シリーズを使えばモデルサイズはグッと小さくなる(Int8LUT版は8.9MB)が、残念ながら精度も体感できるほどに下がる...
そしてYOLOによる推論処理はそれなりに重い。最新のiPhone 12シリーズでも60 fpsでは処理できないし、端末がアツアツになる。大抵の場合他の画像解析も併用することになるので(僕の場合は音声解析も同時に併用することが多い)、なおさら厳しい。
VNDetectHumanRectanglesRequest
iOS 13から、Visionフレームワークで VNDetectHumanRectanglesRequest
というのが使えるようになった [3]。
YOLOのpersonクラスを使う代わりになりそうと期待したが、検出範囲が全身ではなく**上半身のみ(顔+胴)**で、完全な代替にはならなかった。
iOS 15で「全身」の検出が可能に
そんな VNDetectHumanRectanglesRequest
が、iOS 15でアップデートされた。revision
が VNDetectHumanRectanglesRequestRevision2
となり、全身の検出が可能になった。
(WWDC21「Detect people, faces, and poses using Vision」より)
これで、「人間」を検出するためだけにYOLOモデルを導入する必要はなくなった🎉
upperBodyOnly
プロパティ
VNDetectHumanRectanglesRequest
に upperBodyOnly
プロパティが追加された。
var upperBodyOnly: Bool { get set }
**デフォルトは true
**で、この場合、上半身のみの検出となる。
全身を検出したい場合は、false
をセットする。
VNHumanObservation
iOS 13〜14では、VNDetectHumanRectanglesRequest
から得られる結果の型は VNDetectedObjectObservation だった。画像内における上半身のバウンディングボックスだけが得られた。
iOS 15からは、VNDetectHumanRectanglesRequest
で得られる結果の型が VNHumanObservation
という新クラスになった。
var results: [VNHumanObservation]? { get }
VNHumanObservation
は VNDetectedObjectObservation
を継承し、
class VNHumanObservation : VNDetectedObjectObservation
違いとしては、upperBodyOnly
プロパティがひとつ追加されているだけ。
var upperBodyOnly: Bool { get }
VNDetectedObjectObservation
が持つバウンディングボックスが上半身を表すのか全身を表すのかを示すBool値である。
-
12/22時点で空いていたので書きました。 ↩︎
-
あとからダウンロードさせる手段もある: Core MLモデルをクラウドにデプロイして配信する ↩︎
-
本クラスは、iOS 13.0+, macOS 10.15+のほか、visionOS 1.0+でも使用可能。 ↩︎
Discussion