yolov5 は、0 から開始してトレーニングと検出にグレースケール画像を使用できますか?

yolov5 はグレースケール画像でトレーニングできますか? yolov5 のグレースケール画像のトレーニングと検出を 0 から開始します


記事ディレクトリ

1 プレビュー

通常、ターゲット検出には RGB 画像を使用しますが、同時に複数のビデオ ストリームをターゲット検出に使用すると、グラフィック カードのコンピューティング パワーと推論時間が大量に消費されます。実験的な比較を通じて、トレーニングとテストのためにグレースケール画像 (GRAY) と RGB 画像が比較されます。

今回は、yolov5_6.2を使用して、ターゲット検出トレーニングとターゲット検出テスト用のグレースケール画像を試します。

opencv アルゴリズムを通じてカラー画像をグレースケール画像に直接変換し、トレーニングのために「python train.py」を実行します。

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

train.py を実行するとエラーは報告されませんが、出力されるモデル構造の最初の 2 行は次のとおりです。

[表1-1 モデル構造のインターセプト]
から n パラメータ モジュール 引数
0 -1 1 3520 モデル.common.Conv [3、32、6、2、2]
1 -1 1 18560 モデル.common.Conv [32、64、3、2]

上の図から、モデルの入力が 3 チャネルに固定されていることがわかります。これは、トレーニング データ セットがグレースケール画像であっても、画像を読み取るときに画像が処理されることを意味します。

utils/dataloaders.py ファイルのソース コードの 248 行目を確認してください。

245        else:
246            # Read image
247            self.count += 1
248            img0 = cv2.imread(path)  # BGR
249            assert img0 is not None, f'Image Not Found {path}'
250            s = f'image {self.count}/{self.nf} {path}: '

以下はopencvのimreadメソッドの紹介です。

img = cv2.imread(path, flag)   	# flag: the way in which img should be read
								# flag: default value is cv2.IMREAD_COLOR
# cv2.IMREAD_COLOR(1):    BGR
# cv2.IMREAD_GRAYSCALE(0): GRAY
# cv2.IMREAD_UNCHANGED(-1):

デフォルトでは、opencv, 'cv2.imread(path)' は 3 チャンネル (BGR) 画像を読み取ります。グレースケール画像の場合、レイヤーは 3 回コピーされます (BGR デフォルト、B)GR) なので、読み取られる画像は 3 チャンネルになります。

2 ソースコードを変更してグレースケールトレーニングを有効にします

ソース コードの変更箇所の後には、「Hlj2308」というコメントが続きます。

2.1 画像読み取りモードを変更する

utils/dataloaders.py ファイルの 248 行目では、元の

img0 = cv2.imread(path)  # BGR

への変更

img0 = cv2.imread(path, 0)  # Hlj2308_GRAY

2.2 ソースコードパラメータ送信のチャネル数を変更する

2.2.1 train.py ファイルの 122 行目と 130 行目のパラメータ ch=3 を ch=1 に変更します。

model = Model(cfg or ckpt['model'].yaml, ch=1, nc=nc, anchors=hyp.get('anchors')).to(device)  # Hlj2308
model = Model(cfg, ch=1, nc=nc, anchors=hyp.get('anchors')).to(device)  # Hlj2308 create

2.2.2 models/yolo.py ファイルの 151 行目で、ch=3 を ch=1 に変更します。

149 class DetectionModel(BaseModel):
150     # YOLOv5 detection model
151     def __init__(self, cfg='yolov5s.yaml', ch=1, nc=None, anchors=None):  
152         super().__init__()
153         if isinstance(cfg, dict):
154             self.yaml = cfg  # model dict

2.3 train.pyを実行する

train.py の実行プロセスでは、常にエラーが報告され、エラーは修正され、デバッグされます。最後に、通常のトレーニングとテストを実行できます。

【エラー報告1】

