0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【YOLOv8】BBOXの色の変更方法

Last updated at Posted at 2024-02-20

YOLOv8のバウンディングボックスの色を変更

YOLOv8を用いてヘルメットやハーネスなどを着用しているかを自動でチェックするシステムの開発を行っている。

デモを行った際、BBOXの文字の色が分かりにくい、見えずらいなどの意見が出たため変更の仕方のメモを残す。

以下がデモで使用したコード

import cv2
from ultralytics import YOLO
model_chin_detect = YOLO(学習済みの重み) 

cap = cv2.VideoCapture(1)#ウェブカメラ

while cap.isOpened():
    success, frame = cap.read()
    k = cv2.waitKey(1) # 一応キー入力で終了できるようにしておく

    if k != -1:
        break
    if success:
        chin_results = model_chin_detect(frame,conf=0.5)
        annotated_frame = chin_results[0].plot()
        # clothes_results = model_detect(annotated_frame,conf=0.9)
        # annotated_frame = clothes_results[0].plot()
        cv2.imshow("YOLOv8 Inference", annotated_frame)
cap.release()
cv2.destroyAllWindows()

動作環境

  • Windows11
  • ultralytics == 8.0.58

修正箇所を探す

まずgithubからYOLOv8のソースコードを落としてくる。

git clone https://github.com/ultralytics/ultralytics

YOLOv8のdetectの処理を追っているとresults.pyのResultsクラスの228行目に描画系の処理っぽいのを発見。

annotator = Annotator(
            deepcopy(self.orig_img if img is None else img),
            line_width,
            font_size,
            font,
            pil or (pred_probs is not None and show_probs),  # Classify tasks default to pil=True
            example=names,
        )

この処理はresults.pyの258行目のannotator.box_label()で使用されている。

plotting.pyからimportされているのでplotting.pyのannotatorクラスを見に行く。

163行目付近のbox_labelメソッドにopenCVのcv2.rectangleが使われているためここらへんでバウンディングボックスの描画を行っているっぽい??

163行目のbox_labelメソッドの引数に検出したラベルの情報を渡してラベル名に応じてif文でBBoxの色を変更できそう。

このメソッドの引数labelにその情報が入っているがresults.pyで呼び出した際にラベル名や検出確率を文字列で連結して渡しているため不要な情報が含まれている。なのでlabel_onlyを引数に追加。

#デフォルトの引数
def box_label(self, box, label="",color=(128, 128, 128), txt_color=(255, 255, 255), rotated=False):

#変更後の引数
def box_label(self, box, label="",label_only="",color=(128, 128, 128), txt_color=(255, 255, 255), rotated=False):

label_onlyを追加したのでresults.pyのresultsクラスで呼び出されているbox_labelにも変更を加える。

ultralytics/engin/results.pyの251行目から259行目抜粋

# Plot Detect results
        if pred_boxes is not None and show_boxes:
            for d in reversed(pred_boxes):
                c, conf, id = int(d.cls), float(d.conf) if conf else None, None if d.id is None else int(d.id.item())
                name = ("" if id is None else f"id:{id} ") + names[c]
                label = (f"{name} {conf:.2f}" if conf else name) if labels else None
                label_only = f"{name}"
                box = d.xyxyxyxy.reshape(-1, 4, 2).squeeze() if is_obb else d.xyxy.squeeze()
                annotator.box_label(box, label,label_only, color=colors(c, True), rotated=is_obb)

lable情報だけを取得できたのでlabelの種類で条件分岐し色の変更を行う。

ultralytics/utils/plotting.pyの184行目から213行目抜粋 変更前

else:  # cv2
            if rotated:
                p1 = [int(b) for b in box[0]]
                # NOTE: cv2-version polylines needs np.asarray type.
                cv2.polylines(self.im, [np.asarray(box, dtype=int)], True, color, self.lw)
            else:
                p1, p2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
                cv2.rectangle(self.im, p1, p2, color, thickness=self.lw, lineType=cv2.LINE_AA)
            if label:
                print("into if")
                w, h = cv2.getTextSize(label, 0, fontScale=self.sf, thickness=self.tf)[0]  # text width, height
                outside = p1[1] - h >= 3
                p2 = p1[0] + w, p1[1] - h - 3 if outside else p1[1] + h + 3
                cv2.rectangle(self.im, p1, p2, color, -1, cv2.LINE_AA)  # filled
                cv2.putText(
                    self.im,
                    label,
                    (p1[0], p1[1] - 2 if outside else p1[1] + h + 2),
                    0,
                    self.sf,
                    txt_color,
                    thickness=self.tf,
                    lineType=cv2.LINE_AA,
                )

ultralytics/utils/plotting.pyの184行目から213行目抜粋 変更後

else:  # cv2
            if rotated:
                p1 = [int(b) for b in box[0]]
                # NOTE: cv2-version polylines needs np.asarray type.
                cv2.polylines(self.im, [np.asarray(box, dtype=int)], True, color, self.lw)
            else:
                print("into if")
                p1, p2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
                if label_only == "buckle is open":
                    cv2.rectangle(self.im, p1, p2, (0,0,255), thickness=self.lw, lineType=cv2.LINE_AA)
                elif label_only == "above the chin":
                    cv2.rectangle(self.im, p1, p2, (0,0,255), thickness=self.lw, lineType=cv2.LINE_AA)
                elif label_only == "right":
                    cv2.rectangle(self.im, p1, p2, (255,0,0), thickness=self.lw, lineType=cv2.LINE_AA)
            if label:
                w, h = cv2.getTextSize(label, 0, fontScale=self.sf, thickness=self.tf)[0]  # text width, height
                outside = p1[1] - h >= 3
                p2 = p1[0] + w, p1[1] - h - 3 if outside else p1[1] + h + 3
                # cv2.rectangle(self.im, p1, p2, color, -1, cv2.LINE_AA)  # filled
                if label_only == "buckle is open":
                    cv2.rectangle(self.im, p1, p2, (0,0,255), -1, cv2.LINE_AA)
                elif label_only == "above the chin":
                    cv2.rectangle(self.im, p1, p2, (0,0,255), -1, cv2.LINE_AA)
                elif label_only == "right":
                    cv2.rectangle(self.im, p1, p2, (255,0,0), -1, cv2.LINE_AA)
                cv2.putText(
                    self.im,
                    label,
                    (p1[0], p1[1] - 2 if outside else p1[1] + h + 2),
                    0,
                    self.sf,
                    txt_color,
                    thickness=self.tf,
                    lineType=cv2.LINE_AA,
                )

以上でバウンディングボックスの色を変更できました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?