MATLAB xcorr 的 C 语言实现:直接法与 FFT 加速及归一化选项
简介这份资源面向信号处理学习者与嵌入式开发人员提供MATLAB中xcorr函数在C语言环境下的完整实现方案解决跨平台移植与高性能计算场景下互相关计算的需求。包内共2个文件包含1个c源文件与1个h头文件压缩包约2KBc文件承载互相关核心计算逻辑h文件提供函数声明与结构体定义便于直接集成到现有工程。资源围绕数据输入、序列长度计算、内存分配、嵌套循环逐点乘积求和、偏置与无偏及交叉互相关的公式调整、结果存储与输出等关键环节展开读者可据此理解互相关在噪声检测、信号同步与滤波器设计中的应用思路。目前已有3005人学习下载适合希望提升C语言与MATLAB代码转换能力、需要将算法落地到资源受限或高性能平台的开发者参考。1. 从 MATLAB 的 xcorr 到 C 语言一次把互相关算法落到嵌入式工程里做过信号处理的人对 MATLAB 里的xcorr都不陌生——两行代码就能算出序列的互相关画出来的峰值一目了然。但真正把算法搬到 C 语言环境、尤其是资源受限的嵌入式平台时很多人会卡在几个地方结果对不上 MATLAB、边界处理搞不清楚、biased和unbiased到底差在哪、FFT 加速版本怎么保证精度。这份资源就是围绕「MATLAB xcorr 函数的 C 语言实现」展开的覆盖了直接法时域卷积和 FFT 快速法两条路线附带完整的可编译源码和与 MATLAB 输出逐点比对的验证脚本。适合正在做信号同步、时延估计、雷达脉冲压缩、音频对齐这类工作的工程师也适合刚接触算法移植、想把 MATLAB 原型落到 C 代码里的同学。下面我按自己拆包复现的顺序把关键实现和踩过的坑一条条讲清楚。2. 互相关的数学定义与 C 语言直接实现2.1 xcorr 到底在算什么MATLAB 的xcorr(x, y)计算的是两个离散序列的互相关$$R_{xy}(m) \sum_{n} x(n) \cdot y(n m)$$当x和y长度分别为N和M时输出长度为N M - 1滞后索引m从-(M-1)到N-1。如果x y就是自相关。MATLAB 默认不做归一化返回的是原始累加值。理解这个公式的关键在于互相关本质上就是「翻转 卷积」。把y翻转后与x做卷积得到的就是互相关。这个等价关系决定了 C 语言实现有两条路——直接按定义双重循环算或者借助卷积/FFT 来加速。2.2 直接法的 C 实现直接法最直观按定义展开双重循环。下面是我整理后的核心代码#include stdio.h #include stdlib.h #include math.h /* * xcorr_direct: 直接法计算互相关 * x, y : 输入序列 * nx, ny : 序列长度 * r : 输出互相关序列长度 nx ny - 1 * 索引 i 对应滞后 lag i - (ny - 1) */ void xcorr_direct(const double *x, int nx, const double *y, int ny, double *r) { int nout nx ny - 1; int i, k, lag; for (i 0; i nout; i) { r[i] 0.0; lag i - (ny - 1); /* 当前滞后量 */ for (k 0; k nx; k) { int j k - lag; /* 对应 y 的下标 */ if (j 0 j ny) { r[i] x[k] * y[j]; } } } }逻辑说明外层循环遍历输出序列的每个滞后位置内层循环遍历x的所有样本通过j k - lag找到对应的y下标越界则跳过。这样写的好处是不需要真的翻转数组逻辑清晰适合初学者对照 MATLAB 结果验证。参数说明x和y是输入序列指针nx和ny是长度r是调用者预分配的输出缓冲区长度必须是nx ny - 1。注意输出索引i与滞后lag的映射关系——i 0对应最大负滞后-(ny-1)i nout-1对应最大正滞后nx-1。这个映射如果搞反了画出来的图就是左右镜像的。2.3 与 MATLAB 结果对齐的验证方法写完直接法后第一件事是拿 MATLAB 的输出做逐点比对。我一般会在 MATLAB 里生成一组测试数据导出成文本再用 C 程序读入计算最后用 Python 或 MATLAB 画差值图。% MATLAB 侧生成测试数据并导出 x randn(1, 8); y randn(1, 5); r_matlab xcorr(x, y); dlmwrite(x.txt, x, precision, %.15f); dlmwrite(y.txt, y, precision, %.15f); dlmwrite(r_ref.txt, r_matlab, precision, %.15f);/* C 侧读取数据、计算、输出比对 */ /* 假设已实现文件读取函数 read_txt */ int main(void) { double x[8], y[5], r[12]; read_txt(x.txt, x, 8); read_txt(y.txt, y, 5); xcorr_direct(x, 8, y, 5, r); for (int i 0; i 12; i) { printf(lag%2d C%.12f\n, i - 4, r[i]); } return 0; }比对时重点看三个位置最大正滞后处、最大负滞后处、以及零滞后附近。如果只有边缘几个点对不上大概率是边界条件写错了如果整体偏移一个位置那就是索引映射的问题。常见做法是设一个容差1e-10逐点做差超过容差就打印出来定位。3. 归一化选项biased、unbiased 与 coeff 的 C 语言落地3.1 三种归一化的区别MATLAB 的xcorr提供了biased、unbiased、coeff等选项很多人直接默认不传但一旦传了参数C 实现就必须跟着改。选项归一化因子适用场景biased1/NN 为序列长度估计随机信号的统计特性unbiased1/(N -lagcoeff1/sqrt(sum(x²)·sum(y²))归一化到 [-1, 1]看相似度none默认1原始累加值biased和unbiased的核心差异在于当滞后增大时参与累加的样本对数量减少biased不管这个变化统一除以总长度导致大滞后处估计偏小unbiased则除以实际参与累加的样本数保证期望无偏但方差会变大。3.2 在 C 代码中加入归一化在直接法的基础上加归一化并不复杂关键是归一化因子要随滞后变化/* * xcorr_normalized: 带归一化选项的互相关 * mode: 0none, 1biased, 2unbiased, 3coeff */ void xcorr_normalized(const double *x, int nx, const double *y, int ny, double *r, int mode) { int nout nx ny - 1; double ex 0.0, ey 0.0; /* 预计算能量用于 coeff 模式 */ for (int i 0; i nx; i) ex x[i] * x[i]; for (int i 0; i ny; i) ey y[i] * y[i]; for (int i 0; i nout; i) { int lag i - (ny - 1); double sum 0.0; int count 0; for (int k 0; k nx; k) { int j k - lag; if (j 0 j ny) { sum x[k] * y[j]; count; } } switch (mode) { case 1: /* biased */ r[i] sum / nx; break; case 2: /* unbiased */ r[i] (count 0) ? sum / count : 0.0; break; case 3: /* coeff */ r[i] sum / sqrt(ex * ey); break; default: r[i] sum; break; } } }逻辑说明count变量记录当前滞后下实际参与累加的样本对数unbiased模式直接除以它。coeff模式的归一化因子与滞后无关只取决于两个序列的总能量所以可以预先算好。参数说明mode用整数枚举代替字符串方便在嵌入式环境里调用。注意unbiased模式下当count 0时会出现除零虽然理论上不会发生因为输出范围保证了至少有一对样本但保险起见还是加了判断。3.3 归一化选择的实际影响我做过一组对比实验两个长度分别为 64 和 32 的随机序列分别用三种模式计算。biased模式下滞后绝对值超过 20 之后互相关值明显被压低unbiased模式下尾部会出现剧烈抖动因为参与累加的样本数太少方差急剧增大coeff模式则始终保持在 [-1, 1] 区间内适合做相似度判决。提示如果你的应用是做时延估计建议用none或biased峰值位置不受归一化影响如果是做信号检测或相似度打分coeff更合适。4. FFT 加速从 O(N²) 到 O(N log N) 的 C 实现4.1 为什么要用 FFT直接法的计算复杂度是 O(N·M)当序列长度上千甚至上万时耗时急剧上升。互相关等价于卷积而卷积可以用 FFT 加速到 O(N log N)。具体做法是对两个序列分别做 FFT其中一个取共轭相乘后再做 IFFT。数学表达为$$R_{xy} \text{IFFT}\left(\text{FFT}(x) \cdot \overline{\text{FFT}(y)}\right)$$注意这里x和y需要补零到相同长度L ≥ nx ny - 1通常取 2 的幂次方便 FFT 计算。4.2 基于 FFT 的 C 实现框架下面给出一个不依赖外部库的简化实现框架FFT 部分用经典的 Cooley-Tukey 基 2 算法#include complex.h #include math.h #define PI 3.14159265358979323846 /* 基 2 FFTn 必须是 2 的幂 */ void fft(double complex *a, int n, int inverse) { /* 位反转排序 */ for (int i 1, j 0; i n; i) { int bit n 1; for (; j bit; bit 1) j ^ bit; j ^ bit; if (i j) { double complex tmp a[i]; a[i] a[j]; a[j] tmp; } } /* 蝶形运算 */ for (int len 2; len n; len 1) { double ang 2 * PI / len * (inverse ? 1 : -1); double complex wlen cos(ang) I * sin(ang); for (int i 0; i n; i len) { double complex w 1.0; for (int j 0; j len / 2; j) { double complex u a[i j]; double complex v a[i j len / 2] * w; a[i j] u v; a[i j len / 2] u - v; w * wlen; } } } if (inverse) { for (int i 0; i n; i) a[i] / n; } } /* * xcorr_fft: 基于 FFT 的互相关 * 输出 r 长度为 nfft有效数据在前 nxny-1 个 * 注意结果需要做循环移位把零滞后移到中心 */ void xcorr_fft(const double *x, int nx, const double *y, int ny, double complex *r, int nfft) { double complex *X calloc(nfft, sizeof(double complex)); double complex *Y calloc(nfft, sizeof(double complex)); for (int i 0; i nx; i) X[i] x[i]; for (int i 0; i ny; i) Y[i] y[i]; fft(X, nfft, 0); fft(Y, nfft, 0); /* 频域相乘Y 取共轭 */ for (int i 0; i nfft; i) { r[i] X[i] * conj(Y[i]); } fft(r, nfft, 1); /* IFFT */ free(X); free(Y); }逻辑说明先把x和y补零到nfft分别做正向 FFT然后在频域把X与Y的共轭逐点相乘最后做逆 FFT 得到互相关。注意 IFFT 结果的前nx ny - 1个点是有效数据但顺序是循环移位的——零滞后不在中心需要额外做一次移位操作才能和 MATLAB 的输出对齐。参数说明nfft必须是不小于nx ny - 1的 2 的幂。r是输出缓冲区长度至少为nfft。inverse标志控制正变换和逆变换逆变换时多了一步除以n的操作。4.3 循环移位对齐 MATLAB 输出FFT 法算出来的结果零滞后在索引 0 处正滞后在索引 1 到nx-1负滞后在索引nfft-ny1到nfft-1。而 MATLAB 的输出零滞后在索引ny-1处。所以需要做一次循环移位/* * 将 FFT 互相关结果循环移位使其与 MATLAB xcorr 输出对齐 * src: FFT 原始输出长度 nfft * dst: 移位后输出长度 nx ny - 1 */ void align_xcorr(const double complex *src, int nfft, double *dst, int nx, int ny) { int nout nx ny - 1; int offset ny - 1; /* MATLAB 零滞后位置 */ for (int i 0; i nout; i) { int src_idx (i - offset nfft) % nfft; dst[i] creal(src[src_idx]); } }逻辑说明目标索引i对应的滞后是i - offset在 FFT 原始输出中滞后lag对应的索引是lag 0 ? lag : nfft lag。把这两个关系合起来就是上面的取模运算。参数说明offset固定为ny - 1这是由 MATLAB 的输出约定决定的。如果你的参考实现不是 MATLAB需要根据实际约定调整。4.4 精度对比与选择建议FFT 法虽然快但引入了浮点舍入误差。对于长度 1024 的序列直接法和 FFT 法的最大相对误差通常在1e-12量级完全可以接受。但如果序列长度超过 10 万误差会累积到1e-8左右对高精度应用需要留意。选择建议序列长度小于 256 时直接法反而更快没有 FFT 的额外开销256 到 4096 之间两者差距不大超过 4096FFT 法优势明显。我一般会设一个阈值运行时根据长度自动切换。5. 避坑与排查那些让我熬夜的边界问题5.1 输出长度和索引映射搞反现象C 程序算出来的互相关曲线和 MATLAB 完全左右镜像。 原因输出索引i与滞后lag的映射写反了把lag i - (ny-1)写成了lag i - (nx-1)。 解决记住 MATLAB 的输出长度是nx ny - 1零滞后在索引ny - 1处。如果nx ! ny用错长度就会偏移。建议在代码里加一行断言assert(nout nx ny - 1)。5.2 unbiased 模式下的除零现象程序在某些滞后位置输出NaN或inf。 原因unbiased模式除以count当count 0时触发除零。虽然理论上输出范围保证了至少有一对样本但如果索引映射写错就可能出现count 0。 解决加count 0的判断或者在调试阶段打印每个滞后的count值确认映射正确。5.3 FFT 补零长度不够现象FFT 法算出来的结果尾部出现混叠和直接法对不上。 原因nfft小于nx ny - 1导致循环卷积混入了线性卷积的结果。 解决nfft必须取不小于nx ny - 1的最小 2 的幂。比如nx 100ny 50nx ny - 1 149nfft应该取 256 而不是 128。5.4 数据类型精度不够现象用float代替double后长序列的互相关结果偏差明显。 原因float只有约 7 位有效数字累加上千项后舍入误差迅速累积。 解决中间累加变量用double输入输出可以用float。如果平台支持考虑用 Kahan 求和补偿。5.5 MATLAB 版本差异导致的输出不一致现象同样的代码在某个 MATLAB 版本上对得上换一个版本就对不上。 原因不同版本的xcorr在边界处理和归一化细节上可能有微调。 解决以你实际使用的 MATLAB 版本的文档为准导出参考数据时注明版本号。我一般会在测试脚本里加一行ver(signal)打印工具箱版本。6. 进阶技巧用 C 代码复现 xcorr 的完整验证流程把上面所有片段串起来我通常会在工程里建一个test_xcorr.c做三件事生成测试数据、调用不同实现、输出比对报告。下面是一个可复用的验证模板#include stdio.h #include stdlib.h #include math.h #include assert.h /* 声明各实现函数 */ void xcorr_direct(const double *x, int nx, const double *y, int ny, double *r); void xcorr_normalized(const double *x, int nx, const double *y, int ny, double *r, int mode); void xcorr_fft(const double *x, int nx, const double *y, int ny, double complex *r, int nfft); void align_xcorr(const double complex *src, int nfft, double *dst, int nx, int ny); int main(void) { int nx 64, ny 32; int nout nx ny - 1; int nfft 128; /* 95, 取 2 的幂 */ double *x malloc(nx * sizeof(double)); double *y malloc(ny * sizeof(double)); double *r_direct malloc(nout * sizeof(double)); double *r_fft malloc(nout * sizeof(double)); double complex *r_fft_raw malloc(nfft * sizeof(double complex)); /* 用固定种子生成可复现的测试数据 */ srand(42); for (int i 0; i nx; i) x[i] (rand() / (double)RAND_MAX) * 2 - 1; for (int i 0; i ny; i) y[i] (rand() / (double)RAND_MAX) * 2 - 1; /* 直接法 */ xcorr_direct(x, nx, y, ny, r_direct); /* FFT 法 */ xcorr_fft(x, nx, y, ny, r_fft_raw, nfft); align_xcorr(r_fft_raw, nfft, r_fft, nx, ny); /* 逐点比对 */ double max_err 0.0; for (int i 0; i nout; i) { double err fabs(r_direct[i] - r_fft[i]); if (err max_err) max_err err; } printf(max abs error %.3e\n, max_err); assert(max_err 1e-10); /* 输出前 5 个点供人工核对 */ for (int i 0; i 5; i) { printf(lag%3d direct%.10f fft%.10f\n, i - (ny - 1), r_direct[i], r_fft[i]); } free(x); free(y); free(r_direct); free(r_fft); free(r_fft_raw); return 0; }这个模板的价值在于固定随机种子保证每次运行数据一致直接法和 FFT 法互为参照assert卡住精度门槛。我一般会把max_err的阈值根据序列长度动态调整——长度 128 时设1e-12长度 4096 时放宽到1e-9。还有一个实用技巧把 MATLAB 导出的参考数据存成二进制文件而不是文本读取更快精度也不丢。MATLAB 侧用fwrite(fid, r, double)C 侧用fread直接读省去文本解析的麻烦。从那以后我每次移植xcorr到新平台都强制走一遍「MATLAB 导出参考数据 → C 直接法验证 → C FFT 法验证 → 逐点比对」这个流程不跳过任何一步。看起来多花半小时但省下的调试时间远不止这些。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