File "....packages\torch\nn\modules\conv.py", line 442, in _conv_forward
    return F.conv2d(input, weight, bias, self.stride,
RuntimeError: Given groups=1, weight of size [32, 1, 6, 6], expected input[8, 3, 640, 640] to have 1 channels, but got 3 channels instead

データを読み込むチャンネル数が間違っています。本来は 1 チャンネルですが、ここでは 3 チャンネル読み込まれます。

PIL モジュール「Image.open()」がイメージを開くときの「モード」の問題である可能性があります。models/common.py ファイルの 612 行目を変更します。

im, f = Image.open(requests.get(im, stream=True).raw if str(im).startswith('http') else im), im

後で次の 2 行のコードを追加します

if im.mode != 'L':
    im = im.convert('L')

まだあります【エラー1】

2.4 utils/general.pyのソースコードを変更する

utils/general.py のソース コードの 1031 ~ 1032 行目を次のように変更します。

def imread(path, flags=cv2.IMREAD_COLOR):
    return cv2.imdecode(np.fromfile(path, np.uint8), flags)

への変更

def imread(path, flags=cv2.IMREAD_GRAYSCALE):
    return cv2.imdecode(np.fromfile(path, np.uint8), cv2.IMREAD_GRAYSCALE)

まだあります【エラー1】

2.5 dataloaders.py 内のすべての cv2 読み取りイメージのフラグを変更する

utils/dataloaders.py ファイルの 677、691、881、1042、1119、1122、1125 行目では、元の

cv2.imread(f)

次のように変更します。Ctr+F で検索および置換できます。

cv2.imread(f, 0)

この時点で、train.py を実行すると、[エラー 1] は存在しません。

【エラー2】は以下の通りです

File "..../yolov5_6.2_gray/utils/dataloaders.py", line 706, in load_mosaic
    img4 = np.full((s * 2, s * 2, img.shape[2]), 114, dtype=np.uint8)  # base image with 4 tiles
IndexError: tuple index out of range

解決策: 理由は、画像が単一チャネルであるため、img.shape[2] インデックスが存在しないためです。そのため、3 次元配列ではなく、2 次元配列にすぎません。これは 706 行のソース コード \utils\dataloaders.py です。

img4 = np.full((s * 2, s * 2, img.shape[2]), 114, dtype=np.uint8)  

への変更

img4 = np.full((s * 2, s * 2, img.shape[2] if len(img.shape)==3 else 1), 114, dtype=np.uint8) 

【エラー3】は下記の通り、【エラー2】の修正方法が間違っていたためです。

File "..../yolov5_6.2_gray/utils/dataloaders.py", line 721, in load_mosaic
    img4[y1a:y2a, x1a:x2a] = img[y1b:y2b, x1b:x2b]  # img4[ymin:ymax, xmin:xmax]
ValueError: could not broadcast input array from shape (360,640) into shape (360,640,1)

解決策: 印刷エラーは、「img4.shape, img.shape = (1280, 1280, 1) (360, 640)」を含む img4 と img の形状に対応しており、明らかに画像サイズの不一致によって引き起こされます。[エラー2]を次のように修正します。

img4 = np.full((s * 2, s * 2), 114, dtype=np.uint8)  # base image with 4 tiles

【エラー4】は以下の通りです

File "D:\yolov5train\yolov5_6.2_grayTrain\utils\dataloaders.py", line 642, in __getitem__
    augment_hsv(img, hgain=hyp['hsv_h'], sgain=hyp['hsv_s'], vgain=hyp['hsv_v'])
  File "D:\yolov5train\yolov5_6.2_grayTrain\utils\augmentations.py", line 69, in augment_hsv
    hue, sat, val = cv2.split(cv2.cvtColor(im, cv2.COLOR_BGR2HSV))
cv2.error: OpenCV(4.2.0) c:\projects\opencv-python\opencv\modules\imgproc\src\color.simd_helpers.hpp:92: error: (-2:Unspecified error) in function '__cdecl cv::impl::`anonymous-namespace'::CvtHelper<struct cv::impl::`anonymous namespace'::Set<3,4,-1>,struct cv::impl::A0x3b52564f::Set<3,-1,-1>,struct cv::impl::A0x3b52564f::Set<0,5,-1>,2>::CvtHelper(const class cv::_InputArray &,const class cv::_OutputArray &,int)'
> Invalid number of channels in input image:
>     'VScn::contains(scn)'
> where
>     'scn' is 1

解決策: 上記の問題は、hsv チャネル分割によって引き起こされます。ここでは必要ありません。次のように、\utils\dataloaders.py の 642 行目に対応するコードをコメント アウトします。

# augment_hsv(img, hgain=hyp['hsv_h'], sgain=hyp['hsv_s'], vgain=hyp['hsv_v'])

【エラー5】は以下の通りです

File "D:\yolov5train\yolov5_6.2_grayTrain\utils\dataloaders.py", line 665, in __getitem__
    img = img.transpose((2, 0, 1))[::-1]  # HWC to CHW, BGR to RGB
ValueError: axes don't match array

解決策: 上記の問題は、BGR から RGB への変換が原因であると推測されます。\utils\dataloaders.py 内の 665 行のソース コードを置き換えます。

img = img.transpose((2, 0, 1))[::-1]  # HWC to CHW, BGR to RGB

これを次のように変更するのは間違いです

img = img.transpose((2, 0, 1))  # HWC to CHW

opencv は HWC 経由で画像を読み込みますが、Pytorch は CHW を必要とするため、画像は 'transpose((2, 0, 1)) ' を通じて CHW に変換する必要があります。ただし、この時点で「転置」する必要がある「img」のサイズは (640, 640) であり、「転置」操作を直接実行することはできません。そのため、以下のように[エラー5]に変更することで回避できます。

img = img.reshape(1, img.shape[0], img.shape[1])

2.6 この時点で、「train.py」ファイルを実行してエポックを通常どおり実行します。

現時点では、モデル cfg ファイルの変更は必要ありません。train.pyのパラメータは次のように設定されています

'--weights', type=str, default='',
'--cfg', type=str, default='./models/yolov5s.yaml',
'--data', type=str, default= './data/my_yolo5.yaml',
'--epochs', type=int, default=50
'--batch-size', type=int, default=8,
'--imgsz', '--img', '--img-size', type=int, default= 640,

「./models/yolov5s.yaml」パラメータには次のものが含まれます

# Parameters
nc: 11  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple

「./data/my_yolo5.yaml」パラメータには次のものが含まれます

train: ../datasTrain4_LQTest_gray/images/train/
val: ../datasTrain4_LQTest_gray/images/val/

# number of classes
nc: 11

# class names
names: [ 'pedes', 'car', 'bus', 'truck', 'bike', 'elec', 'tricycle','coni', 'warm', 'tralight', 'speVeh']

3 モデルのテスト

今回は、RGB と GRAY の両方で、50 エポックの事前トレーニング ウェイト トレーニングを行わずに yolov5_6.2 を使用します。データ セットは RGB および GRAY 形式の同じ画像セットであり、ラベル ファイルもまったく同じです。–> データセットが 2491 (train)、360 (val) と小さく、事前トレーニング済みモデルが使用されていないため、epoch=50 であるため、P、R、および mAP は比較的低くなります。

3.1 RGB画像トレーニングのモデルテスト

トレーニングの比較

エポックのトレイン時間の範囲は 4:24 ~ 4:34、エポックの val 時間の範囲は 0:13 ~ 0:15 です。

精度の比較

トライアン終了、すべて: P(0.869) R(0.653) mAP(0.717)@.5 mAP(0.48)@.5:.95

val: all:P(0.712) R(0.651) mAP(0.71)@.5 mAP(0.512)@.5:.95

val推論時間の比較

速度: 前処理 0.3 ミリ秒、推論 7.1 ミリ秒、形状 (8、3、640、640) で画像ごとに 1.8 ミリ秒の NMS

3.2 GREYグラフトレーニングのモデル検出テスト

トレーニングの比較

エポックのトレイン時間の範囲は 2:48 ~ 2:54、エポックの val 時間の範囲は 0:08 ~ 0:09 です。

精度の比較

トライアン終了、すべて: P(0.905) R(0.617) mAP(0.705)@.5 mAP(0.464)@.5:.95

val: all:P(0.728) R(0.619) mAP(0.696)@.5 mAP(0.497)@.5:.95

val推論時間の比較

速度: 前処理 0.1 ミリ秒、推論 4 ミリ秒、形状 (8、1、640、640) で画像ごとに 2.3 ミリ秒の NMS

上記の val.py 実行プロセス中に、

【エラー6】は以下の通りです

...
File "D:/yolov5train/yolov5_6.2_grayTrain/val.py", line 169, in run
    model.warmup(imgsz=(1 if pt else batch_size, 3, imgsz, imgsz))  # warmup
...
File "D:\AppData\anaconda3.8\envs\yolov5t\lib\site-packages\torch\nn\modules\conv.py", line 442, in _conv_forward
    return F.conv2d(input, weight, bias, self.stride,
RuntimeError: Given groups=1, weight of size [32, 1, 6, 6], expected input[1, 3, 640, 640] to have 1 channels, but got 3 channels instead

解決策: val.py ソース コード内の 169 行のコードを置き換えます。

model.warmup(imgsz=(1 if pt else batch_size, 3, imgsz, imgsz))  # warmup

以下のように変更すると、【エラー6】が解消されます。

model.warmup(imgsz=(1 if pt else batch_size, 1, imgsz, imgsz))  # warmup

3.3 RGB と GRAY のトレーニングとテストの比較

今回は、RGB と GRAY の両方で、50 エポックの事前トレーニング ウェイト トレーニングを行わずに yolov5_6.2 を使用します。データ セットは RGB および GRAY 形式の同じ画像セットであり、ラベル ファイルもまったく同じです。データセットが割り当てられているため、2491 (train)、360 (val) です。比較結果は以下の通りです。

[表 3-1 RGB モデルと GRAY モデルの結論の比較]

ここに画像の説明を挿入します

4 結論

表 3-1 に基づいて、次の結論を導き出すことができます。

(1) 画像を RGB と GRAY で比較することにより、グレースケール画像を使用したトレーニングと推論の時間が実際に短縮されます。私たちが懸念している推論時間は 7.1 から 4.1 に低下し、時間は 3 / 7.1 = 42% 短縮されました。

(2) テストされた P、R、および [email protected] 値には差がありますが、50 エポックの差は大きくありません。事前トレーニングされたモデルがないため、50 ラウンドのトレーニングが必要です。

5 RGB からグレーへの変換時間をテストする

「detect.py」テストに合格します。モデルに渡されるパラメーター ch=3 を 1 に変更します。「--source」パラメータは、フォルダ内のすべて RGB の画像を取得します。直接検出すると、「runs/val」ディレクトリに灰色の形式で保存されることがわかります。「utils/dataloaders.py」のソースコードの「class LoadImages:」クラスのメソッド「def next (self) :」が「img0 = cv2.imread(path, 0)」に変更されていることが分かりました。そこで、次のように「cv2.imread()」メソッドの消費時間を測定しました。

读取RGB图的耗时(s): 0.02003192901611328
读取灰度图的耗时(s): 0.011004924774169922

実際、「cv2.imread()」メソッドの時間のかかる比較はまったく必要ありません。通常、rtsp ストリームまたはカメラ SDK を通じてストリームを取得します。取得されたカメラ データ ストリームは yuv 形式であり、y チャネル データはグレーのデータです。代わりに、RGB データを取得するには、yuv から RGB への計算式を計算する必要があります。

①目標探知を展開した際に、カメラ内の映像をどのように読み取るのか、検討する必要があります。②カメラSDKで与えられるデータ形式はどのようなものですか。③ ターゲット検出の前処理では、RGB 画像、またはビデオからストリーミングされた他の形式 (またはデータ形式) を処理していますか? 他の前処理操作を実行する前に、RGB 形式に変換する必要がありますか? カメラのエンコードおよびデコード操作を含む原則を考慮してください。

[前の段落で述べた 3 つの点について検討する必要がありますが、他に推奨できるリソースはありますか? ありがとうございます~]

画像内の全ピクセルのR、G、B成分とY、U、V成分間の相互変換式は以下のとおりです。
Y + 0.587*G + .0114*B\\ U = -0.147*R -0.289*G + 0.436*B\\ V = 0.615*R -0.515*G -0.100*B \end{件} Y=0.299R+0.587G+.0114BU=0.147R0.289G+0.436BV=0.615R0.515G0.100B

{ R = Y + 1.14 ∗ VG = Y − 0.39 ∗ U − 0.58 ∗ VB = Y + 2.03 ∗ U \begin{cases} R = Y + 1.14*V\\ G = Y - 0.39*U - 0.58*V\ \ B = Y + 2.03*U \end{件} R=Y+1.14VG=Y0.39U0.58VB=Y+2.03


添付ファイル 1: ソース コードは変更されておらず、グレースケール画像 + yolov6_6.2 がトレーニングに直接使用されています。

モデルパラメータを図 1 に示します。

ここに画像の説明を挿入します

図 1 も実行できます。私の理解によれば、これは 3 チャンネルのランニング トレーニングでもあり、3 つのチャンネルは GRAY チャンネルの値です。yuv の理解によれば、y チャネルはグレースケール チャネルとみなされます。これは、3 つのチャネルすべての y に対応するグレー値に相当します。

付録 2 トレーニング中のデータセットのラベルは次のとおりです。

表1 対象ラベル詳細

ID ラベル 説明する 述べる
0 歩行者(バランスバイクやフラットベッドに乗っている人もこのカテゴリーに含まれます)
1 乗用車(SUV、MPV(ピックアップ)、VAN(バン)を含む)
2 バス バス、バス
3 トラック トラック、バン
4 自転車 自転車
5 エレキ バイク(電動バイク)
6 三輪車 三輪車(電動三輪車、ガソリン三輪車)
7 コニ コーンバレル
8 暖かい 警告ポスト
9 トラライト 信号機
10 スペヴェ 緊急車両または特殊車両(救急車、消防車、クレーンなどの作業車両、掘削機、土木運搬車など)

おすすめ

転載: blog.csdn.net/qq_42835363/article/details/132693597