yolov8 Tiling+NMS
时间: 2025-06-27 09:00:49 浏览: 16
### YOLOv8中的Tiling和NMS
#### Tiling 的实现与用途
在计算机视觉领域,尤其是处理高分辨率图像时,内存管理是一个重要的挑战。YOLOv8通过引入 **tiling** 技术来解决这一问题。Tiling 是指将输入的大尺寸图像分割成多个较小的部分(即 tiles),以便更高效地利用 GPU 或 CPU 的计算资源[^1]。
这种技术的主要优点在于减少单次推理所需的显存占用量,从而允许模型处理更高分辨率的图像而不会超出硬件限制。具体来说,在 YOLOv8 中,tiling 可以通过以下方式实现:
- 输入图像被划分为固定大小的小块。
- 对于每个 tile,独立运行检测算法并生成预测框。
- 将所有 tile 上的结果汇总到原始图像坐标系下,形成最终的目标检测结果。
以下是基于 PyTorch 实现的一个简单 tiling 方法示例代码片段:
```python
def apply_tiling(image, model, tile_size=640, overlap_ratio=0.25):
height, width = image.shape[:2]
stride = int(tile_size * (1 - overlap_ratio))
results = []
for y in range(0, height, stride):
for x in range(0, width, stride):
# 提取当前tile区域
tile_x_start = max(x, 0)
tile_y_start = max(y, 0)
tile_x_end = min(x + tile_size, width)
tile_y_end = min(y + tile_size, height)
tile_image = image[tile_y_start:tile_y_end, tile_x_start:tile_x_end]
# 运行模型推断
detections = model(tile_image.unsqueeze(0))
# 调整边界框至全局坐标系
adjusted_boxes = adjust_bounding_boxes(detections['boxes'], tile_x_start, tile_y_start)
results.append((adjusted_boxes, detections['scores']))
return merge_results(results)
```
#### NMS 的实现与用途
非极大值抑制(Non-Maximum Suppression, NMS)是一种用于消除冗余目标框的技术。它通常应用于对象检测任务中,当同一物体可能由多个候选框覆盖时,NMS 帮助保留最有可能的那个框,并移除其他重叠度较高的低置信度框。
在 YOLOv8 中,NMS 的核心逻辑可以概括如下几个步骤完成:
1. 首先按照分类得分降序排列所有的预测框;
2. 初始化一个空列表用来存储最终选中的框;
3. 循环遍历剩余未处理过的框集合,对于每一个新考虑进去的框 A ,如果其 IoU (Intersection over Union)与其他已选定框 B 大于设定阈值,则丢弃该框;否则将其加入到输出集中继续参与后续比较过程直到结束为止。
下面给出一段标准形式下的 Python 版本伪代码表示如何执行经典版本的 Non Maximum Suppression 操作:
```python
import torch
def non_max_suppression(predictions, conf_thres=0.5, iou_thres=0.45):
"""
Perform non-maximum suppression on detection outputs.
Args:
predictions (Tensor): Model output with shape [batch_size, num_boxes, 5+num_classes].
Each box has format [x_center, y_center, w, h, obj_confidence, class_scores...].
Returns:
List[Tensor]: Filtered boxes after applying NMS per batch item.
"""
device = predictions.device
# Convert from center coordinates to top-left bottom-right corners
xywh_to_xyxy = lambda b: torch.cat([b[..., :2]-b[..., 2:]/2., b[..., :2]+b[..., 2:]/2.], dim=-1)
predictions[:, :, :4] = xywh_to_xyxy(predictions[:, :, :4])
all_outputs = []
for pred_per_img in predictions:
# Apply confidence threshold first
mask = pred_per_img[:, 4] >= conf_thres
filtered_preds = pred_per_img[mask].unsqueeze(dim=0) if len(mask.nonzero()) != 0 else None
if not isinstance(filtered_preds, type(None)):
scores = filtered_preds[..., 4:]
classes = torch.argmax(scores, axis=-1).float().view(-1, 1)
best_class_score = torch.gather(scores, index=classes.long(), dim=-1).squeeze()
sorted_indices = torch.argsort(best_class_score, descending=True)
keep_mask = torch.ones_like(sorted_indices, dtype=torch.bool)
while sum(keep_mask)>0:
current_idx = sorted_indices[torch.where(keep_mask)[0][0]]
remaining_indices = sorted_indices[torch.where(torch.logical_and(
~keep_mask,
calculate_iou(filtered_preds[current_idx][:4],
filtered_preds[sorted_indices][~keep_mask][:,:4])<iou_thres))[0]]
keep_mask.scatter_(dim=0,index=current_idx,dim_value=False)
sorted_indices = remaining_indices
selected_dets = filtered_preds[sorted_indices[keep_mask]].cpu()
all_outputs.append(selected_dets)
else:
all_outputs.append([])
return all_outputs
```
阅读全文
相关推荐
















