顔認識は、AI 研究が世界にもたらした数多くの驚異のうちの 1 つです。これは多くの技術者にとって興味深いトピックであり、彼らは物事がどのように機能するかについて基本的な理解を得たいと考えています。このテーマについて詳しく調べて、仕組みを見てみましょう。 顔認識 このような問題を解決するときは、車輪の再発明をしないことが最善です。それは不可能です!研究者が提供したモデルに従うのが最善です。オープンソースで利用できるツールも数多くあります。そのような Python ライブラリの 1 つが face_recognition です。それはいくつかのステップで機能します: - 与えられた画像内の顔を認識する
- 顔の特徴を認識する
- 128値の顔エンコーディングベクトルを生成する
このエンコーディングに基づいて、2 つの顔画像間の類似性を測定することができ、それによってそれらが同一人物のものであるかどうかがわかります。 まずface_recognitionモジュールをインストールします - 顔認識をpipでインストールする
モジュールのインポート 次に、必要なモジュールをインポートします - PIL.Imageをインポートする
- PIL.ImageDrawをインポートする
- 輸入リクエスト
- ioからBytesIOをインポート
-
- IPython.displayからdisplayをインポートする
-
- 顔認識をインポートする
画像を読み込んでいます 次に、画像を読み込みます。画像をGithubアカウントに保存しました。こうすることで、URL から元の画像を読み取ることができます。 - レスポンス = リクエスト.get( "https://raw.githubusercontent.com/solegaonkar/solegaonkar.github.io/master/img/rahul1.jpeg" )
- fr_image = 顔認識.load_image_file(BytesIO(応答.content))
顔を認識する 顔が読み込まれたら、face_recognition モジュールのさまざまな部分を見てみましょう。どうやって顔を認識するのですか? - 顔の位置 = 顔認識.顔の位置(fr_image)
-
- 面の数 = len(面の位置)
- print( "この写真には {} 人の顔が見つかりました。" .format(number_of_faces))
出力は次のようになります: - この写真の中に1 人の顔が見つかりました。</span>
これは、アルゴリズムが画像内で 1 つの顔のみを検出したことを意味します。認識された画像と顔を見てみましょう。 - pil_image = PIL.Image.fromarray(fr_image)
-
- face_locations 内の face_locationの場合:
- #この画像内の各面の位置を出力します。各面は、(上、右、下、左) の順序で並べられた座標のリストです。
- 上、右、下、左 = 顔の位置
- print( "顔はピクセル位置にあります。上: {}、左: {}、下: {}、右: {}" .format(top, left, bottom, right))
- # 顔の周りにボックスを描きましょう
- 描画 = PIL.ImageDraw.Draw(pil_image)
- draw.rectangle([左、上、右、下]、アウトライン= "黒" )
これにより出力が得られる - 顔は、ピクセル位置上: 68 、左: 117 、下: 291 、右: 340 にあります。
上記のコードは、画像を変更して顔の周囲に四角形を描画します。うまく動作するか確認してみましょう。 それはすでに可能です。 フェイスコーディング これが私たちの顔です。しかし、私たちのアルゴリズムにとって、それは単なる RGB 値の配列であり、私たちが入力したデータ サンプルから学習したパターンに一致するものです。 顔認識の場合、アルゴリズムは目の色、大きさ、傾き、眉間の間隔など、顔の特定の重要な測定値を記録します。これらすべてを組み合わせることで、特定の顔を認識するために使用される顔コード(画像から取得される情報)が定義されます。 顔から何が読み取られるかを理解するために、読み取られるエンコードを見てみましょう。 - face_encodings = face_recognition.face_encodings(fr_image)
- フェイスエンコーディング[ 0 ]
巨大な配列を出力します: - 配列([- 0.10213576 , 0.05088161 , - 0.03425048 , - 0.09622347 , - 0.12966095 ,
- 0.04867411 、 - 0.00511892 、 - 0.03418527 、 0.2254715 、 - 0.07892745 、
- 0.21497472 、 - 0.0245543 、 - 0.2127848 、 - 0.08542262 、 - 0.00298059 、
- 0.13224372 、 - 0.21870363 、 - 0.09271716 、 - 0.03727289 、 - 0.1250658 、
- 0.09436664 、 0.03037129 、 - 0.02634972 、 0.02594662 、 - 0.1627259 、
- - 0.29416466 、 - 0.12254384 、 - 0.15237436 、 0.14907973 、 - 0.09940194 、
- 0.02000656 , 0.04662619 , - 0.1266906 , - 0.11484023 , 0.04613583 ,
- 0.1228286 、 - 0.03202137 、 - 0.0715076 、 0.18478717 、 - 0.01387333 、
- - 0.11409076 、 0.07516225 、 0.08549548 、 0.31538364 、 0.1297821 、
- 0.04055009 , 0.0346106 , - 0.04874525 , 0.17533901 , - 0.22634712 ,
- 0.14879328 、 0.09331974 、 0.17943285 、 0.02707857 、 0.22914577 、
- - 0.20668915 , 0.03964197 , 0.17524502 , - 0.20210043 , 0.07155308 ,
- 0.04467429 , 0.02973968 , 0.00257265 , - 0.00049853 , 0.18866715 ,
- 0.08767469 、 - 0.06483966 、 - 0.13107982 、 0.21610288 、 - 0.04506358 、
- - 0.02243116 、 0.05963502 、 - 0.14988004 、 - 0.11296406 、 - 0.30011353 、
- 0.07316103 、 0.38660526 、 0.07268623 、 - 0.14636359 、 0.08436179 、
- 0.01005938 、 - 0.00661338 、 0.09306039 、 0.03271955 、 - 0.11528577 、
- - 0.0524189 、 - 0.11697718 、 0.07356471 、 0.10350288 、 - 0.03610475 、
- 0.00390615 , 0.17884226 , 0.04291092 , - 0.02914601 , 0.06112404 ,
- 0.05315027 、 - 0.14561613 、 - 0.01887275 、 - 0.13125736 、 - 0.0362937 、
- 0.16490118 、 - 0.09027836 、 - 0.00981111 、 0.1363602 、 - 0.23134531 、
- 0.0788044 、 - 0.00604869 、 - 0.05569676 、 - 0.07010217 、 - 0.0408107 、
- - 0.10358225 、 0.08519378 、 0.16833456 、 - 0.30366772 、 0.17561394 、
- 0.14421709 、 - 0.05016343 、 0.13464174 、 0.0646335 、 - 0.0262765 、
- 0.02722404 、 - 0.06028951 、 - 0.19448066 、 - 0.07304715 、 0.0204969 、
- - 0.03045784 、 - 0.02818791 、 0.06679841 ])
これらの数字はそれぞれ、顔のエンコーディングの直交成分を表します。 類似点 では、次のステップ、つまり顔の類似性を判断することに進みましょう。これを行うには、さらに画像を読み込む必要があります。 まず、3 つの画像を読み込みます。画像を読み込むときも、まず顔を検索し、次に顔のエンコーディングを検索します。 - レスポンス = リクエスト.get( "https://raw.githubusercontent.com/solegaonkar/solegaonkar.github.io/master/img/rahul1.jpeg" )
- image_of_person_1 = face_recognition.load_image_file(BytesIO(response.content))
- 顔の位置 = 顔認識.顔の位置(人物1の画像)
- person_1_face_encoding = face_recognition.face_encodings(人物1の画像、既知の顔の場所=顔の場所)
-
- レスポンス = リクエスト.get( "https://raw.githubusercontent.com/solegaonkar/solegaonkar.github.io/master/img/rahul2.jpg" )
- image_of_person_2 = face_recognition.load_image_file(BytesIO(response.content))
- 顔の位置 = 顔認識.顔の位置(人物2の画像)
- person_2_face_encoding = face_recognition.face_encodings(人物2の画像、既知の顔の場所=顔の場所)
-
- レスポンス = リクエスト.get( "https://raw.githubusercontent.com/solegaonkar/solegaonkar.github.io/master/img/trump.jpg" )
- image_of_person_3 = face_recognition.load_image_file(BytesIO(response.content))
- 顔の位置 = face_recognition.face_locations(人物の画像3)
- person_3_face_encoding = face_recognition.face_encodings(image_of_person_3、known_face_locations=face_locations) のようになります。
今では、類似点を特定することは難しくありません。 face_recognition モジュールはシンプルな API を提供します。 - 顔認識.比較顔([person_1_face_encoding,person_3_face_encoding], person_2_face_encoding[ 0 ], 許容値= 0.08 )
このメソッドは、比較する 2 つの面の各コンポーネントをチェックし、現在のコンポーネントが許容範囲内で変化するかどうかを通知します。上記のコマンドを実行すると、次の出力が表示されます。 - [配列([ 真、真、真、真、真、真、真、真、真、真、
- 本当、本当、本当、本当、本当、本当、本当、本当、本当、本当、
- 本当、本当、本当、本当、本当、本当、本当、本当、本当、本当、
- 本当、本当、本当、本当、本当、本当、本当、本当、本当、本当、
- 本当、本当、本当、本当、偽、本当、本当、本当、本当、
- 本当、本当、本当、本当、本当、本当、本当、本当、本当、偽、
- 本当、本当、本当、本当、本当、本当、本当、本当、本当、本当、
- 本当、本当、本当、本当、本当、本当、偽、本当、本当、本当、
- 本当、本当、本当、本当、本当、本当、本当、本当、本当、偽、
- 本当、本当、本当、本当、本当、本当、本当、本当、本当、本当、
- 本当、本当、本当、偽、本当、本当、本当、本当、本当、
- 本当、本当、本当、本当、本当、本当、本当、本当、本当、本当、
- 本当、本当、本当、本当、本当、本当、本当、本当、本当、本当、
- 本当、本当、本当、本当、本当、本当、本当、本当、本当、偽、
- 本当だよ、本当だよ])、
- 配列([ True, True, True, True, True, True, False, False, False,
- 本当、本当、本当、偽、本当、本当、本当、偽、本当、
- 偽、真、真、真、真、偽、真、真、真、
- 偽、真、真、真、偽、真、真、真、真、
- 本当、本当、本当、本当、偽、本当、偽、本当、本当、
- 本当、本当、本当、偽、本当、偽、本当、本当、本当、
- 偽、偽、真、真、真、真、真、偽、真、
- 偽、偽、偽、偽、真、偽、真、偽、真、
- 偽、真、真、真、真、偽、真、真、真、
- 本当、本当、本当、偽、本当、本当、本当、偽、本当、
- 本当、嘘、本当、本当、本当、本当、本当、本当、本当、本当、
- 本当、本当、本当、本当、本当、本当、偽、偽、本当、本当、
- 偽、偽、偽、真、真、偽、真、真、真、
- 本当、本当、本当、本当、本当、本当、本当、偽り、偽り、本当、
- 本当だよ、本当だよ
これら 2 つの配列は、指定された画像 (2 番目の引数) と、指定されたリスト (最初の引数) 内の各既知の顔エンコーディングとの類似性を表します。 最初の配列の方が類似点が多いことがわかります。人物を正確に識別できます。 デジタルメイク 楽しみたいなら、顔認識ライブラリでできることは他にもたくさんあります。顔の個々の特徴を識別するのに役立つ API があります。 - 顔のランドマークリスト = 顔認識.顔のランドマーク(fr_image)
- print(face_landmarks_list)
これにより、個々の特性曲線の長いリストが得られます。 - [{
- 「あご」 : [( 46 , 47 ), ( 45 , 54 ), ( 44 , 62 ), ( 44 , 69 ), ( 44 , 77 ), ( 46 , 84 ), ( 49 , 91 ), ( 54 , 95 ) , ( 61 , 97 ), ( 68 , 97 ), ( 76 , 95 ), ( 84 , 91 ) , ( 90 , 87 ), ( 94 , 81 ), ( 97 , 75 ) , ( 99 , 68 ) , ( 101 , 60 ) ] ,
- '左眉' : [( 51 , 42 ), ( 54 , 39 ), ( 58 , 39 ), ( 63 , 40 ), ( 67 , 42 )],
- '右眉' : [( 75 , 44 ), ( 80 , 44 ), ( 86 , 44 ), ( 90 , 47 ), ( 93 , 51 )],
- 'ノーズブリッジ' : [( 70 , 48 ), ( 68 , 52 ), ( 67 , 56 ), ( 66 , 60 )],
- '鼻先' : [( 60 , 64 ), ( 62 , 65 ), ( 65 , 67 ), ( 68 , 66 ), ( 71 , 66 )],
- '左目' : [( 55 , 47 ), ( 57 , 45 ), ( 61 , 46 ), ( 63 , 48 ), ( 60 , 48 ), ( 57 , 48 )],
- '右目' : [( 77 , 51 ), ( 80 , 50 ), ( 84 , 51 ), ( 86 , 54 ), ( 83 , 54 ), ( 79 , 53 )],
- '上唇' : [( 54 , 75 ), ( 58 , 72 ), ( 61 , 72 ), ( 64 , 73 ) , ( 66 , 73 ), ( 70 , 75 ), ( 73 , 80 ), ( 71 , 79 ) , ( 66 , 75 ), ( 63 , 75 ), ( 61 , 74 ) , ( 56 , 75 ) ] ,
- '下唇' : [( 73 , 80 ), ( 68 , 81 ), ( 64 , 81 ), ( 62 , 80 ), ( 60 , 80 ), ( 57 , 78 ), ( 54 , 75 ), ( 56 , 75 ) , ( 60 , 77 ), ( 63 , 78 ), ( 65 , 78 ) , ( 71 , 79 ) ]
- }]
この画像にデジタルメイクを施すことができます。 - face_landmarks_list 内の face_landmarksの場合:
- pil_image = PIL.Image.fromarray(fr_image)
- d = PIL.ImageDraw.Draw(pil_image, 'RGBA' ) です。
-
- # 眉毛を悪夢にする
- d.line(face_landmarks[ 'left_eyebrow' ], 塗りつぶし=( 0 , 0 , 0 , 255 ), 幅= 3 )
- d.line(face_landmarks[ 'right_eyebrow' ], 塗りつぶし=( 0 , 0 , 0 , 255 ), 幅= 3 )
- d.polygon(face_landmarks[ 'left_eyebrow' ], fill=( 0 , 0 , 0 , 255 ))
- d.polygon(face_landmarks[ 'right_eyebrow' ], fill=( 0 , 0 , 0 , 255 ))
-
- # 唇にグロスを塗る
- d.line(face_landmarks[ 'top_lip' ], 塗りつぶし=( 0 , 0 , 0 , 255 ), 幅= 10 )
- d.line(face_landmarks[ 'bottom_lip' ], 塗りつぶし=( 0 , 0 , 0 , 255 ), 幅= 10 )
-
- d.polygon(face_landmarks[ 'bottom_lip' ], fill=( 255 , 0 , 0 , 255 ))
- d.polygon(face_landmarks[ 'top_lip' ], fill=( 255 , 0 , 0 , 255 ))
- d.line(face_landmarks[ 'top_lip' ], 塗りつぶし=( 0 , 0 , 0 , 255 ), 幅= 2 )
- d.line(face_landmarks[ 'bottom_lip' ], 塗りつぶし=( 0 , 0 , 0 , 255 ), 幅= 2 )
-
- # チン
- d.polygon(face_landmarks[ 'あご' ], fill=( 255 , 0 , 0 , 16 ))
-
- # アイライナーを塗る
- d.line(face_landmarks[ 'left_eye' ] + [face_landmarks[ 'left_eye' ][ 0 ]], 塗りつぶし=( 10 , 0 , 0 , 255 ), 幅= 6 )
- d.line(face_landmarks[ 'right_eye' ] + [face_landmarks[ 'right_eye' ][ 0 ]], 塗りつぶし=( 10 , 0 , 0 , 255 ), 幅= 6 )
-
- # 目を輝かせる
- d.polygon(face_landmarks[ 'left_eye' ], fill=( 255 , 0 , 0 , 200 ))
- d.polygon(face_landmarks[ 'right_eye' ], fill=( 255 , 0 , 0 , 200 ))
-
- 表示(pil_image)
これが私たちが得たものです。 |