新闻详情

新闻详情

首页 / 资讯中心 / 详情

基于VGG16的人脸表情识别:从48×48灰度图到七类情绪分类

发布时间:2026/9/28 15:58:45来源:尧图网络
基于VGG16的人脸表情识别:从48×48灰度图到七类情绪分类
简介基于深度学习VGG16网络的人脸表情识别项目面向Python开发者和深度学习入门者采用经典VGG16卷积神经网络训练分类模型可识别愤怒、快乐、惊讶、厌恶、悲伤、恐惧六种常见表情。资源包共7个文件以5个Python脚本为核心另含1个数据集压缩包和1个Markdown说明文档整体大小约59.23MB。目前已有139人学习/下载适合图像识别、迁移学习方向的动手实践也可作为课程设计或毕设参考。Python脚本覆盖模型定义、数据加载与预处理、模型训练、评估和交互演示等完整环节数据集打包在data文件夹中训练时解压即可model文件夹内为已训练权重加载后可直接对新图片进行表情分类免去从头训练的等待。说明文档对目录结构和训练注意事项做了说明便于快速复现对于希望深入理解VGG16落地应用、并进一步扩展或部署该模型的开发者这是一份结构清晰的参考实现。1. 基于深度学习VGG16网络的人脸表情识别一张48×48灰度图怎么被拆成七种情绪在教室摄像头里统计学生专注度的时候我踩过一个很尴尬的坑模型对低头看手机的同学格外宽容把三分之一的 neutral 判成了 happy。后来排查发现是数据增强里的水平翻转把左脸和右脸的纹理对称性打乱了。这就是基于深度学习 VGG16 网络的人脸表情识别这个任务的日常——它不像物体识别那样有清晰的类别边界一张 48×48 的灰度图里皱眉和抿嘴的差异可能只有几个像素。VGG16 用 16 层卷积把这种细微差异逐层放大成高维特征再映射到愤怒、厌恶、恐惧、开心、悲伤、惊讶、中性七类。这篇笔记写给两类人做毕设或课程作业的学生需要一条能跑通、能复现的完整链路准备把表情识别接进智能客服、课堂分析、驾驶疲劳监测的工程师需要知道参数怎么定、坑在哪。2. VGG16网络结构拆解16层里每层在干什么为什么表情识别偏要选它2.1 VGG16的骨架卷积块、池化、全连接层的参数账VGG16 是 2014 年 ImageNet 竞赛的经典结构以“规整”著称13 个卷积层加 3 个全连接层。所有卷积核都是 3×3步长 1padding 为 same所有池化都是 2×2步长 2。整个网络被分成五个卷积块通道数依次是 64、128、256、512、512。以 224×224×3 的输入为例特征图尺寸的变化是这样一条链路卷积块层配置输出尺寸Block1conv3-64 × 2112×112×64Block2conv3-128 × 256×56×128Block3conv3-256 × 328×28×256Block4conv3-512 × 314×14×512Block5conv3-512 × 37×7×512全连接FC-4096 → FC-4096 → FC-1000—参数量上卷积部分约 14.7M三层全连接加起来约 102M总计约 138M。也就是说VGG16 的体量有一大半被全连接层吃掉了。对一个七分类的表情任务来说这个尾部明显太重。所以后面我会把全连接层砍掉一层、去掉一层保留一个 4096 就足够。为什么 3×3 卷积要叠两层、三层核心原因是感受野的叠加两个 3×3 级联的感受野等效于一个 5×5三个 3×3 等效于一个 7×7。参数量的账也很划算两个 3×3 是 18 个参数一个 5×5 要 25 个三个 3×3 是 27一个 7×7 要 49。中间还多了非线性激活层模型的判别能力更强。VGG16 的另一个优势是结构规整硬件部署、模型裁剪、可视化都方便这对表情识别这种既要做实验又要落地的场景非常友好。2.2 表情识别为什么要改 VGG16从1000类ImageNet到7类表情原版 VGG16 的输出是 1000 类输入要求 224×224×3。而表情识别领域最常用的 FER2013 数据集是 48×48 的灰度图类别只有七种。直接套原结构会撞上两堵墙第一输入尺寸缩小后卷积核期望的纹理尺度和感受野完全对不上第二FC-4096 层的 1 亿参数压在不到三万张训练图上过拟合几乎是必然的。所以做表情识别时没人会原封不动搬 VGG16大家做的都是“改版 VGG16”。表情识别里为什么选 VGG16 而不是更深的 ResNet我个人的经验是FER2013 这种量级的数据集上ResNet50 的残差结构带来的收益不明显反而更容易在小样本下震荡。VGG16 结构简单过拟合行为可预测搭配 Dropout、EarlyStopping 和权重衰减很容易控制。在大量表情识别论文里VGG16 都作为基线模型出现检索资料、找踩坑经验都方便。常见的改法就三处输入层改成 48×48×1全连接层从两个 4096 减成一个输出层从 1000 改成 7 并接 softmax。2.3 用Keras搭建一个可训练的表情VGG16下面这段代码用 TensorFlow/Keras 搭了一个可直接训练的表情 VGG16保留了原版五个卷积块的通道配置但输入、全连接和输出都按七分类任务做了调整。from tensorflow.keras import Sequential from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout def build_vgg16_emo(input_shape(48, 48, 1), num_classes7): model Sequential(namevgg16_emotion) # Block 1: 64 通道 model.add(Conv2D(64, (3, 3), paddingsame, activationrelu, input_shapeinput_shape)) model.add(Conv2D(64, (3, 3), paddingsame, activationrelu)) model.add(MaxPooling2D(pool_size(2, 2), strides2)) # Block 2: 128 通道 model.add(Conv2D(128, (3, 3), paddingsame, activationrelu)) model.add(Conv2D(128, (3, 3), paddingsame, activationrelu)) model.add(MaxPooling2D(pool_size(2, 2), strides2)) # Block 3: 256 通道 model.add(Conv2D(256, (3, 3), paddingsame, activationrelu)) model.add(Conv2D(256, (3, 3), paddingsame, activationrelu)) model.add(Conv2D(256, (3, 3), paddingsame, activationrelu)) model.add(MaxPooling2D(pool_size(2, 2), strides2)) # Block 4: 512 通道 model.add(Conv2D(512, (3, 3), paddingsame, activationrelu)) model.add(Conv2D(512, (3, 3), paddingsame, activationrelu)) model.add(Conv2D(512, (3, 3), paddingsame, activationrelu)) model.add(MaxPooling2D(pool_size(2, 2), strides2)) # Block 5: 512 通道 model.add(Conv2D(512, (3, 3), paddingsame, activationrelu)) model.add(Conv2D(512, (3, 3), paddingsame, activationrelu)) model.add(Conv2D(512, (3, 3), paddingsame, activationrelu)) model.add(MaxPooling2D(pool_size(2, 2), strides2)) # 分类头只留一个 4096避免过拟合 model.add(Flatten()) model.add(Dense(4096, activationrelu)) model.add(Dropout(0.5)) model.add(Dense(num_classes, activationsoftmax)) return model这段代码的关键在输入尺寸和全连接层的配合。48×48 的输入经过五次 2×2 池化后尺寸变化是 48→24→12→6→3→1最后 Flatten 出来只有 512 个值而不是原版 224×224 输入下的 7×7×512。所以 FC 层保留一个 4096 时总参数量大约 33M比原版 138M 小得多。注意48×48 经过 5 次池化后是 1×1×512这是和原版 VGG16 最不一样的细节。很多新手按 224×224 的链路去算特征图最后在 FC 层维度对不上。参数说明input_shape(48, 48, 1) 表示单通道灰度图这是 FER2013 的标准格式paddingsame 保证每次卷积后尺寸不变池化前宽高永远是偶数这样才能稳定地除到 1。Dropout 放在全连接层之后、输出层之前是处理小数据集过拟合的标配。3. 数据准备与预处理用FER2013把48×48灰度图喂进VGG16的最小流程3.1 公开数据集的选择FER2013的48×48灰度图与七类标签表情识别领域最常用的公开数据集是 FER2013来自 Kaggle 的人脸表情识别挑战赛。它不是一个图片文件夹而是一个 CSV 文件每行三列emotion、pixels、Usage。pixels 是 2304 个 0~255 的灰度值展开成 48×48 就是一张人脸图。Usage 字段把数据标成 Training、PublicTest、PrivateTest 三种。七类标签的原始样本数大致是happy 约 9000、neutral 约 6200、sad 约 6100、fear 约 5100、angry 约 4600、surprise 约 4000、disgust 约 550。disgust 是绝对的少数类七分类里最难学后面第 5 章单独说它。直接用 Usage 字段切分有个隐患它只是按行随机给的划分并没有按人脸身份隔离同一个人完全可能同时出现在训练集和验证集。我的习惯是把 PublicTest 和 PrivateTest 合并重新按 8:1:1 划分 train/val/test保证后续评估数字可信。目录组织建议按 flow_from_directory 的约定来每个类别一个子目录data/fer2013/ train/ angry/ disgust/ fear/ happy/ sad/ surprise/ neutral/ val/ angry/ disgust/ fear/ happy/ sad/ surprise/ neutral/ test/ angry/ disgust/ fear/ happy/ sad/ surprise/ neutral/每个类目录下放对应的 48×48 灰度图。把 CSV 转成图片的脚本很简单注意像素字符串按空格切分、用 numpy 转成 uint8 再 reshape 成 48×48 即可。转换时文件名里带上原始 usage 标记方便后面重新划分时追溯。3.2 数据增强参数旋转、平移、灰度扰动怎么配表情识别的训练集不到三万张VGG16 又有大量参数数据增强不是可选项是必选项。Keras 的 ImageDataGenerator 里我用下面这套参数参数取值说明rotation_range10旋转 ±10°超过这个范围五官结构会被破坏width_shift_range0.1水平平移 10%模拟人脸在画面中的偏移height_shift_range0.1垂直平移 10%zoom_range0.1缩放 ±10%模拟人脸距离摄像头的远近变化horizontal_flipFalse水平翻转默认关闭fill_modenearest平移/旋转产生的空洞用最近邻填充horizontal_flip 在这个任务里是个争议参数。自然场景下的人脸左右纹理本来就不对称比如光照从左边打过来翻转后阴影方向就反了。对 angry、fear 这类依赖局部纹理的类别翻转会让模型学到一个错误的对称先验。我在第一次跑 FER2013 时开了 Flip验证集准确率掉了将近 3 个百分点关了之后才恢复。如果你确定数据采集场景里真的存在镜像人脸再打开它否则保持 False。3.3 用ImageDataGenerator加载训练集与验证集from tensorflow.keras.preprocessing.image import ImageDataGenerator train_datagen ImageDataGenerator( rescale1. / 255, # 像素归一化到 [0, 1] rotation_range10, width_shift_range0.1, height_shift_range0.1, zoom_range0.1, horizontal_flipFalse, fill_modenearest ) val_datagen ImageDataGenerator(rescale1. / 255) # 验证集不做增强 TRAIN_DIR data/fer2013/train VAL_DIR data/fer2013/val train_generator train_datagen.flow_from_directory( TRAIN_DIR, target_size(48, 48), color_modegrayscale, batch_size64, class_modecategorical, shuffleTrue ) val_generator val_datagen.flow_from_directory( VAL_DIR, target_size(48, 48), color_modegrayscale, batch_size64, class_modecategorical, shuffleFalse )这段代码是用 Keras 的 ImageDataGenerator 做数据加载的标准写法。flow_from_directory 会自动遍历子目录名作为类别标签所以目录名必须是 angry、happy 这种英文标签。color_modegrayscale 对应单通道输入如果这里误写成 rgb模型第一层的输入维度对不上直接报错。rescale 在训练和验证时必须保持一致这个细节看起来不起眼但推理阶段漏掉它会让准确率断崖式下跌。shuffle 参数的设置也有讲究训练集必须 True因为增强是在每个 epoch 实时生成的顺序无关验证集设 False这样每个 epoch 的验证顺序固定val_loss 的曲线才有可比性。batch_size64 在这个模型和 48×48 输入下是比较稳的选择显存紧张时降到 32 也可以但学习率最好同步调小。4. 训练与调参从随机初始化到收敛的完整命令与参数4.1 迁移学习加载ImageNet权重还是从零训练很多第一次接触表情识别的人第一个念头是加载 VGG16 在 ImageNet 上的预训练权重。我可以直接说结论在这个任务上从零训练比迁移学习更常见效果也更稳。原因有两个层面。第一输入分布不匹配。ImageNet 权重是在 224×224×3 的彩色图上训出来的它的浅层卷积核学习到的是 RGB 纹理和边缘结构而 FER2013 是 48×48 的灰度图。把灰度图复制成三通道喂进去卷积核看到的还是和预训练时完全不同的统计分布。第二感受野尺度不匹配。预训练模型期望输入里有大范围的上下文48×48 小图直接输入时前两层卷积的感受野就已经覆盖了人脸的大部分区域这个尺度错位很难通过微调弥补。常见的替代方案是把图片上采样到 224×224 再加载预训练权重或者只取预训练的前几个卷积块做特征提取并冻结。这两个做法我都试过在 FER2013 上比从零训练高不了多少却多花了一倍以上的训练时间。所以这个任务里我一般直接用随机初始化从零训练。VGG16 的规整结构加上数据增强在这个数据量下完全能收敛到可用水平。4.2 优化器、学习率、batch size与class_weight优化器选择上我的默认配置是 Adam学习率 1e-4。Adam 的自适应学习率机制让它在小数据集上不太容易因为初始学习率设置不当而发散适合快速验证模型结构。如果想追求那 1~2 个百分点的验证集准确率可以等 Adam 收敛后再换成 SGDmomentum 0.9、学习率 1e-2 继续微调但训练时间会翻倍。batch size 我固定用 64。48×48 的输入本身很小64 张图一个 batch 在消费级显卡上占不了多少显存。大 batch 会降低梯度噪声对小数据集反而容易陷入尖锐极小值所以不建议盲目加大到 128 以上。学习率方面Adam 从 1e-4 起步配合后面的 ReduceLROnPlateau 让它自己衰减是我在表情识别任务里最省心的组合。类别不平衡需要用 class_weight 显式处理尤其是 disgust 只有 550 张左右的情况。权重不能拍脑袋填用 sklearn 按样本数计算最稳from sklearn.utils.class_weight import compute_class_weight import numpy as np train_labels train_generator.classes # 每个训练样本的类别索引 classes np.unique(train_labels) class_weights compute_class_weight( class_weightbalanced, classesclasses, ytrain_labels ) class_weight_dict dict(enumerate(class_weights)) print(class_weight_dict)这段代码输出的权重会按类别样本数的倒数做平衡少数类权重自动变大。train_generator.classes 是 flow_from_directory 给每个样本打的类别索引顺序和目录名的字母序一致。得到 class_weight_dict 后在 model.fit 里把 class_weightclass_weight_dict 传进去即可。注意类别顺序要和模型的 softmax 输出对齐否则权重就白设了。4.3 训练脚本EarlyStopping与学习率衰减的配置环境配置再啰嗦一遍用 conda 建一个 Python 3.9 的环境pip 安装 TensorFlow 2.10 以上版本和 scikit-learnGPU 版不是必须CPU 也能跑通这个规模的小图训练只是每个 epoch 多等几分钟。训练核心代码如下from tensorflow.keras.optimizers import Adam from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint model build_vgg16_emo(input_shape(48, 48, 1), num_classes7) model.compile( optimizerAdam(learning_rate1e-4), losscategorical_crossentropy, metrics[accuracy] ) callbacks [ EarlyStopping(monitorval_loss, patience10, restore_best_weightsTrue), ReduceLROnPlateau(monitorval_loss, factor0.5, patience5, min_lr1e-6), ModelCheckpoint(emotion_vgg16_best.keras, monitorval_accuracy, save_best_onlyTrue) ] history model.fit( train_generator, steps_per_epochtrain_generator.samples // 64, validation_dataval_generator, validation_stepsval_generator.samples // 64, epochs50, class_weightclass_weight_dict, callbackscallbacks, verbose1 )fit 参数里最容易忽略的是 steps_per_epoch 和 validation_steps。这两个值分别表示一个 epoch 里取多少个 batch 的训练和验证步数通常取样本数除以 batch size。如果不设置Keras 会自己去遍历完整个生成器配合 shuffle 反而可能多跑出几个 batch得到的 loss 曲线不平滑。callbacks 的作用要分清EarlyStopping 监控 val_loss连续 10 个 epoch 不下降就停并恢复最佳权重这是防止过拟合的最后一道闸ReduceLROnPlateau 在 val_loss 连续 5 个 epoch 不动时把学习率乘以 0.5min_lr1e-6 防止衰减到零ModelCheckpoint 只保存验证集准确率最高的权重。训练完成后用 history 里的 loss 和 val_loss 画两条曲线如果两者在某个 epoch 后开始分叉说明过拟合从那一步开始了。5. 表情识别落地的避坑指南数据泄漏、类别失衡与过拟合5.1 验证集acc虚高后又崩掉数据泄漏的三种来源现象训练集准确率一路冲到 95% 以上验证集准确率却卡在 60% 出头而且每个 epoch 波动很大。换不同的随机种子重跑结果差距也很明显。原因数据泄漏。最常见的是把 CSV 原样的 train 和 test 合并后按文件顺序或随机方式重新切分同一个人的多张表情图被同时分进了训练集和验证集。VGG16 参数量大、记忆能力强模型记住了这张脸验证集里出现同一张脸的不同表情时准确率自然虚高。解决按人脸身份切分数据而不是按文件行随机切。如果数据集没有提供 subject 字段至少保证同一视频帧序列的图在同一个集合里。FER2013 原始的 Usage 划分其实是按这种思路给的我建议不要轻易合并重切除非你有明确的 subject 标识。检验方法很简单从模型预测错的那几张验证图里看看是不是都能在训练集里找到同一个人能找到就是泄漏。5.2 训练到一半loss变成NaN学习率与黑样本现象训练进行到第 8 个 epoch 左右loss 突然变成 nan之后几个 epoch 要么一直 nan要么跳回一个很大的值再变 nan。准确率也会瞬间掉到接近零。原因这个坑我翻车过两次。第一次是学习率设到 1e-3Adam 在训练中段的参数更新步长过大梯度爆炸直接把权重推成 nan第二次是数据里有全黑的坏样本某些像素值在增强后变成异常值卷积输出产生 inf反向传播一轮就污染了全部参数。解决先把 Adam 的 learning_rate 降到 1e-5看看能否从崩溃点恢复训练不行就从检查数据开始遍历所有训练图片统计每张图的最大值和最小值把全黑、全白、包含 NaN 的样本直接剔除。数据增强的 fill_mode 也要检查fill_modenearest 比 constant 更安全因为常数填充会在图边缘制造出人造的强边缘响应。5.3 模型只会预测neutral类别不平衡怎么办现象训练结束后整体验证准确率有 62%但把预测结果按类别拆开看neutral 占了全部预测的 70% 以上disgust 和 surprise 几乎不预测。这种模型的“准确率”是假象在真实场景里没有使用价值。原因FER2013 里 neutral 样本最多disgust 只有它的十分之一。模型发现把所有样本都猜成 neutral损失就已经很低了尤其在使用默认 categorical_crossentropy 时少数类的梯度贡献被多数类淹没。解决用第 4.2 节里的 compute_class_weight 计算类别权重并传入 model.fit。如果加了权重后少数类准确率仍上不去再考虑两点一是对 disgust、surprise 做针对性数据增强比如随机擦除、局部灰度扰动二是换用 focal loss让模型聚焦难分类样本。先加 class_weight通常就能把 neutral 的预测占比从 70% 压到 40% 以下disgust 的召回率也能从 0 拉到 30% 左右。5.4 摄像头推理卡成PPT全连接层太肥现象模型在 GPU 上训练时很快但部署到笔记本 CPU 上做实时推理每秒只能处理三五帧。用 TensorRT 量化后改善不大。原因VGG16 的推理瓶颈不在卷积层而在全连接层。虽然我们砍掉了一层 4096但剩下那个 4096 和输出层之间的矩阵乘仍然有几千万次浮点运算。卷积层对 48×48 小图的运算量并不大全连接层的权重访问才是 CPU 推理的瓶颈。解决最直接的办法是把 Flatten 后面的 Dense(4096) 换成 GlobalAveragePooling2D。GAP 把每个特征图池化成一个值512 个特征图就是 512 维向量直接接 softmax参数量骤降几乎不影响准确率。如果必须保留全连接层就把 4096 降到 512再配合模型量化。我自己的经验是GAP 版本在 CPU 上能跑到 15 帧以上比保留 4096 的版本快三倍左右。6. 把模型接到摄像头实时推理流水线与验证技巧6.1 用OpenCV人脸检测VGG16推理的完整流水线import cv2 import numpy as np from tensorflow.keras.models import load_model model load_model(emotion_vgg16_best.keras) emotion_labels [angry, disgust, fear, happy, sad, surprise, neutral] face_cascade cv2.CascadeClassifier( cv2.data.haarcascades haarcascade_frontalface_default.xml ) cap cv2.VideoCapture(0) while True: ret, frame cap.read() gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces face_cascade.detectMultiScale( gray, scaleFactor1.1, minNeighbors5, minSize(48, 48)) for (x, y, w, h) in faces: roi gray[y:yh, x:xw] roi cv2.resize(roi, (48, 48)) roi roi.astype(np.float32) / 255.0 # 归一化必须与训练一致 roi roi.reshape(1, 48, 48, 1) pred model.predict(roi, verbose0)[0] label emotion_labels[np.argmax(pred)] cv2.rectangle(frame, (x, y), (xw, yh), (0, 255, 0), 2) cv2.putText(frame, label, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2) cv2.imshow(Emotion Recognition, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这段流水线的关键是把训练时的预处理步骤原样搬过来BGR 转灰度、resize 到 48×48、除以 255。detectMultiScale 的 scaleFactor1.1 表示每次缩放 10%值越小检测越慢但越全minNeighbors5 表示至少 5 个邻近框才算人脸值越大漏检越多。6.2 用混淆矩阵和单张图片验证模型没白训实时推理看起来正常不代表模型真的学到了表情差异。我每次训练完都会先跑一遍混淆矩阵用验证集生成真实标签和预测标签的交叉表确认 bug 没有藏在预测逻辑里。from sklearn.metrics import confusion_matrix, classification_report import seaborn as sns import matplotlib.pyplot as plt y_true val_generator.classes y_pred model.predict(val_generator, verbose0).argmax(axis1) cm confusion_matrix(y_true, y_pred) print(classification_report(y_true, y_pred, target_namesemotion_labels)) sns.heatmap(cm, annotTrue, fmtd, cmapBlues, xticklabelsemotion_labels, yticklabelsemotion_labels) plt.show()混淆矩阵的看点不是对角线有多亮而是哪些类别互相串。最常见的串法是 fear 和 surprise 混淆、angry 和 sad 混淆这是表情判别本身模糊导致的。如果某两类之间的误判特别集中第一件事不是调模型而是回去翻数据看这两类的标注是不是本身就有问题。我第一次跑这个项目时忘了在推理前做 rescale像素值按 0~255 直接进了模型单张图片准确率只有三成。后来把所有预处理统一成“灰度→resize→除以 255→reshape”一条线准确率才恢复正常。如果你现在刚跑通训练先把验证集上单张图片的预处理链路和训练时完全对齐再谈优化模型。这个习惯帮我避开了后面一多半的坑希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

