mmdetection模型解析:从配置文件到检测框的完整拆解
1. 从配置文件到检测框mmdetection模型解析到底在解析什么刚接触mmdetection的人十有八九会被它那套配置文件体系绕晕。打开一个configs/目录下的py文件里面嵌套着model、data、schedule、runtime好几层字典每个字典里又套着backbone、neck、head、train_cfg、test_cfg。你照着官方文档跑通了训练脚本loss也在降但真要问你一句这个模型到底是怎么从一张图算出框的很多人就卡壳了。这篇内容就是来解决这个卡壳的。我把它定位成一篇模型解析向的入门拆解适合两类人一类是刚跑通mmdetection demo、想搞清楚配置文件里每个字段对应网络哪一部分的初学者另一类是已经会训模型、但遇到改结构、换head、调anchor时不知道从哪下手的中级使用者。核心目标只有一个——把mmdetection里模型这个概念从配置文件的一堆字典还原成一条清晰的、从输入图像到输出检测框的数据流。mmdetection是商汤系开源的目标检测工具箱它最大的特点是模块化和配置驱动。所谓模块化是指它把检测网络拆成了backbone、neck、head、roi_head、bbox_coder、loss这些可替换的组件所谓配置驱动是指你不需要改一行Python代码只靠改配置文件就能拼出一个新模型。这两点决定了想真正理解mmdetection的模型你不能盯着某一个xxx.py看而要顺着配置字典→注册器→实例化→前向传播这条链路走一遍。我下面会按这个链路拆。先讲清楚配置文件里model字典的层级结构再讲注册器机制是怎么把字符串映射成类的然后重点拆解单阶段和双阶段两类检测器的前向流程最后落到实操——怎么改一个head、怎么加一个自定义模块、以及解析模型时最容易踩的几个坑。全程用生活化的类比配合代码片段尽量让没读过源码的人也能跟上。提示本文所有代码示例基于mmdetection 2.x系列的API风格。3.x版本在注册器和部分接口上有调整但核心的配置驱动模块化思想是一致的思路可以直接迁移。2. model字典的层级结构一张图看懂backbone到head的组装逻辑2.1 为什么mmdetection要把模型写成嵌套字典先看一个典型的单阶段检测器配置以RetinaNet为例model字段大概长这样model dict( typeRetinaNet, backbonedict( typeResNet, depth50, num_stages4, out_indices(0, 1, 2, 3), frozen_stages1, norm_cfgdict(typeBN, requires_gradTrue), norm_evalTrue, stylepytorch), neckdict( typeFPN, in_channels[256, 512, 1024, 2048], out_channels256, start_level1, add_extra_convson_input, num_outs5), bbox_headdict( typeRetinaHead, num_classes80, in_channels256, stacked_convs4, feat_channels256, anchor_generatordict( typeAnchorGenerator, octave_base_scale4, scales_per_octave3, ratios[0.5, 1.0, 2.0], strides[8, 16, 32, 64, 128]), bbox_coderdict( typeDeltaXYWHBBoxCoder, target_means[.0, .0, .0, .0], target_stds[1.0, 1.0, 1.0, 1.0]), loss_clsdict( typeFocalLoss, use_sigmoidTrue, gamma2.0, alpha0.25, loss_weight1.0), loss_bboxdict(typeL1Loss, loss_weight1.0)))第一次看这坨东西感觉就是字典套字典套到天荒地老。但如果你把它想象成搭乐高逻辑立刻就清楚了最外层的typeRetinaNet是你要拼的整艘飞船的型号backbone是底座负责从原图提取特征neck是连接件把底座的不同高度特征融合起来bbox_head是炮塔负责在融合后的特征上预测类别和框的偏移。每个子字典里的type字段就是这块乐高零件的型号名。mmdetection拿到这个字符串会去一个叫**注册器Registry**的零件仓库里找对应的类然后用字典里剩下的键值对作为参数去实例化它。这就是配置驱动的本质——字符串寻址 参数注入。2.2 backbone、neck、head三段式划分的由来为什么偏偏是这三段这要从检测网络的发展史说起。早期的检测器比如Faster R-CNN刚出来时其实没有明确的neck概念backbone直接接RPN和RoI head。后来FPNFeature Pyramid Network被提出大家发现把不同尺度的特征图融合一下对检测小目标特别有用于是这段融合逻辑被单独抽出来成了neck。所以三段式的分工是backbone把一张H×W×3的图逐级下采样成C2、C3、C4、C5等不同分辨率的特征图。以ResNet-50为例输出四个stage的特征通道数分别是256、512、1024、2048空间尺寸依次减半。neck接收backbone的多级输出做融合。FPN的做法是自顶向下上采样再横向相加最终输出5个尺度的特征图P3到P7通道统一成256。head在neck输出的每个尺度特征图上预测每个位置的类别分数和框回归量。这个划分不是mmdetection硬性规定的而是社区约定俗成的抽象。你完全可以在配置里把neck设成None让backbone直接接head很多早期的单阶段检测器就是这么干的。2.3 双阶段检测器多出来的那部分rpn_head和roi_head单阶段检测器只有bbox_head一个头双阶段比如Faster R-CNN则有两个头model dict( typeFasterRCNN, backbonedict(...), neckdict(...), rpn_headdict( typeRPNHead, in_channels256, feat_channels256, anchor_generatordict(...), bbox_coderdict(...), loss_clsdict(...), loss_bboxdict(...)), roi_headdict( typeStandardRoIHead, bbox_roi_extractordict( typeSingleRoIExtractor, roi_layerdict(typeRoIAlign, output_size7, sampling_ratio0), out_channels256, featmap_strides[4, 8, 16, 32]), bbox_headdict( typeShared2FCBBoxHead, in_channels256, fc_out_channels1024, roi_feat_size7, num_classes80, bbox_coderdict(...), loss_clsdict(...), loss_bboxdict(...))))rpn_head负责第一阶段——在特征图上撒anchor判断这里有没有东西输出粗略的候选框proposal。roi_head负责第二阶段——把每个候选框对应的特征抠出来RoIAlign再精细分类和回归。这里有个容易混淆的点roi_head里面又套了一个bbox_head。这个bbox_head和单阶段的bbox_head不是一回事它作用在抠出来的固定尺寸特征比如7×7上而不是整张特征图。名字撞车是mmdetection历史遗留问题读配置时一定要看清它挂在哪个父节点下。3. 注册器机制字符串是怎么变成网络层的3.1 Registry的本质就是一个字典理解了配置结构下一个问题自然是typeResNet这个字符串mmdetection是怎么把它变成真正的ResNet类的答案在mmdet/models/registry.py里核心就几行BACKBONES Registry(backbone) NECKS Registry(neck) ROI_EXTRACTORS Registry(roi_extractor) SHARED_HEADS Registry(shared_head) HEADS Registry(head) LOSSES Registry(loss) DETECTORS Registry(detector)Registry这个类你可以理解成一个带装饰器功能的字典。当你写BACKBONES.register_module() class ResNet(nn.Module): ...这行装饰器做的事就是把ResNet这个字符串作为keyResNet这个类作为value塞进BACKBONES这个字典里。之后配置里写typeResNet框架就去BACKBONES里查查到就实例化。3.2 build_from_cfg配置字典的实例化流程真正干活的是build_from_cfg函数逻辑简化后是这样def build_from_cfg(cfg, registry, default_argsNone): args cfg.copy() obj_type args.pop(type) if isinstance(obj_type, str): obj_cls registry.get(obj_type) return obj_cls(**args)三步走取出type字符串 → 去注册器查类 → 用剩下的参数实例化。就这么简单。所以你在配置里写的每一个键值对最终都会变成对应类__init__的入参。这也是为什么改配置能改模型——你改的其实是构造函数的参数。注意如果配置里写了typeXXX但注册器里没有会直接报KeyError。新手最常见的报错之一就是自定义模块忘了加XXX.register_module()装饰器或者模块没被__init__.py导入导致没注册上。3.3 自定义模块为什么必须挂装饰器我见过太多人写了个自定义backbone文件放对了配置也写了一跑就报XXX is not in the backbone registry。原因几乎都是类定义时忘了加装饰器或者这个文件没有被包的__init__.py导入。注册器是运行时构建的只有被Python实际导入执行的模块它的装饰器才会生效。所以自定义模块的标准姿势是两步一是在类上加BACKBONES.register_module()二是在同目录的__init__.py里from .my_backbone import MyBackbone并把类名加进__all__。少任何一步注册器里就没有这个零件。4. 单阶段检测器的前向传播以RetinaNet为例逐层拆解4.1 forward_train训练时数据怎么流动光看结构还不够得看数据实际怎么流。RetinaNet的forward_train方法大致是def forward_train(self, img, img_metas, gt_bboxes, gt_labels, ...): x self.extract_feat(img) # backbone neck outs self.bbox_head(x) # head 前向 loss_inputs outs (gt_bboxes, gt_labels, img_metas) losses self.bbox_head.loss(*loss_inputs) return lossesextract_feat是基类BaseDetector提供的方法内部就是backbone(img)再neck(backbone_outs)。以RetinaNet为例输入一张800×1200的图backbone输出四个尺度的特征neckFPN融合后输出五个尺度P3到P7尺寸分别是100×150、50×75、25×38、13×19、7×10通道都是256。然后bbox_head(x)对这五个特征图分别做几层卷积输出每个位置的分类logits和框回归量。RetinaNet的head有4层stacked conv每层256通道最后接两个分支一个输出num_anchors × num_classes维的分类分数一个输出num_anchors × 4维的框偏移。4.2 anchor的生成与匹配正负样本是怎么定的head输出的框偏移是相对于anchor的所以必须搞清楚anchor从哪来。AnchorGenerator根据配置里的strides、ratios、scales生成anchor。以stride8、ratios[0.5,1,2]、scales_per_octave3、octave_base_scale4为例每个位置生成9个anchor3种比例×3种尺度基础边长是4×832三个尺度分别是32×2^(0/3)、32×2^(1/3)、32×2^(2/3)。训练时这些anchor要和GT框做匹配。RetinaNet用的是MaxIoUAssigner对每个GT框找出与它IoU最大的anchor作为正样本对每个anchor如果与某个GT的IoU超过阈值比如0.5也算正样本低于0.4算负样本中间的直接忽略。这个忽略机制很关键它避免了让模型去学那些模棱两可的样本。4.3 loss计算Focal Loss为什么能解决正负样本失衡单阶段检测器最大的痛点是正负样本极度失衡——一张图可能只有几个目标但anchor有几万个负样本占了99%以上。如果直接用交叉熵负样本的loss会淹没正样本。Focal Loss的解法是给每个样本乘一个调制因子FL(p_t) -alpha_t * (1 - p_t)^gamma * log(p_t)当gamma2时一个容易分类的负样本p_t接近1的loss会被(1-p_t)^2压到接近0而难分的样本loss基本不变。这样模型就会把注意力集中在难样本上。配置里use_sigmoidTrue表示用sigmoid而非softmax做二分类式的多标签分类这也是RetinaNet的标配。5. 双阶段检测器的两阶段流程RPN和RoIHead如何接力5.1 RPN阶段从特征图到候选框Faster R-CNN的第一阶段是RPN。它的前向逻辑和单阶段head很像——在FPN输出的每个尺度上撒anchor预测每个anchor是前景还是背景以及框的偏移。但RPN不区分类别它只关心是不是目标。RPN的输出经过后处理get_bboxes变成proposal先按前景分数排序取前N个比如2000个做NMS去重再取前M个比如1000个作为最终候选框。这些框是归一化坐标相对图像宽高方便后续处理。5.2 RoIAlign候选框特征是怎么抠出来的第二阶段的核心操作是RoIAlign。给定一个候选框和某一层特征图RoIAlign要做的是把这个框映射到特征图上的对应区域然后把这个区域池化成固定尺寸比如7×7的特征。这里有个细节候选框可能对应多个尺度的特征图SingleRoIExtractor会根据框的面积决定用哪一层。大框用stride大的层P5小框用stride小的层P3这就是所谓的多尺度RoIAlign。配置里的featmap_strides[4,8,16,32]就是告诉它每层特征图相对原图的缩放比例。RoIAlign相比早期的RoI Pooling关键改进是去掉了量化操作。RoI Pooling在把框坐标映射到特征图时会取整导致小目标的特征错位RoIAlign用双线性插值每个采样点都精确计算对小目标检测提升明显。5.3 第二阶段head精细分类与回归抠出来的7×7×256特征经过Shared2FCBBoxHead——两层1024维全连接然后分两个分支一个输出num_classes1维多一个背景类的分类分数一个输出4×num_classes维的框偏移每个类别一套回归参数。训练时第二阶段的正负样本由候选框和GT的IoU决定通常IoU0.5为正0.1~0.5之间忽略0.1为负。loss是分类交叉熵加回归L1/SmoothL1。推理时第二阶段输出每个候选框的类别分数和精修后的框再做一次NMS得到最终检测结果。6. 改模型实战从换head到加自定义模块6.1 换一个head把RetinaHead换成ATSSHead假设你想把RetinaNet的head换成ATSS最省事的做法是直接改配置model dict( typeRetinaNet, backbonedict(...), neckdict(...), bbox_headdict( typeATSSHead, num_classes80, in_channels256, stacked_convs4, feat_channels256, anchor_generatordict( typeAnchorGenerator, ratios[1.0], octave_base_scale8, scales_per_octave1, strides[8, 16, 32, 64, 128]), ...))注意ATSS的anchor配置和RetinaNet不同——它每个位置只生成1个anchorratios[1.0], scales_per_octave1因为ATSS用自适应样本分配替代了固定IoU阈值。改head时一定要同步改anchor_generator否则anchor和head的匹配逻辑会对不上。6.2 加一个自定义backbone注册与配置两步走自定义backbone的完整流程# my_backbone.py import torch.nn as nn from mmdet.models import BACKBONES BACKBONES.register_module() class MyBackbone(nn.Module): def __init__(self, in_channels3, base_channels64): super().__init__() self.stem nn.Conv2d(in_channels, base_channels, 7, 2, 3) # ... 更多层 def forward(self, x): # 返回多级特征 return [feat1, feat2, feat3, feat4]然后在__init__.py里导入配置里写typeMyBackbone。关键约束是forward必须返回一个list或tuple每个元素是一个尺度的特征图顺序从高分辨率到低分辨率。因为neck默认按这个顺序接收。6.3 改配置时最容易忽略的通道数对齐改backbone或neck时最常见的报错是通道数不匹配。比如你把backbone换成输出通道为[64,128,256,512]的轻量网络但neck的in_channels还写着[256,512,1024,2048]实例化时不会报错但前向传播时FPN的横向卷积会因通道对不上而崩。所以改结构时backbone的输出通道、neck的in_channels、neck的out_channels、head的in_channels这四个值必须形成一条对齐的链。我一般会在改完后画一张通道流转图逐个核对。7. 解析模型时的几个高频坑与排查思路7.1 配置文件继承导致的参数覆盖陷阱mmdetection的配置支持_base_继承。比如configs/retinanet/retinanet_r50_fpn_1x.py里可能只有几行大部分参数来自_base_里的数据集和schedule配置。新手改参数时如果改的是base文件会影响所有继承它的配置如果改的是子文件又要确保键路径写对。排查这类问题的办法是在训练脚本里加一行print(cfg.pretty_text)把最终合并后的完整配置打出来。你看到的才是框架真正用的而不是你以为的。7.2 注册器找不到类的三种原因报KeyError: XXX is not in the xxx registry时按这个顺序查类上有没有加XXX.register_module()装饰器类所在的文件有没有被包的__init__.py导入配置里的type字符串和注册时的名字是否完全一致大小写敏感。我踩过最隐蔽的一次是模块导入顺序导致循环导入装饰器没执行到。解决办法是把注册相关的导入放到文件顶部避免在函数内部导入。7.3 前向传播shape对不上的定位方法shape报错时别急着改代码先用一个最小输入跑一遍。比如构造一个torch.randn(1, 3, 320, 320)手动调model.extract_feat(img)打印每一级输出的shape。这样能快速定位是backbone输出不对、neck融合不对、还是head输入不对。我习惯在extract_feat后面加临时print确认backbone输出是4个尺度、neck输出是5个尺度、通道都是256。这三条对了head基本不会出问题。7.4 训练能跑但推理结果异常的常见原因有时候loss正常下降但推理出来的框全是乱的。这种情况八成是test_cfg配错了。比如nms_pre设得太小导致候选框不够score_thr设得太高导致漏检或者max_per_img和nms的阈值不匹配。单阶段和双阶段的test_cfg结构不同改head时记得同步检查。8. 我个人的一点使用体会把mmdetection的模型解析清楚本质上就是搞清楚三件事配置字典怎么描述网络、注册器怎么把描述变成实例、数据怎么在实例之间流动。这三件事想通了你会发现它那套看似繁琐的嵌套字典其实非常优雅——换backbone、换neck、换head、换loss全都是改字符串和参数的事不用动框架代码。我刚开始用的时候总想着去读源码里的每一个类结果越读越乱。后来换了个思路拿一个能跑通的配置从forward_train入口开始一层层print shape把数据流画在纸上。画完两三遍之后整个框架的结构就刻在脑子里了。这个方法比死磕源码高效得多推荐你也试试。最后一个实用建议改任何结构之前先git commit一下当前能跑通的配置。mmdetection的报错有时候很隐晦改崩了想回退却记不清改了哪几行那种感觉相当难受。有个干净的基线折腾起来心里才有底。

