【數據集介紹】
數據集格式:Pascal VOC格式+YOLO格式(不包含分割路徑的txt文件,僅僅包含jpg圖片以及對應的VOC格式xml文件和yolo格式txt文件)
圖片數量(jpg文件個數):6734
標注數量(xml文件個數):6734
標注數量(txt文件個數):6734
標注類別數:32
所在倉庫:firc-dataset
標注類別名稱(注意yolo格式類別順序不和這個對應,而以labels文件夾classes.txt為準):["Apple","Apple-core","Apple-peel","Bone","Bone-fish","Bread","Bun","Egg-hard","Egg-scramble","Egg-shell","Egg-steam","Egg-yolk","Fish","Meat","Mussel","Mussel-shell","Noodle","Orange","Orange-peel","Other-waste","Pancake","Pasta","Pear","Pear-core","Pear-peel","Potato","Rice","Shrimp","Shrimp-shell","Tofu","Tomato","Vegetable"]
每個類別標注的框數:
Apple 框數 = 1354
Apple-core 框數 = 759
Apple-peel 框數 = 1612
Bone 框數 = 4379
Bone-fish 框數 = 722
Bread 框數 = 928
Bun 框數 = 36
Egg-hard 框數 = 37
Egg-scramble 框數 = 20
Egg-shell 框數 = 3811
Egg-steam 框數 = 98
Egg-yolk 框數 = 784
Fish 框數 = 138
Meat 框數 = 1020
Mussel 框數 = 27
Mussel-shell 框數 = 86
Noodle 框數 = 538
Orange 框數 = 2512
Orange-peel 框數 = 2194
Other-waste 框數 = 152
Pancake 框數 = 33
Pasta 框數 = 9
Pear 框數 = 1186
Pear-core 框數 = 272
Pear-peel 框數 = 404
Potato 框數 = 140
Rice 框數 = 873
Shrimp 框數 = 13
Shrimp-shell 框數 = 48
Tofu 框數 = 20
Tomato 框數 = 71
Vegetable 框數 = 4170
總框數:28446
使用標注工具:labelImg
標注規則:對類別進行畫矩形框
重要說明:暫無
圖片分辨率:640x640
特別聲明:本數據集不對訓練的模型或者權重文件精度作任何保證
圖片預覽:
標注例子:
【訓練步驟】
這里以yolo11訓練為例。首先我們獲取數據集壓縮包7z格式或者zip格式后解壓到一個非中文或者有空格路徑下面。比如解壓到C:\Users\Administrator\Downloads目錄,下面都是以這個目錄演示訓練流程。
然后我們在數據集data文件夾下面新建一個腳本split.py寫入下面代碼:
import os
import shutil
import randomclass VOCDataSplit(object):def __init__(self):passdef split(self, image_dir, label_dir, save_dir, trainval_radio=0.9, train_radio=0.9, copy_it=True,need_test_dataset=False, shuffle_file=True):train_images_dir = os.path.join(save_dir, 'train', 'images')train_labels_dir = os.path.join(save_dir, 'train', 'labels')val_images_dir = os.path.join(save_dir, 'val', 'images')val_labels_dir = os.path.join(save_dir, 'val', 'labels')test_images_dir = os.path.join(save_dir, 'test', 'images')test_labels_dir = os.path.join(save_dir, 'test', 'labels')os.makedirs(train_images_dir, exist_ok=True)os.makedirs(train_labels_dir, exist_ok=True)os.makedirs(val_images_dir, exist_ok=True)os.makedirs(val_labels_dir, exist_ok=True)if need_test_dataset:os.makedirs(test_images_dir, exist_ok=True)os.makedirs(test_labels_dir, exist_ok=True)files = []for file in os.listdir(image_dir):if file.endswith('.jpg'):files.append(file)total_count = len(files)print('find {} images'.format(total_count))if shuffle_file:random.shuffle(files)if need_test_dataset:test_count = int(total_count * (1 - trainval_radio))train_count = int((total_count - test_count) * train_radio)val_count = total_count - test_count - train_countelse:train_count = int(total_count * train_radio)val_count = total_count - train_counttest_count = 0print('train={},val={},test={}'.format(train_count, val_count, test_count))train_files = files[:train_count]val_files = files[train_count:train_count + val_count]test_files = files[train_count + val_count:]print('start copy or move train files...')for file in train_files:if copy_it:shutil.copy(os.path.join(image_dir, file), os.path.join(train_images_dir, file))label_file = os.path.join(label_dir, file[:-3] + 'txt')if os.path.exists(label_file):shutil.copy(label_file, os.path.join(train_labels_dir, file[:-3] + 'txt'))else:shutil.move(os.path.join(image_dir, file), os.path.join(train_images_dir, file))label_file = os.path.join(label_dir, file[:-3] + 'txt')if os.path.exists(label_file):shutil.move(label_file, os.path.join(train_labels_dir, file[:-3] + 'txt'))print('start copy or move val files...')for file in val_files:if copy_it:shutil.copy(os.path.join(image_dir, file), os.path.join(val_images_dir, file))label_file = os.path.join(label_dir, file[:-3] + 'txt')if os.path.exists(label_file):shutil.copy(label_file, os.path.join(val_labels_dir, file[:-3] + 'txt'))else:shutil.move(os.path.join(image_dir, file), os.path.join(val_images_dir, file))label_file = os.path.join(label_dir, file[:-3] + 'txt')if os.path.exists(label_file):shutil.move(label_file, os.path.join(val_labels_dir, file[:-3] + 'txt'))if need_test_dataset and test_count > 0:print('start copy or move test files...')for file in test_files:if copy_it:shutil.copy(os.path.join(image_dir, file), os.path.join(test_images_dir, file))label_file = os.path.join(label_dir, file[:-3] + 'txt')if os.path.exists(label_file):shutil.copy(label_file, os.path.join(test_labels_dir, file[:-3] + 'txt'))else:shutil.move(os.path.join(image_dir, file), os.path.join(test_images_dir, file))label_file = os.path.join(label_dir, file[:-3] + 'txt')if os.path.exists(label_file):shutil.move(label_file, os.path.join(test_labels_dir, file[:-3] + 'txt'))class_file=os.path.join(label_dir, 'classes.txt')if os.path.exists(class_file):class_names=[]with open(class_file, 'r') as f:class_names=f.read().rstrip('\n').split('\n')nc = len(class_names)content='train: '+train_images_dir+'\n'content += 'val: '+val_images_dir+'\n'if need_test_dataset:content += 'test: '+test_images_dir+'\n'content += 'nc: '+str(nc)+'\n'content += 'names:\n'content += "\n".join([f" {i}: {name}" for i, name in enumerate(class_names)])with open(os.path.join(save_dir,'coco128.yaml'), 'w') as f:f.write(content)print('all done!')
if __name__ == '__main__':images_dir=r'C:\Users\Administrator\Downloads\data\JPEGImages'labels_dir=r'C:\Users\Administrator\Downloads\data\labels'save_dir=r'C:\Users\Administrator\Downloads\dataset'vs = VOCDataSplit()vs.split(images_dir,labels_dir,save_dir,trainval_radio=0.9, train_radio=0.9, copy_it=True,shuffle_file=True,need_test_dataset=False)
?注意?images_dir,labels_dir,save_dir根據自己實際情況進行調整。這個split.py腳本功能就是將JPEGImages和labels文件進行自動隨機分割成標準yolo訓練目錄格式。腳本放在data文件夾下面即可:
然后運行腳本:
然后在C:\Users\Administrator\Downloads看到有個dataset文件夾生成?
至此標準訓練格式完成了。打開coco128.yaml看到下面類似格式:
train: C:\Users\Administrator\Downloads\dataset\train\images
val: C:\Users\Administrator\Downloads\dataset\val\images
nc: 32
names:0: Apple1: Apple-core2: Apple-peel3: Bone4: Bone-fish5: Bread6: Bun7: Egg-hard8: Egg-scramble9: Egg-shell10: Egg-steam11: Egg-yolk12: Fish13: Meat14: Mussel15: Mussel-shell16: Noodle17: Orange18: Orange-peel19: Other-waste20: Pancake21: Pasta22: Pear23: Pear-core24: Pear-peel25: Potato26: Rice27: Shrimp28: Shrimp-shell29: Tofu30: Tomato31: Vegetable
?這些都不用修改,我們只需要檢查一下是不是對的就行。
之后就是開始訓練了,注意訓練yolov8模型需要自己提前安裝好環境。
使用預訓練模型開始訓練
yolo task=detect mode=train model=yolo11n.pt data=coco128.yaml epochs=100 imgsz=640 batch=8 workers=2
參數說明:
model: 使用的模型類型,如 yolo11s.pt(小模型)、yolo11m.pt(中)、yolo11l.pt(大)
data: 指定數據配置文件
epochs: 訓練輪數
imgsz: 輸入圖像尺寸
batch: 批量大小(根據顯存調整)
workers:指定進程數(windows最好設置0或者1或2,linux可以設置8)
訓練完成后,最佳權重保存路徑為:runs/detect/train/weights/best.pt,如果多次運行命令runs/detect/train2,runs/detect/train3文件夾生成只需要到數字最大文件夾查看就可以找到模型
圖片預測:
from ultralytics import YOLO# 加載訓練好的模型
model = YOLO('runs/detect/train/weights/best.pt')# 圖像預測
results = model('path_to_your_image.jpg')
視頻或攝像頭預測
results = model('path_to_video.mp4') # 視頻
#results = model(0) # 攝像頭
?驗證集評估
yolo task=detect mode=val model=runs/detect/train/weights/best.pt data=data.yaml
輸出指標圖像,一般在模型訓練后生成,文件位置在runs/detect/train/results.png:
上面訓練結果圖片常用評估參數介紹
【常用評估參數介紹】
在目標檢測任務中,評估模型的性能是至關重要的。你提到的幾個術語是評估模型性能的常用指標。下面是對這些術語的詳細解釋:
- Class:
- 這通常指的是模型被設計用來檢測的目標類別。例如,一個模型可能被訓練來檢測車輛、行人或動物等不同類別的對象。
- Images:
- 表示驗證集中的圖片數量。驗證集是用來評估模型性能的數據集,與訓練集分開,以確保評估結果的公正性。
- Instances:
- 在所有圖片中目標對象的總數。這包括了所有類別對象的總和,例如,如果驗證集包含100張圖片,每張圖片平均有5個目標對象,則Instances為500。
- P(精確度Precision):
- 精確度是模型預測為正樣本的實例中,真正為正樣本的比例。計算公式為:Precision = TP / (TP + FP),其中TP表示真正例(True Positives),FP表示假正例(False Positives)。
- R(召回率Recall):
- 召回率是所有真正的正樣本中被模型正確預測為正樣本的比例。計算公式為:Recall = TP / (TP + FN),其中FN表示假負例(False Negatives)。
- mAP50:
- 表示在IoU(交并比)閾值為0.5時的平均精度(mean Average Precision)。IoU是衡量預測框和真實框重疊程度的指標。mAP是一個綜合指標,考慮了精確度和召回率,用于評估模型在不同召回率水平上的性能。在IoU=0.5時,如果預測框與真實框的重疊程度達到或超過50%,則認為該預測是正確的。
- mAP50-95:
- 表示在IoU從0.5到0.95(間隔0.05)的范圍內,模型的平均精度。這是一個更嚴格的評估標準,要求預測框與真實框的重疊程度更高。在目標檢測任務中,更高的IoU閾值意味著模型需要更準確地定位目標對象。mAP50-95的計算考慮了從寬松到嚴格的多個IoU閾值,因此能夠更全面地評估模型的性能。
這些指標共同構成了評估目標檢測模型性能的重要框架。通過比較不同模型在這些指標上的表現,可以判斷哪個模型在實際應用中可能更有效。
將模型導出為ONNX、TensorRT等格式以用于部署:
yolo export model=runs/detect/train/weights/best.pt format=onnx
支持格式包括:onnx, engine, tflite, pb, torchscript 等。
經過上面訓練可以使用模型做進一步部署,比如使用onnx模型在嵌入式部署,使用engine模型在jetson上deepstream部署,使用torchscript模型可以在C++上部署等等。