【Python】画像から物体の種類、座標、幅、高さを検出する

概要

Info

(2021/9/11追記)PyTorchとYOLOv5を使用して、物体の種類、座標、幅、高さを検出する方法を書きました。
準備と物体検出が簡単にできるので、こちらを参照することをおすすめします。

以前、keras-yolo3を使用して画像と動画から物体検出を行う方法を書きました。

https://kazusa-pg.com/use-keras-yolo3/

keras-yolo3を利用すると画像から物体を検出して、検出した物体のクラス名と確率を画像に出力してくれます。

Photo by rawpixel.com from Pexels

検出した物体を切り抜きたいときは、物体の座標、幅、高さが必要になります。
keras-yolo3を利用して物体の種類、左上の座標、幅、高さを求められるようにしてみます。

動作環境

  • Windows10
  • Python3.7.9
  • パッケージ管理にPipenvを使用

object-detection-keras-yolo3の利用方法

keras-yolo3のコードを利用して物体の種類、左上の座標、幅、高さを画像から検出するPythonスクリプトを作成しました。
https://github.com/kazusapg/object-detection-keras-yolo3

keras-yolo3のweight変換方法を踏襲しているので、検出できる物体は80種類です。
検出できる物体はこちらを参照してください。
https://github.com/kazusapg/object-detection-keras-yolo3/blob/master/model_data/coco_classes.txt

インストール方法

object-detection-keras-yolo3のダウンロード

gitでcloneをする場合は以下を入力してください。

1git clone https://github.com/kazusapg/object-detection-keras-yolo3.git

またはgithubのページ右側の緑色のclone or downloadをクリック後Download ZIPを選択し、
ファイルをダウンロードしてから解凍してください。
https://github.com/kazusapg/object-detection-keras-yolo3

Pipenvを利用したインストール

Pipenvで仮想環境を作成する場合はコマンドプロンプトまたはPowerShellで
object-detection-keras-yolo3フォルダに移動後、pipenv installを入力します。
必要なパッケージをインストールした後に、pipenv shellで仮想環境に入ります。

1cd object-detection-keras-yolo3
2pipenv install
3pipenv shell

YOLOv3 weightsの変換

YOLO: Real-Time Object DetectionからYOLOv3 weightsをダウンロードします。
https://pjreddie.com/darknet/yolo/

weightsファイルはページ内のhere(237MB)をクリックするとダウンロードできます。

You already have the config file for YOLO in the cfg/ subdirectory.
You will have to download the pre-trained weight file here (237 MB).

ダウンロードしたweightsファイルをobject-detection-keras-yolo3フォルダに移動し、
下記のコマンドを入力してweightsファイルをkerasで利用できる形に変換します。

1python keras_yolo3/convert.py keras_yolo3/yolov3.cfg yolov3.weights model_data/yolo.h5

使用方法

  1. keras.yolo3からYOLOクラスをインポートします。
  2. objectsからget_objects_informationをインポートします。
  3. YOLOクラスのインスタンスを作成します。
  4. YOLOインスタンスと画像のファイルパスを引数としてget_objects_information関数を呼び出します。
  5. get_objects_information関数は、検出した物体ごとにdictionaryを生成し、生成したdictionaryをListに加えて返します。
    物体が検出できないときは空のListを返します。

get_objects_information関数内で生成されるdictionaryは下記のキーを参照することで、それぞれの物体の情報を取得できます。

キー 情報
predicted_name 検出した物体のクラス名(人、自転車、車など)
x 検出した物体の左上座標のx位置
y 検出した物体の左上座標のy位置
width 検出した物体の幅
height 検出した物体の高さ

使用例

下記の画像から物体の情報を取得してみます。

Photo by rawpixel.com from Pexels

コードは以下になります。
画像はsample_picture.jpgという名前でpictureフォルダに保存されているとします。

 1from PIL import Image
 2from keras_yolo3.yolo import YOLO
 3from objects import get_objects_information
 4
 5if __name__ == '__main__':
 6    yolo = YOLO()
 7    image_path = "./picture/sample_picture.jpg"
 8    objects_info_list = get_objects_information(yolo, image_path)
 9    yolo.close_session()
10
11    img = Image.open(image_path)
12    count = 0
13    for object_info in objects_info_list:
14        class_name = object_info['predicted_name']
15        x = object_info['x']
16        y = object_info['y']
17        width = object_info['width']
18        height = object_info['height']
19        cropped_img = img.crop((x, y, x + width, y + height))
20        cropped_img.save("./picture/{}{}.jpg".format(class_name, count))
21        count = count + 1

画像内に人が2人写っているので、get_objects_information関数から2つのdictionaryを含んだ状態でListが返ってきます。

1[{'x': 102.010155, 'y': 395.04367, 'width': 530.84344,
2 'height': 500.70053, 'predicted_name': 'person'},
3 {'x': 700.43365, 'y': 400.91656, 'width': 433.38104,
4 'height': 494.5551, 'predicted_name': 'person'}]

List内のそれぞれのdictionaryを利用して、Pillowで保存した画像は下記の2つになります。

関連ページ