You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

YOLO如何划分图像网格单元?YOLO与SSD的CNN结构及Python代码问询

YOLO 核心逻辑与CNN结构设计

YOLO 网格划分逻辑

  • 输入图像统一缩放到固定尺寸(YOLOv1默认448×448),划分为S×S个等大的网格单元(YOLOv1默认S=7)
  • 若某个目标的真实标注框中心坐标落在某一个网格内,该网格就唯一负责预测这个目标
  • 每个网格输出固定数量的预测框、置信度得分和类别概率,推理阶段通过非极大值抑制过滤冗余结果得到最终检测框

YOLO CNN结构演进

  • v1版本:基于GoogLeNet改造,包含24个卷积层提取视觉特征,最后接2个全连接层输出所有预测结果。缺点是全连接层限制输入图像尺寸,小目标检测效果较差。
  • v2版本:改用Darknet19骨干网(19个卷积层+5个池化层),移除全连接层,支持多尺度训练,引入锚框机制大幅提升定位精度。
  • v3及后续版本:改用Darknet53骨干网,加入残差结构解决深度网络梯度消失问题,采用多尺度特征融合输出,不同尺寸目标的检测效果均有明显提升。
SSD 核心逻辑与CNN结构设计

SSD是单阶段多尺度检测模型,兼顾检测速度与精度,结构设计特点如下:

  • 骨干网络采用修改后的VGG16:将原VGG16的最后两个全连接层替换为卷积层,降低参数量,保留低层特征的细节信息。
  • 额外新增6个卷积层,逐步减小特征图尺寸,形成多尺度特征金字塔。
  • 每个尺度的特征图独立负责检测对应大小的目标:大尺寸特征图(对应低层特征,细节丰富)检测小目标,小尺寸特征图(对应高层特征,语义丰富)检测大目标。
  • 每个特征图的每个空间位置预设多个不同宽高比的锚框,直接预测锚框的偏移量、置信度和类别,无需后续全连接层处理。
简化版Python实现(基于PyTorch)

以下仅保留核心网络结构逻辑,完整实现还需补充损失计算、锚框编解码、非极大值抑制等模块。

import torch
import torch.nn as nn

# 简化版YOLOv1网络结构
class SimpleYOLOv1(nn.Module):
    def __init__(self, grid_size=7, num_boxes=2, num_classes=20):
        super(SimpleYOLOv1, self).__init__()
        self.S = grid_size
        self.B = num_boxes
        self.C = num_classes
        
        # 特征提取卷积层
        self.features = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),
            nn.LeakyReLU(0.1),
            nn.MaxPool2d(2, stride=2),
            
            nn.Conv2d(64, 192, kernel_size=3, padding=1),
            nn.LeakyReLU(0.1),
            nn.MaxPool2d(2, stride=2),
            
            nn.Conv2d(192, 256, kernel_size=3, padding=1),
            nn.LeakyReLU(0.1),
            nn.Conv2d(256, 512, kernel_size=3, padding=1),
            nn.LeakyReLU(0.1),
            nn.MaxPool2d(2, stride=2),
            
            nn.Conv2d(512, 1024, kernel_size=3, padding=1),
            nn.LeakyReLU(0.1),
            nn.MaxPool2d(2, stride=2)
        )
        
        # 预测头
        self.predict = nn.Sequential(
            nn.Linear(1024 * 7 * 7, 4096),
            nn.LeakyReLU(0.1),
            nn.Dropout(0.5),
            nn.Linear(4096, self.S * self.S * (self.B * 5 + self.C))
        )
    
    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        x = self.predict(x)
        # 输出维度:(batch_size, S, S, B*5 + C)
        return x.view(-1, self.S, self.S, self.B * 5 + self.C)
# 简化版SSD网络结构
class SimpleSSD(nn.Module):
    def __init__(self, num_classes=21):
        super(SimpleSSD, self).__init__()
        self.num_classes = num_classes
        
        # VGG16基础层,输出多尺度特征
        self.base_layers = nn.Sequential(
            # 第1个卷积块,输出尺寸:(batch, 64, 300, 300)
            nn.Conv2d(3, 64, kernel_size=3, padding=1), nn.ReLU(),
            nn.Conv2d(64, 64, kernel_size=3, padding=1), nn.ReLU(),
            nn.MaxPool2d(2, stride=2),
            # 第2个卷积块,输出尺寸:(batch, 128, 150, 150)
            nn.Conv2d(64, 128, kernel_size=3, padding=1), nn.ReLU(),
            nn.Conv2d(128, 128, kernel_size=3, padding=1), nn.ReLU(),
            nn.MaxPool2d(2, stride=2),
            # 第3个卷积块,输出尺寸:(batch, 256, 75, 75)
            nn.Conv2d(128, 256, kernel_size=3, padding=1), nn.ReLU(),
            nn.Conv2d(256, 256, kernel_size=3, padding=1), nn.ReLU(),
            nn.Conv2d(256, 256, kernel_size=3, padding=1), nn.ReLU(),
            nn.MaxPool2d(2, stride=2, ceil_mode=True),
            # 第4个卷积块,输出尺寸:(batch, 512, 38, 38) 用于检测小目标
            nn.Conv2d(256, 512, kernel_size=3, padding=1), nn.ReLU(),
            nn.Conv2d(512, 512, kernel_size=3, padding=1), nn.ReLU(),
            nn.Conv2d(512, 512, kernel_size=3, padding=1), nn.ReLU()
        )
        
        # 额外卷积层,输出更高层、更小尺寸的特征
        self.extra_layers = nn.Sequential(
            nn.Conv2d(512, 1024, kernel_size=3, padding=6, dilation=6), nn.ReLU(),
            nn.Conv2d(1024, 1024, kernel_size=1), nn.ReLU(), # 输出尺寸 (batch, 1024, 19, 19)
            nn.Conv2d(1024, 256, kernel_size=1), nn.ReLU(),
            nn.Conv2d(256, 512, kernel_size=3, stride=2, padding=1), nn.ReLU(), # 输出尺寸 (batch, 512, 10, 10)
            nn.Conv2d(512, 128, kernel_size=1), nn.ReLU(),
            nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1), nn.ReLU() # 输出尺寸 (batch, 256, 5, 5)
        )
        
        # 每个尺度特征对应的预测头,每个位置预设4个锚框,输出通道为4*(num_classes + 4)
        self.predict_heads = nn.ModuleList([
            nn.Conv2d(512, 4*(num_classes + 4), kernel_size=3, padding=1),
            nn.Conv2d(1024, 4*(num_classes + 4), kernel_size=3, padding=1),
            nn.Conv2d(512, 4*(num_classes + 4), kernel_size=3, padding=1),
            nn.Conv2d(256, 4*(num_classes + 4), kernel_size=3, padding=1)
        ])
    
    def forward(self, x):
        features = []
        x = self.base_layers(x)
        features.append(x)
        for idx, layer in enumerate(self.extra_layers):
            x = layer(x)
            # 收集符合要求的多尺度特征
            if idx == 1 or idx == 3 or idx ==5:
                features.append(x)
        
        outputs = []
        for feat, head in zip(features, self.predict_heads):
            pred = head(feat)
            # 调整维度为 (batch, num_anchors, num_classes + 4)
            pred = pred.permute(0, 2, 3, 1).contiguous().view(pred.size(0), -1, self.num_classes + 4)
            outputs.append(pred)
        # 合并所有尺度的预测结果
        return torch.cat(outputs, dim=1)

内容的提问来源于stack exchange,提问作者Uygar Usta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 13:24:07