OpenBiliClaw架构解析:Agent编排、灵魂画像、五层记忆与发现引擎全景图 2026/9/28 20:33:54

OpenBiliClaw架构解析:Agent编排、灵魂画像、五层记忆与发现引擎全景图

OpenBiliClaw架构解析:Agent编排、灵魂画像、五层记忆与发现引擎全景图 【免费下载链接】OpenBiliClaw 本地私有、开源的自进化跨平台 AI 内容发现 Agent:先理解你,再主动从 B站、小红书、抖音、YouTube、X、知乎、Reddit、微博等平台与开放 …

阅读更多 →
原生Servlet+JDBC点餐系统:从请求路由到事务处理的完整实战解析 2026/9/28 20:33:54

原生Servlet+JDBC点餐系统:从请求路由到事务处理的完整实战解析

简介:基于MVC开发模式的原生Servlet与JDBC点餐系统完整项目,面向Java Web学习者、毕业设计与课程设计人群,可用于理解经典三层协作在真实业务中的落地方式。压缩包共139个文件,包含21个jsp页面、6个java源码、6个class编译文件、7…

阅读更多 →
GitHub 热榜项目:周榜(2026-09-27) 2026/9/28 20:33:54

GitHub 热榜项目:周榜(2026-09-27)

本期共收录 18 个热门开源项目,合计新增 ⭐ 56,645 stars,热门语言:Python、TypeScript、JavaScript。 数据来源:GitHub Trending | 统计周期:周榜 | 更新日期:2026-09-27 📝 本期综述 给编码智…

