先说说我为什么盯上这个方向。做图像修复实验的同学应该都有过这种经历TVTotal Variation全变分修复模型效果确实能打边缘保持是它祖传的看家本领但那个正则化参数λ一旦靠手试整个实验就很折磨。调小了噪声压不下去调大了图像糊成一团一张图试了20多组参数才勉强发朋友圈。后来接触了哈里斯鹰算法Harris Hawks OptimizationHHO发现把参数寻优这件事扔给鹰群去搜比人肉网格搜索靠谱得多。这篇东西不是纯粹的论文复现而是一个能直接跑通的HHO优化TV图像修复的Matlab流程附带我实验过程中踩出来的坑和改细节的心得。适合正在做图像修复、也愿意尝试元启发式算法做超参寻优的同学参考。1. TV修复的地基与大坑不搞懂这些HHO也救不了你1.1 TV修复到底在解一个什么问题图像修复Image Inpainting本质上是求解一个病态逆问题已知退化观测f希望恢复出干净图像u。TV模型把解约束在一个“分块光滑、局部有界变差”的函数空间里对应的能量泛函长这样E(u) ∫Ω |∇u| dΩ (λ/2) ‖ H u - f ‖²第一项是全变分正则项衡量图像梯度的总幅度它允许强边缘存在同时抑制细小抖动第二项是保真项要求修复结果不能离观测太远。H是退化算子当成掩码矩阵或模糊算子都行。求这个泛函极小值常用Chambolle投影、梯度下降或split Bregman。设置好迭代次数、正则化参数λ就能得到一张还算干净的修复图。问题就出在“设置好”这三个字上。λ小了保真项压不住噪声λ大了正则项会把原本清晰的边缘也磨掉split Bregman里的惩罚参数μ也影响收敛速度和解的质量。不同图像的高斯噪声方差、不同掩码密度最优参数完全不一样。某一次实验我对着同一张lena图换了三种噪声强度网格搜索出来的最优λ从0.03一路变到0.15跨度大到根本没有一个“通用经验值”可以拍脑袋定下来。1.2 为什么手动调参是反人类的手动调参的路径通常是从λ0.01开始按倍率递增跑完一组图算PSNR再缩小区间加密网格。这种方法的致命伤不在效果而在时间成本。一张256×256的灰度图split Bregman迭代30次大约0.5秒网格里塞20组参数就是10秒看着不多但目标图像换成512×512甚至一批测试集30张图整个调参过程就是小时起步了。而且网格搜索有个隐藏问题最优区间内的PSNR曲面往往不够陡相邻几个参数值之间的PSNR差距只有零点几dB手动选参时很容易被取整误差带偏选到一个“看着还行但根本不在峰值附近”的参数。元启发式算法擅长解决的恰好就是这类连续、非凸、计算代价高的参数搜索问题HHO就是干这个活的。2. 哈里斯鹰算法HHO的捕猎数学四个姿势与能量模型2.1 探索阶段鹰群还没锁定猎物的走位HHO是2019年提出的群智能优化算法模拟哈里斯鹰联合捕猎兔子的行为。整体流程分三大阶段探索、探索转开发、开发。探索阶段对应猎物位置不确定时鹰群的漫游搜索位置更新有两种等概率策略X(t1) X_rand(t) - r₁|X_rand(t) - 2r₂X(t)|当q ≥ 0.5X(t1) X_rabbit(t) - X_m(t) - r₃ ( LB r₄(UB - LB) )当q 0.5X_m(t)是当前种群平均位置。前一半公式让鹰绕着随机个体的大致范围到处探后一半公式在“已知最好的猎物位置”和“整个种群质心”之间做减法生成新位置再叠加一个边界域内的随机扰动。这两种策略决定了前期搜索的广度和随机性避免算法一上来就全挤进一个局部峰。2.2 逃逸能量模型探索与开发的闸门猎物最优解的逃跑能力用逃逸能量E来刻画E 2E₀(1 - t/T)E₀是每次迭代重新生成的[-1,1]之间随机数。这个模型很聪明用归一化迭代次数t/T让能量随时间衰减迭代初期E的绝对值大偏向探索后期绝对值变小算法转入精细开发。|E| ≥ 1时执行探索阶段|E| 1时执行开发阶段。T越大前期探索的时间越长后期收敛越精细但代价是计算时间直线上升。2.3 开发阶段软包围、硬包围和渐进式俯冲进入开发阶段后鹰会根据猎物剩余能量E和随机数r模拟猎物能否成功逃出包围圈选择四种攻击策略软包围r ≥ 0.5且|E| ≥ 0.5猎物还有体力鹰缓慢收圈。位置更新加入当前位置与全局最优位置的差值项步长随|E|变化。硬包围r ≥ 0.5且|E| 0.5猎物体力耗尽鹰直接猛扑。位置更新大幅向全局最优靠拢。软包围加渐进式快速俯冲r 0.5且|E| ≥ 0.5猎物还有一定能量鹰会以更复杂的莱维飞行模式试探性扑击再和当前最优位置比较效果择优更新。硬包围加渐进式快速俯冲r 0.5且|E| 0.5猎物能量很低鹰群直接快速突进压缩包围圈。四种策略的差异可以直观理解成随机数r决定的是“兔子还能不能蹦跶”能量E决定的是“鹰该用多大力气扑”。策略设计的不同组合保证了算法在山谷区域既不会早早停滞也不会因过度收敛而失去局部精细搜索能力。3. 把HHO接到TV修复上参数编码、适应度函数与主流程3.1 什么样的“鹰位置”对TV修复才有意义连接HHO和TV修复的关键是把TV修复过程里需要人工设定的超参数编成鹰的位置向量。我的实验里选了三个参数正则化参数λ、split Bregman惩罚参数μ、迭代停止阈值tol。鹰的位置就是一个三维向量X [λ, μ, tol]边界设置很有讲究。λ设为[0.005, 0.5]太小则修复结果几乎等于原图加噪声太大则全图被磨成卡通画μ设为[1, 50]主要影响Bregman更新的稳定性tol设在[1e-6, 1e-3]控制迭代提前终止的松紧。初始种群在边界内均匀随机生成20只鹰最大迭代次数T设为30。为什么特别强调边界因为群智能算法再聪明也没法自律。没有任何边界处理的HHO跑上十代λ经常越界变成负值TV修复求解器立刻报错。边界处理不是加分项是保命项。3.2 适应度函数怎么评价一只鹰的好坏适应度函数的选取直接决定算法向哪个方向优化。做有参考修复实验时我用的适应度是峰值信噪比PSNR定义不必多说越大越好。但在没有真值图像的应用场景PSNR根本用不了此时可以用一种梯度保持指标对修复前后图像的梯度幅值计算相关性边缘保持越好适应度越高。选适应度函数还有一个工程化考量计算速度。PSNR计算本身极快但它依赖一次完整的TV修复才能拿到修复图而修复图是算法的主循环瓶颈。为了控制总耗时我做了两步优化将适应度评估图像下采样到128×128先粗筛出有潜力的参数区域确定后再跑全分辨率精细修复在HHO主循环中预计算差分矩阵和算子不在每只鹰的每次迭代里反复重建系数矩阵。3.3 HHO-TV主流程从鹰群初始化到最优参数输出整体流程可以概括成下面这条链路读入退化图像f、掩码mask初始化HHO参数种群规模N20最大迭代次数T30边界LB[0.005, 1, 1e-6]UB[0.5, 50, 1e-3]第一代对每个鹰位置X执行一次TV修复得到修复图u计算PSNR作为适应度记录全局最优位置X_rabbit它对应的一组[λ, μ, tol]就是当前最佳参数进入迭代主循环按2.2和2.3的机制更新每个鹰的位置越界截断再次调用TV修复评估适应度更新全局最优达到最大迭代次数后输出X_rabbit和对应的修复图u_best。这个流程的设计逻辑很直白把“跑一组TV修复”看成一次昂贵的函数估值让HHO用尽量少的估值次数找到尽量好的参数组合。对比网格搜索HHO用20×30600次估值覆盖三维空间网格搜索要达到同等密度需要几十个节点计算量差距是数量级的。4. Matlab代码骨架从主函数到TV求解器的完整实现4.1 主函数HHO_TV_main.m% 主函数HHO 优化 TV 图像修复 clc; clear; close all; rng(20240315); % 固定随机种子保证实验可复现 img im2double(imread(test.png)); % 原始图像有真值用于评估PSNR mask imread(test_mask.png) 0; % 掩码缺陷区域为true f img .* (1 - mask); % 生成受损观测图 % HHO 参数 N 20; % 种群规模 T 30; % 最大迭代次数 dim 3; % [lambda, mu, tol] LB [0.005, 1, 1e-6]; UB [0.5, 50, 1e-3]; % 初始化种群与适应度 X repmat(LB, N, 1) rand(N, dim) .* repmat(UB - LB, N, 1); Fit zeros(N, 1); for i 1:N u TVinpaint_sb(f, mask, X(i,1), X(i,2), X(i,3)); Fit(i) psnr(u, img); end [bestFit, bestIdx] max(Fit); X_rabbit X(bestIdx, :); % 全局最优参数4.2 split Bregman求解器TVinpaint_sb.mfunction u TVinpaint_sb(f, mask, lambda, mu, tol) [M, N] size(f); u f; % Bregman 变量初始化 bx zeros(M, N); by zeros(M, N); % 差分算子 [Dx, Dy] make_difference_operator(M, N); for k 1:30 % 子问题基于保真项和Bregman迭代求解 u rhs f .* mask mu * (Dx * (Dx * u - bx) Dy * (Dy * u - by)); % 这里用了掩码矩阵处理修复区域保留已知像素 u solve_linear_system(rhs, mask, lambda, mu); % 子问题shrinkage 更新 gx Dx * u bx; gy Dy * u by; s sqrt(gx.^2 gy.^2); bx gx - max(s - 1/mu, 0) .* gx ./ (s eps); by gy - max(s - 1/mu, 0) .* gy ./ (s eps); % 检查收敛 if k 1 norm(u - u_prev, fro) / norm(u_prev, fro) tol break; end u_prev u; end end这个求解器的主干是标准的split Bregman交替更新u和辅助变量bx、by。make_difference_operator用于生成离散梯度算子Dx、Dysolve_linear_system是一个基于共轭梯度的线性求解函数在掩码区域外直接复制观测值在缺陷区域内部以TV平滑约束为准。此处的λ和μ就是HHO要优化的对象。4.3 HHO位置更新与边界处理for t 1:T E0 2 * rand() - 1; E 2 * E0 * (1 - t / T); % 逃逸能量衰减 for i 1:N % 探索或开发切换 if abs(E) 1 % 探索阶段略同标准HHO公式 else r rand(); if r 0.5 abs(E) 0.5 X(i,:) X_rabbit - X(i,:) - E * abs(2*E*X_rabbit - X(i,:)); elseif r 0.5 abs(E) 0.5 X(i,:) X_rabbit - E * abs(X_rabbit - X(i,:)); else % 渐进式俯冲结合莱维飞行忽略详细展开 S X_rabbit - X(i,:); X(i,:) X_rabbit S .* levy_flight(dim); end end % 边界截断 X(i,:) max(min(X(i,:), UB), LB); % 评估适应度 u TVinpaint_sb(f, mask, X(i,1), X(i,2), X(i,3)); Fit(i) psnr(u, img); end [bestFit, bestIdx] max(Fit); if bestFit Fit_rabbit X_rabbit X(bestIdx, :); Fit_rabbit bestFit; end end边界截断处理用一行max/min就搞定了简单却极其关键缺少这一步的HHO在迭代中会产生非法参数直接让TV求解器崩溃。渐进式俯冲部分用Levy飞行生成随机步长核心是为了避免开发阶段陷入局部最优。完整的levy_flight函数我放最后了有兴趣可以直接抄。4.4 Levy飞行与辅助函数function L levy_flight(dim) beta 1.5; sigma (gamma(1beta) * sin(pi*beta/2) / (gamma((1beta)/2) * beta * 2^((beta-1)/2)))^(1/beta); u randn(1, dim) * sigma; v randn(1, dim); L abs(u) ./ (abs(v).^(1/beta)); endLevy飞行是元启发式算法里最常见的随机游走方式它能让步长具备重尾分布特性偶尔飞出很远避免算法停在局部极值。5. 实测结果HHO寻优后的TV修复到底强在哪5.1 实验设置与基准测试用的模拟图像来自某公开灰度图库尺寸统一处理为256×256。退化方式分两种第一种在30%随机像素区域添加高斯白噪声噪声方差σ0.05第二种用不规则文字条带掩码模拟划痕损坏。对比基准是“手调网格寻优”λ按0.01到0.05五等分、μ取10和20遍历全部组合共30组参数中的最优PSNR再与HHO寻优结果对比每组实验固定随机种子重复20次取平均。退化场景网格搜索最优PSNR (dB)HHO寻优PSNR (dB)HHO平均耗时 (s)30%随机噪声31.2532.01约86文字条带掩码36.8738.12约74HHO收窄的PSNR提升大约在0.9~1.3dB之间单看数值不算惊艳但网格搜索额外消耗了大量人机交互时间且搜索分辨率还有限。实际操作中网格搜索想要逼近这个水平组数翻倍都不够HHO全程自动这也是元启发式算法在参数寻优场景里最大的价值。5.2 收敛行为分析从HHO迭代曲线可以明显看到两个阶段前8代左右是快速爬升期每代平均提升0.6dB得益于探索机制在参数空间里大范围扫描第8到20代增速放缓每代提升不足0.1dB此时算法转入软包围和渐进式俯冲的精细开发阶段。20代以后基本收敛PSNR曲线呈平台状偶尔有一两次小幅跳变是Levy飞行带来的一次“意外跳出”又跳回峰值附近。这个收敛形态印证了一个判断HHO的高效率来自探索开发和莱维重尾分布的配合而不是单一的策略设计。如果用纯随机搜索替代HHO相同预算下PSNR普遍低1.5dB左右因为参数空间里存在大量“平庸区”。5.3 修复图的肉眼差异HHO寻优参数修复的图像在文本条带修复场景中条带边缘的振铃效应明显弱于网格最优参数。另外HHO选出的λ值往往居于网格最优区间的非整数倍位置这意味着网格搜索要么被取整限制错失真正峰值要么就只能靠中间插值人工猜。修复图在纯色区域更干净在纹理区保留更多细节没出现TV模型典型的过度卡通化。实测下来的一个重要心得HHO不是把TV模型本身改强了而是把所有“手动参数经验”转化成了有针对性的搜索过程。同一张图换一个噪声强度HHO能自己去适应而不需要我再重新看一遍PSNR曲线。6. 跑完整个流程我必须提醒的六件事6.1 适应度函数计算成本是全局瓶颈HHO每组种群都要完整调一次TV修复一次修复几百毫秒20只鹰30代就是约600次修复串行执行的话总耗时是分钟级别。想提速一是用小尺寸图像做粗搜索二是用并行计算工具箱给适应度计算加parfor。代码里的适应度评估循环是完全可以并行的只改一个关键字的事但我最初没有意识到白白多等了两小时。6.2 边界设置比算法本身更容易翻车边界太紧鹰群只能在很窄的区间里搜索最优解可能在边界外边界太松大量无效区域会让HHO把预算浪费在探索上。不建议直接拍脑袋设边界先小范围手动跑一两组TV修复观察什么区间内PSNR变化明显再把这个区间适当外扩设成边界。我对μ的初始边界设过[0.1, 200]结果HHO花了12代才从适应度很低的区域爬出来。6.3 固定随机种子实验才可复现群智能算法天然带随机性E₀、r、Levy飞行全部涉及随机数生成器。不锁定rng同一段代码两次运行的结果会有0.2dB左右的浮动没法做严谨的对比实验。主函数开头用rng固定随机种子这是算法实验的基本卫生习惯。6.4 无参考图像的场景适应度要换着花PSNR用不了时我再推荐两个无参考替代品一个是基于拉普拉斯算子的清晰度指标计算修复结果的高频能量另一个是基于梯度的边缘保持系数统计掩码边界附近梯度幅值在修复前后的比值。实测下来边缘保持系数对评价TV修复更有区分度因为它直接对应TV模型“保持边缘”的核心诉求。6.5 初始种群可以让算法更快HHO默认随机初始种群但如果对图像特点有经验比如知道它是强纹理图像可以在初始种群里放几组偏向更大λ的个体如果是强噪声图像则多塞几组偏向小λ的个体。好的初值类似人类调参的“起手式”能帮算法省去前期摸索时间但也不要过度压缩种群多样性否则容易早熟。6.6 和更有针对性的修复算法配合效果更佳HHO-TV更适合做参数标定和教学验证如果追求修复质量天花板建议将HHO作为“元学习器”套在更深度的修复模型之上例如用它优化卷积稀疏编码或深度展开网络中的正则化权重。对这套思路感兴趣的话后续可以从HHO的适应度设置和深度模型共享参数这两块入手展开更深入的工作。跑完这套HHO-TV流程最大的收获不是PSNR提高了多少而是彻底解放了手动调参的精力让整个修复实验变成了一条自动化的流水线。算法实验领域里“参数怎么来”这个问题长期被忽视这也是HHO这类元启发式算法在图像修复场景中最落地的切入位置。