自己構築データセットでのyolov3のトレーニングの準備(3):データセットの処理中に使用できる実用的で効果的なpythonスクリプト(train.txtの生成、ランダムな名前の変更、ランダムなトリミング、行と列の内容を指定するためのテキストファイルの変更など)


序文


        オンラインでダウンロードしたデータセット、または独自に収集した画像でマークされたギャラリー、またはダウンロードした画像でマークされたギャラリー。さまざまなソースからのこれらのデータは、一部の名前が統一されていないなど、すべての要件を満たしていない場合があります。サイズが適切でない、一部のカテゴリコードがずれている、一部のラベルが画像から分離されている、一部の画像がマークされていない、またはラベルの数が画像よりも多いなど。これらの問題は、次のスクリプトで解決できます。


ツール


  • cmd
  • python3

train.txtスクリプトを生成する


    train.txtには、すべての画像の相対パスのリストが含まれており、パスの文字列を分割して相対パスを取得し、相対パス情報を行単位でtrain.txtに書き込みます。

import os
 
image_dir = r"G:\YOLO_train\darknet\build\darknet\x64\data\train"
dir_data = image_dir.split("\\")
f_train = open("train.txt", 'w')   
for f in os.listdir(image_dir):
    if(f.split(".")[1] == "jpg"):
        f_train.write(dir_data[len(dir_data)-2]+'\\'+dir_data[len(dir_data)-1]+'\\'+f+'\n')

     効果画像:

                                                       


ファイルのランダムな名前変更スクリプト


    システムには名前の変更方法があり、特定の長さのランダムなシーケンスを生成するだけで済みます。スクリプトは、ループを通じて毎回文字シーケンスから要素を選択し、最終的に16回ループして、16文字の文字列にスプライシングします。このようにして、何万もの画像の名前を変更しても基本的には名前が変更されず、画像は相関関係を課すことなくランダムに分散されます。

import os
import random

file_dir = r"G:\Yolo_mark-master\x64\Release\data\new\new\training_set"
seed=('abcdefghijklmnopqrstuvwxyz0123456789')
letter = []
for f in os.listdir(file_dir):
    if(f.split(".")[1] == "jpg"):  
        for i in range(16):
            letter.append(random.choice(seed))
            newName = ''.join(letter)	
        os.rename(file_dir+'\\'+f, file_dir+'\\'+newName+'.jpg')
        if(os.path.exists(file_dir+'\\'+f.split(".")[0]+ ".txt")) == True:
            os.rename(file_dir+'\\'+f.split(".")[0]+'.txt', file_dir+'\\'+newName+'.txt')
        print(newName)
        letter = []

    効果画像: 

                                     


画像ランダムトリミングスクリプト


       スクリプトの基本的な考え方は、最初に画像の特定の領域に点をランダムに生成し、次に開始点によって決定された特定の点に描画された画像領域をインターセプトし、次に画像領域を保存することです。これは画像をランダムにトリミングすることと同じです。個人的には、tfのランダムなトリミング機能よりも優れていると感じています。

import cv2
import os
import random
 
in_dir = r"G:\Yolo_mark-master\other"
out1_dir = "G:\\Yolo_mark-master\\out5"
 
 
if not os.path.exists(out1_dir):
   os.mkdir(out1_dir) 
 
for f in os.listdir(in_dir):
    if(f.split(".")[1] == "jpg"):   
        path = in_dir +'/'+ f
        img = cv2.imread(path)
        size = img.shape
 
        for n in range(3):
            if((size[0]>=300)&(size[1]>=300)):
                x = random.randrange(size[0]-299)
                y = random.randrange(size[1]-299)
                cut_img = img[x:x+300,y:y+300]
                cropImg = cv2.resize(cut_img,(608,608),interpolation = cv2.INTER_CUBIC)
                cv2.imwrite(out1_dir+'\\'+str(n)+'a_a'+f,cropImg)  #写入图像路径 

        効果画像: 

                                         


テキストドキュメントの指定した行と列の内容を変更するスクリプト


       基本的な操作のアイデアは、最初に元のテキストドキュメントを行ごとに分割することです。次に、各行の内容をスペースで分割します。次に、要素を目的のコンテンツに置き換え、最後に要素を文字列に再構成して別のテキストドキュメントに格納し、テキストドキュメントの行と列のコンテンツを変更します。

import os
 