阅读更多 →
合肥GEO优化服务商怎么选?排名前五实力公司参考汇总 2026/9/28 20:33:47

合肥GEO优化服务商怎么选?排名前五实力公司参考汇总

合肥GEO优化服务商怎么选?排名前五实力公司参考汇总 开篇:合肥GEO优化用户的4大典型踩坑难题在合肥寻找GEO优化服务商的企业主,大多都曾在选型过程中踩过不少隐性坑。从搜索结果看,用户高频吐槽的痛点主要集中在这四个方面: 选了…

阅读更多 →
代码托管平台访问慢与下载卡顿的排查思路与加速方案 2026/9/28 20:33:47

代码托管平台访问慢与下载卡顿的排查思路与加速方案

1. 从一次拉取代码卡了四十分钟说起那天下午我在调一个开源项目的构建脚本,git clone一条命令敲下去,进度条像被冻住一样,十分钟走了不到百分之三。我一开始以为是仓库太大,换了个小仓库试,结果一样。打开浏览器想直接…

阅读更多 →
Sphinx 4.2 版本解析:autodoc 类属性支持、mock 对象警告与 C/C++ 类型体系扩展 2026/9/28 20:33:47

Sphinx 4.2 版本解析:autodoc 类属性支持、mock 对象警告与 C/C++ 类型体系扩展

文档开发工具 【免费下载链接】sphinx The Sphinx documentation generator 项目地址: https://gitcode.com/gh_mirrors/sp/sphinx 点击查看 免费下载 Sphinx 4.2.0 是 Sphinx 文档生成器于 2021 年 9 月 12 日发布的一个重要维护版本,聚焦于 autodoc 扩…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