车辆损伤评估数据集(提供分割和检测两种标注方式)
标注类型包括
dent: 凹痕
scratch: 划痕
crack: 裂缝
glass shatter: 玻璃破碎
tire flat: 轮胎扁平
lamp broken: 车灯损坏
4000张高分辨率图共9000余标注,6GB数据量
车辆损伤评估数据集介绍
数据集概述
名称:车辆损伤评估数据集
图像数量:4,000张高分辨率图像
标注总数:9,000余项
数据量:6GB
标注类型:
- 分割标注:像素级的损伤区域分割掩码
- 检测标注:边界框标注,用于目标检测
类别:
- 凹痕 (Dent)
- 划痕 (Scratch)
- 裂缝 (Crack)
- 玻璃破碎 (Glass Shatter)
- 轮胎扁平 (Tire Flat)
- 车灯损坏 (Lamp Broken)
用途:用于车辆损伤检测和评估任务,适用于保险理赔、维修服务、车辆质量控制等领域。该数据集特别适合基于深度学习的目标检测模型(如YOLO、Faster R-CNN)和语义分割模型(如U-Net、DeepLab)。
数据集特点
- 规模:包含4,000张高分辨率图像,每张图像都带有详细的分割或边界框标注。
- 多样性:图像涵盖了不同的光照条件、天气状况和背景环境,确保模型能够适应多样的实际场景。
- 标注质量:每张已标注的图像都有精确的手动分割掩码和边界框,确保了高质量的训练数据。
- 标注方式:
- 分割标注:提供像素级的损伤区域掩码,适用于语义分割任务。
- 检测标注:提供边界框标注,适用于目标检测任务。
应用领域
- 保险理赔:自动识别和评估车辆损伤情况,加快理赔流程。
- 维修服务:通过检测结果,快速定位和评估损伤部位,辅助进行维修工作。
- 质量控制:在车辆制造和检验过程中,自动检测潜在的质量问题。
- 数据分析:通过数据分析,提供关于车辆损伤类型的统计报告,优化维修和管理策略。
获取方式
通常情况下,研究人员可以通过官方提供的链接或相关机构网站下载该数据集。请注意,使用时应遵循相应的许可协议和引用要求。
关键代码示例
1. 下载数据集
假设我们已经有了数据集的下载链接,可以使用 Python 的 requests
库来下载数据集:
import requests
import os
# 定义下载链接和保存路径
url = 'http://example.com/path/to/vehicle_damage_dataset.zip' # 替换为实际的下载链接
save_path = './vehicle_damage_dataset.zip'
# 检查是否已经下载过
if not os.path.exists(save_path):
print("Downloading dataset...")
response = requests.get(url, stream=True)
with open(save_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
print("Download complete.")
else:
print("Dataset already exists.")
# 解压数据集
import zipfile
with zipfile.ZipFile(save_path, 'r') as zip_ref:
zip_ref.extractall('./vehicle_damage_dataset')
2. 加载和显示图像及其标注
以下是一个加载和显示图像及其分割掩码和边界框标注的示例:
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import xml.etree.ElementTree as ET
def load_image_and_mask(image_path, mask_path, anno_path):
image = Image.open(image_path).convert("RGB")
mask = Image.open(mask_path).convert("L") # 转换为灰度图
tree = ET.parse(anno_path)
root = tree.getroot()
bboxes = []
for obj in root.findall('object'):
class_name = obj.find('name').text
bbox = obj.find('bndbox')
xmin = int(bbox.find('xmin').text)
ymin = int(bbox.find('ymin').text)
xmax = int(bbox.find('xmax').text)
ymax = int(bbox.find('ymax').text)
bboxes.append((class_name, [xmin, ymin, xmax, ymax]))
return image, mask, bboxes
def display_image_with_annotations(image, mask, bboxes):
fig, axes = plt.subplots(1, 2, figsize=(12, 6))
axes[0].imshow(image)
axes[0].set_title('Image with Bounding Boxes')
axes[0].axis('off')
for class_name, bbox in bboxes:
xmin, ymin, xmax, ymax = bbox
rect = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, fill=False, edgecolor='red', linewidth=2)
axes[0].add_patch(rect)
axes[0].text(xmin, ymin, class_name, color='red', fontsize=12, backgroundcolor='white')
axes[1].imshow(mask, cmap='gray')
axes[1].set_title('Segmentation Mask')
axes[1].axis('off')
plt.show()
# 示例路径
image_path = './vehicle_damage_dataset/images/image_0001.jpg'
mask_path = './vehicle_damage_dataset/masks/mask_0001.png'
anno_path = './vehicle_damage_dataset/annotations/anno_0001.xml'
image, mask, bboxes = load_image_and_mask(image_path, mask_path, anno_path)
display_image_with_annotations(image, mask, bboxes)
3. 创建 PyTorch Dataset 和 DataLoader
以下是一个简单的 PyTorch Dataset 和 DataLoader 示例,同时处理分割和检测标注:
import torch
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
from PIL import Image
import numpy as np
import xml.etree.ElementTree as ET
class VehicleDamageDataset(Dataset):
def __init__(self, image_dir, mask_dir, anno_dir, transform=None):
self.image_dir = image_dir
self.mask_dir = mask_dir
self.anno_dir = anno_dir
self.transform = transform
self.images = os.listdir(image_dir)
def __len__(self):
return len(self.images)
def __getitem__(self, idx):
img_name = self.images[idx]
image_path = os.path.join(self.image_dir, img_name)
mask_path = os.path.join(self.mask_dir, img_name.replace('.jpg', '.png'))
anno_path = os.path.join(self.anno_dir, img_name.replace('.jpg', '.xml'))
image = Image.open(image_path).convert("RGB")
mask = Image.open(mask_path).convert("L") # 转换为灰度图
tree = ET.parse(anno_path)
root = tree.getroot()
bboxes = []
labels = []
for obj in root.findall('object'):
class_name = obj.find('name').text
label = get_class_id(class_name) # 假设有一个函数获取类别ID
bbox = obj.find('bndbox')
xmin = int(bbox.find('xmin').text)
ymin = int(bbox.find('ymin').text)
xmax = int(bbox.find('xmax').text)
ymax = int(bbox.find('ymax').text)
bboxes.append([xmin, ymin, xmax, ymax])
labels.append(label)
if self.transform:
image = self.transform(image)
mask = self.transform(mask)
bboxes = torch.tensor(bboxes, dtype=torch.float32)
labels = torch.tensor(labels, dtype=torch.int64)
return image, mask, bboxes, labels
def get_class_id(class_name):
class_map = {
'Dent': 0,
'Scratch': 1,
'Crack': 2,
'Glass Shatter': 3,
'Tire Flat': 4,
'Lamp Broken': 5
}
return class_map[class_name]
# 数据增强和预处理
transform = transforms.Compose([
transforms.Resize((256, 256)),
transforms.ToTensor(),
])
# 创建 Dataset 和 DataLoader
dataset = VehicleDamageDataset(
image_dir='./vehicle_damage_dataset/images',
mask_dir='./vehicle_damage_dataset/masks',
anno_dir='./vehicle_damage_dataset/annotations',
transform=transform
)
dataloader = DataLoader(dataset, batch_size=4, shuffle=True, num_workers=2)
# 遍历数据
for images, masks, bboxes, labels in dataloader:
# 在这里进行模型训练
pass
4. 使用 YOLOv5 进行目标检测
以下是一个使用 YOLOv5 进行目标检测的简单示例:
-
安装 YOLOv5:
git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt
-
准备数据集配置文件: 将数据集转换为YOLO所需的格式,并创建配置文件(例如
data.yaml
):train: ./vehicle_damage_dataset/train/images val: ./vehicle_damage_dataset/val/images test: ./vehicle_damage_dataset/test/images nc: 6 # 类别数 names: ['Dent', 'Scratch', 'Crack', 'Glass Shatter', 'Tire Flat', 'Lamp Broken'] # 类别名称
-
训练模型: 使用YOLOv5进行训练:
python train.py --img 640 --batch 16 --epochs 50 --data data.yaml --weights yolov5s.pt
-
评估模型: 训练完成后,可以使用验证集进行评估:深色版本
-
python detect.py --source ./vehicle_damage_dataset/test/images --weights runs/train/exp/weights/best.pt --conf 0.4
5. 使用 U-Net 进行语义分割
以下是一个使用 U-Net 进行语义分割的简单示例:
-
定义 U-Net 模型:
import torch import torch.nn as nn import torch.nn.functional as F class UNet(nn.Module): def __init__(self, in_channels=3, out_channels=6): super(UNet, self).__init__() self.enc1 = self.conv_block(in_channels, 64) self.enc2 = self.conv_block(64, 128) self.enc3 = self.conv_block(128, 256) self.enc4 = self.conv_block(256, 512) self.pool = nn.MaxPool2d(2, 2) self.bottleneck = self.conv_block(512, 1024) self.upconv4 = nn.ConvTranspose2d(1024, 512, 2, stride=2) self.dec4 = self.conv_block(1024, 512) self.upconv3 = nn.ConvTranspose2d(512, 256, 2, stride=2) self.dec3 = self.conv_block(512, 256) self.upconv2 = nn.ConvTranspose2d(256, 128, 2, stride=2) self.dec2 = self.conv_block(256, 128) self.upconv1 = nn.ConvTranspose2d(128, 64, 2, stride=2) self.dec1 = self.conv_block(128, 64) self.final_conv = nn.Conv2d(64, out_channels, kernel_size=1) def conv_block(self, in_channels, out_channels): return nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1), nn.BatchNorm2d(out_channels), nn.ReLU(inplace=True), nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1), nn.BatchNorm2d(out_channels), nn.ReLU(inplace=True) ) def forward(self, x): enc1 = self.enc1(x) enc2 = self.enc2(self.pool(enc1)) enc3 = self.enc3(self.pool(enc2)) enc4 = self.enc4(self.pool(enc3)) bottleneck = self.bottleneck(self.pool(enc4)) dec4 = self.upconv4(bottleneck) dec4 = torch.cat((dec4, enc4), dim=1) dec4 = self.dec4(dec4) dec3 = self.upconv3(dec4) dec3 = torch.cat((dec3, enc3), dim=1) dec3 = self.dec3(dec3) dec2 = self.upconv2(dec3) dec2 = torch.cat((dec2, enc2), dim=1) dec2 = self.dec2(dec2) dec1 = self.upconv1(dec2) dec1 = torch.cat((dec1, enc1), dim=1) dec1 = self.dec1(dec1) return self.final_conv(dec1) model = UNet()
-
训练模型:
import torch.optim as optim device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model.to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) num_epochs = 50 for epoch in range(num_epochs): model.train() running_loss = 0.0 for images, masks, _, _ in dataloader: images, masks = images.to(device), masks.to(device) optimizer.zero_grad() outputs = model(images) loss = criterion(outputs, masks) loss.backward() optimizer.step() running_loss += loss.item() print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(dataloader)}')
-
评估模型:
model.eval() with torch.no_grad(): for images, masks, _, _ in dataloader: images, masks = images.to(device), masks.to(device) outputs = model(images) predicted_masks = torch.argmax(outputs, dim=1) # 可视化预测结果 for i in range(images.size(0)): fig, axes = plt.subplots(1, 3, figsize=(15, 5)) axes[0].imshow(images[i].permute(1, 2, 0).cpu().numpy()) axes[0].set_title('Image') axes[0].axis('off') axes[1].imshow(masks[i].cpu().numpy(), cmap='gray') axes[1].set_title('Ground Truth') axes[1].axis('off') axes[2].imshow(predicted_masks[i].cpu().numpy(), cmap='gray') axes[2].set_title('Predicted Mask') axes[2].axis('off') plt.show()
通过上述步骤,您将拥有一个完整的车辆损伤评估系统,包括数据集、预训练模型和相关的训练流程。希望这些代码能帮助您更好地利用该数据集!