DeepLabV3实战:Cityscapes标签转trainId与训练迁移全指南
简介面向计算机视觉语义分割研究者的PyTorch实现基于Cityscapes数据集训练DeepLabV3解决街景场景中物体边缘模糊与多尺度特征提取问题。压缩包共18个文件约258MB其中12个py脚本覆盖模型结构定义、数据预处理、DataLoader加载、训练、验证评估与可视化4个pth文件为预训练权重可加载后继续训练或直接推理另有README说明文档与license许可文件目录结构清晰便于复现实验。这一实现引入空洞空间金字塔池化ASPP和全局上下文模块能够捕获不同感受野下的语义信息数据处理环节针对Cityscapes图像缩放、归一化与标签编码做了适配配套交叉熵损失、SGD/Adam优化器及mIoU评估流程。从配置到训练再到评估的完整链路均已打通适合初中级开发者快速跑通语义分割项目进而深入理解DeepLabV3的设计思想。目前已有2097人学习下载。1. 在 Cityscapes 数据集上训练 DeepLabV3真正花时间的是标签管线不是网络结构很多同学以为把 DeepLabV3 放到 Cityscapes 数据集上训练核心难点在网络结构上真正动过手的人才会发现PyTorch 实现的成本大头在标签管线和类别索引对齐上。这个标题处理的是一整套工程下载两份数据、把原始 labelId 映射成 19 类 trainId、写好带随机缩放的 DataLoader、用 SGD 加 poly 学习率把网络训到能迁移的程度再用 mIoU 验证效果。它解决的问题不是“把模型跑起来”而是“跑出可复现、可迁移的结果”。这篇文章适合想在自有分割任务上用 Cityscapes 预训练模型做迁移的从业者新手能照着命令走熟手可以直接跳到避坑那张表。2. 网络选型DeepLabV3 为什么适合街景分割ASPP 和输出步长怎么定2.1 高分辨率图像下空洞卷积和 ASPP 是怎么把感受野撑起来的Cityscapes 的原始图像是 2048×1024这个分辨率决定了网络不能靠单纯加深来获得足够大的感受野。普通卷积每卷一层感受野线性增长到了深层还得不停下采样最后特征图缩到 1/32对小目标极不友好。DeepLabV3 的核心思路是不急着把分辨率压低用空洞卷积在保持特征图分辨率的同时扩大感受野。空洞率 r 意味着卷积核相邻采样点之间隔 r-1 个像素同样一个 3×3 卷积r1 是普通感受野r2 就能覆盖 7×7 的区域r4 能覆盖 15×15。真正让 DeepLabV3 在街景上站住脚的是它末端的 ASPP 模块。这个模块把同一份特征并行喂给四个分支一个 1×1 卷积三个空洞率分别为 6、12、18 的 3×3 卷积另外再接一个全局平均池化分支来捕捉整张图的上下文。四个分支输出拼在一起再过 1×1 卷积融合。这样设计的好处是它不依赖单一空洞率而是让不同尺度目标各取所需小目标靠 1×1 分支和低空洞率大目标靠高空洞率和全局分支。车辆、行人、建筑在街景里尺度差异极大单一感受野很难同时兼顾。2.2 选 backbone 和输出步长时的 3 个实测依据我的经验是backbone 优先选 ResNet101而不是 ResNet50。Cityscapes 训练集只有 2975 张很多人担心 ResNet101 会过拟合实际上在这个数据集上更深的主干带来的精度提升非常稳定风险完全可以用数据增强和早停来控制。ResNet50 的 mIoU 会比 101 低 2 到 3 个点这个差距在后续迁移到自有数据时会被放大。如果显存实在紧张ResNet50 也能用但别期望它和 101 表现相当。输出步长这里要做一个取舍。DeepLabV3 论文里常用 output_stride16输入分辨率是 1024×2048 时特征图是 64×128每个像素对应的原图区域约 16×16足够密。output_stride8 特征图更密精度略高但显存和训练时间都会涨。我一般先用 16 训练最后如果需要提点再单独跑一个 output_stride8 的微调实验不要一上来就上 8。另一个相关参数是 backbone 最后一层的空洞率output_stride16 时stage4 的卷积会改成空洞率 2这样才能保证输出分辨率不下探到 1/32。2.3 Cityscapes 19 类索引表为什么不能直接训练原始 gtFine 标签Cityscapes 官方给的是 34 类的 labelId其中很多类别互相嵌套比如“人”和“骑车人”在标注时区分得很细但实际训练时并不需要那么碎。标准做法是把 34 类合并成 19 个 trainId这个映射关系在官方脚本里有但只要理解下面这张表就够了。trainId类别说明0road道路1sidewalk人行道最容易和 road 混淆2building建筑3wall墙体4fence围栏5pole杆状物6traffic light交通灯7traffic sign交通标志8vegetation植被9terrain地形比 vegetation 更矮更杂10sky天空11person行人12rider骑车人13car小汽车14truck卡车15bus公交车16train火车17motorcycle摩托车18bicycle自行车原始 gtFine 里无法标注的区域、边界线和空洞都属于 voidtrainId 是 255。训练时必须把这个值传给损失函数的 ignore_index否则它会作为第 20 类参与梯度计算背景像素直接把 loss 带偏。转换这块坑我后面会单独讲这里先记住一个原则训练用 trainId可视化用 19 类调色板两者千万别混用。3. 准备数据官方目录结构、labelId 到 trainId 的转换脚本、DataLoader3.1 下载后的目录长什么样两份数据缺一不可Cityscapes 要下载两个部分leftImg8bit 是左侧摄像头拍摄的原始图像gtFine 是高精度标注。很多人只下载了图像跑起来才发现没有标签又回下载页补一次浪费时间。gtFine 里每个样本包含多个文件我们训练只用_gtFine_labelIds.png这个文件是 8 位单通道的 PNG像素值存的就是 labelId 0-33。目录结构整理成下面这样后续所有脚本都按这个路径来# 只展示目录骨架下载好的压缩包解压后放到 data/Cityscapes/ 下 mkdir -p data/Cityscapes/leftImg8bit/train mkdir -p data/Cityscapes/leftImg8bit/val mkdir -p data/Cityscapes/gtFine/train mkdir -p data/Cityscapes/gtFine/val一定要把 train 和 val 分开放在 leftImg8bit 和 gtFine 下而且两份目录里的文件名前缀严格一致。左图文件是aachen_000000_000019_leftImg8bit.png标签是aachen_000000_000019_gtFine_labelIds.png代码里只要把后缀替换就能配对。如果目录结构不一致后面 glob 排序时图片和标签会错位训练等于白跑。3.2 用一个脚本把 labelId 批量转成 trainId官方源码里有现成转换逻辑但很多人不愿意为了一个脚本引入整个仓库依赖。我习惯直接写一个独立的小脚本几十行搞定逻辑透明出了问题也好改。这个脚本会遍历 gtFine/ 下的所有_labelIds.png生成对应的_labelTrainIds.png到另一个目录方便 DataLoader 直接读。# tools/convert_trainid.py # 将 Cityscapes 原始 labelId 转换为 19 类 trainIdvoid 区域统一为 255 import cv2 import numpy as np from pathlib import Path # labelId - trainId 映射仅列需要保留的类别 label2train { 0: 0, # road 1: 1, # sidewalk 2: 2, # building 3: 3, # wall 4: 4, # fence 5: 5, # pole 6: 6, # traffic light 7: 7, # traffic sign 8: 8, # vegetation 9: 9, # terrain 10: 10, # sky 11: 11, # person 12: 12, # rider 13: 13, # car 14: 14, # truck 15: 15, # bus 16: 16, # train 17: 17, # motorcycle 18: 18, # bicycle } def convert(src_path: Path, dst_path: Path) - None: # imread 默认按彩色图读这里必须加 0 按灰度读才能拿到原始 labelId 数值 img cv2.imread(str(src_path), cv2.IMREAD_GRAYSCALE) out np.full(img.shape, 255, dtypenp.uint8) for src_id, train_id in label2train.items(): out[img src_id] train_id dst_path.parent.mkdir(parentsTrue, exist_okTrue) cv2.imwrite(str(dst_path), out) if __name__ __main__: root Path(data/Cityscapes) for split in [train, val]: srcs sorted((root / gtFine / split).glob(*_gtFine_labelIds.png)) for src in srcs: dst root / gtFine_labelTrainId / split / (src.name.replace(labelIds, labelTrainIds)) convert(src, dst)这个脚本的核心是那个映射表原图中不是这 19 个 labelId 的像素全部置成 255也就是 void。这样在后续计算损失和 mIoU 时只需一个 ignore_index 就能处理所有无效像素。写完后先跑一张图用 matplotlib 打开_labelTrainIds.png检查应该能看到明显的区块边界背景区域是黑色而不是灰蒙蒙的一片。如果看到满屏 255说明 cv2.imread 按通道处理导致数值错乱检查读取方式。3.3 DataLoader 里的随机缩放、裁剪和归一化参数图像和标签都准备好了往下走是 Dataset。Cityscapes 原始图是 2048×1024直接把整张图送进显存一张就可能吃掉 4GB 以上。常见做法是训练时随机缩放加随机裁剪到固定尺寸。我习惯用 769×769这个尺寸是 DeepLabV3 论文里的常用设置正好覆盖在 output_stride16 下约 49×49 像素的特征区域。# dataset/cityscapes.py # 读取转换好的 labelTrainIds 图训练时做随机缩放和随机裁剪 import random import cv2 import numpy as np import torch from torch.utils.data import Dataset class CityscapesDataset(Dataset): def __init__(self, root, splittrain, crop_size769): self.images sorted((root / leftImg8bit / split).glob(*_leftImg8bit.png)) self.masks sorted((root / gtFine_labelTrainId / split).glob(*_labelTrainIds.png)) self.crop_size crop_size self.train (split train) def __len__(self): return len(self.images) def __getitem__(self, idx): img cv2.imread(str(self.images[idx]), cv2.IMREAD_COLOR) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) mask cv2.imread(str(self.masks[idx]), cv2.IMREAD_GRAYSCALE) if self.train: # 先随机缩放再裁剪最后随机水平翻转 scale random.uniform(0.5, 2.0) new_h, new_w int(img.shape[0] * scale), int(img.shape[1] * scale) img cv2.resize(img, (new_w, new_h), interpolationcv2.INTER_LINEAR) mask cv2.resize(mask, (new_w, new_h), interpolationcv2.INTER_NEAREST) h, w img.shape[:2] y random.randint(0, h - self.crop_size) if h self.crop_size else 0 x random.randint(0, w - self.crop_size) if w self.crop_size else 0 img img[y:y self.crop_size, x:x self.crop_size] mask mask[y:y self.crop_size, x:x self.crop_size] if random.random() 0.5: img img[:, ::-1].copy() mask mask[:, ::-1].copy() # 归一化使用 ImageNet 统计量PyTorch 生态分割模型默认沿用这套 img img.astype(np.float32) / 255.0 img (img - np.array([0.485, 0.456, 0.406])) / np.array([0.229, 0.224, 0.225]) img torch.from_numpy(img.transpose(2, 0, 1)).float() mask torch.from_numpy(mask.astype(np.int64)).long() return img, mask注意 mask 的 resize 插值必须用INTER_NEAREST不能用线性插值。线性插值会在类别边界上造出 0.5 这种不存在的类别训练时 CrossEntropyLoss 直接报错或学出界面糊成一团的模型。图像 resize 用线性插值没问题因为人眼可能感知到但标签是离散标号必须最近邻。随机缩放范围 0.5 到 2.0 看起来很大实战中这个范围能显著提升对不同距离目标的泛化能力代价是训练集内每张图每次迭代的形状都不同GPU 利用率会略降这个折中值得。4. 训练与验证从 deeplabv3_resnet101 到 mIoU 的一张完整流程4.1 模型初始化、损失函数和带 poly 策略的 SGD 配置PyTorch 生态里的分割模型包已经提供了 DeepLabV3 的完整结构不需要自己手写 backbone 和 ASPP。我一般这样初始化模型先加载一个在通用数据集上预训练的 backbone再把最后的分类头改成 19 类。但这里有个特别容易混淆的点开箱即用的 DeepLabV3 模型默认是在 ImageNet 或 COCO 这类通用数据上训练的它给出的“预训练权重”并不等于“Cityscapes 训练好的权重”我们这一步只是继承通用视觉特征让它从更优的起点开始 Cityscapes 训练。# train.py 模型与优化器配置节选 import torch import torch.nn as nn from torchvision.models.segmentation import deeplabv3_resnet101 base_lr 0.007 model deeplabv3_resnet101(weightsbackbone, num_classes19) # 分类头学习率放大 10 倍新初始化的层更需要大步长 optimizer torch.optim.SGD([ {params: model.backbone.parameters(), lr: base_lr}, {params: model.classifier.parameters(), lr: base_lr * 10}, ], momentum0.9, weight_decay1e-4) criterion nn.CrossEntropyLoss(ignore_index255)损失函数必须带 ignore_index255这个参数会在计算交叉熵时自动跳过所有 void 像素不参与梯度回传。学习率这里没有用固定值而是计划在训练循环里按迭代数实时更新这就是 DeepLabV3 论文里常用的 poly 策略lr base_lr * (1 - iter / total_iter) ** 0.9。它的特点是后期学习率下降得很平缓能让模型在收敛附近多磨一阵。优化器选 SGD 而不是 Adam 不是玄学分割任务里 Adam 容易在长尾类别上震荡SGD 配合 poly 学习率更稳。4.2 训练循环里我习惯盯的几个信号训练脚本本身并不复杂几个关键点写出来就是完整的骨架。数据加载用前面写的 Dataset 包成 DataLoaderbatch size 要看显存。769×769 的输入、batch 大小 4 到 8 是常见范围更大就等着 OOM。# train.py 单卡训练循环节选 from torch.utils.data import DataLoader from dataset.cityscapes import CityscapesDataset dataset CityscapesDataset(rootdata/Cityscapes, splittrain, crop_size769) loader DataLoader(dataset, batch_size4, shuffleTrue, num_workers4, drop_lastTrue) max_iter 300 * len(loader) # 300 个 epoch约等于 17.2 万步 iter_idx 0 for epoch in range(300): for images, masks in loader: # 根据迭代进度动态调整学习率 lr base_lr * (1 - iter_idx / max_iter) ** 0.9 for g in optimizer.param_groups: g[lr] lr images, masks images.cuda(), masks.cuda() out model(images)[out] # 输出形状 [B, 19, H, W]未上采样 loss criterion(out, masks) optimizer.zero_grad() loss.backward() optimizer.step() if iter_idx % 500 0: # 打印 loss 和当前学习率loss 在 0.3-0.5 区间波动是正常现象 print(fiter {iter_idx}, loss {loss.item():.4f}, lr {lr:.6f}) iter_idx 1模型输出的out是 1/8 分辨率特征而 mask 是原始尺寸的注释CrossEntropyLoss 会自动广播因为 PyTorch 的交叉熵会匹配 logits 和 target 的形状。loss 的走势要注意一点前 5000 步里损失可能从 4 猛降到 1然后又慢慢爬回 2 附近这是分类头在自适应不代表坏事。真正要看的是 loss 震荡的底部是否缓慢下移如果到了 20 万步还在 0.5 附近晃大概率是数据加载或标签映射的问题。训练时长按 2975 张训练图、batch 4 来算17 万步要跑很多天。中间检查点是刚需每 20000 步保存一次权重文件名带上迭代号这是后悔药。别只留最后一个因为最优 mIoU 通常不在最后一轮。4.3 验证阶段跳过类别 255 算 mIoU训练到中段就该跑验证了。mIoU 是 Cityscapes 官方认可的主指标计算方式是对每个类别算交并比最后对 19 类取平均。验证时要把网络输出的 logits 做 argmax得到预测类别再和 ground truth 逐类比对。这里需要忽略 255否则 void 像素会被当成错误虚标 mIoU。# evaluate.py mIoU 计算核心 def compute_miou(pred, target, num_classes19): # pred/target 形状 [B, H, W]来自模型 argmax 结果 ious [] for cls in range(num_classes): pred_mask (pred cls) target_mask (target cls) inter (pred_mask target_mask).sum().float() union (pred_mask | target_mask).sum().float() if union 0: ious.append(float(nan)) # 当前图中没有该类不参与平均 else: ious.append((inter / union).item()) # 忽略 nan 类别后再平均避免拉低分数 valid [v for v in ious if not np.isnan(v)] return np.mean(valid)验证时更推荐做多尺度推理把输入图缩放成 0.5、0.75、1.0、1.25、1.5、1.75 六种尺度每张都前向一次再把 logits 双线性插值回原图尺寸后相加最后取 argmax。这个技巧在这个数据集上能稳定带来 1.5 到 2 个点的 mIoU 提升。代价是验证速度慢 6 倍但验证集只有 500 张完全能接受。5. 踩坑与排查类别索引、权重加载、多尺度推理的三类血泪问题5.1 结果可视化全是同一颜色先查标签再查预测现象训练 loss 正常下降但把预测结果画出来整张图几乎是一种颜色或者某些区域出现明显的马赛克块。原因绝大多数情况是标签转换错了。最常见的是直接用_gtFine_labelIds.png参与训练而没有剪裁成 trainId。原始 labelId 有 34 类类别之间数值不连续模型无法学习从 20 到 29 这些空缺索引的语义另一种情况是可视化时拿 trainId 直接套调色板19 类索引对应的颜色偏差不明显人眼看起来就像全是一个类。解决先单独可视化_labelTrainIds.png用 matplotlib 的 imshow 显示灰度图确认只有 0 到 18 和 255 这些值再保存完整的 19 类调色板字典每次可视化都必须走该字典映射。如果标签图看起来是对的再检查模型的输出确认 argmax 是在类别维度上做的。我写过一个快速脚本打印预测图里出现的类别集合只需要一行np.unique(pred)立刻能看出是不是把背景 255 当成了第 20 类。5.2 加载预训练权重时 shape 不匹配现象加载某个权重文件时报unexpected key in state dict或size mismatch报错停留在classifier.4.weight附近。原因权重文件的分类头维度与当前模型不一致。DeepLabV3 默认是在 21 类数据集上训练的直接把 num_classes19 的模型和 21 类的权重对不上。还有一类坑是保存时用了torch.save(model.module.state_dict())加载时模型没有 DataParallel 包装state dict 的 key 多出一个module.前缀。解决如果报错在分类头很简单先加载只包含 backbone 的预训练权重然后让模型随机初始化分类头再开始训练。如果报错是 module 前缀处理办法是遍历 state dict 重建一个去前缀的字典# 处理旧权重里多余的 module. 前缀 new_state {k.replace(module., ): v for k, v in old_state.items() if module. in k} model.load_state_dict(new_state, strictFalse)加载时用strictFalse并打印缺失的 key能快速确认是哪些层对不上。我在这个环节花过一整晚现在养成了新项目先打印模型的 state_dict 结构和权重结构作对比的习惯这个习惯后来帮我避开很多类似坑。5.3 验证分数停在某个区间上不去现象mIoU 陷入平台期单尺度验证分数比预期的低很多大概 60 或 65 就上不去了。原因模型过拟合到训练集的裁剪分布。Cityscapes 训练图全是城市街景固定区域反复裁剪后模型对图像边缘的车辆、行人的泛化变差。另一个常见原因是验证时没有做多尺度推理单尺度 769 的输入窗口实际上看不到远处的小目标感受野不够。解决验证时切换到多尺度推理这是最大的一次涨点来源。再者检查渲染目标时有没有做随机缩放到 0.5-2.0有些人贪方便只做固定裁剪这等于人为收窄了训练分布。值得一提的是多尺度推理并不会显著增加显存占用因为每次推理是一张一张图和缩略图逐个跑的结果直接累加最后占的显存还是单张的规模。5.4 训练到一半显存爆掉现象训练一段时间后CUDA out of memory有时报错在 loss.backward() 这行。原因Cityscapes 的 769×769 裁剪加上 batch 4 在 11G 显存上已经接近上限。如果中途内存增长通常是把验证集混进训练 DataLoader 时累积了图。解决先把 batch size 降到 2确认可以稳定跑完一个小 epoch 再往上加。如果 batch size 已经很小还爆就要检查数据加载确认没有中途把验证集图也 append 到训练集里产生了数据混叠。真到了这一步就别在数据管线省事了NumPy 数组转张量前先释放中间占用的 float32 数组再走保留到 CUDA 的路径。6. 把 Cityscapes 模型迁移到自己的分割任务换分类头和解冻策略当你在 Cityscapes 上把模型训练好真正的价值才刚刚开始。你自己的数据绝不会正好是 19 类这个预训练模型在你那 3000 张小图上关键是换分类头后不要让整个网络重学一遍而是让它基于已经掌握的边缘、纹理和几何结构快速适配新类别。# finetune.py 换分类头并选择性解冻 model deeplabv3_resnet101(num_classes19) model.load_state_dict(torch.load(cityscapes_best_19.pth)) # 替换最后的 1x1 分类卷积num_classes 换成你自己的类别数 new_conv nn.Conv2d(256, num_classes, kernel_size1) model.classifier[4] new_conv这个替换逻辑里classifier 前几层是 ASPP 分支最后是 1×1 卷积所以只换索引 4 就能保留大部分迁移特征。换完后的策略我总结成一句数据少于 500 张就冻结 backbone只训练分类头数据在 500 到 5000 张之间把 backbone 最后一层解冻在架构上分离的轻量层解冻上也行。学习率不要再按 poly 从头走了固定 1e-4 或从 5e-4 线性衰减SGD 依然是首选Adam 在迁移阶段反而波动更明显。我吃过一次亏就是解冻了太多层又用大了学习率结果新任务的 loss 不降反升最后发现是早期特征被冲掉了。这个方向值不值得做我的答案很明确如果你面对的道路、园区、工地场景和 Cityscapes 有交集迁移起步至少省掉一周的收敛时间最终效果也明显好于从随机初始化硬训。现在的习惯是拿到新任务先看类别分布和 Cityscapes 的重叠度重叠高就大胆微调重叠低就只训分类头。这个判断比调任何损失函数都重要。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

