图像分割之数据预测

标签: 无 分类: 未分类 创建时间:2025-01-04 12:31:26 更新时间:2025-01-17 10:39:23

1.前言

完成了数据训练和模型生成之后,解析来就是图像分割了。

2.测试代码

推理代码主要就是 model.predict ,包括了各种参数可以设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from ultralytics import YOLO

# 加载预训练的YOLOv11n模型
model = YOLO(r"runs/segment/train2/weights/best.pt")

# 对指定的图像文件夹进行推理,并设置各种参数
results = model.predict(
source="datasets/seg_point_offer_20240930_num30/images/", # 数据来源,可以是文件夹、图片路径、视频、URL,或设备ID(如摄像头)
conf=0.45, # 置信度阈值
iou=0.6, # IoU 阈值
imgsz=640, # 图像大小
half=False, # 使用半精度推理
device=None, # 使用设备,None 表示自动选择,比如'cpu','0'
max_det=300, # 最大检测数量
vid_stride=1, # 视频帧跳跃设置
stream_buffer=False, # 视频流缓冲
visualize=False, # 可视化模型特征
augment=False, # 启用推理时增强
agnostic_nms=False, # 启用类无关的NMS
classes=None, # 指定要检测的类别
retina_masks=False, # 使用高分辨率分割掩码
embed=None, # 提取特征向量层
show=False, # 是否显示推理图像
save=True, # 保存推理结果
save_frames=False, # 保存视频的帧作为图像
save_txt=True, # 保存检测结果到文本文件
save_conf=False, # 保存置信度到文本文件
save_crop=False, # 保存裁剪的检测对象图像
show_labels=True, # 显示检测的标签
show_conf=True, # 显示检测置信度
show_boxes=True, # 显示检测框
line_width=None # 设置边界框的线条宽度,比如2,4
)

3.结果对象

经过尝试和修改,主要产生了下面的代码,就是把不同的类别用不同的颜色进行区分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# 加载预训练的YOLO模型
model = YOLO(r'D:\zlc\drone\drone-train\runs\segment\train\weights\best.pt') # 替换为你的模型路径
# 设置要预测的图像文件夹路径
image_folder = r"D:\zlc\drone\drone-train\data\land\test\images" # 替换为你的图像文件夹路径
# 设置保存结果的文件夹路径
output_folder = r"D:\zlc\drone\drone-train\data\land\test\output" # 替换为你要保存结果的文件夹路径
os.makedirs(output_folder, exist_ok=True)
names = ['background','land']
# 支持的图像文件扩展名
valid_image_extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.tif', '.tiff']

# 创建一个颜色表,为每个类别分配固定颜色
def create_color_map(num_classes):
color_map = {}
for class_id in range(num_classes):
# 生成随机但固定的RGB颜色值
color = tuple(np.random.randint(0, 255, size=3).tolist())
color_map[class_id] = color
return color_map

# 假设 names 是从模型结果中获得的类别名称列表
num_classes = len(names)
color_map = create_color_map(num_classes)

def process_images_in_folder(folder_path):
for filename in os.listdir(folder_path):
# 检查文件是否为图像
ext = os.path.splitext(filename)[1].lower()
if ext not in valid_image_extensions:
continue

# 构建完整的文件路径
image_path = os.path.join(folder_path, filename)

# 读取图像
image = cv2.imread(image_path)
if image is None:
print(f"无法读取图像: {image_path}")
continue

# 进行预测
results = model.predict(source=image_path, conf=0.25, iou=0.45, imgsz=640,show_labels=False,show_boxes=False,show_conf=False)

# 将图像从 BGR 转换为 RGB 格式(OpenCV 默认是 BGR)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 创建一个与输入图像相同大小的全透明图像,用于绘制掩码
mask_overlay = np.zeros_like(image_rgb)

for result in results: # 遍历所有检测结果
boxes = result.boxes.cpu().numpy() if hasattr(result.boxes, 'cpu') else result.boxes
masks = result.masks.data.cpu().numpy() if hasattr(result, 'masks') and hasattr(result.masks, 'data') else None
names = result.names

for i, (box, cls) in enumerate(zip(boxes.xyxy, boxes.cls)):
if masks is not None and i < len(masks): # 确保有对应的掩码
mask = masks[i]

# 确保掩码是一个 NumPy 数组
if not isinstance(mask, np.ndarray):
print("掩码不是 NumPy 数组")
continue

# 调整掩码大小以匹配图像
mask_resized = cv2.resize(mask, (image.shape[1], image.shape[0]))

# 使用预定义的颜色映射获取当前类别的颜色
class_id = int(cls)
color = color_map.get(class_id, (0, 0, 0)) # 默认黑色

# 在 mask_overlay 上绘制掩码
mask_overlay[mask_resized > 0.5] = color

# 绘制边界框和标签
# x1, y1, x2, y2 = map(int, box)
# cv2.rectangle(image_rgb, (x1, y1), (x2, y2), color, 2)
# label = f"{names[int(cls)]}"
# cv2.putText(image_rgb, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, color, 2)

# 将掩码与原始图像合并
alpha = 0.5 # 掩码透明度
output_image = cv2.addWeighted(image_rgb, 1, mask_overlay, alpha, 0)

# 构建输出文件路径
output_path = os.path.join(output_folder, filename)
# 保存带有标注的图像到输出文件夹
cv2.imwrite(output_path, output_image)
print(f"已处理并保存: {output_path}")
参考文章:
【1】.模型预测Ultralytics YOLO
【2】.使用YOLO11实例分割模型进行人物分割【附完整源码】
【3】.Reference for ultralytics/engine/results.py 这里是关于 推理结果的 Results 说明。
【4】.yolov8实例分割mask可视化
【5】.YOLOV8_Segment——ultralytics.ipynb 这是人家的一些例子,我暂时没有下载下来仔细看过。
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。