柯西分布量子粒子群优化CQPSO在LTE基站选址覆盖优化中的应用

柯西分布量子粒子群优化CQPSO在LTE基站选址覆盖优化中的应用

1. 从现场问题说起:基站覆盖率为什么不是一个“多建站”就能解决的问题我在做LTE网络规划优化的时候,最常听到的一句话就是“覆盖不行就加站”。这个说法听起来简单,但实际做起来完全不是这么回事。某片区基站数量并不算少,可是因…

2026/10/16 4:06:13 阅读更多 →
Spring Boot 整合 Elasticsearch 7 实战指南:从版本匹配到复杂查询

Spring Boot 整合 Elasticsearch 7 实战指南:从版本匹配到复杂查询

这次手头项目里有个检索模块,数据量不算大,MySQL里几百万条商品记录,但客户要求按品牌、分类、价格区间做实时过滤,还要支持关键字分词搜索。用MySQL硬扛实在力不从心,最后决定把Elasticsearch 7 引进来。因为整体技术…

2026/10/16 4:06:13 阅读更多 →
systemd 介绍

systemd 介绍

systemd 是一个 Linux 系统基础组件的集合,提供了一个系统和服务管理器,运行为 PID 1 并负责启动其它程序。功能包括:支持并行化任务;同时采用 socket 式与 D-Bus 总线式激活服务;按需启动守护进程 (daemon)&#xff1…

