yolov5 検出フレームに中国語ラベルを表示#
注意:この注釈は yolov5 の 5.0 バージョンに対応しています!!!#
前言#
多くの人がyolov5を使って物体検出を訓練する際、ラベルは英語のみ表示されます。物体を検出し、中国語ラベルを表示するモデルをどのように訓練すればよいのでしょうか。以下で一歩ずつ進めていきます。
1、中国語ラベルのデータセット#
まず、データセットを収集する際に、公開されているデータセットの一部は、ラベルがすべて英語で、形式は voc 形式で、ファイルは xml ファイルです。もちろん、xml ファイル形式のラベルは非常に直感的で、ラベル内の画像サイズ、注釈位置、注釈のカテゴリが直感的にわかります。yolov5 を訓練する際には yolo 形式のデータセットを使用しますが、データセットを注釈する際はできるだけ voc 形式で注釈を付けると便利で直感的です。その後、YOLOv5 モデルを訓練する際に、コードでワンクリックで変換できます。コードブログ:目標検出 --- データセット形式の変換と訓練セットおよび検証セットの分割。
自分で中国語ラベルのデータセットを作成する場合、labelimg というツールを使用してデータセットを注釈する際に、ラベルを中国語に変更すれば大丈夫です。具体的なチュートリアルブログ:目標検出 ---labelimg を使用して自分の深層学習目標検出データセットを作成する。
もしここに英語ラベルの voc 形式のデータセットがある場合、以下のコードを使用してデータセット内の英語ラベルを中国語ラベルに変換できます。
# encoding:utf-8
import os
import xml.etree.ElementTree as ET
count = 0
list_xml = []
dict = {"ball": "サッカーボール",
"messi": "メッシ",
}
openPath = "VOCdevkit\VOC2007\Annotations"
savePath = "VOCdevkit\VOC2007\Annotations1"
fileList = os.listdir(openPath) # 現在の作業ディレクトリ内のすべてのファイル名のリストを取得
for fileName in fileList: # ファイルリストからファイルを取得
if fileName.endswith(".xml"): # xmlファイルのみを見る
print("filename=:", fileName)
tree = ET.parse(os.path.join(openPath, fileName))
root = tree.getroot()
print("root-tag=:", root.tag) # ',root-attrib:', root.attrib, ',root-text:', root.text)
for child in root: # 第一層解析
if child.tag == "object": # objectタグを見つける
print(child.tag)
for sub in child:
if sub.tag == "name":
print("ラベル名:", sub.tag, ";テキスト内容:", sub.text)
if sub.text not in list_xml:
list_xml.append(sub.text)
if sub.text in list(dict.keys()):
sub.text = dict[sub.text]
print(sub.text)
count = count + 1
tree.write(os.path.join(savePath, fileName), encoding='utf-8')
print("=" * 20)
print(count)
for i in list_xml:
print(i)
このコードは、中国語ラベルの voc 形式のデータセットを英語ラベルのデータセットに変換することもできます。以下の図のように、中国語と英語の位置を入れ替えるだけで済みます。
中国語ラベルの voc 形式のデータセットは、目標検出 --- データセット形式の変換と訓練セットおよび検証セットの分割のブログにあるコードを使用して、voc 形式のデータセットを yolo データセットに変換し、訓練セットと検証セットに分割できます。
これで中国語ラベルのデータセットが準備できました。
2、yolov5 コードを中国語ラベルに対応するように修正#
特に説明しておきたいのは、このブログで使用されているのは yolov5 の 5.0 バージョンです。
(1)train.py ファイルの修正、py ファイルの 63 行目のコードを以下のように修正します:
with open(opt.data, encoding='UTF-8') as f:
(2)test.py ファイルの修正、py ファイルの 73 行目のコードを以下のように修正します:
with open(opt.data, encoding='UTF-8') as f:
(3)utils/general.py ファイルの修正、このコードに以下のパッケージをインポートします:
from PIL import Image, ImageDraw, ImageFont
(4)utils/plots.py ファイルの修正、py ファイルの 64 行目、plot_one_box 関数の if label の後のコードを以下のように修正します:
tf = max(tl - 1, 1) # フォントの厚さ
t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
font_size = t_size[1]
font = ImageFont.truetype('msyh.ttc', font_size)
t_size = font.getsize(label)
c2 = c1[0] + t_size[0], c1[1] - t_size[1]
cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA) # 塗りつぶし
img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img_PIL)
draw.text((c1[0], c2[1] - 2), label, fill=(255, 255, 255), font=font)
return cv2.cvtColor(np.array(img_PIL), cv2.COLOR_RGB2BGR)
(5)utils/plots.py ファイルの修正、py ファイルの 144 行目、plot_images 関数を以下のように修正します:
mosaic = plot_one_box(box, mosaic, label=label, color=color, line_thickness=tl)
(6)detect.py ファイルの修正、py ファイルの 178 行目のコードを以下のように修正します:
im0 = plot_one_box(xyxy, im0, label=label, color=colors[int(cls)], line_thickness=3)
注意、この im0 は非常に重要です。画像がすでにフレームで囲まれているが、ラベルに文字が表示されない場合、im0
が欠落している可能性が高いです。このim0
は後のplot_one_box(xyxy, im0
内の im0 と対応する必要があります。
これで中国語ラベルをサポートするためのコードの修正が完了しました。
もしその後のモデル訓練や推論テスト作業については、ブログを参考にしてください:目標検出 ---yolov5 を使用して自分の目標検出モデルを訓練する方法。
ここで特に注意しておきたいのは、data ディレクトリ内の yaml ファイルを修正する際、そのラベルも必ず注釈された中国語のカテゴリに対応させる必要があります。
参考リンク:(下文)
YoloV5 実現中国語ラベル目標検出 - 知乎 (zhihu.com)
YoloV5 実現中国語ラベル目標検出#
1、yolov5 プロジェクトをローカルにコピー#
https://github.com/ultralytics/yolov5
2、フォントを確認#
デフォルトでC:\Windows\Fonts
のフォントを呼び出します。適切なものを見つけてください。例えば、私は今回simhei.ttf
を使用しました。
3、train.pyファイル
#
with open(opt.data) as f:
を以下のように変更します。
with open(opt.data, encoding='UTF-8') as f:
4、test.py ファイル#
with open(data) as f:
を以下のように変更します。
with open(data, encoding='UTF-8') as f:
5、utils/general.py ファイル#
パッケージをインポートします。
from PIL import Image, ImageDraw, ImageFont
6、utils/plot.py ファイル#
plot_one_box
関数を修正し、if labelの後のコード
を以下のように変更します。
if label:
tf = max(tl - 1, 1) # フォントの厚さ
t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
font_size = t_size[1]
font = ImageFont.truetype('MSYH.TTC', font_size)
t_size = font.getsize(label)
c2 = c1[0] + t_size[0], c1[1] - t_size[1]
cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA) # 塗りつぶし
img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img_PIL)
draw.text((c1[0], c2[1] - 2), label, fill=(255, 255, 255), font=font)
return cv2.cvtColor(np.array(img_PIL), cv2.COLOR_RGB2BGR)
7、utils/plot.py ファイル#
plot_images
関数内で
plot_one_box(box, mosaic, label=label, color=color, line_thickness=tl)
を以下のように変更します。
mosaic = plot_one_box(box, mosaic, label=label, color=color, line_thickness=tl)
8、detect.py ファイル#
plot_one_box(xyxy, im0, label=label, color=colors[int(cls)], line_thickness=3)
を以下のように変更します。
im0 = plot_one_box(xyxy, im0, label=label, color=colors[int(cls)], line_thickness=3)