NC57与Oracle 10g安装部署实战:从系统参数到应用启动的完整避坑指南

NC57与Oracle 10g安装部署实战:从系统参数到应用启动的完整避坑指南

简介:这份文档面向用友NC57的部署实施人员与运维初学者,聚焦Oracle 10g数据库与NC57产品的完整安装流程,帮助读者在较短时间内理清从数据库准备到系统管理设置的各环节要点。资源包内共1个doc文件,压缩后约2.77MB,以图…

2026/10/9 14:38:05 阅读更多 →
机器人学导论教案实战:从位姿到雅可比的完整学习路线

机器人学导论教案实战:从位姿到雅可比的完整学习路线

简介:机器人学导论是连接机械工程与智能控制的桥梁,而位姿描述、坐标变换、正逆运动学与雅可比矩阵则是其中最核心的基础概念。很多学习者拿到教学PPT后,往往只是收藏却难以真正内化,原因在于缺少一条从公式推导到仿真验证的完整路…

2026/10/9 14:38:05 阅读更多 →
Linux下手动搭建Hadoop 3.3.6集群实战指南

Linux下手动搭建Hadoop 3.3.6集群实战指南

简介:本资源是一份面向大数据初学者与高校实验教学的Hadoop集群搭建实操指南,聚焦Linux环境下从零构建分布式Hadoop 2.7集群的核心流程,解决环境配置复杂、节点通信异常、服务启动失败等典型实践痛点。文档为单文件Word格式(.doc&…

2026/10/9 14:38:05 阅读更多 →

最新新闻

金融数据库规范运维:审计回溯、变更闭环与合规落地

金融数据库规范运维:审计回溯、变更闭环与合规落地

简介:本资源《金融数据库规范运维.pdf》是一份面向金融行业DBA、运维工程师及技术管理者的核心实践指南,聚焦双态运维(稳态敏态)落地难题,系统解决千级数据库规模下的流程标准化、人员容灾与知识传承等关键挑战。文档深…

2026/10/9 15:13:48 阅读更多 →
派单系统源码实战:订单状态机与并发派单避坑指南

派单系统源码实战:订单状态机与并发派单避坑指南

简介:这套Java派单系统平台源码完整版内置Android端客户端与项目说明,专为Java后端和Android开发者设计,覆盖订单分配、任务派发、用户管理、状态跟踪等业务场景,并借鉴了Upwork式的工作流管理机制,支持后台调度与移动…

2026/10/9 15:13:48 阅读更多 →
t3code:打造本地代码资产库的离线复用CLI工具实践

t3code:打造本地代码资产库的离线复用CLI工具实践

1. 为什么要做 t3code:从旧代码库到个人代码资产库如果你和我一样,手上有好几个维护了大半年的项目,你一定遇到过这种感觉:新项目里要写一个功能,脑子马上反应“这个我在老项目里写过了”,然后打开老仓库&a…

2026/10/9 15:13:47 阅读更多 →
Java+Android派单系统源码解析:从双端架构到状态机设计与部署避坑

Java+Android派单系统源码解析:从双端架构到状态机设计与部署避坑

简介:一套基于Java的派单系统完整源码,附带Android客户端工程及项目说明文档,适合希望掌握Java后端与Android移动端全栈开发的开发者。系统可应用于外卖、家政、跑腿等场景的订单分配与调度,包含任务发布、接单、状态跟踪、用户管…

2026/10/9 15:13:47 阅读更多 →
OllyDbg逆向工程入门:单步跟踪、断点设置与授权逻辑分析实战

OllyDbg逆向工程入门:单步跟踪、断点设置与授权逻辑分析实战

简介:OllyDbg 1.09C 汉化版是一款面向逆向工程初学者与安全分析人员的汇编级调试工具,主要解决程序动态跟踪、底层指令分析与软件调试中的语言障碍问题。压缩包共13个文件,约676KB,包含可执行主程序、5个功能扩展dll、5个说明文档…

2026/10/9 15:13:47 阅读更多 →
全国湖泊湿地shp数据实战:坐标系、叠加分析与PostGIS空间查询

全国湖泊湿地shp数据实战:坐标系、叠加分析与PostGIS空间查询

简介:这份资源面向GIS从业者、地理信息专业学生及从事国土空间规划、水文生态研究的技术人员,提供全国尺度的湖泊、水库、沼泽湿地与滨海湿地矢量数据,可用于专题制图、空间分析与可视化表达。压缩包共31个文件,约11.3MB&#xff…

2026/10/9 15:12:47 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →