牛羊檢測(cè)數(shù)據(jù)集:3538張VOC/YOLO/JSON三格式實(shí)戰(zhàn)指南)
簡(jiǎn)介這份牛羊檢測(cè)數(shù)據(jù)集面向智慧牧場(chǎng)、智慧農(nóng)場(chǎng)系統(tǒng)開(kāi)發(fā)及目標(biāo)檢測(cè)課程作業(yè)、競(jìng)賽與科研項(xiàng)目解決家畜識(shí)別與計(jì)數(shù)場(chǎng)景中高質(zhì)量標(biāo)注樣本稀缺的問(wèn)題。數(shù)據(jù)共3538張圖片標(biāo)簽同步提供VOCxml、YOLOtxt與JSON三種格式目標(biāo)類(lèi)別為“?!焙汀把颉眱深?lèi)可直接接入主流檢測(cè)算法訓(xùn)練。壓縮包約706.2MB內(nèi)含3538張jpg原圖、3538個(gè)xml標(biāo)注、3539個(gè)txt標(biāo)簽文件及1個(gè)zip包文件組織清晰便于按格式快速取用。數(shù)據(jù)集分布均勻、標(biāo)注精準(zhǔn)背景與場(chǎng)景多樣性充足模型擬合效果較好適合從算法驗(yàn)證到實(shí)際部署的多種需求。目前已有473人學(xué)習(xí)下載所有數(shù)據(jù)均來(lái)自作者實(shí)際項(xiàng)目與實(shí)驗(yàn)demo質(zhì)量有保障下載后可直接用于訓(xùn)練與評(píng)估。1. 智慧牧場(chǎng)里的牛羊檢測(cè)3538 張三種標(biāo)簽格式的數(shù)據(jù)集到底怎么用去年幫一個(gè)做智慧牧場(chǎng)系統(tǒng)的團(tuán)隊(duì)排查計(jì)數(shù)誤差現(xiàn)場(chǎng)攝像頭裝在牛棚和草場(chǎng)交界處白天逆光、夜里補(bǔ)光牛和羊還經(jīng)常貼在一起走。他們模型在測(cè)試集上 mAP 看著還行一到真實(shí)場(chǎng)景就漏檢、誤檢最后定位到問(wèn)題不在網(wǎng)絡(luò)結(jié)構(gòu)而在訓(xùn)練數(shù)據(jù)的標(biāo)注格式和分布。這件事讓我意識(shí)到做牛羊識(shí)別檢測(cè)這類(lèi)家畜檢測(cè)項(xiàng)目數(shù)據(jù)集的質(zhì)量和格式兼容性往往比換 backbone 更決定成敗。這次拆的這份智慧牧場(chǎng)牛羊檢測(cè)數(shù)據(jù)集一共 3538 張圖片標(biāo)簽同時(shí)給了 VOC 的 xml、YOLO 的 txt 和 json 三種格式目標(biāo)就兩類(lèi)牛和羊。它適合課程作業(yè)、設(shè)計(jì)、比賽也適合直接塞進(jìn)實(shí)際項(xiàng)目里跑 baseline。下面我按「這是什么、怎么用、坑在哪」的順序把這份資源從解壓到訓(xùn)練再到驗(yàn)證的完整鏈路講清楚新手能照著復(fù)現(xiàn)熟手能直接看參數(shù)和邊界。2. 三種標(biāo)簽格式的取舍VOC、YOLO、JSON 各自適合什么場(chǎng)景拿到壓縮包先別急著解壓訓(xùn)練得先搞清楚為什么同一批圖要配三種標(biāo)簽。這不是為了湊數(shù)而是因?yàn)椴煌蚣堋⒉煌A段對(duì)標(biāo)注格式的胃口完全不一樣。選錯(cuò)格式輕則寫(xiě)一堆轉(zhuǎn)換腳本重則坐標(biāo)對(duì)不上、類(lèi)別錯(cuò)位訓(xùn)練半天 loss 不降。這一章把三種格式的字段結(jié)構(gòu)、適用框架和轉(zhuǎn)換關(guān)系講透后面動(dòng)手才不會(huì)翻車(chē)。2.1 VOC xml 的結(jié)構(gòu)與適用場(chǎng)景VOC 格式是目標(biāo)檢測(cè)里最老牌也最通用的標(biāo)注形式每張圖對(duì)應(yīng)一個(gè)同名 xml 文件。它的核心信息在object節(jié)點(diǎn)里包含類(lèi)別名name和邊界框bndbox的 xmin、ymin、xmax、ymax坐標(biāo)是絕對(duì)像素值原點(diǎn)在左上角。這份數(shù)據(jù)集里牛和羊兩類(lèi)xml 里的 name 字段就是「?!埂秆颉箤?duì)應(yīng)的英文或中文標(biāo)簽具體以解壓后實(shí)際內(nèi)容為準(zhǔn)。VOC 的好處是可讀性強(qiáng)用文本編輯器打開(kāi)就能核對(duì)標(biāo)注對(duì)不對(duì)適合做數(shù)據(jù)清洗和人工抽檢。它常被 PyTorch 的 torchvision、早期 SSD 實(shí)現(xiàn)、以及很多課程作業(yè)模板直接讀取。缺點(diǎn)是文件數(shù)量翻倍3538 張圖就是 3538 個(gè) xml磁盤(pán)上小文件多批量讀取時(shí) IO 壓力比單文件格式大。# 解析 VOC xml提取類(lèi)別和框坐標(biāo) import xml.etree.ElementTree as ET def parse_voc_xml(xml_path): tree ET.parse(xml_path) root tree.getroot() objects [] for obj in root.findall(object): name obj.find(name).text # 類(lèi)別名牛 / 羊 bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) # 左上角 x絕對(duì)像素 ymin int(bbox.find(ymin).text) # 左上角 y xmax int(bbox.find(xmax).text) # 右下角 x ymax int(bbox.find(ymax).text) # 右下角 y objects.append((name, xmin, ymin, xmax, ymax)) return objects這段代碼的關(guān)鍵點(diǎn)是坐標(biāo)直接取整VOC 不做歸一化。參數(shù)上要注意 xmax 和 ymax 是包含邊界的右下角坐標(biāo)轉(zhuǎn) YOLO 時(shí)寬高要用 xmax-xmin 而不是 xmax-xmin1這個(gè) 1 的玄學(xué)差異會(huì)讓框整體偏移一個(gè)像素小目標(biāo)上尤其明顯。2.2 YOLO txt 的歸一化邏輯與訓(xùn)練接入YOLO 格式每張圖對(duì)應(yīng)一個(gè) txt每行一個(gè)目標(biāo)格式是class_id x_center y_center width height后四個(gè)值全部是相對(duì)圖像寬高的歸一化浮點(diǎn)數(shù)范圍 0 到 1。class_id 從 0 開(kāi)始這份數(shù)據(jù)集兩類(lèi)通常 0 是牛、1 是羊但一定要以數(shù)據(jù)集自帶的類(lèi)別映射文件或?qū)嶋H txt 內(nèi)容為準(zhǔn)不能想當(dāng)然。YOLO 格式最大的優(yōu)勢(shì)是讀取快、體積小Ultralytics 的 YOLOv5/v8/v11 系列直接吃這種格式。訓(xùn)練時(shí)只需要一個(gè) data.yaml 指向圖片目錄和標(biāo)簽?zāi)夸浽倥浜?nc 和 names 就能開(kāi)跑。歸一化坐標(biāo)的好處是圖片 resize 后標(biāo)簽不用改但代價(jià)是可讀性差肉眼看不出框在哪必須可視化驗(yàn)證。# VOC 絕對(duì)坐標(biāo)轉(zhuǎn) YOLO 歸一化坐標(biāo) def voc_to_yolo(xmin, ymin, xmax, ymax, img_w, img_h): x_center (xmin xmax) / 2.0 / img_w # 中心點(diǎn) x 歸一化 y_center (ymin ymax) / 2.0 / img_h # 中心點(diǎn) y 歸一化 w (xmax - xmin) / img_w # 寬歸一化 h (ymax - ymin) / img_h # 高歸一化 return x_center, y_center, w, h參數(shù)說(shuō)明img_w 和 img_h 必須用原圖真實(shí)尺寸不能用 resize 后的尺寸否則歸一化基準(zhǔn)錯(cuò)了框會(huì)整體縮放錯(cuò)位。常見(jiàn)做法是用 PIL 或 OpenCV 讀圖拿 shape再逐張轉(zhuǎn)換。轉(zhuǎn)換完建議隨機(jī)抽 20 張用可視化腳本畫(huà)框確認(rèn)牛和羊的框都貼合目標(biāo)沒(méi)有出現(xiàn)框跑到圖外或全擠在左上角的情況。2.3 JSON 標(biāo)簽的字段與多模態(tài)/服務(wù)化用途JSON 格式在這份數(shù)據(jù)集里更像是給服務(wù)化和多模態(tài)場(chǎng)景準(zhǔn)備的。它把一張圖的所有標(biāo)注組織成一個(gè)結(jié)構(gòu)化對(duì)象通常包含圖片文件名、寬高、以及一個(gè) objects 數(shù)組數(shù)組里每個(gè)元素有類(lèi)別、bbox 坐標(biāo)有的還會(huì)帶置信度或分割點(diǎn)。JSON 的好處是能被后端服務(wù)、數(shù)據(jù)庫(kù)、以及大模型分析鏈路直接消費(fèi)比如智慧牧場(chǎng)系統(tǒng)里要把檢測(cè)結(jié)果和牛只檔案關(guān)聯(lián)JSON 就是天然的中間格式。{ image: 000000054594.jpg, width: 640, height: 480, objects: [ {category: 牛, bbox: [120, 80, 300, 260]}, {category: 羊, bbox: [340, 150, 420, 240]} ] }字段說(shuō)明bbox 這里用的是絕對(duì)坐標(biāo) [xmin, ymin, xmax, ymax]和 VOC 一致方便互轉(zhuǎn)。如果要做 COCO 風(fēng)格訓(xùn)練需要把 category 映射成數(shù)字 idbbox 轉(zhuǎn)成 [x, y, w, h]。JSON 的坑在于不同來(lái)源的字段命名不統(tǒng)一有的用 label 有的用 category有的 bbox 是歸一化的讀之前一定先打印一條看結(jié)構(gòu)別直接寫(xiě)死解析邏輯。2.4 三種格式的轉(zhuǎn)換與一致性校驗(yàn)三種格式并存時(shí)最怕的是同一張圖在 xml 和 txt 里框不一致。轉(zhuǎn)換腳本寫(xiě)完必須做一致性校驗(yàn)隨機(jī)抽若干張把 VOC 轉(zhuǎn)成 YOLO 后和數(shù)據(jù)集自帶的 YOLO txt 逐行比對(duì)坐標(biāo)誤差超過(guò)一個(gè)像素就要查原因。常見(jiàn)原因是轉(zhuǎn)換時(shí)用了 resize 后的尺寸或者類(lèi)別 id 映射反了。格式坐標(biāo)類(lèi)型每圖文件數(shù)典型框架主要用途VOC xml絕對(duì)像素1 個(gè) xmltorchvision、SSD數(shù)據(jù)清洗、抽檢YOLO txt歸一化1 個(gè) txtYOLOv5/v8/v11直接訓(xùn)練JSON絕對(duì)像素可合并為 1 個(gè)后端服務(wù)、多模態(tài)服務(wù)化、檔案關(guān)聯(lián)校驗(yàn)通過(guò)后再進(jìn)入訓(xùn)練能省掉大量「訓(xùn)練不收斂其實(shí)是標(biāo)簽錯(cuò)了」的排查時(shí)間。這一步看著笨但它是后面所有環(huán)節(jié)的地基。3. 從解壓到跑通 YOLO 訓(xùn)練目錄組織與 data.yaml 配置格式搞明白之后真正動(dòng)手訓(xùn)練。這一章按實(shí)際工程順序走先規(guī)劃目錄再寫(xiě) data.yaml然后啟動(dòng)訓(xùn)練最后看日志判斷是否正常。很多人卡在路徑和類(lèi)別數(shù)上其實(shí)都是配置問(wèn)題不是模型問(wèn)題。3.1 目錄結(jié)構(gòu)與文件命名規(guī)范拿到壓縮包解壓后先別改文件名。YOLO 要求圖片和標(biāo)簽同名、分目錄存放常見(jiàn)結(jié)構(gòu)是 images 和 labels 兩個(gè)平行目錄下面再分 train 和 val。如果數(shù)據(jù)集原始結(jié)構(gòu)不是這樣用腳本批量整理不要手動(dòng)拖拽3538 張手動(dòng)操作必出錯(cuò)。# 整理成 YOLO 訓(xùn)練目錄結(jié)構(gòu) dataset/ ├── images/ │ ├── train/ # 訓(xùn)練圖片 │ └── val/ # 驗(yàn)證圖片 ├── labels/ │ ├── train/ # 對(duì)應(yīng) txt 標(biāo)簽 │ └── val/ └── data.yaml # 數(shù)據(jù)集配置整理時(shí)注意圖片和標(biāo)簽必須同名比如000000054594.jpg對(duì)應(yīng)000000054594.txt。如果數(shù)據(jù)集里 txt 文件名和圖片對(duì)不上訓(xùn)練時(shí)會(huì)被當(dāng)成無(wú)標(biāo)簽圖跳過(guò)表現(xiàn)為 loss 異?;蚰承﹫D完全不參與。建議整理完跑一遍配對(duì)檢查統(tǒng)計(jì)圖片數(shù)和標(biāo)簽數(shù)是否一致。3.2 data.yaml 的關(guān)鍵字段與類(lèi)別映射data.yaml 是 YOLO 訓(xùn)練的入口配置寫(xiě)錯(cuò)一個(gè)字段訓(xùn)練就起不來(lái)。核心字段是 path、train、val、nc、names。nc 是類(lèi)別數(shù)這份數(shù)據(jù)集是 2names 的順序必須和 txt 里的 class_id 嚴(yán)格對(duì)應(yīng)0 對(duì)應(yīng)第一個(gè)名字1 對(duì)應(yīng)第二個(gè)。# data.yaml path: /home/user/dataset # 數(shù)據(jù)集根目錄 train: images/train # 訓(xùn)練圖片相對(duì)路徑 val: images/val # 驗(yàn)證圖片相對(duì)路徑 nc: 2 # 類(lèi)別數(shù)牛、羊 names: 0: niu # class_id 0 對(duì)應(yīng)牛 1: yang # class_id 1 對(duì)應(yīng)羊參數(shù)說(shuō)明path 建議用絕對(duì)路徑避免訓(xùn)練時(shí)工作目錄變化導(dǎo)致找不到文件。names 用英文或拼音更穩(wěn)中文在某些版本的可視化里會(huì)亂碼。如果發(fā)現(xiàn)訓(xùn)練日志里類(lèi)別名顯示異常先查 names 縮進(jìn)和冒號(hào)后的空格YAML 對(duì)格式很敏感少一個(gè)空格就解析失敗。3.3 啟動(dòng)訓(xùn)練與關(guān)鍵超參設(shè)置配置好之后啟動(dòng)訓(xùn)練。以 Ultralytics YOLOv8 為例命令行和 Python 兩種方式都行。第一次跑建議先用小 epoch 驗(yàn)證鏈路通不通別一上來(lái)就 300 epoch浪費(fèi)時(shí)間。# 命令行啟動(dòng) YOLOv8 訓(xùn)練 yolo detect train \ datadataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0參數(shù)說(shuō)明model 用預(yù)訓(xùn)練權(quán)重能加快收斂yolov8n 是最小的適合先跑通imgsz 是輸入尺寸640 是通用值牛羊目標(biāo)如果普遍偏小可以提到 960但顯存占用會(huì)上升batch 根據(jù)顯存調(diào)16 是 8G 顯存左右的穩(wěn)妥值device0 指定第一塊 GPU沒(méi)有 GPU 就去掉用 CPU但會(huì)很慢。訓(xùn)練過(guò)程中重點(diǎn)看 box_loss 和 mAP50 是否下降和上升如果 loss 一直震蕩不降先回去查標(biāo)簽格式和類(lèi)別映射。3.4 訓(xùn)練日志解讀與中斷恢復(fù)訓(xùn)練日志里幾個(gè)關(guān)鍵指標(biāo)box_loss 衡量框回歸cls_loss 衡量分類(lèi)mAP50 是 IoU 0.5 下的平均精度。正常情況 box_loss 在前幾個(gè) epoch 快速下降mAP50 逐步上升。如果 mAP50 長(zhǎng)期在 0 附近大概率是標(biāo)簽沒(méi)讀到或類(lèi)別全錯(cuò)。中斷恢復(fù)用 resume 參數(shù)指向 last.pt 即可接著跑不用從頭來(lái)。# 中斷后恢復(fù)訓(xùn)練 yolo detect train resume modelruns/detect/train/weights/last.pt注意 resume 會(huì)沿用之前的配置改超參要重新起訓(xùn)練。訓(xùn)練完的權(quán)重在 runs/detect/train/weights/ 下best.pt 是驗(yàn)證集最好的last.pt 是最后一輪部署一般用 best.pt。4. 避坑與排查牛羊檢測(cè)數(shù)據(jù)集落地時(shí)最容易翻車(chē)的五件事這一章是我和幾個(gè)做智慧牧場(chǎng)項(xiàng)目的朋友踩過(guò)的坑匯總每條都按現(xiàn)象、原因、解決寫(xiě)。數(shù)據(jù)集本身質(zhì)量不錯(cuò)但工程落地時(shí)的坑往往不在數(shù)據(jù)而在使用方式。4.1 現(xiàn)象訓(xùn)練 loss 不降mAP 長(zhǎng)期為 0原因最常見(jiàn)的是標(biāo)簽路徑?jīng)]配對(duì)YOLO 找不到 txt把所有圖當(dāng)負(fù)樣本其次是 class_id 超出 nc 范圍比如 txt 里寫(xiě)了 2 但 nc2 只允許 0 和 1。解決先跑配對(duì)檢查腳本確認(rèn)每張圖都有同名 txt再統(tǒng)計(jì)所有 txt 里的 class_id 最大值必須小于 nc。這兩個(gè)檢查五分鐘能做完能省幾小時(shí)瞎調(diào)參。4.2 現(xiàn)象驗(yàn)證集指標(biāo)很好實(shí)際場(chǎng)景漏檢嚴(yán)重原因數(shù)據(jù)集分布和真實(shí)場(chǎng)景不匹配。3538 張圖里如果牛棚內(nèi)景多、草場(chǎng)遠(yuǎn)景少模型在遠(yuǎn)景小目標(biāo)上就弱。另外牛羊貼在一起時(shí) NMS 容易把其中一個(gè)框抑制掉。解決先做場(chǎng)景分層統(tǒng)計(jì)看訓(xùn)練集覆蓋了哪些光照和距離推理時(shí)適當(dāng)調(diào)低 conf 閾值并調(diào)高 iou 閾值減少誤抑制。必要時(shí)補(bǔ)充真實(shí)場(chǎng)景圖做微調(diào)。4.3 現(xiàn)象VOC 轉(zhuǎn) YOLO 后框整體偏移原因轉(zhuǎn)換時(shí)用了 resize 后的尺寸做歸一化或者 xmax-xmin 時(shí)多加了 1。解決歸一化必須用原圖寬高寬高計(jì)算用 xmax-xmin不要 1。轉(zhuǎn)完抽 20 張可視化和原 xml 疊在一起看偏移超過(guò)一兩個(gè)像素就回查代碼。4.4 現(xiàn)象JSON 解析報(bào) key 錯(cuò)誤原因不同來(lái)源的 JSON 字段命名不一致有的用 category 有的用 label有的 bbox 是對(duì)象不是數(shù)組。解決解析前先打印一條完整 JSON按實(shí)際字段寫(xiě)解析邏輯別照搬網(wǎng)上的模板。加 try-except 跳過(guò)異常條目并記錄避免一條壞數(shù)據(jù)中斷整個(gè)流程。4.5 現(xiàn)象訓(xùn)練顯存溢出或速度極慢原因imgsz 或 batch 設(shè)太大或者數(shù)據(jù)加載用了太多 worker 導(dǎo)致 CPU 瓶頸。解決先降 batch 到 8 或 4 跑通再逐步加imgsz 從 640 起小目標(biāo)多再升。worker 數(shù)一般設(shè)成 CPU 核數(shù)的 1/4 到 1/2太多反而搶資源。顯存不夠時(shí)還可以開(kāi)混合精度YOLOv8 默認(rèn)就帶 AMP不用額外配。5. 進(jìn)階驗(yàn)證與技巧用可視化抽檢和分層評(píng)估把數(shù)據(jù)集吃透訓(xùn)練跑通只是開(kāi)始真正讓這份數(shù)據(jù)集發(fā)揮價(jià)值的是驗(yàn)證環(huán)節(jié)。我一般不會(huì)只看一個(gè) mAP 數(shù)字就下結(jié)論而是做兩件事可視化抽檢和分層評(píng)估??梢暬闄z是隨機(jī)抽一批驗(yàn)證圖把預(yù)測(cè)框和真實(shí)框畫(huà)在一起肉眼看有沒(méi)有系統(tǒng)性偏移、漏檢、類(lèi)別混淆。這一步能發(fā)現(xiàn)指標(biāo)掩蓋的問(wèn)題比如羊被大量識(shí)別成牛mAP 可能還行但業(yè)務(wù)上完全不可用。# 可視化真實(shí)框與預(yù)測(cè)框?qū)Ρ?import cv2 def draw_boxes(img_path, gt_boxes, pred_boxes, save_path): img cv2.imread(img_path) for (x1, y1, x2, y2) in gt_boxes: # 真實(shí)框綠色 cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) for (x1, y1, x2, y2) in pred_boxes: # 預(yù)測(cè)框紅色 cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(save_path, img)參數(shù)說(shuō)明gt_boxes 從 VOC 或 YOLO 反歸一化得到pred_boxes 從模型輸出拿兩邊都轉(zhuǎn)成絕對(duì)像素再畫(huà)。綠色真實(shí)框和紅色預(yù)測(cè)框重疊度高說(shuō)明定位準(zhǔn)紅色框缺失說(shuō)明漏檢紅綠錯(cuò)位說(shuō)明回歸有問(wèn)題。抽檢數(shù)量建議不少于 50 張覆蓋不同光照和距離。分層評(píng)估是把驗(yàn)證集按目標(biāo)尺寸、目標(biāo)數(shù)量、光照條件分組分別算 mAP。比如小目標(biāo)組、密集組、逆光組哪一組指標(biāo)明顯低就針對(duì)性地補(bǔ)數(shù)據(jù)或調(diào) anchor。這份數(shù)據(jù)集背景豐富、多樣性充足正好適合做這種分層分析能快速定位模型短板。還有一個(gè)實(shí)用技巧是標(biāo)簽一致性交叉驗(yàn)證把 VOC 轉(zhuǎn)成 YOLO 后和數(shù)據(jù)集自帶的 YOLO txt 做逐行比對(duì)統(tǒng)計(jì)不一致的比例。如果超過(guò) 1%說(shuō)明轉(zhuǎn)換腳本或原始標(biāo)注有問(wèn)題必須先修數(shù)據(jù)再訓(xùn)練。我吃過(guò)這個(gè)虧曾經(jīng)因?yàn)檗D(zhuǎn)換時(shí)類(lèi)別 id 映射反了牛和羊?qū)φ{(diào)模型訓(xùn)出來(lái)指標(biāo)虛高上線后計(jì)數(shù)全錯(cuò)返工花了兩天。從那以后我每次拿到多格式標(biāo)簽的數(shù)據(jù)集都強(qiáng)制先跑一遍一致性校驗(yàn)和可視化抽檢確認(rèn)無(wú)誤才進(jìn)訓(xùn)練。希望這份拆解幫到你少走點(diǎn)彎路。本文還有配套的精品資源點(diǎn)擊獲取