在數據科學與機器學習項目中,數據預處理始終扮演著不可或缺的角色。尤其當你面對多類別圖像標注任務,而標注數據卻是以 JSON 形式存在,而目標檢測模型卻偏好 VOC 格式的 XML 時,這個轉換過程就變得極為關鍵。
本文將帶你深入解讀一個完整的實戰項目:如何將圖像分類數據集中每個標注 JSON 批量轉換為標準 Pascal VOC 格式的 XML 文件,并同步整理圖像資源。文章不僅附帶完整代碼,還涵蓋路徑組織、格式規范、注意事項等細節。
🧭 背景設定與挑戰目標
想象你正進行一個貓狗識別任務,圖像已經用 LabelMe 等工具標注為 JSON 格式,其中包含了邊界框(bounding box)、類別信息、圖像路徑等。你需要:
- 從多個子類別文件夾(如“貓/狗”、“訓練集/驗證集”)中提取圖片;
- 將對應的 JSON 文件轉換為 VOC 結構的 XML;
- 輸出統一、清晰、便于訓練的數據目錄結構。
聽起來瑣碎?沒錯。但只需一套 Python 腳本,這些都能自動化完成!
🗂? 項目結構設計(自動創建)
最終數據結構如下所示:
├── your_target_path/
│ ├── 訓練/
│ │ ├── images/
│ │ └── xml/
│ └── 驗證/
│ ├── images/
│ └── xml/
無須手動創建目錄,程序將自動完成所有結構的搭建與數據整理!
🔍 代碼核心邏輯剖析
🧩 1. JSON 轉 Pascal VOC XML:convert_json_to_voc_xml
該函數負責讀取單個標注文件,提取圖像尺寸、目標框信息等,并生成標準 Pascal VOC XML。使用了 Python 的 xml.etree.ElementTree
庫,無需額外依賴。
🧩 2. XML 構建核心:make_voc_xml
該函數將目標對象逐一轉寫為 <object>
標簽結構,包括:
label
標簽名points
坐標點(自動計算為 bbox)difficult
標簽(可選)
并將其打包為完整的 <annotation>
結構。
🧩 3. 批量處理:process_split
它是處理每個子集(如“訓練”/“驗證”)的核心函數:
- 遍歷 JSON 文件夾
- 復制圖像文件至目標目錄
- 調用轉換函數生成 XML
- 控制最大數量(默認為 3000)
🛠? 完整可運行腳本
import os
import shutil
import json
import xml.etree.ElementTree as ETdef make_voc_xml(json_path, img_filename, img_shape, objects, xml_path):# 構建 Pascal VOC XML...def convert_json_to_voc_xml(json_file, xml_file):# 從 JSON 文件中提取圖像信息與目標對象,生成 XML...def process_split(split, base_dir, target_base, max_count=3000):img_dst = os.path.join(target_base, split, 'images')xml_dst = os.path.join(target_base, split, 'xml')os.makedirs(img_dst, exist_ok=True)os.makedirs(xml_dst, exist_ok=True)img_count = 0for animal in ['cat', 'dog']:img_src = os.path.join(base_dir, animal, split + '集', 'images')json_src = os.path.join(base_dir, animal, split + '集', 'json')if not os.path.exists(img_src) or not os.path.exists(json_src):continuefiles = [f for f in os.listdir(json_src) if f.endswith('.json')]files = files[:max(0, max_count - img_count)]for fname in files:json_path = os.path.join(json_src, fname)with open(json_path, 'r', encoding='utf-8') as f:data = json.load(f)img_name = os.path.basename(data['imagePath'])img_path = os.path.join(img_src, img_name)if not os.path.exists(img_path):continueshutil.copy(img_path, os.path.join(img_dst, img_name))xml_name = os.path.splitext(img_name)[0] + '.xml'xml_path = os.path.join(xml_dst, xml_name)convert_json_to_voc_xml(json_path, xml_path)img_count += 1if img_count >= max_count:breakif __name__ == "__main__":# ?? 請將以下兩個路徑替換為你自己的輸入/輸出目錄base_dir = r"請在此填寫你的原始數據集路徑"target_base = r"請在此填寫你希望保存轉換結果的位置"# 分別處理訓練集與驗證集process_split('訓練', base_dir, target_base, max_count=3000)process_split('驗證', base_dir, target_base, max_count=3000)print("圖片和VOC格式xml已整理完成!")
🧷 使用步驟指南(務必替換路徑)
- 在本地準備如下數據結構:
原始路徑/ ├── cat/ │ ├── 訓練集/ │ │ ├── images/ │ │ └── json/ │ └── 驗證集/ └── dog/
- 修改腳本中的
base_dir
與target_base
變量為你自己的實際路徑。 - 運行腳本,觀察終端輸出轉換進度。
- 轉換結果將自動按“訓練 / 驗證”分文件夾整理好圖像與 XML 標注。
📌 技術亮點回顧
- ? 純標準庫實現,跨平臺無依賴
- ? 支持多標簽、多邊框結構
- ? 支持 JSON 合法性與圖像路徑檢查
- ? 自動路徑管理與目錄創建
- ? 輸出即訓練,直接上手模型訓練流程
💡 總結
從標注到模型訓練,中間這一步格式轉換往往被忽視。本文不僅提供了解決方案,更以實戰項目為例,系統講解了數據清洗與結構化管理的全流程。對于任何從事圖像識別、目標檢測的開發者而言,這都是一份值得收藏的工程模板。
👋 如果你覺得本文有幫助,歡迎點贊 + 收藏 + 關注,一起探索更多 AI 項目實踐!