txt_dir = "G:\\Yolo_mark-master\\test"
other_dir = "G:\\Yolo_mark-master\\other"
if not os.path.exists(other_dir):
   os.mkdir(other_dir)
txt_dirlist = os.listdir(txt_dir)        
list = []
for f in txt_dirlist:
    if(f.split(".")[1] == "txt"):
        f1=open(txt_dir+'/'+f,'r+')		
        lines=f1.readlines()	
        f2=open(other_dir+'/'+f,'w+')
        for i in range(len(lines)):
            data = lines[i].split()
            if(data[0] == '7'):                                    #分离出的类别序号
               clip_query = '6'+' '+data[1]+' '+data[2]+' '+data[3]+' '+data[4]+'\n'
               f2.write(clip_query)
            else:
               f2.write(lines[i])

 効果画像:

                                       


マークされたファイルのないクリアな画像スクリプト


        データセットでマークされていない画像をクリアします。画像にマークが付いていない場合、トレーニングに役立たず、エラーが発生する可能性があります。次のスクリプトを使用して、マークされたファイルのない画像を削除します。それらの画像も役立つ場合は、shutil.moveを使用して画像を他のフォルダーに移動し、マークを付け直してから元に戻すことができます。

import os

image_dir = "G:\\Yolo_mark-master\\test"
txt_dir = "G:\\Yolo_mark-master\\test"

for f in os.listdir(image_dir):
	if(f.split(".")[1] == "jpg"):
		if(os.path.exists(txt_dir+'/'+f.split(".")[0]+ ".txt")) == False:
			os.remove(image_dir+'/'+f)

画像なしの注釈ファイルスクリプトをクリア


        データセットに画像ファイルがないtxtファイルをクリアします。前の質問と同様に、このようなファイルは役に立たない。手動選択中に一部の画像が削除され、対応するtxtファイルが削除されないために生成され、特に画像と注釈が同じフォルダーにない場合、またはデータセットのダウンロード中に問題が発生しました。次のスクリプトを使用して、余分な注釈ファイルを削除します。

import os

image_dir = "G:\\Yolo_mark-master\\test"
txt_dir = "G:\\Yolo_mark-master\\test"

for f in os.listdir(txt_dir):
	if(f.split(".")[1] == "txt"):
		if(os.path.exists(image_dir+'/'+f.split(".")[0]+ ".jpg")) == False:
			os.remove(txt_dir+'/'+f)

空の注釈ファイルを含む画像と注釈ファイルを指定したフォルダーに移動するスクリプト


         空の注釈ファイルを含む画像と注釈ファイルを対応するフォルダに移動します。ラベルファイルが空の写真はネガティブサンプルであり、トレーニングにはネガティブサンプルが不可欠であることはわかっています。ポジティブサンプルとネガティブサンプルはすべて最後にまとめられていますが、ポジティブサンプルとネガティブサンプルの最初で、各カテゴリーを分けるように、2つのサンプルの数を理解できます。yolo_markでラベル付ける過程で、一部の写真が検出したくないネガティブサンプルであることがわかります。現時点では、ラベルを付けませんでしたが、ラベルファイルは生成されましたが、空でした。別の用途もあります:yolo_markを使用してより適切なデータ選択する場合、「C」を使用してあまり良くないデータの注釈を削除できます。処理が完了したら、次のスクリプトを使用してこれらの画像と注釈を簡単に削除できます。

import os
import shutil

image_dir = "G:\\Yolo_mark-master\\test"
txt_dir = "G:\\Yolo_mark-master\\test"
other_dir = "G:\\Yolo_mark-master\\other"
if not os.path.exists(other_dir):
   os.mkdir(other_dir)      
for f in os.listdir(image_dir):
    if((f.split(".")[1] == "jpg")&((os.path.exists(txt_dir+'/'+f.split(".")[0]+ ".txt"))==True)):
        if(os.path.getsize(txt_dir+'/'+f.split(".")[0]+ ".txt")<1) :
            shutil.move(image_dir +'/'+ f,other_dir + '/'  + f)
            shutil.move(txt_dir+'/'+f.split(".")[0]+ ".txt",other_dir+'/'+f.split(".")[0]+ ".txt")