相关新闻

Oracle基金交易平台实战:七张表设计+PL/SQL全流程开发

Oracle基金交易平台实战:七张表设计+PL/SQL全流程开发

简介:面向Oracle数据库学习者的项目实战文档,聚焦基金交易平台的数据库设计,适合正在准备项目实训或课程设计的开发人员。文档以招商银行某分行的开放式基金交易系统为业务背景,先梳理基金管理、客户账户管理、交易审核等核心功能…

2026/10/17 23:28:25 阅读更多 →
8086汇编Debug调试实战:从闰年判断看寄存器与标志位

8086汇编Debug调试实战:从闰年判断看寄存器与标志位

简介:北京交通大学汇编与接口课程配套的Debug调试实验文档,以leapYear.exe闰年判断程序为线索,完整呈现汇编语言从源码编译、链接生成可执行文件,到利用Debug工具逐步跟踪运行的实验过程。资料为1个docx格式实验报告,压…

2026/10/17 23:28:25 阅读更多 →
Kafka接入AI大模型:从集群部署到实时消息处理的完整实践

Kafka接入AI大模型:从集群部署到实时消息处理的完整实践

“Kafka已正式接入AI”是我们最近一个内部项目的周报标题。当时写这句话其实就是想表达“我们已经把Kafka消息管道和大模型推理服务打通了”,没想到被领导看中,硬拉成了团队分享。分享完后很多同事问我细节,索性整理成这篇博文。项目本身不算…

