语义分割为图像中的每个像素分配一个类标签,从而生成覆盖整个场景的密集类映射。与区分单个对象的实例分割不同,语义分割将同一类的所有像素组合在一起,而不管存在多少个不同的对象。语义分割模型的输出是一个单一的宽高类映射,其中每个像素值对应一个预测的类ID。这使得语义分割非常适合场景解析任务,如自动驾驶、医学成像和土地覆盖映射。YOLO26语义分割模型文件使用-sem后缀,例如yolo26n-sem.pt。

      数据集格式语义分割数据集使用单通道掩码图像(通常为PNG),其中每个像素值代表一个类ID。值为255的像素被视为"忽略"并从损失计算中排除。数据集YAML应指定图像及其对应掩码目录的路径。

      语义分割为图像中的每个像素分配一个类别标签。与实例分割不同,语义分割不会区分同一类别的单个对象。训练目标是一个密集类掩码,其中每个像素存储一个类ID。

      支持的数据集格式:支持两种标签格式。数据集加载器会根据数据集YAML是否定义了masks_dir键来选择路径

      1.PNG掩码格式:语义分割数据集每个样本使用一个图像文件和一个掩码文件。掩码是单通道图像,通常为PNG格式,其中每个像素值都是对应图像像素的类别索引。

      (1).像素值0、1、2等代表数据集names映射中的类ID。

      (2).像素值255被视为忽略标签,并在损失和指标计算中被排除。

      (3).掩码文件应与其匹配的图像文件使用相同的文件名。

      (4).掩码默认被解析为.png文件;如果缺失,也接受其他支持的图像扩展名。使用无损格式(如.png或.tiff),因为有损压缩(如.jpg)会损坏类ID像素值。

      (5).默认布局将图像和掩码保留在并行文件夹中。数据集YAML中的masks_dir值会替换images路径组件以查找掩码。

      2.YOLO多边形标签格式:如果你的数据集已经拥有Ultralytics YOLO多边形标签(每张图像一个.txt文件,包含<class-index> <x1> <y1> <x2> <y2> ...行),你可以直接从中训练语义分割,无需转换为PNG掩码。

      当数据集YAML省略masks_dir时,会自动选择此路径。其行为如下:

      (1).多边形在加载时会被转换为每张图像的语义掩码,并按面积排序,以便在重叠区域中较小的对象覆盖较大的对象。

      (2).Multi-class(N > 1 in names): an extra background class is appended after your declared classes for pixels not covered by any polygon. The model is built with N + 1 output channels and the last channel is background.

      (3).Single-class(N == 1 in names): still trained as 1 class. The mask is binary, with your declared class shown as 1 and pixels not covered by any polygon as 0. No extra background class is added to names.

      (4).由增强填充(例如随机裁剪)添加的像素仍使用255作为忽略标签。

      数据集YAML格式:语义分割数据集使用YAML文件进行配置。主要字段包括:

      (1).path:数据集根目录。

      (2).train:相对于path的训练图像路径,或绝对路径。

      (3).val:相对于path的验证图像路径,或绝对路径。

      (4).test:可选的测试图像路径。

      (5).masks_dir:用于语义掩码的目录名称。省略此键可切换至YOLO多边形标签格式。

      (6).names:类ID到类名称的映射。

      (7).label_mapping:可选的从源数据集ID到训练ID或ignore_label的映射。当源掩码ID与连续的训练类ID不匹配时,使用label_mapping。例如官方cityscapes8.yaml文件内容如下:

# Dataset root directory
path: cityscapes8 # dataset root dir
train: images/train # train images (relative to 'path') 4 images
val: images/val # val images (relative to 'path') 4 images

masks_dir: masks # semantic mask directory

# Cityscapes 19-class labels
names:
  0: road
  1: sidewalk
  2: building
  3: wall
  4: fence
  5: pole
  6: traffic light
  7: traffic sign
  8: vegetation
  9: terrain
  10: sky
  11: person
  12: rider
  13: car
  14: truck
  15: bus
  16: train
  17: motorcycle
  18: bicycle

# Map source label IDs to train IDs; ignore_label is converted to 255.
label_mapping:
  -1: ignore_label
  0: ignore_label
  1: ignore_label
  2: ignore_label
  3: ignore_label
  4: ignore_label
  5: ignore_label
  6: ignore_label
  7: 0
  8: 1
  9: ignore_label
  10: ignore_label
  11: 2
  12: 3
  13: 4
  14: ignore_label
  15: ignore_label
  16: ignore_label
  17: 5
  18: ignore_label
  19: 6
  20: 7
  21: 8
  22: 9
  23: 10
  24: 11
  25: 12
  26: 13
  27: 14
  28: 15
  29: ignore_label
  30: ignore_label
  31: 16
  32: 17
  33: 18

      Cityscapes数据集:是一个大规模的语义分割基准,专注于在50个欧洲城市中拍摄的城市街景。它提供了高质量的像素级标注。

      (1).Cityscapes精细标注包括2975张训练图像、500张验证图像和1525张测试图像。

      (2).该数据集涵盖19个评估类别,横跨道路、车辆、人类、建筑、物体、自然和天空等类别。

      (3).Cityscapes提供标准化的评估指标,如用于语义分割的平均交并比(mIoU),从而实现对模型性能的有效比较。

      训练测试代码如下:在Cityscapes8数据集(训练集和验证集各4幅图像)上以1024图像尺寸训练YOLO26n-sem模型

def train(task, model_name, yaml, epochs, imgsz, patience, batch, optimizer, lr0, lrf, dropout, augment):
	model = YOLO(model_name) # load a pretrained model, should be a *.pt PyTorch model to run this method, n/s/m/l/x

	# petience: Training stopped early as no improvement observed in last patience epochs, use patience=0 to disable EarlyStopping
	model.train(data=yaml, epochs=epochs, imgsz=imgsz, patience=patience, batch=batch, optimizer=optimizer, lr0=lr0, lrf=lrf, dropout=dropout, augment=augment) # train the model, supported parameter reference, for example: runs/segment(detect)/train3/args.yaml

	if task == "semantic":
		metrics = model.val(data=yaml)
		print(f"miou: {metrics.miou}") # mean Intersection over Union
		print(f"pixel_accuracy: {metrics.pixel_accuracy}")  # overall pixel accuracy
	else:
		metrics = model.val() # It'll automatically evaluate the data you trained, no arguments needed, dataset and settings remembered
		if task == "classify":
			print(f"Top-1 Accuracy:{metrics.top1:.6f}") # top1 accuracy
			print(f"Top-5 Accuracy: {metrics.top5:.6f}") # top5 accuracy
		else:
			print(f"map50-95(B):", metrics.box.map)
			print(f"map50(B):", metrics.box.map50)
			print(f"map75(B):", metrics.box.map75)

	model.export(format="onnx", opset=12, simplify=True, dynamic=False, imgsz=imgsz) # onnx, export the model, cannot specify dynamic=True, opencv does not support
	model.export(format="torchscript", imgsz=imgsz) # libtorch
	model.export(format="openvino", imgsz=imgsz, dynamic=False, half=False, int8=False) # openvino fp32
	# model.export(format="openvino", imgsz=imgsz, dynamic=False, half=True) # openvino fp16
	# model.export(format="openvino", imgsz=imgsz, dynamic=False, int8=True, data=yaml) # openvino int8, INT8 export requires 'data' arg for calibration
	if torch.cuda.is_available():
		model.export(format="engine", imgsz=imgsz, dynamic=False, verbose=False, batch=1, workspace=2) # tensorrt fp32
		# model.export(format="engine", imgsz=imgsz, dynamic=False, verbose=False, batch=1, workspace=2, half=True) # tensorrt fp16
		# model.export(format="engine", imgsz=imgsz, dynamic=False, verbose=False, batch=1, workspace=2, int8=True, data=yaml) # tensorrt int8

      训练如下图所示:

      预测测试代码如下:

def _get_images(dir):
	# supported image formats
	img_formats = (".bmp", ".jpeg", ".jpg", ".png", ".webp")
	images = []

	for file in os.listdir(dir):
		if os.path.isfile(os.path.join(dir, file)):
			# print(file)
			_, extension = os.path.splitext(file)
			for format in img_formats:
				if format == extension.lower():
					images.append(file)
					break

	return images

def predict(task, model_name, device, verbose, dir_images, dir_result):
	model = YOLO(model_name) # load an model, support format: *.pt, *.onnx, *.torchscript, *.engine, openvino_model
	# model.info() # display model information # only *.pt format support

	if task == "detect" or task =="segment" or task == "obb" or task == "semantic":
		os.makedirs(dir_result, exist_ok=True)

	images = _get_images(dir_images)

	for image in images:
		results = model.predict(dir_images+"/"+image, verbose=verbose, device=device)

		if task == "detect" or task =="segment" or task == "obb" or task == "semantic":
			for result in results:
				# print("result:", result)
				result.save(dir_result+"/"+image)
		else:
			print(f"class names:{results[0].names}: top5: {results[0].probs.top5}; conf:{results[0].probs.top5conf}")

      预测结果如下图所示:

      GitHubhttps://github.com/fengbingchun/NN_Test

Logo

免费领 150 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