画像ファイルと注釈ファイルが置かれているフォルダーをマージするためのスクリプト


        ラベルを画像のあるフォルダにマージします。この問題は主にデータセットを自分でダウンロードするときに発生します。たとえば、開いている画像の記事でダウンロードしたデータセットのラベルと画像は分離されているため、yolo_markでクリーニングすることはできません。yolo_markでマークされたデータ画像とラベルが同じディレクトリにある場合、そのような問題はありません。後で書き込まれる洗脳データセットなど、他のデータセットの注釈ファイルテーブルからの注釈ファイルもあります。これは、いくつかのフィルタリング方法を通過する場合があります。現時点では、次のスクリプトを使用して、対応する画像を注釈ファイルに移動できます。フォルダ。

        別のディレクトリに移動します。

import os
import shutil

image_dir = "G:\\Yolo_mark-master\\test"
txt_dir = "G:\\Yolo_mark-master\\test2"
other_dir = "G:\\Yolo_mark-master\\other"
if not os.path.exists(other_dir):
   os.mkdir(other_dir)      
for f in os.listdir(image_dir):
    if(f.split(".")[1] == "jpg"):
        if(os.path.exists(txt_dir+'/'+f.split(".")[0]+ ".txt")) == True:
            shutil.move(image_dir +'/'+ f,other_dir + '/'  + f)
            shutil.move(txt_dir+'/'+f.split(".")[0]+ ".txt",other_dir+'/'+f.split(".")[0]+ ".txt")

        画像カタログに移動:

import os
import shutil

image_dir = "G:\\Yolo_mark-master\\test"
txt_dir = "G:\\Yolo_mark-master\\test2"
     
for f in os.listdir(image_dir):
    if(f.split(".")[1] == "jpg"):
        if(os.path.exists(txt_dir+'/'+f.split(".")[0]+ ".txt")) == True:
            shutil.move(txt_dir+'/'+f.split(".")[0]+ ".txt",image_dir+'/'+f.split(".")[0]+ ".txt")

         アノテーションディレクトリに移動します。 

import os
import shutil

image_dir = "G:\\Yolo_mark-master\\test"
txt_dir = "G:\\Yolo_mark-master\\test2"
     
for f in os.listdir(txt_dir):
    if(f.split(".")[1] == "txt"):
        if(os.path.exists(image_dir+'/'+f.split(".")[0]+ ".jpg")) == True:
            shutil.move(image_dir+'/'+f.split(".")[0]+ ".jpg",txt_dir+'/'+f.split(".")[0]+ ".jpg")

ファイルスクリプトをランダムに抽出する


         データセット内の画像とラベルを指定したフォルダーにランダムに抽出します。これは主に、特定の種類のデータが多すぎて削除する必要があるためです。開いている画像の記事でいくつかのカテゴリダウンロードしました。数万枚の画像と、わずか100枚または200枚の画像です。私たちは知っている、AlexeyABは転送の学習トレーニングyolo3、クラスごとに2000枚が十分にある彼のために好ましいのは、2000年のすべてのクラス、約推奨しました。データが多すぎると、トレーニングの難易度が大幅に上がるので、次のスクリプトを作成して、いくつかの写真と注釈をランダムに選択しました。


import os
import shutil
import random
 
image_dir = "C:\\down_openimages\\JPEGImages\\Laptop"
txt_dir = "C:\\down_openimages\\labels"
other_dir = "G:\\Yolo_mark-master\\other"
if not os.path.exists(other_dir):
   os.mkdir(other_dir) 
image_dirlist = os.listdir(image_dir)        
sample = random.sample(image_dirlist, 400)   
for f in sample:
    if(f.split(".")[1] == "jpg"):
        if(os.path.exists(txt_dir+'/'+f.split(".")[0]+ ".txt")) == True:
             shutil.move(image_dir +'/'+ f,other_dir + '/'  + f)
             shutil.move(txt_dir+'/'+f.split(".")[0]+ ".txt",other_dir+'/'+f.split(".")[0]+ ".txt")

 


おわりに


        データセットを処理するプロセスで使用したいくつかの小さなスクリプトを次に示します。私にとって、これらのスクリプトは依然として非常に効果的です。あなたが見て、少しの助けがあれば、それは本当に名誉です。閲覧中に問題が見つかった場合は、メッセージを残して以下で議論してください。それを見てから返信します。

参考資料 


https://github.com/AlexeyAB/darknet

https://github.com/spmallick/learnopencv/blob/master/YOLOv3-Training-Snowman-Detector/splitTrainAndTest.py

 

 

公開された28元の記事 ウォン称賛34 ビュー20000 +

おすすめ

転載: blog.csdn.net/sinat_35907936/article/details/89605978