资讯动态

人流量检测实战:从YOLO+DeepSORT到密度估计的完整指南

发布时间:2026/10/4 20:14:10 来源:尧图企业网站定制
简介一份基于深度学习的人流量检测方向的论文参考文档适合毕业设计、课程设计以及相关课题研究者使用。内容围绕MobileNet-SSD轻量级检测模型展开从数据集构建、模型训练与部署到视频监控场景下的行人检测、追踪与人流量输出形成了完整的技术链路论文中给出了网络层结构、训练参数、开发环境及质心跟踪等实现细节对理解深度学习目标检测应用及撰写专业论文均有参考价值。特别适合在公园、文化广场等人流密集且移动速度较慢的场景下进行人流量统计与疏散参考兼具理论性与实践性。资源包内共1个docx文档大小约224KB为排版规整的论文正文便于直接阅读、批注与引用。该文档已有82人浏览/学习可作为同类项目开发与论文写作的借鉴资料但建议在理解原理的基础上灵活运用避免直接照搬。1. 开题先别急着写先用 30 分钟想清楚你的人流量检测到底要做什么毕设和课设里最容易被导师否掉的题目不是“基于深度学习的人流量检测方法”本身而是把它当成一个空泛的口号。人流量检测这个方向核心解决的是在固定场景下实时/准实时估计画面中的人数、密度和流动方向落点可以是商场消防预警、景区限流、教室到课率统计甚至地铁站台调度。往深了做它同时牵扯目标检测、多目标跟踪、密度估计回归三条技术线每一条都能写成一篇能过答辩的论文。这篇文章按我给学生辅导毕设时的一套固定流程来写先看你手头有什么数据、要交什么结果再定技术路线数据怎么标、怎么转格式模型怎么训、参数怎么设最后是论文里最能加分的评估与可视化。全程不依赖任何实验室私有代码用公开数据集加 PyTorch 就能复现。适合两类人一类是刚接触深度学习、需要一个能跑通主流程的课程设计另一类是已经会用 YOLO 但论文里缺理论深度、想补密度估计路线的毕业生。我会把每条路线的选型逻辑、训练命令、参数边界和常见翻车点讲透你照着做至少能少走两周弯路。2. 两条主流技术路线检测跟踪和密度估计怎么选才不给自己挖坑2.1 检测跟踪路线适用于稀疏场景、需要知道“谁在哪”人流量检测最常见的落地做法是把它拆成“目标检测 多目标跟踪”两步。检测部分负责把画面里的人框出来跟踪部分负责给同一个跨帧的人分配同一个 ID从而统计一段时间内经过某条线的人数。这条路线在商场出入口、教室门口这类场景里非常可靠因为人跟人之间遮挡少每个人都能被完整框住。主流实现是 YOLO 系列做检测DeepSORT 做跟踪输出结果是每个人的边界框坐标和轨迹。这套方案的技术主线非常清晰检测器给出每一帧的框 → 卡尔曼滤波预测下一帧位置 → 匈牙利算法做前后帧框的匹配 → 给新出现的人分配全局 ID。你在论文里不需要把每一步都推到公式但至少要能讲清楚为什么 DeepSORT 比单纯的 IOU 匹配抗遮挡因为它融合了运动特征卡尔曼和外观特征ReID 小网络。但对毕设来说直接用现成的 YOLOv8 权重和 DeepSORT 权重就能出结果关键是自己能训得动检测器。我一般建议如果你的毕业设计只需要“统计总人数”且画面里同时出现的人不超过 20 个就走这条路线。它的优点是可解释性强导师问起来你能每个模块都答上缺点是遇到拥挤场景比如景区台阶、下课走廊会大面积漏检跟踪 ID 频繁切换统计结果崩得很快。2.2 密度估计路线拥挤场景的救命稻草用回归代替检测当你面对的图片是密密麻麻的人头检测框根本没法画准的时候检测跟踪路线就集体翻车了。这时候应该换到密度估计路线不需要框出每个人而是训练一个回归网络对每个像素输出一个密度值对整张图的密度积分就是总人数。代表工作是 Shang 等人提出的 CSRNet用 VGG16 前几个卷积层做前端特征提取后面接空洞卷积层扩大感受野在 ShanghaiTech 数据集上效果好于当时的检测方案。密度估计路线在论文里的亮点在于“换个角度解决遮挡问题”它把人的位置从离散边界框变成了连续的密度图本质是用回归模型在空间上做分布假设——每个头中心是一个高斯核的峰值重叠时就叠加。你不需要标注框只需要标出每个头的中心点然后用高斯核生成监督用的密度图。这条路线做课程设计其实更友好因为代码量少训练只需要图像和对应的密度图标签预测时一次前向传播就能输出人数。选型时我常用这个判断画面里人流一旦开始“人贴人”检测框 IOU 小于 0.3 时检测跟踪基本就报废了密度估计仍然能稳。反过来密度估计对相机角度和透视极其敏感同一套权重换个摄像头角度效果可能掉一半所以需要收集尽可能贴近你应用场景的数据来微调。如果你的毕设题目里没有明确要求“画框可视化”只要求“输出人数和热力图”密度估计是性价比更高的选择。2.3 决策条件一览训练成本、算力需求和论文创新点很多同学卡在选型上本质是不知道自己的毕设该以什么为标准。这里给出一张我用来做判断的对照表你在开题答辩前可以拿它对照自己的场景。对比维度检测跟踪路线YOLO DeepSORT密度估计路线CSRNet / DM-Count适用人密度稀疏到中等单帧不超过 30 人中等到极拥挤上百人也能处理输出结果边界框 轨迹 过线计数密度图 热力图 总人数标注成本需要画边界框成本高只需要点头部中心点快很多训练难度需要先做目标检测预训练再微调端到端回归直接训密度图答辩可讲性模块多能讲的结构点丰富理论集中空洞卷积/高斯核可以深挖典型数据集CrowdHuman、MOT16ShanghaiTech、UCF-QNRF、UCF-CC-50算力要求单张 1080Ti 可训相同算力下可以训更大的输入分辨率我的建议是课程设计选题选密度估计毕业设计想冲高分选检测跟踪或两者融合检测稀疏区域 密度估计拥挤区域。融合路线是近年的热门写法但工作量接近两倍需要谨慎评估时间。至于“基于深度学习的人流量检测”这种泛题目导师默认你应该自己定义场景和指标而不是模糊地说“我用深度学习检测人”。3. 数据是唯一的黑匣子标注头中心、生成密度图和格式转换全流程3.1 数据从哪来标注怎么标公开数据集方面密度估计首选 ShanghaiTech 的 Part A拥挤场景 482 张图和 Part B稀疏场景 716 张图UCF-QNRF 数据量更大但图片分辨率高消费级显卡训起来吃力。检测跟踪路线可以用 CrowdHuman 做训练MOT16 做跟踪验证。如果你需要贴合自己的真实场景比如教室、寝室楼道那就只能自己拍自己标我一般用 LabelMe 点头部中心点导出 JSON再写成脚本转密度图。这段听着简单实际坑很多。第一个坑是标注规范密度估计的所有标注都基于“头部中心”不是身体中心。因为人一旦密集身体大面积互相遮挡但头通常是可见的如果标身体中心生成的密度图高斯核位置会偏移模型会学到错误的空间分布。第二个坑是边缘人头要不要标我统一建议“能看到完整头就算只看清半张脸也标”但遮挡超过一半不标这套规则要在整个数据集里保持完全一致否则模型对半遮挡人头的响应会飘忽不定。第三个坑是尺度问题。同一张图里近处人头直径可能有 50 像素远处只有 8 像素而密度估计核心是保证人头中心点附近的高斯核积分等于 1。这就意味着高斯核的方差sigma不能全局固定。常见做法是上海科技大学开源的几何自适应高斯核对每个头中心计算该点到最近三个相邻头中心的平均距离 d令 sigma 0.3 * d。这样近处的头在密度图上是一片大而矮的峰远处是小而高的峰积分都为 1。3.2 把 JSON 标注转成密度图的 Python 脚本这里给出我自己常用的密度图生成脚本。输入是 LabelMe 导出的 JSON 文件每个文件的 shapes 里存了每个头的 point 坐标输出是下采样后的密度图。注意代码里的缩放因子因为 CSRNet 的原始输入会被缩放到原图的 1/8密度图也得跟着做相同缩放不能只缩放图不缩放标注。import json import numpy as np import cv2 from scipy.ndimage import gaussian_filter from scipy.spatial import KDTree def generate_density_map(img_shape, points, k3, sigma_factor0.3): 生成几何自适应密度图 img_shape: (H, W) points: [(x, y), ...] 每个头中心点的坐标 k: 取最近 k 个邻居计算平均距离 sigma_factor: 高斯核的 sigma sigma_factor * 平均距离 h, w img_shape density np.zeros((h, w), dtypenp.float32) if len(points) 0: return density pts np.array(points, dtypenp.float32) # 只有一个人时没有邻居距离退化为固定 sigma if len(pts) 1: for x, y in pts: density[int(y), int(x)] 1.0 density gaussian_filter(density, sigma4) return density # KDTree 加速最近邻查询 tree KDTree(pts) for x, y in pts: # distances 是到所有点的距离取前 k1 个包含自身 distances, _ tree.query([x, y], kk 1) # 排除距离为 0 的自身点 nearest distances[distances 0] if len(nearest) 0: sigma 4.0 else: sigma sigma_factor * nearest.mean() # 在该点位置放一个单位质量再用高斯核抹开 density[int(y), int(x)] 1.0 # 对每个点单独做高斯模糊避免互相干扰导致积分不准 density gaussian_filter(density, sigmasigma) # 缩放密度图保持积分等于总人数 density density * (len(pts) / density.sum()) return density def load_labelme_json(json_path, img_h, img_w): 读 LabelMe JSON提取所有 point 标注 with open(json_path, r, encodingutf-8) as f: data json.load(f) points [] for shape in data[shapes]: if shape[shape_type] point: x, y shape[points][0] points.append((float(x), float(y))) return points # 使用示例 json_path images/IMG_001.json img cv2.imread(images/IMG_001.jpg) img_h, img_w img.shape[:2] points load_labelme_json(json_path, img_h, img_w) density generate_density_map((img_h, img_w), points) # 下采样到 1/8与 CSRNet 的输出分辨率对齐 density_small cv2.resize(density, (img_w // 8, img_h // 8), interpolationcv2.INTER_AREA) density_small density_small * (len(points) / density_small.sum())这段脚本有三个关键设计。第一每个点先单独高斯模糊再缩放而不是整张图模糊后缩放避免不同 sigma 的点互相“污染”第二最后的缩放保证密度图积分等于标注人数这是训练时 MAE 损失能回归到正确量级的前提第三KDTree 的作用是快速找最近邻如果你用纯双层循环遍历几百个点生成一张高分辨率密度图可能要好几秒而 KDTree 是毫秒级。实际训练时我会把这个逻辑改成 PyTorch 的 batched 版本在getitem里实时生成不提前存成文件既省空间又能做在线数据增强。3.3 检测跟踪路线的数据准备VOC 转 YOLO 格式的坑如果你的检测器要自己训 YOLO就需要把标注从 VOC 的 XML 格式转成 YOLO 的 txt 格式。很多人在这里翻车不是转格式本身难而是坐标归一化时把中心坐标和宽高算错。VOC 存的是左上角 (xmin, ymin) 和右下角 (xmax, ymax)YOLO 需要的是归一化后的 (center_x, center_y, width, height)四者都除以图片宽或高。import xml.etree.ElementTree as ET import os def voc2yolo(xml_path, output_dir, class_names): VOC XML 转 YOLO txt class_names: [person]检测类别列表 tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) yolo_lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_names: continue # 跳过难例和截断目标保证训练标签干净 difficult int(obj.find(difficult).text) if difficult 1: continue bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 坐标裁剪防止标注越界成负数宽高 xmin max(0, min(xmin, img_w - 1)) xmax max(0, min(xmax, img_w - 1)) ymin max(0, min(ymin, img_h - 1)) ymax max(0, min(ymax, img_h - 1)) center_x (xmin xmax) / 2.0 / img_w center_y (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h cls_id class_names.index(name) yolo_lines.append(f{cls_id} {center_x:.6f} {center_y:.6f} {width:.6f} {height:.6f}) # 输出跟 XML 同名的 txt txt_path os.path.join(output_dir, os.path.splitext(os.path.basename(xml_path))[0] .txt) with open(txt_path, w, encodingutf-8) as f: f.write(\n.join(yolo_lines)) return len(yolo_lines)这个脚本里最容易忽略的是 difficult 标志。CrowdHuman 这类公开数据集里有一部分目标标了“difficult”意思是极暗、极小或严重遮挡人肉眼都很难确认如果不过滤直接训练模型会去强行拟合这些噪声标签影响对人头细节特征的学习。另一个隐蔽问题是宽高为 0 的标注比如两个点重合或坐标裁剪后变成一条线训练时 loss 会变成 NaN处理办法是在循环里加判断width 或 height 小于 1e-6 就直接跳过。4. 训练细节决定成败CSRNet 和 YOLOv8 的脚本、调参与曲线判读4.1 CSRNet 端到端训练的最小脚本CSRNet 本身不复杂前端是 VGG16 的前十层不动权重后端用空洞卷积层代替池化保持输出分辨率。训练时输入图固定为 768×1024按数据集情况调整输出密度图为 96×128损失函数用欧氏距离损失。下面是一份可以直接照着跑的 PyTorch 训练骨架我加上了关键注释。import torch import torch.nn as nn import torchvision.models as models class CSRNet(nn.Module): def __init__(self, load_weightsTrue): super().__init__() # 前端VGG16 的 conv1 到 conv5去掉 maxpool5 保持分辨率 vgg models.vgg16(pretrainedload_weights).features self.frontend nn.Sequential(*list(vgg)[:23]) # 后端空洞卷积扩大感受野不缩小分辨率 self.backend nn.Sequential( nn.Conv2d(512, 512, kernel_size3, padding2, dilation2), nn.ReLU(inplaceTrue), nn.Conv2d(512, 512, kernel_size3, padding2, dilation2), nn.ReLU(inplaceTrue), nn.Conv2d(512, 512, kernel_size3, padding2, dilation2), nn.ReLU(inplaceTrue), nn.Conv2d(512, 256, kernel_size3, padding2, dilation2), nn.ReLU(inplaceTrue), nn.Conv2d(256, 128, kernel_size3, padding2, dilation2), nn.ReLU(inplaceTrue), nn.Conv2d(128, 1, kernel_size1) ) def forward(self, x): x self.frontend(x) x self.backend(x) return x # 损失与优化器 criterion nn.MSELoss() # 欧氏距离损失适合像素级密度回归 model CSRNet().cuda() optimizer torch.optim.Adam(model.parameters(), lr1e-5) # 训练循环节选关键部分 for epoch in range(epochs): model.train() running_loss 0.0 for img, density_map in train_loader: img, density_map img.cuda(), density_map.cuda() optimizer.zero_grad() pred model(img) loss criterion(pred, density_map) loss.backward() optimizer.step() running_loss loss.item() * img.size(0) epoch_loss running_loss / len(train_loader.dataset) print(fEpoch {epoch1}/{epochs}, Loss: {epoch_loss:.6f}) # 每个 epoch 结束做一次验证用 MAE 而不是 loss 判断好坏 if (epoch 1) % 5 0: evaluate(model, val_loader)三点必须说清楚。第一学习率 1e-5 不是我随便填的常用于数据集扩充后的 CSRNet 训练如果你用更大的数据集比如 UCF-QNRF可以上调到 1e-4但要配合 StepLR 每 15 个 epoch 衰减 0.1。第二输入分辨率直接决定显存占用和性能上限把图片无脑怼到 2048 分辨率会把显存打爆常见做法是保持原始宽高比、限制长边不超过 1024。第三训练时必须做随机裁剪从大图里随机切 256×256 的区域喂网络否则模型看到的是固定视野遇到测试时不同尺度的场景会很飘。训练曲线的判读也有一套经验。MSELoss 降到 0.05 附近时MAE 可能在 20 左右如果 loss 卡在 0.1 不再下降最常见的原因是密度图标签没做好——高斯核 sigma 太小导致密度图里每个头都是一个小尖点网络学到的不是泛化特征而是记忆尖点位置。另一个常见问题是 loss 不断下降但验证 MAE 反而上升说明过拟合了这时优先做数据增强随机水平翻转、颜色抖动、随机裁剪而不是换更小的模型。4.2 YOLOv8 训练三个必调的参数和一次就能跑通的命令检测跟踪路线里检测器我建议直接用 YOLOv8它集成了训练和推理接口不用自己写数据加载。假设你已经有整理好的 coco 风格数据集目录images 和 labels 文件夹下面这条命令就能开训。# 在项目根目录执行data.yaml 指定训练/验证图片路径和类别 yolo detect train \ modelyolov8n.pt \ # 用 nano 骨架做预训练速度最快 datadata.yaml \ epochs50 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ augmentTrue \ patience10 \ device0参数里我至少要解释三个。imgsz640 是检测精度和显存的最优折中1920 长边的监控画面直接喂 640 会导致小目标检测大幅变差我会先把长边缩放到 1280 再裁切成多个 640 的 patchbatch16 取决于显存如果你是 8G 显存把 batch 调成 8 后还要把 lr0 按比例调低到 0.005因为大 batch 要用大学习率小 batch 用大学习率会发散patience10 的意思是连续 10 个 epoch 验证集 mAP 不提升就早停毕设场景没时间一个个试 epoch 数早停是最省心的收敛策略。训练完成后验证和可视化走这两步# 验证集上评估 mAP50 和 mAP50-95 yolo detect val modelruns/detect/train/weights/best.pt datadata.yaml # 导出 ONNX 推理方便写进论文的部署章节 yolo export modelruns/detect/train/weights/best.pt formatonnx验证输出里重点看两个数字mAP50 表示预测框和真实框的重叠度超过 50% 的准确率人群场景里人几乎占满画面中景mAP50 应当不低于 0.85mAP50-95 是更严格的多阈值平均如果它远低于 mAP50说明框的位置精度不够常见原因是标注框本身画得粗糙、边缘留白太多。导 ONNX 不是必须的但毕设答辩时能说一句“我已验证模型可以无缝部署到 CPU 推理”印象分会高不少。4.3 跟踪部分搭上 DeepSORT用现成权重快速跑通视频计数在训练好的检测器后面挂 DeepSORT整个链路才算完整。DeepSORT 的权重不用自己训直接下载在 MOT16 上训练好的 ReID 模型即可约 10MB它的作用只有一件事提取检测框内人物外观特征供跨帧匹配使用。下面是我常用的推理脚本骨架。import cv2 from ultralytics import YOLO from deep_sort_realtime.deepsort_tracker import DeepSort # 加载检测器和跟踪器 detector YOLO(runs/detect/train/weights/best.pt) tracker DeepSort(max_age30, n_init3, nn_budget100) # 设置计数线从 (200, 600) 到 (800, 600)过线人数只统计一次 line_y 600 passed_ids set() total_count 0 cap cv2.VideoCapture(test_video.mp4) while cap.isOpened(): ret, frame cap.read() if not ret: break # 检测conf 0.4 以下过滤掉低置信度框 results detector(frame, conf0.4)[0] detections [] for box in results.boxes: x1, y1, x2, y2 box.xyxy[0].tolist() conf float(box.conf[0]) detections.append(([x1, y1, x2, y2], conf, person)) # 跟踪返回每个目标的 track_id 和更新后的框 tracks tracker.update_tracks(detections, frameframe) for track in tracks: if not track.is_confirmed(): continue track_id track.track_id ltrb track.to_ltrb() # left, top, right, bottom center_y (ltrb[1] ltrb[3]) / 2 # 过线计数只在从上方穿过计数线的一瞬间加一 if ltrb[1] line_y center_y and track_id not in passed_ids: passed_ids.add(track_id) total_count 1 cap.release()这段代码里最关键的参数是 max_age30。它表示当一个目标连续 30 帧都没匹配上时才判定为离开场景并注销 ID。调大它可以让被短时遮挡的人不丢 ID但也会让离开画面的人滞留一段时间调小则相反。人群密集场景我建议 max_age 调到 50稀疏场景 20 够用。另一个细节是出画面再进画面的同一个人会被分配新 ID经典计数逻辑没法避免只能靠加装出入口的物理约束来控制误差。5. 人流量检测避坑指南训练、计数和答辩前最容易翻车的六个场景5.1 密度图下采样后总人数对不上现象训练时 loss 正常下降但验证集 MAE 奇高把预测密度图求和后发现人数只有真实值的一半。原因生成密度图后做了 cv2.resize 缩放到 1/8这个操作相当于做了像素平均插值密度图积分减小了如果不同时按比例缩放计数会系统性偏小。解决resize 后必须重新归一化把密度图乘上真实人数 / density_small.sum()。这个 bug 是密度估计毕设里最高频的翻车点没有之一。5.2 YOLO 训练时 loss 变成 NaN现象训练到第 3 个 epochloss 突然变成 nan然后一直无法恢复。原因95% 的情况是标签里有宽高为 0 的框或坐标越界少数情况是学习率过大导致梯度爆炸。解决数据加载时过滤掉面积小于 25 像素的框把 lr0 从 0.01 下调到 0.005 再跑一次。不要花时间去查别的先把数据清洗干净。5.3 人群遮挡导致跟踪 ID 疯狂切换现象视频里每帧检测框稳定但统计出来的过线人数比真实人数多一倍。原因两个人并排走互相遮挡时DeepSORT 会把两人的外观特征匹配错A 的 ID 变成 B 的 ID相当于重复计数。解决过线计数的判定条件不要只用 center_y还要记录上一个 center_y只有“上一帧在线下、这一帧在线上”才计数并且同一 track_id 只计一次。这个方法能消掉大部分 ID 切换带来的虚报。5.4 测试图片和训练图片分辨率不一致现象训练时输入 640×640测试时来了一个 1920×1080 的监控画面检测器把人漏掉一半密度图也全是噪点。原因模型在固定输入尺度上学习特征分辨率突变会让特征金字塔失效。解决测试前把长边缩放到训练时的尺寸而不是直接 resize 成正方形——直接拉伸会破坏宽高比人形特征变形。缩放后用 padding 补成正方形模型输出时再裁掉 padding 区域。5.5 论文里 MAE 就是降不下来现象ShanghaiTech Part B 上 MAE 在 15 左右徘徊网上那些论文写的是 5。原因人家用的训练集比你多了数据增强和尺度归一化且输入分辨率比你高。解决不要追着 SOTA 的打分跑对你自己的场景做多尺度测试记录每张图的误差分布找出误差最大的图片类型通常是最远处的小头针对性增加该区域的标注密度。答辩老师更想听到你分析误差来源而不是背数字。5.6 答辩被问“你的创新点是什么”答不上来现象整个方案都是调包能从原理层面说出来。解决找一个你能实际做的小改进例如用 Swin Transformer 替换 CSRNet 后端做密度回归虽然精度不一定比空洞卷积高多少但“把视觉 Transformer 引入人流量密度估计”就是一个能站住脚的题目或者把稀疏区域的检测框数量做先验加权融合进密度图积分消除背景误报。不要选完全没公开参考的伪创新你有多少时间做实验自己心里要有数。6. 论文收尾最后一步用评估指标和可视化让工作量被看见毕业设计论文里实验结果部分不需要堆砌所有训练细节但三样东西必须有客观指标、误差分布分析和可视化对比图。指标上密度估计路线必报 MAE绝对值误差和 MSE均方误差MSE 对大面积错误更敏感能反映误差的稳定性检测跟踪路线报 mAP 和计数准确率真实过线人数与统计人数之比其中计数准确率建议分别报“总人数”和“分时段人数”分时段更能体现跟踪稳定性。可视化部分密度估计输出密度热力图叠加原图检测跟踪输出带 ID 的轨迹线这两张图是答辩 PPT 里最有说服力的素材。我最后说一个我一直保留的验证习惯不止用测试集算指标还找一段 3 到 5 分钟的连续视频手动数前 30 秒的真实人数然后跑你的完整链路把按照 30 秒滑动窗口统计的误差曲线画出来。这个误差曲线能直接暴露你方案在“人流突然增多瞬间”的响应滞后或突增问题比一张测试集的表格有用得多。做毕设时我第一次没画这个曲线答辩被问“人流高峰时你的系统表现如何”时只能含糊过去后来所有学生的方案我都要求补上这一张图。这个习惯也帮你提前暴露很多训练集里看不出来的并发问题希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