news 2026/10/30 7:22:49

Matlab 实现 AES-256:有限域、轮函数与 CBC/CTR/GCM

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Matlab 实现 AES-256:有限域、轮函数与 CBC/CTR/GCM

简介:AES-256加解密代码包面向学习对称密码算法与MATLAB实现的信息安全学生、教师及工程人员,基于MATLAB 2012B环境,围绕256位密钥的AES标准给出可运行、可拆解的实现范例,适合课程实验、算法复现与代码研读。压缩包共16个文件,约448KB,以13个m函数脚本为主体,覆盖密钥扩展、Cipher/InvCipher、SubBytes与InvSubBytes、ShiftRows与InvShiftRows、MixColumns与InvMixColumns、AddRoundKey等模块;另附txt许可说明、PDF参考文档和xlsx数据表,便于核对流程与组织测试输入。已有532人学习,说明其在密码学入门与MATLAB编程练习中具有一定参考价值。代码将轮函数拆分为独立函数,并提供ECB模式与PKCS7填充的加解密调用及核心测试脚本,读者可据此观察每轮状态变化、验证加解密结果,并进一步理解S盒替换、列混淆和轮密钥加的作用。

1. AES-256 在 Matlab 里到底卡在哪:一份加密脚本的三次返工

很多人第一次在 Matlab 里做 AES-256,都是被逼的:仿真数据要落盘、算法课设要交作业、C 端已经上线了、Matlab 这边得能对上同一份密文。AES_256.zip 这类包在圈子里流传很广,里面常见的东西无非是 S 盒表、密钥扩展、轮函数和几个 demo 脚本,能跑,但一换密钥长度、一换分组模式、一碰大文件就开始出问题。真正难的不是算法本身,AES-256 公开了二十多年,规格书就那几页;难的是 Matlab 这个环境:uint8 加法会饱和、状态矩阵是列主序、循环写起来慢得让人怀疑人生。这篇按我自己的返工顺序讲:先把 GF(2^8) 和状态布局钉死,再写轮函数,再上模式,最后收在性能和验收上。适合要在本地闭环做完加解密、又不想引一堆外部依赖的人。

2. 有限域与轮变换:AES-256 的数学骨架怎么落到 Matlab 矩阵上

AES-256 的参数是固定的:分组 128 位、密钥 256 位、Nb=4 个 32 位字的状态、Nk=8 个字的密钥、Nr=14 轮。这三个数字决定了后面所有索引换算,写错一个,密文从第几块开始发散都不一定。这一章不急着写加密函数,先把两件最容易埋雷的事讲清楚:GF(2^8) 上的乘法怎么算得快,以及 16 个字节怎么摆成 Matlab 的矩阵。

2.1 GF(2^8) 乘法查表:为什么 256×256 的表比循环快一个量级

AES 的字节运算全部定义在 GF(2^8) 上,模多项式是 m(x)=x^8+x^4+x^3+x+1,十六进制写 0x11B。加法就是异或,这个 Matlab 的 bitxor 直接给;乘法是多项式相乘再对 m(x) 取模,手写循环的话每次要判 8 次最高位,列混合一轮 4 列 16 个字节,14 轮下来就是几百次分支,纯 Matlab 的 for 循环跑这个,速度会难看到你想砸键盘。

工程上的做法是先建表。注意列混合矩阵的系数只有 1、2、3 三个值,逆列混合只有 9、11、13、14,所以完全不需要 256×256 的全表,只要乘 2 和乘 3 两张 256 长度的小表就够,内存 512 字节。

function [MUL2, MUL3] = aes_mul_tables() % 预计算 GF(2^8) 下乘 2、乘 3 的查表,列混合只用到这两张 MUL2 = zeros(256,1,'uint8'); MUL3 = zeros(256,1,'uint8'); for a = 0:255 x = uint8(a); t = bitshift(x, 1); % x*2,高位直接丢弃 if bitand(x, uint8(0x80)) ~= 0 t = bitxor(t, uint8(0x1B)); % 溢出时对 0x11B 取模,等价异或 0x1B end MUL2(a+1) = t; % 下标 +1:Matlab 从 1 开始 MUL3(a+1) = bitxor(t, x); % 3*a = 2*a xor a end end

