文件结构:只有.jpg和.json的文件,全在一个文件夹中
时间: 2025-07-28 11:06:35 浏览: 12
<think>我们面临两个主要问题:1.在使用`train_test_split`时出现的`ValueError`,具体是`test_size`参数设置不当以及样本数量为0。2.数据集包含.jpg图像和.json标注文件,需要正确划分并生成相应的训练集和测试集JSON文件(类似引用[1]中的做法)。根据错误信息,核心原因有两个:-数据集为空(n_samples=0),导致无法划分。-当`test_size`为整数时,必须小于样本总数,且大于0。解决方案步骤:###步骤1:检查数据集路径和文件读取确保数据集路径正确,并且能够正确读取到图像文件(.jpg)和对应的标注文件(.json)。假设数据集结构如下:```data_root/├──images/#存放所有.jpg图像└──annotations/#存放所有.json标注文件```我们需要从`images`文件夹中读取所有.jpg文件,并确保每个图像在`annotations`文件夹中有对应的.json文件。###步骤2:获取有效文件列表为了避免样本数量为0,我们需要确认:-图像文件存在-每个图像文件都有对应的标注文件示例代码:```pythonimportosdata_root='path/to/your/dataset'image_dir=os.path.join(data_root,'images')annotation_dir=os.path.join(data_root,'annotations')#获取所有.jpg图像文件名(不带路径)all_image_files=[fforfinos.listdir(image_dir)iff.endswith('.jpg')]#过滤掉没有对应标注文件的图像valid_image_files=[]forimg_fileinall_image_files:#假设标注文件与图像文件同名,只是扩展名为.jsonbase_name=os.path.splitext(img_file)[0]annotation_file=os.path.join(annotation_dir,base_name+'.json')ifos.path.exists(annotation_file):valid_image_files.append(img_file)#检查有效图像数量num_samples=len(valid_image_files)ifnum_samples==0:raiseValueError("Novalidsamplesfound!Checkyourdatasetpathsandfilecorrespondence.")```###步骤3:正确划分数据集使用`train_test_split`时,如果测试集样本数很小(比如2个),则`test_size`应设置为一个浮点数比例(如2/num_samples)而不是整数2,以避免当样本数变化时出错。示例:```pythonfromsklearn.model_selectionimporttrain_test_split#划分训练集和测试集(先分测试集)test_ratio=0.15#或者用具体比例:2/num_samplestrain_files,test_files=train_test_split(valid_image_files,test_size=test_ratio,random_state=42)#如果需要进一步划分验证集,可以从训练集中再分train_files,val_files=train_test_split(train_files,test_size=0.15,random_state=42)print(f"Totalsamples:{num_samples}")print(f"Train:{len(train_files)},Validation:{len(val_files)},Test:{len(test_files)}")```###步骤4:生成JSON文件(类似引用[1])我们需要生成两个JSON文件(train.json和test.json),每个JSON文件应包含对应集合中每个图像的路径和标注信息。假设每个JSON标注文件包含该图像的标注信息(如边界框、关键点等),我们需要将这些信息整合到一个大的JSON文件中。根据引用[1](clean-pvnet处理自定义数据集)的做法,生成的JSON文件可能包含以下结构:```json[{"image_path":"path/to/image1.jpg","annotations":{"bbox":[x,y,width,height],"keypoints":[[x1,y1],[x2,y2],...],"class":"yourclass"}},...]```但是,具体结构取决于你的模型需求。这里我们假设每个原始JSON文件已经包含了所需的标注信息,我们只需将图像路径和对应的标注文件内容关联起来。示例代码生成train.json:```pythonimportjsondefgenerate_json_file(image_files,image_dir,annotation_dir,output_json_path):data_list=[]forimg_fileinimage_files:base_name=os.path.splitext(img_file)[0]annotation_file=os.path.join(annotation_dir,base_name+'.json')#读取标注文件内容withopen(annotation_file,'r')asf:annotation_data=json.load(f)#构建数据项item={"image_path":os.path.join(image_dir,img_file),#或者只保留文件名,根据模型要求"annotations":annotation_data}data_list.append(item)#写入JSON文件withopen(output_json_path,'w')asf:json.dump(data_list,f,indent=2)#生成训练集和测试集的JSON文件generate_json_file(train_files,image_dir,annotation_dir,os.path.join(data_root,'train.json'))generate_json_file(test_files,image_dir,annotation_dir,os.path.join(data_root,'test.json'))```###完整代码示例```pythonimportosimportjsonfromsklearn.model_selectionimporttrain_test_split#设置数据集根目录data_root='D:/dataset/vessel'#请替换为你的实际路径image_dir=os.path.join(data_root,'images')annotation_dir=os.path.join(data_root,'annotations')#步骤1:获取所有图像文件并过滤无效标注all_image_files=[fforfinos.listdir(image_dir)iff.endswith('.jpg')]valid_image_files=[]forimg_fileinall_image_files:base_name=os.path.splitext(img_file)[0]annotation_file=os.path.join(annotation_dir,base_name+'.json')ifos.path.exists(annotation_file):valid_image_files.append(img_file)num_samples=len(valid_image_files)ifnum_samples==0:raiseValueError("Novalidsamplesfound!")#步骤2:划分数据集test_ratio=0.15#测试集比例train_files,test_files=train_test_split(valid_image_files,test_size=test_ratio,random_state=42)#可选:划分验证集val_ratio=0.15#验证集占训练集的比例train_files,val_files=train_test_split(train_files,test_size=val_ratio,random_state=42)print(f"数据集总数:{num_samples}")print(f"训练集:{len(train_files)}")print(f"验证集:{len(val_files)}")print(f"测试集:{len(test_files)}")#步骤3:生成JSON文件defgenerate_json_file(image_files,image_dir,annotation_dir,output_json_path):data_list=[]forimg_fileinimage_files:base_name=os.path.splitext(img_file)[0]annotation_file=os.path.join(annotation_dir,base_name+'.json')withopen(annotation_file,'r')asf:ann_data=json.load(f)#注意:这里存储的图像路径是绝对路径,如果模型需要相对路径,可以调整item={"image_path":os.path.join(image_dir,img_file),"annotations":ann_data}data_list.append(item)withopen(output_json_path,'w')asf:json.dump(data_list,f,indent=2)#生成训练集、验证集和测试集的JSON文件(根据需求生成)generate_json_file(train_files,image_dir,annotation_dir,os.path.join(data_root,'train.json'))generate_json_file(val_files,image_dir,annotation_dir,os.path.join(data_root,'val.json'))generate_json_file(test_files,image_dir,annotation_dir,os.path.join(data_root,'test.json'))```###注意事项1.**路径格式**:在Windows系统中使用正斜杠`/`或反斜杠`\\`,避免单反斜杠(因为它是转义字符)。上面的代码使用`os.path.join`会自动处理。2.**标注文件结构**:上述代码假设每个标注文件的内容可以直接作为`annotations`字段。如果标注文件结构不同,需要调整解析方式。3.**图像路径存储**:存储绝对路径可能在不同机器上运行有问题,可以考虑存储相对于`data_root`的相对路径。###引用文献说明上述方法参考了clean-pvnet处理自定义数据集的方式[^1],通过生成JSON文件来组织训练和测试数据,便于后续模型读取。如果后续遇到其他问题,如样本不均衡或标注文件格式不匹配,需要进一步调整。§§相关问题§§1.如何解决数据集样本不均衡问题?2.标注文件格式与模型要求不一致怎么办?3.除了JSON格式,还有哪些常用的数据集组织方式?4.如何在数据划分时保持类别分布平衡?</think>## 解决 train_test_split 中的 test_size 错误及数据集处理
### 问题分析
您遇到的 `ValueError` 主要由两个原因引起:
1. **数据集为空**:错误显示 `number of samples 0`,表明 `all_imgs` 为空列表
2. **test_size 参数无效**:整数型 `test_size` 必须小于样本总数
3. **文件结构问题**:数据集包含 .jpg 图像和 .json 标注文件,需要特殊处理
### 完整解决方案
#### 步骤 1:验证数据集路径和文件读取
```python
import os
from sklearn.model_selection import train_test_split
# 确认路径存在
data_root = 'D:/dataset/vessel'
print(f"数据集根目录存在: {os.path.exists(data_root)}") # 应为 True
# 获取所有有效图像文件
image_dir = os.path.join(data_root, 'images')
all_images = [f for f in os.listdir(image_dir)
if f.endswith(('.jpg', '.png', '.jpeg'))] # 支持多种图像格式
print(f"找到 {len(all_images)} 张图像文件")
```
#### 步骤 2:处理 test_size 参数错误
```python
# 检查样本数量
if len(all_images) == 0:
raise ValueError("未找到任何图像文件!请检查路径和文件扩展名")
# 使用浮点数比例代替整数
total_samples = len(all_images)
test_ratio = 0.15 # 或根据需求计算:test_size = 2/total_samples
# 正确划分数据集
train_imgs, test_imgs = train_test_split(
all_images,
test_size=test_ratio, # 使用比例而非绝对值
random_state=42
)
```
#### 步骤 3:处理 .jpg 和 .json 文件的数据集
```python
import json
# 创建自定义数据集类
class CustomDataset:
def __init__(self, data_root, file_list):
self.image_dir = os.path.join(data_root, 'images')
self.annotation_dir = os.path.join(data_root, 'annotations')
self.file_list = file_list
def __len__(self):
return len(self.file_list)
def __getitem__(self, idx):
img_name = self.file_list[idx]
img_path = os.path.join(self.image_dir, img_name)
# 获取对应的 JSON 标注文件
json_name = os.path.splitext(img_name)[0] + '.json'
json_path = os.path.join(self.annotation_dir, json_name)
# 读取图像和标注
image = load_image(img_path) # 您的图像加载函数
with open(json_path, 'r') as f:
annotations = json.load(f)
return image, annotations
# 创建数据集实例
train_dataset = CustomDataset(data_root, train_imgs)
test_dataset = CustomDataset(data_root, test_imgs)
```
#### 步骤 4:生成训练/测试 JSON 文件(参考引用[1])
```python
def generate_json_files(data_root, file_lists, output_names):
"""
生成数据集JSON文件
:param data_root: 数据集根目录
:param file_lists: 文件列表字典 {'train': [...], 'test': [...]}
:param output_names: 输出文件名 {'train': 'train.json', 'test': 'test.json'}
"""
for set_name in file_lists:
dataset_info = []
for img_name in file_lists[set_name]:
json_name = os.path.splitext(img_name)[0] + '.json'
json_path = os.path.join(data_root, 'annotations', json_name)
# 验证标注文件存在
if not os.path.exists(json_path):
print(f"警告: 缺少标注文件 {json_path}")
continue
# 添加到数据集信息
dataset_info.append({
'image_path': os.path.join('images', img_name),
'annotation_path': os.path.join('annotations', json_name)
})
# 写入JSON文件
output_path = os.path.join(data_root, output_names[set_name])
with open(output_path, 'w') as f:
json.dump(dataset_info, f, indent=2)
print(f"已生成 {output_path} 包含 {len(dataset_info)} 个样本")
# 使用示例
generate_json_files(
data_root,
file_lists={'train': train_imgs, 'test': test_imgs},
output_names={'train': 'train.json', 'test': 'test.json'}
)
```
### 关键注意事项
1. **路径验证**:
```python
print(os.path.exists('D:/dataset/vessel/images')) # 必须返回 True
```
使用 `os.path.join` 构建路径确保跨平台兼容性
2. **文件匹配**:
```python
# 检查每个图像是否有对应标注
for img in all_images:
json_file = os.path.splitext(img)[0] + '.json'
if not os.path.exists(os.path.join(annotation_dir, json_file)):
print(f"缺失标注: {img}")
```
3. **小数据集处理**:
- 当样本量少时(如引用[2]的情况),使用绝对数量而非比例:
```python
if total_samples < 50:
test_size = max(1, int(total_samples * 0.1)) # 至少保留1个测试样本
```
4. **随机种子**:
```python
train_test_split(..., random_state=42) # 确保可复现结果
```
### 文件结构建议
```
D:/dataset/vessel/
├── images/
│ ├── image1.jpg
│ ├── image2.jpg
│ └── ...
├── annotations/
│ ├── image1.json
│ ├── image2.json
│ └── ...
├── train.json # 自动生成
└── test.json # 自动生成
```
此解决方案解决了 `test_size` 参数错误问题,同时处理了包含图像和JSON标注的自定义数据集,并生成训练/测试集描述文件,符合 clean-pvnet 的数据格式要求[^1]。
阅读全文
相关推荐




















