OpenCVとPythonを使用して画像から顔を検出および抽出する方法

_著者はhttps://www.brightfunds.org/funds/open-internet-free-speech[Open Internet / Free Speech Fund]を選択してhttps://do.co/w4do-ctaの一部として寄付を受け取りました[寄付のために書く]プログラム。

前書き

画像は毎日生成される大量のデータを構成するため、これらの画像を処理する能力が重要になります。 画像を処理する1つの方法は、_顔検出_を使用することです。 顔検出は、機械学習を使用して画像内の顔を検出する画像処理のブランチです。

Haar Cascadeは、画像内の目的のオブジェクトを見つけるために使用されるオブジェクト検出方法です。 アルゴリズムは、多数の正および負のサンプルでトレーニングされます。ここで、正のサンプルは、目的のオブジェクトを含む画像です。 ネガサンプルは、目的のオブジェクト以外のものを含む可能性のある画像です。 訓練された分類器は、新しい画像で関心のあるオブジェクトを見つけることができます。

このチュートリアルでは、事前トレーニング済みのhttps://github.com/opencv/opencv/tree/master/data/haarcascades[Haar Cascade]モデルをhttps://opencv.org/[OpenCV]およびhttpsから使用します。 //www.python.org/[Python]は、画像から顔を検出して抽出します。 OpenCVは、画像の処理に使用されるオープンソースのプログラミングライブラリです。

前提条件

  • httpsを含むhttps://www.digitalocean.com/community/tutorial_series/how-to-install-and-set-up-a-local-programming-environment-for-python-3 [ローカルPython 3開発環境] ://pypi.org/project/pip/ [+ pip +]、Pythonパッケージをインストールするためのツール、およびhttps://docs.python.org/3/library/venv.html [+ venv +]、仮想環境を作成します。

手順1-ローカル環境の構成

コードの記述を開始する前に、まずコードを保持するワークスペースを作成し、いくつかの依存関係をインストールします。

`+ mkdir +`コマンドでプロジェクト用のディレクトリを作成します:

mkdir

新しく作成したディレクトリに移動します。

cd

次に、このプロジェクトの仮想環境を作成します。 仮想環境は異なるプロジェクトを分離するため、異なる依存関係が混乱を引き起こすことはありません。 このプロジェクトで使用する `+ face_scrapper +`という名前の仮想環境を作成します。

python3 -m venv

隔離された環境をアクティブにします。

source /bin/activate

これで、プロンプトの前に仮想環境の名前が付いていることがわかります。

仮想環境を有効にしたので、 `+ nano `またはお気に入りのテキストエディターを使用して ` requirements.txt +`ファイルを作成します。 このファイルは、必要なPython依存関係を示しています。

nano requirements.txt

次に、このチュートリアルを完了するには、3つの依存関係をインストールする必要があります。

  • + numpy +:https://en.wikipedia.org/wiki/NumPy[numpy]は、大規模な多次元配列のサポートを追加するPythonライブラリです。 また、配列を操作する数学関数の大規模なコレクションが含まれています。

  • + opencv-utils +:これは、ヘルパー関数を含むOpenCVの拡張ライブラリです。

  • + opencv-python +:これはPythonが使用するコアOpenCVモジュールです。

ファイルに次の依存関係を追加します。

requirements.txt

numpy
opencv-utils
opencv-python

ファイルを保存して閉じます。

`+ requirements.txt `ファイルをPythonパッケージマネージャーの ` pip `に渡すことで、依存関係をインストールします。 ` -r `フラグは、 ` requirements.txt +`ファイルの場所を指定します。

pip install -r requirements.txt

このステップでは、プロジェクトの仮想環境をセットアップし、必要な依存関係をインストールします。 次のステップで入力画像から顔を検出するコードの記述を開始する準備ができました。

ステップ2-顔検出スクリプトの作成と実行

このセクションでは、イメージを入力として受け取り、次の2つのことを返すコードを作成します。

  • 入力画像で見つかった顔の数。

  • 検出された各顔の周りに長方形のプロットがある新しい画像。

コードを保持する新しいファイルを作成することから始めます。

nano app.py

この新しいファイルで、最初に必要なライブラリをインポートして、コードの記述を開始します。 ここでは、2つのモジュール「+ cv2 」と「 sys 」をインポートします。 ` cv2 `モジュールは ` OpenCV `ライブラリをプログラムにインポートし、 ` sys `はコードが使用する ` argv +`などの一般的なPython関数をインポートします。

app.py

import cv2
import sys

次に、入力画像が実行時にスクリプトに引数として渡されるように指定します。 Pythonの最初の引数を読み取る方法は、 `+ sys.argv [1] +`関数によって返される値を変数に割り当てることです。

app.py

...
imagePath = sys.argv[1]