逻辑说明:bitshift(x,1)对 uint8 会保持类型并截断到 8 位,正好就是"乘 2 后丢掉 x^8 项";bitand(x,0x80)判断的是 x^7 位是否为 1,为 1 说明乘 2 之后溢出了 x^8,需要减掉 m(x),而在 GF(2^8) 里减等于加等于异或,所以异或 0x1B 即可。参数说明:返回值是 256×1 的 uint8 列向量,索引方式是MUL2(double(a)+1),a 是 0~255 的整数值;千万不要用 uint8 直接当下标,Matlab 会报索引类型错误。

把表建好之后,列混合里每个字节的乘法就退化成一次数组索引。这一步做与不做,在 1 MB 数据上是数量级的差别,不是百分比。

2.2 状态矩阵与列主序:Matlab 的 reshape 为什么天然对齐 AES

AES 标准规定,16 字节的输入按列填入 4×4 状态矩阵,即 state[r][c] = in[r + 4c]。也就是说第 0~3 字节是第一列,第 4~7 字节是第二列。而 Matlab 的数组是列优先存储,reshape(v, 4, 4)恰好就是按列填充:结果的第 1 列装 v 的前 4 个元素,第 2 列装接下来 4 个,完全对上。

block = uint8((0:15)'); % 16x1 输入 state = reshape(block, 4, 4); % state(r+1,c+1) = block(r + 4c + 1) % state = % 0 4 8 12 % 1 5 9 13 % 2 6 10 14 % 3 7 11 15

逻辑说明:这段不是功能代码,是给你对拍用的。写完之后打印一次状态矩阵,如果看到第一行是 0/4/8/12,说明布局对了;如果看到 0/1/2/3 在第一行,说明你按行主序摆了,行移位和列混合的方向都会跟着反。参数说明:reshape的第二个参数固定是 4,第三个是 4,不要写成reshape(block,4,4)',那个转置会把列主序毁掉。

这里有个血泪经验。网上大量 C 实现为了顺手,用的是行主序加转置的写法,state[c][r]之类,逻辑本身没错,你照着抄进 Matlab 会发现第一轮加密能对上,从第二轮开始全错。原因就是 ShiftRows 变成了向右移,而标准要求向左移。这类 bug 的表现很迷惑:密钥扩展是对的、S 盒是对的、单轮单独测也对,拼起来就是不对。所以宁可多花十分钟把布局钉死,也别急着往下写。

2.3 密钥扩展:8 字密钥、14 轮、60 个扩展字的索引换算

AES-256 需要 4×(Nr+1)=60 个 32 位字,也就是 240 字节扩展密钥。前 8 个字直接来自用户密钥,后面 52 个字靠递推。和 AES-128 相比,它多了一个分支:当 i mod 8 == 4 时,也要对字做一次 SubWord,这个分支是 256 位密钥独有的,漏掉它,前面四轮还能对上,第五轮开始整段崩。

function w = key_expansion(key) % key : 32x1 uint8,256 位密钥 % w : 4x60 uint8,每一列是一个 32 位扩展字 Nk = 8; Nr = 14; w = zeros(4, 4*(Nr+1), 'uint8'); w(:, 1:Nk) = reshape(key, 4, Nk); % 前 8 个字直接来自密钥 S = aes_sbox(); rcon = uint8(1); % Rcon[1] = 0x01 for i = Nk : 4*Nr+3 % 0 基下标 i = 8 .. 59 temp = w(:, i); % 取 0 基的 w[i-1],即 Matlab 第 i 列 if mod(i, Nk) == 0 temp = temp([2 3 4 1]); % RotWord:字节左旋一位 temp = S(double(temp)+1); % SubWord,索引形状保持不变 temp(1) = bitxor(temp(1), rcon);% 只异或到首字节 rcon = aes_xtime(rcon); % Rcon 只在 8 的倍数处推进 elseif mod(i, Nk) == 4 temp = S(double(temp)+1); % AES-256 独有分支,别漏 end w(:, i+1) = bitxor(w(:, i-Nk+1), temp); end end function y = aes_xtime(x) % GF(2^8) 上乘 2 y = bitshift(x, 1); if bitand(x, uint8(0x80)) ~= 0 y = bitxor(y, uint8(0x1B)); end end

逻辑说明:循环变量 i 用的是 0 基语义,注释里写清楚了每一处和 Matlab 1 基索引的换算关系。temp = w(:, i)拿到的是 0 基的 w[i-1],w(:, i-Nk+1)拿到的是 w[i-8],这两个偏移是最容易抄错的地方。参数说明:key必须是 32 字节,如果你从文件里读出来是 64 个十六进制字符,要先转成 32 字节再传进来,直接把字符串丢进去会导致 reshape 失败或者得到错误的密钥。返回的 w 是 4×60,第 r 轮的轮密钥是w(:, 4*r+1 : 4*r+4),r 从 0 到 14。

写完之后建议立刻验证一次:把密钥设成全 0,打印w(:, 1:8)和w(:, 9:12),前者应该和输入一致,后者应该能被手算对上。这一步不验证,后面所有调试都是在流沙上盖楼。

3. 加密核心落地:S 盒生成、轮函数与 14 轮迭代的可复现写法

骨架搭好,下面就是往上填肉。这一章的顺序是:先生成 S 盒(别手抄),再写单块加密并用标准测试向量对拍,最后加上填充和文件主循环。每一步都有明确的验收标志,过不了就不往下走,这是我排错效率最高的习惯。

3.1 S 盒不要手抄:用仿射变换程序化生成并与标准表比对

S 盒是 256 个字节,理论上照着标准抄一遍也能用,但手抄 256 个十六进制数,中间错一个字节,你会在几百轮之后才发现,而且发现的时候根本定位不到。正确做法是用数学定义生成:先求 GF(2^8) 上的乘法逆元(0 映射到 0),再做一次仿射变换。

function S = aes_sbox() % 程序化生成 AES S 盒:求逆 + 仿射变换,避免手抄出错 EXP = zeros(1,256,'uint8'); % 生成元 0x03 的幂表 LOG = zeros(1,256,'double'); % 对应的离散对数表 x = uint8(1); for i = 1:255 EXP(i) = x; LOG(double(x)+1) = i - 1; x = aes_xtime(x); % 这里用 0x02 做生成元的步进,配合下面的逆元公式 end S = zeros(1,256,'uint8'); rotl = @(v) bitor(bitshift(v,1), bitshift(bitand(v,uint8(0x80)),-7)); % 循环左移 1 位 for a = 0:255 if a == 0 b = uint8(0); else b = EXP(256 - LOG(a+1)); % a^-1 = g^(255-k),用 256-k 规避下标 0 end s = b; for k = 1:4 b = rotl(b); s = bitxor(s, b); % b ^ rotl1 ^ rotl2 ^ rotl3 ^ rotl4 end S(a+1) = bitxor(s, uint8(0x63)); % 最后异或常数 0x63 end end

逻辑说明:仿射变换的定义是 b'i = b_i ⊕ b(i+4) ⊕ b_(i+5) ⊕ b_(i+6) ⊕ b_(i+7) ⊕ c_i,其中 c = 0x63。把"循环左移 k 位再异或"累加四次,正好覆盖 i+4 到 i+7 这四个错位项,比写成位循环清晰得多。参数说明:rotl里的bitshift(...,-7)是对 uint8 做右移,把最高位搬到最低位,bitor 之后类型仍是 uint8,不会被悄悄提升成 double。

生成完必须做一次自检:S(1) 应该等于 0x63,S(2) 应该等于 0x7C,S(256) 应该等于 0x16。这三个点对了,整张表基本就对了。逆 S 盒不要另外推公式,直接反查:Si(S(double(x)+1)) = uint8(x),一行搞定,还顺便保证了正反一致。

3.2 单块加密函数与标准测试向量对拍

轮函数的四个步骤每个都很短,麻烦的是顺序:SubBytes → ShiftRows → MixColumns → AddRoundKey,循环 13 轮,第 14 轮去掉 MixColumns。这是"逆序"最容易写反的地方。

function ct = aes256_encrypt_block(pt, w, S, MUL2) % pt : 16x1 uint8 明文块 % w : 4x60 uint8 扩展密钥 % ct : 16x1 uint8 密文块 state = reshape(pt, 4, 4); state = bitxor(state, reshape(w(:,1:4), 4, 4)); % 初始轮密钥加 for round = 1:13 state = S(double(state)+1); % SubBytes state(2,:) = circshift(state(2,:), -1); % ShiftRows:第 r 行左移 r state(3,:) = circshift(state(3,:), -2); state(4,:) = circshift(state(4,:), -3); state = mix_columns(state, MUL2); % MixColumns state = bitxor(state, reshape(w(:,4*round+1:4*round+4), 4, 4)); end state = S(double(state)+1); % 最后一轮:无 MixColumns state(2,:) = circshift(state(2,:), -1); state(3,:) = circshift(state(3,:), -2); state(4,:) = circshift(state(4,:), -3); state = bitxor(state, reshape(w(:,57:60), 4, 4)); ct = state(:); % 按列展开回 16x1 end function s = mix_columns(s, MUL2) % 用 t = a0^a1^a2^a3 的技巧,把每列 4 次乘法压到 4 次查表 a0 = s(1,:); a1 = s(2,:); a2 = s(3,:); a3 = s(4,:); t = bitxor(bitxor(a0,a1), bitxor(a2,a3)); s(1,:) = bitxor(a0, bitxor(t, MUL2(double(bitxor(a0,a1))+1))); s(2,:) = bitxor(a1, bitxor(t, MUL2(double(bitxor(a1,a2))+1))); s(3,:) = bitxor(a2, bitxor(t, MUL2(double(bitxor(a2,a3))+1))); s(4,:) = bitxor(a3, bitxor(t, MUL2(double(bitxor(a3,a0))+1))); end

逻辑说明:circshift(row,-1)把 [a b c d] 变成 [b c d a],就是标准的左移;第 3 行移 2 位用 -2,第 4 行移 3 位用 -3,行号与移位量严格对应。mix_columns里那个 t 是经典优化:每列的四个输出都可以写成"原字节 ⊕ t ⊕ 2·(相邻两字节异或)",这样每列只需要 4 次乘 2 查表,而不是 16 次。参数说明:S和MUL2都建议在外面建一次传进来,不要写在函数体内,否则每次调用都重建 256 长度的表,性能直接腰斩。

验收代码用标准测试向量,一次定生死:

hex2bytes = @(s) uint8(hex2dec(reshape(s, 2, []).')); key = hex2bytes('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'); pt = hex2bytes('00112233445566778899aabbccddeeff'); want = hex2bytes('8ea2b7ca516745bfeafc49904b496089'); S = aes_sbox(); MUL2 = aes_mul_tables(); w = key_expansion(key, S); ct = aes256_encrypt_block(pt, w, S, MUL2); assert(isequal(ct, want), 'AES-256 单块不匹配:%s', sprintf('%02x', ct)); fprintf('AES-256 单块 OK\n');

逻辑说明:这是 FIPS-197 附录 C.3 给出的 AES-256 官方向量,密钥是 0x00~0x1F 递增,明文是 0x00 0x11 0x22……0xFF 循环,密文固定为 8ea2b7ca516745bfeafc49904b496089。参数说明:hex2bytes用 reshape 把字符串切成两列再转置,hex2dec按行解析,返回列向量;如果这里报错,八成是字符串长度不是偶数。这条断言过了,说明 S 盒、密钥扩展、轮函数顺序、状态布局四件事同时正确,比逐个模块单测省事得多。

3.3 填充、分块与整文件加密的主循环

单块能过,文件加密就只剩组帧问题。AES 是分组密码,明文长度不是 16 的整数倍时必须填充,PKCS#7 是最通用的规则:缺 n 个字节就补 n 个值为 n 的字节,注意当明文正好是 16 的整数倍时要补满一整块 16 个 0x10,否则解密端没法判断尾部。

function ct = cbc_encrypt_bytes(pt, key, iv, S, MUL2) % pt : Nx1 uint8,任意长度明文 % iv : 16x1 uint8,初始化向量 w = key_expansion(key, S); pad = 16 - mod(numel(pt), 16); % 1..16,整除时补 16 pt = [pt; repmat(uint8(pad), pad, 1)]; n = numel(pt)/16; ct = zeros(size(pt), 'uint8'); prev = iv; for i = 1:n blk = bitxor(pt((i-1)*16+(1:16)), prev); prev = aes256_encrypt_block(blk, w, S, MUL2); ct((i-1)*16+(1:16)) = prev; end end

逻辑说明:mod(numel(pt),16)为 0 时pad算出来是 16,正好满足"补满一整块"的要求,不需要额外判断分支。CBC 的链式依赖体现在prev上:加密时用上一块密文异或明文,所以加密必须串行;解密时反过来,可以先解出所有块再统一异或,这是并行优化的入口。参数说明:iv必须 16 字节且每次加密都换,同一密钥下重复用 iv 会让相同前缀的明文产生相同密文,这是实际部署里最常见的低级错误。

4. 解密与分组模式:CBC、CTR、GCM 在 Matlab 里的取舍

写完加密,很多人默认解密就是"把顺序倒过来",真写的时候会发现逆列混合的系数不一样,逆 S 盒要另外准备,逆行移位方向相反,稍不留神就跟加密端对不上。这一章讲清解密怎么写,以及四种常见模式在 Matlab 里到底该选哪个。

4.1 逆轮变换:为什么我更推荐等价逆密码

最直观的写法是"逆序逆密码":把加密的每一步换成逆操作,顺序倒过来走,即 InvShiftRows → InvSubBytes → AddRoundKey → InvMixColumns。这种写法可读性最好,调试也方便,缺点是没法复用加密的循环骨架,两套代码要维护两份。

工程上更常用的是"等价逆密码":把 InvMixColumns 提到 AddRoundKey 之前,利用线性变换和异或可交换的性质,轮结构变成 AddRoundKey → InvMixColumns → InvShiftRows → InvSubBytes,和加密的轮结构在形式上完全一致,只是每个位置换成逆。代价是要对轮密钥预处理一次——除首尾两轮外,其余轮密钥都要先过一遍 InvMixColumns。

逆列混合的系数是 0x09、0x0b、0x0d、0x0e,用 xtime 迭代生成查表非常干净:

function T = aes_inv_mix_tables() % 生成乘 9/11/13/14 的查表,返回 256x4 T = zeros(256,4,'uint8'); for a = 0:255 x = uint8(a); x2 = aes_xtime(x); x4 = aes_xtime(x2); x8 = aes_xtime(x4); T(a+1,:) = [bitxor(x8,x), ... % 9 = 8+1 bitxor(bitxor(x8,x2),x), ... % 11 = 8+2+1 bitxor(bitxor(x8,x4),x), ... % 13 = 8+4+1 bitxor(bitxor(x8,x4),x2)]; % 14 = 8+4+2 end end

逻辑说明:把每个系数拆成 2 的幂次之和,用三次 xtime 得到 x2、x4、x8,再组合异或,避免了在循环里写多项式乘法。参数说明:T的第 1、2、3、4 列分别对应乘 9、11、13、14,调用时按T(double(a)+1, k)索引,k 用 1~4 而不是 9/11/13/14。

我的建议是:如果这套代码只用来加密存盘、解密交给现成工具,那就别自己写解密,直接对拍;如果确实要在 Matlab 里闭环,先写等价逆密码,因为它的轮结构和加密镜像,对着加密函数改比从头写快。另外提一句,很多实现里解密结果尾部多出几个字节或者少几个字节,基本都是填充去除那一步没做,不是解密本身错。

4.2 CBC 与 CTR:串行依赖和可并行的那条分界线

CBC 和 CTR 的差别,在 Matlab 里体现得比在 C 里更明显,因为循环开销占比大得多。

| 模式 | 需要填充 | 加密可并行 | 随机读某一块 | 完整性校验 | Matlab 里单块开销 | | ECB | 是 | 是 | 是 | 无 | 1 次分组加密 | | CBC | 是 | 否(解密可) | 否 | 无 | 1 次分组加密 + 1 次异或 | | CTR | 否 | 是 | 是 | 无 | 1 次分组加密 + 计数器拼装 | | GCM | 否 | 是 | 是 | 有 | 1 次分组加密 + GHASH |

CTR 的实现要点是计数器块:16 字节里前 8 字节放 nonce,后 8 字节放大端计数值,每加密一块加一。Matlab 里直接对 uint8 做加一会饱和(255+1=255),必须转成 double 累加再转回来,这个坑第四章会细讲。

function out = ctr_crypt(data, key, nonce, S, MUL2) % data : Nx1 uint8;nonce : 8x1 uint8 w = key_expansion(key, S); n = ceil(numel(data)/16); data(end+1 : n*16) = 0; % CTR 是流式,尾部补零不写出 out = zeros(n*16, 1, 'uint8'); for i = 0:n-1 ctr = [nonce; uint8(typecast(uint64(i), 'uint8'))]; % 大端计数器 ks = aes256_encrypt_block(ctr, w, S, MUL2); % 只加密,不解密 out(i*16+(1:16)) = bitxor(data(i*16+(1:16)), ks); end out = out(1:numel(data)); end

逻辑说明:CTR 的核心是"加密和解密是同一个操作",都用密钥流异或,所以只需要一个加密函数,不需要逆 S 盒和逆列混合,这是它在嵌入式场景里省代码的关键。typecast(uint64(i),'uint8')在小端机器上返回的是小端序,如果后端要和 C 实现对接,这里要手工翻成flip。参数说明:nonce必须每次加密都换,同一密钥下 nonce 重用等于密钥流重用,两个密文一异或明文就出来了,这是 CTR 的致命禁区。

CBC 适合小文件、一次性写入的场景,因为串行链式没法并行,Matlab 里一个 16 字节一个 for 循环跑 10 MB 要等很久。CTR 适合大文件和随机读,代价是必须严格管好 nonce。

4.3 GCM 认证标签:Matlab 里手写 GHASH 的边界

GCM 在 CTR 的基础上加了一个 GF(2^128) 上的 GHASH,输出 16 字节认证标签。它的价值在于"加密 + 完整性"一次做完,解密时先验证标签再返回明文,被篡改的数据直接拒绝,

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/30 7:22:39

Apriori算法在超市购物篮分析中的应用与实践

1. 项目背景与核心目标超市购物篮分析是零售行业最经典的数据挖掘应用场景之一。想象一下这样的场景:当你在超市购买啤酒时,收银台旁边的货架上恰好摆放着薯片和花生——这不是巧合,而是基于海量购物数据得出的科学决策。这个毕业设计项目正是…

作者头像 李华
网站建设 2026/10/30 7:21:58

基于YOLO的玉米虫害智能检测系统开发实践

1. 项目概述:当农业遇上AI去年夏天在河北某玉米种植基地调研时,发现农户们仍在用最原始的方法检查虫害——每天清晨拿着放大镜一片片叶子翻找。这种低效的人工检测方式,往往导致发现虫害时已错过最佳防治期。这正是我们开发这套基于YOLO系列算…

作者头像 李华
网站建设 2026/10/30 7:21:55

Transformer模型在自动驾驶中的应用与优化

1. Transformer模型基础解析Transformer架构最初由Google团队在2017年提出,其核心创新在于完全摒弃了传统的循环神经网络(RNN)和卷积神经网络(CNN)结构,转而采用自注意力机制(self-attention)来处理序列数据。这种架构在机器翻译任务中展现出显著优势&am…

作者头像 李华
网站建设 2026/10/30 7:20:11

Objective-C UI开发核心技术与现代应用实践

1. 为什么现在还要学Objective-C的UI开发? 作为一个从2010年就开始接触iOS开发的老程序员,我经常被问到这个问题。虽然Swift已经成为苹果生态的主流语言,但现实情况是: 超过40%的存量iOS应用仍在使用Objective-C(根据…

作者头像 李华
网站建设 2026/10/30 7:17:31

YOLO实战:10个计算机视觉项目入门指南

1. 项目概述:计算机视觉实战入门指南计算机视觉作为人工智能领域最活跃的分支之一,正在深刻改变我们与机器交互的方式。从手机相册的自动分类到工厂的质量检测系统,这项技术已经渗透到日常生活的方方面面。最近在给团队新人做技术培训时&…

作者头像 李华
网站建设 2026/10/30 7:15:49

基于YOLOv11的轻量级无人机检测技术解析

1. 项目背景与核心挑战在无人机技术快速普及的今天,反无人机检测已成为公共安全领域的关键课题。传统基于雷达或无线电侦测的方案存在设备笨重、响应延迟高、易受干扰等问题。我们团队基于改进版YOLOv11开发的轻量级检测方法,在保证精度的同时将模型体积…

作者头像 李华