2026/10/16 4:06:13 阅读更多 →

最新新闻

Python控制硬件:Arduino与树莓派实战对比与协同架构

Python控制硬件:Arduino与树莓派实战对比与协同架构

聊到用Python控制硬件,大部分教程会把Arduino和树莓派放在同一个标题下讲,好像这俩就是同一个东西的两种形态。等我把两种方案都跑进真实项目里,才发现开发体验完全不一样:Arduino这条路,核心是和串口协议斗智斗勇&…

2026/10/16 4:48:25 阅读更多 →
eSIM开户安全基石:二要素认证的技术拆解与工程实践

eSIM开户安全基石:二要素认证的技术拆解与工程实践

eSIM这个概念聊了很多年,真正大规模落地也就是近几年的事。我最早接触eSIM开户相关的项目,是在给某运营商做线上开户支撑系统的时候。那时候团队讨论最多的还是Profile怎么下发、兼容性怎么处理,等到线上开户量真正涨起来,大家才猛…

2026/10/16 4:48:25 阅读更多 →
eSIM开户的二要素认证:原理、落地与避坑指南

eSIM开户的二要素认证:原理、落地与避坑指南

eSIM开户已经不是什么新鲜事,但很多人不知道,真正决定开户能不能顺利完成的,不是手机型号,也不是网络条件,而是二要素认证。我在处理线上开户反馈时,经常遇到用户卡在“身份核验”这一步,要么证…