画像処理の一般的な方法は、最初に入力画像をグレースケールに変換することです。 これは、色ではなく輝度を検出すると、一般的にオブジェクト検出の結果が向上するためです。 次のコードを追加して、入力画像を引数として取得し、グレースケールに変換します。

app.py

...
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

`+ .imread()`関数は、スクリプトに引数として渡される入力画像を取得し、OpenCVオブジェクトに変換します。 次に、OpenCVの ` .cvtColor()+`関数は入力画像オブジェクトをグレースケールオブジェクトに変換します。

画像を読み込むコードを追加したので、指定した画像の顔を検出するコードを追加します。

app.py

...
faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
faces = faceCascade.detectMultiScale(
       gray,
       scaleFactor=1.3,
       minNeighbors=3,
       minSize=(30, 30)
)

print("Found {0} Faces!".format(len(faces)))

このコードは、 `+ cv2.CascadeClassifier `メソッドでHaar Cascadeファイルをロードする ` faceCascade +`オブジェクトを作成します。 これにより、PythonとコードでHaar Cascadeを使用できます。

次に、コードはOpenCVの `+ .detectMultiScale()`メソッドを ` faceCascade `オブジェクトに適用します。 これにより、画像内で検出されたすべての顔の_長方形のリスト_が生成されます。 長方形のリストは、 ` Rect(x、y、w、h)+`の形式の、画像からのピクセル位置のコレクションです。

コードで使用する他のパラメーターの概要は次のとおりです。

  • + gray +:これは、前にロードしたOpenCVグレースケールイメージオブジェクトの使用を指定します。

  • + scaleFactor +:このパラメーターは、各画像スケールで画像サイズを縮小するレートを指定します。 トレーニング中のモデルのスケールは固定されているため、検出を改善するために入力画像を縮小できます。 このプロセスは、「+ maxSize 」と「 minSize +」で定義されたしきい値制限に達した後に停止します。

  • + minNeighbors +:このパラメーターは、各候補長方形がそれを保持する必要がある近傍または検出の数を指定します。 値を大きくすると誤検知が少なくなる場合がありますが、値が高すぎると真の陽性が除去される可能性があります。

  • + minSize +:これにより、ピクセル単位で測定可能な最小オブジェクトサイズを定義できます。 このパラメーターより小さいオブジェクトは無視されます。

長方形のリストを生成した後、面は `+ len +`関数でカウントされます。 検出された顔の数は、スクリプトの実行後に出力として返されます。

次に、OpenCVの `+ .rectangle()+`メソッドを使用して、検出された顔の周りに長方形を描画します。

app.py

...
for (x, y, w, h) in faces:
   cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)

このコードは、_for loop_を使用して、検出された各オブジェクトの `+ faceCascade.detectMultiScale `メソッドから返されたピクセル位置のリストを反復処理します。 ` rectangle +`メソッドは4つの引数を取ります:

  • `+ image +`は、元の入力画像上に長方形を描くようにコードに指示します。

  • `(x、y)、(x + w、y + h)`は、検出されたオブジェクトの4つのピクセル位置です。 `+ rectangle +`はこれらを使用して、入力画像で検出されたオブジェクトの周囲に長方形を配置して描画します。

  • `(0、255、0)`は形状の色です。 この引数は、BGRのタプルとして渡されます。 たとえば、青には「(255、0、0)」を使用します。 この場合、緑を使用しています。

  • 「2」は、ピクセル単位で測定される線の太さです。

長方形を描画するコードを追加したので、OpenCVの `+ .imwrite()`メソッドを使用して、新しい画像をローカルファイルシステムに ` faces_detected.jpg `として書き込みます。 このメソッドは、書き込みが成功した場合は「 true 」を返し、新しいイメージを書き込むことができなかった場合は「 false +」を返します。

app.py

...
status = cv2.imwrite('faces_detected.jpg', image)

最後に、このコードを追加して、 + .imwrite()+`関数の `+ true`または + false`ステータスをコンソールに返します。 これにより、スクリプトの実行後に書き込みが成功したかどうかがわかります。

app.py

...
print ("Image faces_detected.jpg written to filesystem: ",status)

完成したファイルは次のようになります。

app.py

import cv2
import sys

imagePath = sys.argv[1]

image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
faces = faceCascade.detectMultiScale(
   gray,
   scaleFactor=1.3,
   minNeighbors=3,
   minSize=(30, 30)
)

print("[INFO] Found {0} Faces!".format(len(faces)))

for (x, y, w, h) in faces:
   cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)

status = cv2.imwrite('faces_detected.jpg', image)
print("[INFO] Image faces_detected.jpg written to filesystem: ", status)

すべてが正しく入力されていることを確認したら、ファイルを保存して閉じます。

コードが完成し、スクリプトを実行する準備が整いました。

ステップ3-スクリプトの実行

