批量下载百度搜索图片+labelimg制作自己的数据集+转换至Yolo-v5训练数据集
? ? ? ?由于課題需要,需要自己制作數據集進行訓練,目前是自己制作的第二個數據集,發現有某些細節已經忘記,記錄備忘,同時為后來者提供借鑒。文章以car-tank數據集做為例子介紹
整體流程:
 1.準備數據:從各種途徑獲取原始數據,博主的car-tank原始數據是在網上搜索然后批量保存的
2.標注數據:使用labelimg標注軟件標注數據,最終得到images、label文件
3.分配數據轉換格式:label標注的標簽文件為xml文件,需要劃分數據集,并轉換到txt格式
4.修改yolo-v5代碼,使用car-tank數據集訓練、測試
1.準備數據
? ? ? ? ?使用Fatkun瀏覽器插件批量下載圖片(博主試驗多種插件后推薦此款),可同時下載界面中的所有圖片。若只為學習,推薦分開下載分開保存,標注數據會省勁。如果你還沒嘗試過自己訓練數據集,推薦以此方法做個小的數據集學習此過程,博主用了一兩天標注測試了200多張圖片就做好了自己的數據集。
? ? ? ? 注意,圖片最好為jpg格式,標注過程中不知為啥png的標注有點問題,時間久遠記不清現象了,特意轉換格式后才可以。----好像是標注完后xml文件中沒有圖片的寬度和高度
?
?
?2.標注數據
labelimg自行下載,是常用的一款圖片標注軟件?
(1)打開圖片保存目錄
(2)選定label文件(xml文件)保存目錄
(3)view-Auto saving? ? 設置自動保存
開始標注吧,關鍵記住快捷鍵
w:框選目標
a: 上一張
d: 下一張
????????博主習慣先按一類標注,右上角使用默認label,按下w鍵后,點擊鼠標左鍵框選目標,點擊a進行下一張,框選完繼續下一張~~~,注意文件目錄最好全部為英文路徑
3.分配數據轉換格式
(1)分配數據
? ? ? ?將所有的圖片(不同種類的)放到一個文件夾image,將所有的label放到一個文件夾xmllabel,注意不同來源的圖片不要重名。至此數據標注完整理到了一塊。
?????????分配數據,將所有標注的數據分為train,test,trainval,val等,makeTXT.py將數據劃分到幾個txt文件,這幾個文件保存的都是圖片的名字(不帶后綴的)。
?
?makeTXT.py
# 劃分數據集,劃分到4個TXT文件import os import random# 初始化劃分比例和xml文件路徑 trainval_percent = 0.1 train_percent = 0.9 xmlfilepath = 'xmllabel' # xml 標簽目錄 total_xml = os.listdir(xmlfilepath)num = len(total_xml) list = range(num) tv = int(num * trainval_percent) tr = int(tv * train_percent) trainval = random.sample(list, tv) train = random.sample(trainval, tr)# 創建分割后的文件,用以保存圖片名稱(不帶后綴的) ftrainval = open('SplitTXT/trainval.txt', 'w') ftest = open('SplitTXT/test.txt', 'w') ftrain = open('SplitTXT/train.txt', 'w') fval = open('SplitTXT/val.txt', 'w')for i in list:name = total_xml[i][:-4] + '\n'if i in trainval:ftrainval.write(name)if i in train:ftest.write(name)else:fval.write(name)else:ftrain.write(name)ftrainval.close() ftrain.close() fval.close() ftest.close()至此分割數據集完成
(2)轉換格式
先上代碼
voc_label2.py
import xml.etree.ElementTree as ET import pickle import os from os import listdir, getcwd from os.path import join import shutil# 1.makeTXT生成四個txt,記錄切分情況(只記錄圖片名字,不記錄路徑),test、train 、val、trainval # 2.創建label文件夾,再創建test、train 、val的txt文件,用于保存各部分圖片的路徑 # 3.將所有圖片的xml文件從一個文件夾讀取,轉存到另一個文件夾(label)變成多個txt文件(yolov5格式的,每個圖片一個txt,每一行標注有1個目標的類別及位置) # 4.將各個部分的圖片按照剛才保存的路徑,拷貝到目標路徑sets = [('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')] # classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", # "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"] classes = ["1", "2"]# 轉換box位置標簽 def convert(size, box):dw = 1. / size[0]dh = 1. / size[1]x = (box[0] + box[1]) / 2.0y = (box[2] + box[3]) / 2.0w = box[1] - box[0]h = box[3] - box[2]x = x * dww = w * dwy = y * dhh = h * dhreturn (x, y, w, h)# 從xml標簽轉換到txt標簽 def convert_annotation(image_id):in_file = open('xmllabel/%s.xml' % (image_id)) # 打開對應的xml文件out_file = open('labels/%s.txt' % (image_id), 'w') # 輸出文件,yolov5格式的labeltree = ET.parse(in_file)root = tree.getroot()print("image_id", image_id)size = root.find('size')w = int(size.find('width').text)h = int(size.find('height').text)print("size", size)print("w", w)print("h", h)for obj in root.iter('object'):print("")print("hhhhhhhhhh")if obj.find('difficult'):difficult = obj.find('difficult').textelse:difficult = 0cls = obj.find('name').textif cls not in classes or int(difficult) == 1:continuecls_id = classes.index(cls)xmlbox = obj.find('bndbox')b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),float(xmlbox.find('ymax').text))bb = convert((w, h), b)print("bbbbbb", str(cls_id), bb)out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n') # 將數據寫入輸出文件for year, image_set in sets:# 2.創建label文件夾,再創建test、train 、val的txt文件,用于保存各部分圖片的路徑if not os.path.exists('labels/'): # 創建標簽文件夾os.makedirs('labels/')# 讀取TXT文件,保存圖片IDimage_ids = open('SplitTXT/%s.txt' % (image_set)).read().strip().split() # 讀取已經分好的標簽list_file = open('%s.txt' % (image_set), 'w') # 保存各個部分數據(test、val、train)圖片的路徑print("image_set", image_set)for image_id in image_ids:list_file.write('image/%s.jpg\n' % image_id) # 將每個圖片的路徑暫時保存到txt------成功# 3.將所有圖片的xml文件從一個文件夾讀取,轉存到另一個文件夾(label)變成多個txt文件(yolov5格式的,每個圖片一個txt,每一行標注有1個目標的類別及位置)convert_annotation(image_id) # 將xml文件的標簽轉存到label下的每個TXTlist_file.close()# 合并多個文本文件 def mergeTxt(file_list, outfile):with open(outfile, 'w') as wfd:for f in file_list:with open(f, 'r') as fd:shutil.copyfileobj(fd, wfd)# 創建VOC文件夾及子文件夾 wd = os.getcwd() data_base_dir = os.path.join(wd, "cartank_mlw/")if not os.path.isdir(data_base_dir):os.mkdir(data_base_dir) img_dir = os.path.join(data_base_dir, "images/") if not os.path.isdir(img_dir):os.mkdir(img_dir) img_train_dir = os.path.join(img_dir, "train/") if not os.path.isdir(img_train_dir):os.mkdir(img_train_dir) img_val_dir = os.path.join(img_dir, "val/") if not os.path.isdir(img_val_dir):os.mkdir(img_val_dir) label_dir = os.path.join(data_base_dir, "labels/") if not os.path.isdir(label_dir):os.mkdir(label_dir)label_train_dir = os.path.join(label_dir, "train/") if not os.path.isdir(label_train_dir):os.mkdir(label_train_dir)label_val_dir = os.path.join(label_dir, "val/") if not os.path.isdir(label_val_dir):os.mkdir(label_val_dir)# 使用train.txt中的圖片作為yolov5的訓練集 print(os.path.exists('train.txt')) f = open('train.txt', 'r') lines = f.readlines()# 4.將各個部分的圖片按照剛才保存的路徑,拷貝到目標路徑 for line in lines:line = line.replace('\n', '')if (os.path.exists(line)):shutil.copy(line, "cartank_mlw/images/train") # 復制圖片到voc_mlw/images/trainprint('coping train img file %s' % line + '\n')print("line", line)line = line.replace('image', 'labels') # 復制label,將圖片路徑名字換成對應TXT的路徑名字line = line.replace('jpg', 'txt')print("line", line)if (os.path.exists(line)):shutil.copy(line, "cartank_mlw/labels/train")print('copying train label file %s' % line + '\n')# 使用test.txt中的圖片作為yolov5驗證集 print(os.path.exists('test.txt')) f = open('test.txt', 'r') lines = f.readlines()for line in lines:line = line.replace('\n', '')if (os.path.exists(line)):shutil.copy(line, "cartank_mlw/images/val") #line是圖片路徑,復制圖片到 voc_mlw/images/valprint('coping val img file %s' % line + '\n')line = line.replace('image', 'labels') # 復制label,將圖片路徑名字換成對應TXT的路徑名字line = line.replace('jpg', 'txt')if (os.path.exists(line)):shutil.copy(line, "cartank_mlw/labels/val")print('copying val img label %s' % line + '\n') 這部分比較主要也稍復雜,加上makeTXT一塊考慮: 1.makeTXT生成四個txt,記錄切分情況,test、train 、val、trainval,作為后期文件轉移用 2.創建labels文件夾,用于保存所有轉化完的txt 再創建test、train 、val的txt文件,用于暫時保存各部分圖片的路徑,便于后期拷貝圖片 3.將所有圖片的xml文件從一個文件夾讀取,轉換成txt文件(yolov5格式的,每個圖片一個txt,每一行標注有1個目標的類別及位置),轉存到另一個文件夾(labels) 4.將各個部分的圖片按照剛才保存的路徑,拷貝到目標路徑(train or val目錄),將各個圖片的txt 標簽拷貝到對應目錄。?
?
?
?至此數據集轉換格式完成,具體細節可研究voc_label2.py
4.修改yolo-v5部分代碼,使用car-tank數據集訓練、測試
https://github.com/ultralytics/yolov5https://github.com/ultralytics/yolov5博主使用上面的yolov5代碼
(1)仿照已有的yaml文件,在 data目錄下創建car-tank數據集的yaml文件-VOC_cartank_mlw.yaml文件,修改其中的數據集目錄
(2)修改models,yolo-v5s.yaml
????????其他的研究清楚可以自己改,如anchors大小,關鍵改nc, number of class,car-tank共2種目標,應該為2
?(3)修改train.py,
數據變量改為準備用的數據集的yaml~如VOC_cartank_mlw.yaml?,batchsize對應自己的GPU能力,然后run即可
總結
以上是生活随笔為你收集整理的批量下载百度搜索图片+labelimg制作自己的数据集+转换至Yolo-v5训练数据集的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 金山WPS面经 c++开发工程师
 - 下一篇: 遥感影像预处理步骤