2026/10/16 4:48:25 阅读更多 →
KV Cache 显存优化实战:长上下文推理性能瓶颈与调优策略

KV Cache 显存优化实战:长上下文推理性能瓶颈与调优策略

1. 从一次对话卡顿说起:KV Cache 到底在解决什么问题如果你用过任何基于 Transformer 架构的对话模型,大概率遇到过这样一种体验:刚开始聊的时候,回复速度飞快,字是一个一个往外蹦的;聊到几十轮之后&#x…

2026/10/16 4:48:25 阅读更多 →
JavaScript数组reduce实战:核心原理、业务场景与边界问题

JavaScript数组reduce实战:核心原理、业务场景与边界问题

提起数组的reduce方法,大多数前端开发者的状态是:面试前背过“累加器”“归并”这些概念,真到项目里却很少主动用。我观察过不少团队的代码评审,reduce常常被两派人争论:一派觉得它晦涩难懂,看到就想改成fo…

2026/10/16 4:48:25 阅读更多 →
光储充换电站分时电价双层优化模型及Matlab实现

光储充换电站分时电价双层优化模型及Matlab实现

光储充换电站和分时电价互动这两件事,放在一起研究的论文和代码我见过不少,但真正能把“用户充电负荷”这个变量建模得当、又能在Matlab里跑通寻优的,确实不算多。这个标题对应的方向,简单说就是:站在运营商的视角&…

2026/10/16 4:47:24 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* 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 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 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/15 0:14:36 阅读更多 →
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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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/15 9:49:14 阅读更多 →