この手順では、画像を使用してスクリプトをテストします。 テストに使用したい画像を見つけたら、 `+ app.py +`スクリプトと同じディレクトリに保存します。 このチュートリアルでは、次の画像を使用します。

image:https://assets.digitalocean.com/articles/CART-63965/people_with_phones.png [携帯電話を見ている4人の入力画像]

同じイメージでテストする場合は、次のコマンドを使用してダウンロードします。

curl -O https://assets.digitalocean.com/articles/CART-63965/people_with_phones.png

スクリプトをテストするためのイメージを作成したら、スクリプトを実行し、引数としてイメージパスを提供します。

python app.py

スクリプトの実行が完了すると、次のような出力が表示されます。

Output[INFO] Found 4 Faces!
[INFO] Image faces_detected.jpg written to filesystem:

`+ true +`の出力は、更新されたイメージがファイルシステムに正常に書き込まれたことを示しています。 ローカルマシンでイメージを開き、新しいファイルの変更を確認します。

image:https://assets.digitalocean.com/articles/CART-63965/people_with_phones_detection.png [検出された顔の出力画像]

スクリプトが入力画像で4つの顔を検出し、それらをマークするために長方形を描いたことがわかります。 次のステップでは、ピクセル位置を使用して画像から顔を抽出します。

ステップ4-顔の抽出とローカルでの保存(オプション)

前のステップでは、OpenCVとHaar Cascadeを使用して画像内の顔の周囲の長方形を検出および描画するコードを作成しました。 このセクションでは、コードを変更して、検出された顔を画像から独自のファイルに抽出します。

テキストエディタで `+ app.py +`ファイルを再度開くことから始めます。

nano app.py

次に、 `+ cv2.rectangle +`行の下に強調表示された行を追加します。

app.py

...
for (x, y, w, h) in faces:
   cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)



...

`+ roi_color `オブジェクトは、元の入力画像の ` faces `リストからピクセル位置をプロットします。 「 x 」、「 y 」、「 h 」、および「 w 」変数は、「 faceCascade.detectMultiScale +」メソッドで検出された各オブジェクトのピクセル位置です。 次に、コードは、オブジェクトが見つかり、ローカルに保存されることを示す出力を印刷します。

それが完了すると、コードは `+ cv2.imwrite +`メソッドを使用して、プロットを新しいイメージとして保存します。 プロットの幅と高さを、書き込まれる画像の名前に追加します。 これにより、複数の顔が検出された場合に名前が一意になります。

更新された `+ app.py +`スクリプトは次のようになります。

app.py

import cv2
import sys

imagePath = sys.argv[1]

image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
faces = faceCascade.detectMultiScale(
   gray,
   scaleFactor=1.3,
   minNeighbors=3,
   minSize=(30, 30)
)

print("[INFO] Found {0} Faces.".format(len(faces)))

for (x, y, w, h) in faces:
   cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
   roi_color = image[y:y + h, x:x + w]
   print("[INFO] Object found. Saving locally.")
   cv2.imwrite(str(w) + str(h) + '_faces.jpg', roi_color)

status = cv2.imwrite('faces_detected.jpg', image)
print("[INFO] Image faces_detected.jpg written to filesystem: ", status)

要約すると、更新されたコードはピクセル位置を使用して、画像から顔を新しいファイルに抽出します。 コードの更新が完了したら、ファイルを保存して閉じます。

コードを更新したので、スクリプトをもう一度実行する準備ができました。

python app.py

スクリプトが画像の処理を完了すると、同様の出力が表示されます。

Output[INFO] Found 4 Faces.
[INFO] Object found. Saving locally.
[INFO] Object found. Saving locally.
[INFO] Object found. Saving locally.
[INFO] Object found. Saving locally.
[INFO] Image faces_detected.jpg written to file-system:

サンプル画像に含まれる顔の数に応じて、多少の出力が表示される場合があります。

スクリプトの実行後に作業ディレクトリの内容を見ると、入力画像で見つかったすべての顔のヘッドショットのファイルが表示されます。

image:https://assets.digitalocean.com/articles/CART-63965/directory.png [ディレクトリ一覧]

作業ディレクトリに収集された入力画像から抽出されたヘッドショットが表示されます。

image:https://assets.digitalocean.com/articles/CART-63965/extracted_faces.png [抽出された顔]

この手順では、入力画像から検出されたオブジェクトを抽出し、ローカルに保存するようにスクリプトを変更しました。

結論

このチュートリアルでは、OpenCVとPythonを使用して、入力画像から顔を検出、カウント、抽出するスクリプトを作成しました。 このスクリプトを更新して、OpenCVライブラリの事前トレーニング済みの異なるHaar Cascadeを使用して異なるオブジェクトを検出するか、https://docs.opencv.org/3.3.0/dc/d88/tutorial_traincascade.htmlの方法を学習できます。 [独自のトレーニング] Haar Cascade。