1.はじめに
ちょっと前まで、顔・手・ポーズのリアルタイム検出をしようと思ったら高性能なGPUを積んだPCが必要でしたが、今回はこれらをCPUだけでも行える MediaPipe をご紹介します。
2.MediaPipeとは?
MediaPipie は、Googleが提供しているライブメディアやストリーミングメディア向けのMLソリューション で、以下の特徴があります。
高速なエンドツーエンド処理 :一般的なハードウェアでも高速化されたML推論と処理を実現 様々なプラットフォームで使用可能 :Android、iOS、C++、Pythonに対応 無料のオープンソース : Apache 2.0で、拡張やカスタマイズが可能
現在、4つのプラットフォームで、15種類のソリューションを提供されています。今回はその中から、Python プラットフォームの、顔検出、手検出、ポーズ検出、ホリスティック検出 (顔・手・ポーズの統合検出)についてご紹介します。
3.コード(動画から検出)
最初のデモはオジサンより、女優やダンサーの方が見ていて楽しいと思うので、あえて動画からホリスティック検出(顔・手・ポーズの統合検出)をやってみます。
コードはGoogle Colab で動かす形にしてGithub に上げてありますので、それに沿って説明して行きます。自分で動かしてみたい方は、この「リンク」 をクリックし表示されたノートブックの先頭にある「Colab on Web」 ボタンをクリックすると動かせます。なお、GPUは使っていません。
まず、セットアップを行います。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#@title **set up**
# install mediapipe
! pip install mediapipe
# clone github code
! git clone https : //github.com/cedro3/mediapipe.git
% cd mediapipe /
# initial setting
import mediapipe as mp
mp_holistic = mp . solutions . holistic
# Initialize MediaPipe Holistic.
holistic = mp_holistic . Holistic (
static_image_mode = True , min_detection_confidence = 0.5 )
# Prepare DrawingSpec for drawing the face landmarks later.
WHITE_COLOR = ( 224 , 224 , 224 )
BLACK_COLOR = ( 0 , 0 , 0 )
RED_COLOR = ( 0 , 0 , 255 )
GREEN_COLOR = ( 0 , 128 , 0 )
BLUE_COLOR = ( 255 , 0 , 0 )
mp_drawing = mp . solutions . drawing_utils
drawing_face_spec = mp_drawing . DrawingSpec ( color = WHITE_COLOR , thickness = 1 , circle_radius = 1 )
drawing_pose_spec = mp_drawing . DrawingSpec ( color = WHITE_COLOR , thickness = 3 , circle_radius = 3 )
drawing_hand_spec = mp_drawing . DrawingSpec ( color = WHITE_COLOR , thickness = 3 , circle_radius = 3 )
drawing_dot_spec = mp_drawing . DrawingSpec ( color = RED_COLOR , thickness = 2 , circle_radius = 3 )
# define fuction
from function import *
次に、video で指定した動画を読み込み静止画に分解し、framesフォルダ に保管します。既に frames フォルダ がある場合(2回目以降)は、既にあるフォルダを一旦削除してから処理を開始します。ここでは、video = satomi.mp4 を指定しています。
ご自分の動画を使いたい場合は、その動画をPCから videoフォルダ にドラッグ&ドロップでアップロードして下さい。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#@title **video-to-frames**
#@markdown upload video(mp4) with sound to movie/video folder
video = 'satomi.mp4' #@param {type:"string"}
video_file = 'video/' + video
image_dir = 'frames/'
image_file = '%s.jpg'
# video_2_images
reset_folder ( 'frames' )
fps , i , interval = video_2_images ( video_file , image_dir , image_file )
# display strat frame
from google . colab . patches import cv2_imshow
img = cv2 . imread ( 'frames/000000.jpg' )
cv2_imshow ( img )
# display parameter
print ( 'fps = ' , fps )
print ( 'frames = ' , i )
print ( 'interval = ' , interval )
fps = 30.0 frames = 106 interval = 1
読み込んだ動画の最初のフレームのみを表示しています。
そして、MediaPipeを使って、frames フォルダ の中にある静止画から顔・手・ポーズを検出し、結果を images フォルダ に保管して行きます。既に images フォルダ がある場合(2回目以降)は、既にあるフォルダを一旦削除してから処理を開始します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#@title **MediaPipe from frames to images**
import cv2
from google . colab . patches import cv2_imshow
import numpy as np
import glob
from tqdm import tqdm ###
# reset images folder
reset_folder ( 'images' )
# image file names to files in list format
files = [ ]
for name in sorted ( glob . glob ( './frames/*.jpg' ) ) :
files . append ( name )
# Read images with OpenCV.
images = { name : cv2 . imread ( name ) for name in files }
#for name, image in images.items():
for name , image in tqdm ( images . items ( ) ) :
# Convert the BGR image to RGB and process it with MediaPipe Pose.
results = holistic . process ( cv2 . cvtColor ( image , cv2 . COLOR_BGR2RGB ) )
# Draw pose landmarks.
annotated_image = image . copy ( )
mp_drawing . draw_landmarks (
image = annotated_image ,
landmark_list = results . left_hand_landmarks ,
connections = mp_holistic . HAND_CONNECTIONS ,
landmark_drawing_spec = drawing_dot_spec ,
connection_drawing_spec = drawing_hand_spec )
mp_drawing . draw_landmarks (
image = annotated_image ,
landmark_list = results . right_hand_landmarks ,
connections = mp_holistic . HAND_CONNECTIONS ,
landmark_drawing_spec = drawing_dot_spec ,
connection_drawing_spec = drawing_hand_spec )
mp_drawing . draw_landmarks (
image = annotated_image ,
landmark_list = results . face_landmarks ,
connections = mp_holistic . FACEMESH_TESSELATION , ###
landmark_drawing_spec = drawing_face_spec ,
connection_drawing_spec = drawing_face_spec )
mp_drawing . draw_landmarks (
image = annotated_image ,
landmark_list = results . pose_landmarks ,
connections = mp_holistic . POSE_CONNECTIONS ,
landmark_drawing_spec = drawing_pose_spec ,
connection_drawing_spec = drawing_pose_spec )
save_name = 'images/' + os . path . basename ( name ) ###
cv2 . imwrite ( save_name , annotated_image )
最後に、images フォルダ の中にある検出結果を読み込んでmp4動画を作成します。このとき、with_sound のチェックボックス にチェックを入れておくと、元動画の音声を検出動画に付加します。元動画に音声が付いていない場合にチェックを入れるとエラーになりますので、ご注意下さい。
#@title **make movie from images**
#@markdown check with_sound if the video has sound
with_sound = False #@param {type:"boolean"}
fps_r = fps / interval
print ( 'making movie...' )
if with_sound == True :
! ffmpeg - y - r $ fps_r - i images / % 6d.jpg - vcodec libx264 - pix_fmt yuv420p - loglevel error out . mp4
# audio extraction/addition
print ( 'preparation for sound...' )
! ffmpeg - y - i $ video_file - loglevel error sound . mp3
! ffmpeg - y - i out . mp4 - i sound . mp3 - loglevel error output . mp4
else :
! ffmpeg - y - r $ fps_r - i images / % 6d.jpg - vcodec libx264 - pix_fmt yuv420p - loglevel error output . mp4
display_mp4 ( 'output.mp4' )
顔と手は、かなり細かい検出がされていることが分かります。写っている範囲が狭いので、ポーズは肩の線のみ見えています。作成したmp4動画は、下記を実行するとダウンロードできます。
#@title **download movie** (chrome)
from google . colab import files
files . download ( 'output.mp4' )
ビデオ指定のところを、video = mana.mp4 に変更して、それ以降のコードを実行すると、
上半身が写ると、ポーズも検出していることが分かります。シングルパーソン用のため、より大きく写っている人物を優先して検出するので、後ろの男性は検出されません。
ビデオ指定のところを、video = dance.mp4 に変更して、それ以降のコードを実行すると、
全身を写した場合の検出例です。一時的に右手の検出が外れますが、まずまずではないでしょうか。
4.コード(PCのカメラから検出)
※ご注意
以下のコードは、google colabでは動作しません 。ご自分のPCに、このリンク を参考にJupyter Notebookをインストールして実行して下さい。また、Git(コードをコピーするライブラリー)をインストールしてなければ、このリンク を参考に合わせてインストールして下さい。
いよいよ、メインのリアルタイム検出です。カメラ付きのPCで Jupyter Nootbook を開いて、適当なフォルダーに移動し、下記のコードを実行します。GPUは不要です。
# MediaPipeをインストール
! pip install mediapipe
# Gitgub からコードをコピー
! git clone https : //github.com/cedro3/mediapipe.git
% cd mediapipe /
ホリスティック検出(顔・手・ポーズの統合検出)をする場合は、下記のコードを実行するだけです。左上にFPSが表示されています。私のPCは3年前に買った MacbookAir ですが、それでも10FPSくらい出ます。凄い!
! python sample_holistic . py
顔の検出をする場合は、下記のコードを実行します。顔だけだと、20〜30FPSくらいでしょうか。
手の検出をする場合は、下記のコードを実行します。手だけだと、15FPSくらいでしょうか。
ポーズの検出をする場合は、下記のコードを実行します。ポーズだけだと、15FPSくらいでしょうか。
MediaPipeの狙いはエッジデバイスでの検出です。特に、スマホで、顔・手・ポーズなどの検出を使って色々な応用が出来そうですね。
では、また。
(Googleオリジナル) https://mediapipe.dev/index.html
(Githubオリジナル)https://github.com/Kazuhito00/mediapipe-python-sample
(Twitter投稿)
%cd mediapipe/ の後、!python sample_holistic.py
を実行したが、何も表示されません。他の3つも同じです。webカメラのライトが正常なら2つ点灯するのですが、最初から点灯している1つしか点灯していません。
bravoastroさん
コメントありがとうございます。
詳しい状況を知りたいので、下記3点教えて下さい。
1)下記を実行した時に、返って来るコメントを教えて下さい。
————
# MediaPipeをインストール
!pip install mediapipe
# Gitgub からコードをコピー
!git clone https://github.com/cedro3/mediapipe.git
%cd mediapipe/
————
2)下記を実行した時に、返って来るコメントを教えて下さい。
——-
!python sample_holistic.py
——-
3)ご自分で設定したフォルダーの中に、mediapipeというファルダーは出来ていますでしょうか。
!python sample_holistic.py を実行した時のメッセージを次に示します。
[ WARN:0] global /io/opencv/modules/videoio/src/cap_v4l.cpp (802) open VIDEOIO ERROR: V4L: can’t open camera by index 0
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
また、「自分で設定したフォルダー」と言う意味が分かりません。%cd mediapipe を実行しても何のエラーも出ないので出来ているのではないでしょうか?
bravoastro さん
ご連絡ありがとうございます。
!python sample_holistic.py を実行した時のメッセージを拝見しますと、google colabで動かそうとされている様です。このコードは、google colabでは動作しません。
ブログにあります様に、リンク(https://qiita.com/tttamaki/items/0d4fc01c10dd40a13552)をご覧頂き、PCにJupyter Notebook をインストールして実行して下さい。
また、Git(コードをコピーするライブラリー)をインストールしてなければ、このリンク(https://qiita.com/libra219/items/e49f9cc833ad9bb5d1ca)を参考に合わせてインストールして下さい。
*「自分で設定したフォルダー」というは、!git clone する時のディレクトリという意味です。分かり難くてすみません。
bravoastro さん
ブログの該当部分が勘違いし易いように思いましたので、修正します。
ありがとうございます。
cedro様
姿勢推定について最近調べ始めたAIも全く分からない素人です。
今週になってCOLAB等で姿勢推定が比較的簡単にできることを知りました。
さて、拝見したコードをそのままコピペして試していますが、MP4を自分で用意したものに変えて動かしてみたいのですが、ファイルをPCのどこに保存すればよいのか分かりません。
# ビデオの指定
video_path = ‘./video/satomi.mp4’
この部分を変更すればよいと記載があるものの、実際にファイルをPCのどこに格納すればよいかが分かりません。
ご教示賜れますでしょうか。
よろしくお願いいたします。
! python sample_holistic.py
を使おうと思ったとき
Traceback (most recent call last):
File “sample_holistic.py”, line 662, in
main()
File “sample_holistic.py”, line 58, in main
holistic = mp_holistic.Holistic(
TypeError: __init__() got an unexpected keyword argument ‘upper_body_only’
[ WARN:0] global C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-k1ohfcms\opencv\modules\videoio\src\cap_msmf.cpp (438) `anonymous-namespace’::SourceReaderCB::~SourceReaderCB terminating async callback
というエラーがおきました。
upper_body_onlyが必要ないhand.pyのみうまくいきましたが、それ以外はこのエラーが起きてしまいます。
理由などが分かれば返信よろしくお願いいたします。
諸橋さん
コメントありがとうございます。
先ほど、こちらでも試してみましたがご連絡頂いたエラーが再現しません。
ライブラリーの何かのバージョンが古いせいかもしれませんね。
試しに、argparse のバージョンをアップデートしてみて下さい。
G3さん
コメントありがとうございます。
ブログにあるcolabリンクをお使いですよね。
その場合は、ご自分で用意されたmp4動画を、PCからドラッグ&ドロップで、./mediapipe/video フォルダーにアップロードして下さい。あとは、video_path = ‘./video/***.mp4 の***.mp4 をご自分で用意されたファイル名に変更すればOKです。
cedro様
お世話になります。
家でやってみた所、うまくできました。
ありがとうございました。
G3さん
それは良かったです。^^
こんにちはこんばんは、このエラーが発生します。
私はすでにargparseをpycharm1.4を含む最新バージョンに更新しました、そしてそれは出続けます、私は何ができますか?
ファイル “C:\ Users \ JUnty \ Desktop \ Tska \ RULA \ Holistic.py”、58行目、メイン
holistic = mp_holistic.Holistic(
TypeError:__ init __()が予期しないキーワード引数 ‘upper_body_only’を取得しました
Linaさん
ご連絡ありがとうございます。
Mediapipeがアップデートされ、今まで使われていた引数が使われなくなりエラーが発生していました。助かりました。
コードは修正済みですので、もう一度使ってみて下さい。
自分で撮った動画でキャプション出来るかをgoogle colaboで試してみました。mediapipe/imageに動画のpngが出来ていることは確認できましたが、そのあとに次のエラーが出ます。何かお判りでしょうか?上のコメントと同じようにMediapipeのアップデートでしょうか?cedroさんがForkされていても影響を受けるのでしょうか?
AttributeError Traceback (most recent call last)
in ()
23 image=annotated_image,
24 landmark_list=results.face_landmarks,
—> 25 connections=mp_holistic.FACE_CONNECTIONS,
26 landmark_drawing_spec=drawing_spec,
27 connection_drawing_spec=drawing_spec)
AttributeError: module ‘mediapipe.python.solutions.holistic’ has no attribute ‘FACE_CONNECTIONS’
bravoastroさん
こんにちは。
お察しの通り、Mediapipeがアップデートされて、当初のままではエラーが発生していたのでgithub(google colab含む)の一部をアップデートしました。
再度、ブログのリンクから飛んで下さい。
cedro様
お世話になります。
Jupyter Notebookにて、
# MediaPipeをインストール
!pip install mediapipe
# Gitgub からコードをコピー
!git clone https://github.com/cedro3/mediapipe.git
%cd mediapipe/
を実行し、mediapipeのファイルがインストールされております。次に
!python sample_holistic.py
を実行しますと、
Traceback (most recent call last):
File “sample_holistic.py”, line 6, in
import cv2 as cv
ModuleNotFoundError: No module named ‘cv2’
というエラーが表示されます。
これは、
!python sample_hand.py
!python sample_pose.py
でも同じエラーメッセージが出てまいります。
どのように対処すれば良いかをお教えいただけませんでしょうか?
よろしくお願いいたします。
ピーチママさん
OpenCVがインストールされていないようですので、下記リンクを参考にインストールしてみて下さい。
https://techacademy.jp/magazine/51404
cedro様
お世話になります。OpenCVをJupyter Notebookにインストールできていませんでした。やってみます。ご指導ありがとうございました。