みなさん、こんにちは!
みやしんです。^^
今回はYOLOv5を使って物体検出をやってみたいと思います!
物体検出はPythonを勉強している人なら一度はやってみたいスキルですにゃ!
簡単に出来ますので早速やっていきましょう!!
この記事で出来ること_YOLOv5
- 画像内の物体検出
- 物体検出は全部で80種類
- バウンディングBOXの座標、幅、高さをCSV出力
- 検出した物体の画像を切り抜く
1、画像内の物体検出
YOLOv5ではこんな感じで物体検出ができます!
元画像
物体検出
人間:person、カップ:cup、ケーキ:cake をしっかり検出できていますね!
2、物体検出は全部で80種類
下記の80種類の物体を検出可能です!
[‘person’, ‘bicycle’, ‘car’, ‘motorcycle’, ‘airplane’, ‘bus’, ‘train’, ‘truck’, ‘boat’, ‘traffic light’, ‘fire hydrant’, ‘stop sign’, ‘parking meter’, ‘bench’, ‘bird’, ‘cat’, ‘dog’, ‘horse’, ‘sheep’, ‘cow’, ‘elephant’, ‘bear’, ‘zebra’, ‘giraffe’, ‘backpack’, ‘umbrella’, ‘handbag’, ‘tie’, ‘suitcase’, ‘frisbee’, ‘skis’, ‘snowboard’, ‘sports ball’, ‘kite’, ‘baseball bat’, ‘baseball glove’, ‘skateboard’, ‘surfboard’, ‘tennis racket’, ‘bottle’, ‘wine glass’, ‘cup’, ‘fork’, ‘knife’, ‘spoon’, ‘bowl’, ‘banana’, ‘apple’, ‘sandwich’, ‘orange’, ‘broccoli’, ‘carrot’, ‘hot dog’, ‘pizza’, ‘donut’, ‘cake’, ‘chair’, ‘couch’, ‘potted plant’, ‘bed’, ‘dining table’, ‘toilet’, ‘tv’, ‘laptop’, ‘mouse’, ‘remote’, ‘keyboard’, ‘cell phone’, ‘microwave’, ‘oven’, ‘toaster’, ‘sink’, ‘refrigerator’, ‘book’, ‘clock’, ‘vase’, ‘scissors’, ‘teddy bear’, ‘hair drier’, ‘toothbrush’]
おまけ
ちなみにこれは、「person」「horse」もしくは「両方」のどのパターンで物体検出されるでしょうか?笑
答えは記事の最後で!
3、 バウンディングBOXの座標、幅、高さをCSV出力
CSVファイルにバウンディングBOXの「座標」「幅」「高さ」の情報をcsv出力します。
座標情報の出力は後々の解析にも使えますので、便利だと思い機能追加しました。
detction_Result.csv のファイル名で検出結果を出力します。
detection_Result.csv
検出した物体の画像を切り抜く
検出した物体をバウンディングBOXで切り抜いて保存します。
下記のように、それぞれフォルダーを分けて保存します。
それでは、実際にやり方を解説していきます!
動作環境の準備
pipとsetuptoolsの更新
出来れば個別で仮想環境を作ってからが良いと思います。自分はAnacondaで実施しています。
まずは、pipとsetuptoolsを更新します。
python -m pip install --upgrade pip setuptools
必要なライブラリをインストール
pipコマンドを実施して動作環境を設定します。
pip install -qr https://raw.githubusercontent.com/ultralytics/yolov5/master/requirements.txt
下記の内容をセッティングしています。
requirements.txt
# pip install -r requirements.txt
# Base ----------------------------------------
matplotlib>=3.2.2
numpy>=1.18.5
opencv-python>=4.1.2
Pillow>=7.1.2
PyYAML>=5.3.1
requests>=2.23.0
scipy>=1.4.1
torch>=1.7.0
torchvision>=0.8.1
tqdm>=4.41.0
# Logging -------------------------------------
tensorboard>=2.4.1
# wandb
# Plotting ------------------------------------
pandas>=1.1.4
seaborn>=0.11.0
# Export --------------------------------------
# coremltools>=4.1 # CoreML export
# onnx>=1.9.0 # ONNX export
# onnx-simplifier>=0.3.6 # ONNX simplifier
# scikit-learn==0.19.2 # CoreML quantization
# tensorflow>=2.4.1 # TFLite export
# tensorflowjs>=3.9.0 # TF.js export
# openvino-dev # OpenVINO export
# Extras --------------------------------------
# albumentations>=1.0.3
# Cython # for pycocotools https://github.com/cocodataset/cocoapi/issues/172
# pycocotools>=2.0 # COCO mAP
# roboflow
thop # FLOPs computation
物体検出の実行スクリプト
まずはフォルダー構成です。yolov5.pyのコードは以下に記載しています。物体検出したい画像のファイル名は変えて、コピペしてお使い頂けます。
yolov5.py を実行します。
yolov5.py
import torch
import csv
# PyTorch Hubから学習済みモデルをダウンロード
model = torch.hub.load("ultralytics/yolov5", "yolov5s", pretrained=True)
# 検出できる物体を表示する(80種類)
print(model.names)
results = model("birthday.jpg") # 画像パスを設定し、物体検出を行う
objects = results.pandas().xyxy[0] # 検出結果を取得してobjectに格納
# objectに格納したデータ
# => バウンディングBOX左上のx座標とy座標、信頼度、クラスラベル、物体名
# 物体検出結果を出力するためのcsvファイルを作成
with open('detection_Result.csv', 'w') as f:
print("ID,種類,x座標,y座標,幅,高さ", file=f) # print()の第2引数で出力先を指定可能
for i in range(len(objects)):
name = objects.name[i]
xmin = objects.xmin[i]
ymin = objects.ymin[i]
width = objects.xmax[i] - objects.xmin[i]
height = objects.ymax[i] - objects.ymin[i]
# print(f"{i}, 種類:{name}, 座標x:{xmin}, 座標y:{ymin}, 幅:{width}, 高さ:{height}")
# csvファイルにバウンディングBOX情報を出力
print(f"{i},{name},{xmin},{ymin},{width},{height}", file=f)
results.show() # 検出した物体の表示
results.crop() # 検出した物体の切り取り
処理が終了すると、下記のようなフォルダー構成でデータが出力されます。
もしエラーが発生したら
AttributeError: ‘Upsample’ object has no attribute ‘recompute_scale_factor’
■解決策
下記のコード修正をすることで解決しました。
修正するファイル:upsampling.py
C:\Users\[ユーザー名]\anaconda3\envs\[仮想環境名]\Lib\site-packages\torch\nn\modules\upsampling.py
修正前
def forward(self, input: Tensor) -> Tensor:
return F.interpolate(input, self.size, self.scale_factor, self.mode, self.align_corners,recompute_scale_factor=self.recompute_scale_factor)
修正後
def forward(self, input: Tensor) -> Tensor:
return F.interpolate(input, self.size, self.scale_factor, self.mode, self.align_corners)
これでOKです!
おまけの答え
答えは「person」でした! ウケル!意外www!
物体検出をもっと学習したい方にUdemyがお勧めです。
コメント
はじめましてみやしんさん、私はyoloxで実装しているのですが、座標出力をやってみたくてできるのでしょうか? csv出力について情報をお聞かせ願えませんか?