2026/10/17 23:28:25 阅读更多 →

最新新闻

从零开发轻量记事本:IndexedDB存储、自动保存与同步实践

从零开发轻量记事本:IndexedDB存储、自动保存与同步实践

记事本这玩意儿,看着简单,做起来全是坑。之前我接了一个内部工具需求,要做一款能随手记录、随时翻查、离线也不慌的轻量记事本,产品代号叫“轻记”。从UI线框到功能实现,前后大概花了三周时间,中间踩了不少…

2026/10/18 0:23:12 阅读更多 →
SysML与UML核心区别:系统工程建模的底层逻辑

SysML与UML核心区别:系统工程建模的底层逻辑

简介:本资源是系统工程领域权威入门与进阶指南《Systems Engineering with SysML/UML》,面向系统工程师、嵌入式/航空航天/汽车/医疗设备领域研发人员及高校相关专业师生,聚焦OMG标准下SysML与UML协同建模方法,解决复杂系统需求追…

2026/10/18 0:23:12 阅读更多 →
Matplotlib三维绘图避坑指南:从空白图到工程级可视化

Matplotlib三维绘图避坑指南:从空白图到工程级可视化

简介:本资源是一份面向Python初学者与数据可视化学习者的matplotlib三维绘图实战指南,聚焦解决“如何用matplotlib快速绘制可复现、可定制的三维曲面图”这一核心问题。内容以两个完整可运行示例为核心:其一基于笛卡尔坐标系,使用…

2026/10/18 0:22:12 阅读更多 →
智谱清华唐杰:LLM Memory最新全景综述——用TaoToken统一Key复现记忆模块评测

智谱清华唐杰:LLM Memory最新全景综述——用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/18 0:21:11 阅读更多 →
跳出代码,彻底看懂 MCP 与 Function Calling 的底层关系:TaoToken 统一 Key 通道下的调用链路拆解

跳出代码,彻底看懂 MCP 与 Function Calling 的底层关系: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/18 0:21:11 阅读更多 →
地理空间坐标系统实战:用TaoToken统一Key打通七参数坐标转换链路

地理空间坐标系统实战:用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/18 0:21:11 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →