公式基础
TV算法(也称为Total Variation算法)是一种用于图像去噪、图像分割和图像恢复等问题的常用算法。首先了解以下概念:
- 向量的 L p L^p Lp范数:对于一个 n n n维向量 x = ( x 1 , x 2 , … , x n ) \mathbf{x}=(x_1,x_2,\ldots,x_n) x=(x1,x2,…,xn),它的 L p L^p Lp范数定义为 ∥ x ∥ p = ( ∑ i = 1 n ∣ x i ∣ p ) 1 / p \|\mathbf{x}\|_p=\left(\sum_{i=1}^n |x_i|^p\right)^{1/p} ∥x∥p=(∑i=1n∣xi∣p)1/p,其中 p ≥ 1 p\geq 1 p≥1。当 p = 1 p=1 p=1时, L 1 L^1 L1范数也称为曼哈顿距离;当 p = 2 p=2 p=2时, L 2 L^2 L2范数也称为欧几里得距离。
- 向量的 L ∞ L^\infty L∞范数:对于一个 n n n维向量 x = ( x 1 , x 2 , … , x n ) \mathbf{x}=(x_1,x_2,\ldots,x_n) x=(x1,x2,…,xn),它的 L ∞ L^\infty L∞范数定义为 ∥ x ∥ ∞ = max i = 1 n ∣ x i ∣ \|\mathbf{x}\|_\infty=\max_{i=1}^n |x_i| ∥x∥∞=maxi=1n∣xi∣。
- 梯度:对于一个二维图像 f ( x , y ) f(x,y) f(x,y),它的梯度是一个二维向量 ∇ f ( x , y ) = ( ∂ f ∂ x , ∂ f ∂ y ) \nabla f(x,y)=\left(\frac{\partial f}{\partial x},\frac{\partial f}{\partial y}\right) ∇f(x,y)=(∂x∂f,∂y∂f),其中 ∂ f ∂ x \frac{\partial f}{\partial x} ∂x∂f和 ∂ f ∂ y \frac{\partial f}{\partial y} ∂y∂f分别表示 f f f在 x x x和 y y y方向上的偏导数。
- 二维图像的总变差:对于一个二维图像 f ( x , y ) f(x,y) f(x,y),它的总变差定义为 T V ( f ) = ∫ − ∞ ∞ ∫ − ∞ ∞ ∣ ∇ f ( x , y ) ∣ d x d y TV(f)=\int_{-\infty}^\infty\int_{-\infty}^\infty |\nabla f(x,y)| dxdy TV(f)=∫−∞∞∫−∞∞∣∇f(x,y)∣dxdy。
有了这些基本概念后,开始推导TV算法。
假设我们要对一幅二维图像 f ( x , y ) f(x,y) f(x,y)进行去噪,即找到一个近似的图像 u ( x , y ) u(x,y) u(x,y),使得 u ( x , y ) u(x,y) u(x,y)尽可能接近 f ( x , y ) f(x,y) f(x,y),但又要保持 u ( x , y ) u(x,y) u(x,y)比 f ( x , y ) f(x,y) f(x,y)更加平滑。为了达到这个目的,我们可以使用以下优化问题:
min u ∥ u − f ∥ 2 2 + λ T V ( u ) \min_u \|u-f\|_2^2+\lambda TV(u) minu∥u−f∥22+λTV(u)
其中 ∥ ⋅ ∥ 2 \|\cdot\|_2 ∥⋅∥2表示 L 2 L^2 L2范数, λ \lambda λ是一个正则化参数,用于平衡平滑性和精度。
我们可以使用梯度下降法求解这个优化问题,即不断迭代以下更新:
u k + 1 = u k − μ ( 2 ( u k − f ) − λ ∇ ⋅ ( ∇ u k ∣ ∇ u k ∣ + ϵ ) ) u^{k+1}=u^k-\mu\left(2(u^k-f)-\lambda\nabla\cdot\left(\frac{\nabla u^k}{|\nabla u^k|+\epsilon}\right)\right) uk+1=uk−μ(2(uk−f)−λ∇⋅(∣∇uk∣+ϵ∇uk))
其中 k k k表示迭代次数, μ \mu μ是学习率, ∇ ⋅ \nabla\cdot ∇⋅表示散度运算, ϵ \epsilon ϵ是一个很小的正数,用于防止分母为零。这个更新公式的含义是,我们沿着误差梯度的反方向向目标移动,同时加入一个平滑项的梯度,用于保持平滑性。
在每次迭代中,我们需要计算 ∇ u k \nabla u^k ∇uk和 ∇ ⋅ ( ∇ u k ∣ ∇ u k ∣ + ϵ ) \nabla\cdot\left(\frac{\nabla u^k}{|\nabla u^k|+\epsilon}\right) ∇⋅(∣∇uk∣+ϵ∇uk)。这些计算可以通过图像的差分运算来实现,具体来说,我们可以使用以下近似:
∂ u ∂ x ≈ u ( x + 1 , y ) − u ( x , y ) Δ x \frac{\partial u}{\partial x}\approx\frac{u(x+1,y)-u(x,y)}{\Delta x} ∂x∂u≈Δxu(x+1,y)−u(x,y)
∂ u ∂ y ≈ u ( x , y + 1 ) − u ( x , y ) Δ y \frac{\partial u}{\partial y}\approx\frac{u(x,y+1)-u(x,y)}{\Delta y} ∂y∂u≈Δyu(x,y+1)−u(x,y)
∇ u ≈ [ ∂ u ∂ x ∂ u ∂ y ] \nabla u\approx\begin{bmatrix} \frac{\partial u}{\partial x} \\ \frac{\partial u}{\partial y} \end{bmatrix} ∇u≈[∂x∂u∂y∂u]
∇ ⋅ ( ∇ u ∣ ∇ u ∣ + ϵ ) ≈ ∂ ∂ x ( ∂ u ∂ x ( ∂ u ∂ x ) 2 + ( ∂ u ∂ y ) 2 + ϵ 2 ) + ∂ ∂ y ( ∂ u ∂ y ( ∂ u ∂ x ) 2 + ( ∂ u ∂ y ) 2 + ϵ 2 ) \nabla\cdot\left(\frac{\nabla u}{|\nabla u|+\epsilon}\right)\approx\frac{\partial}{\partial x}\left(\frac{\frac{\partial u}{\partial x}}{\sqrt{\left(\frac{\partial u}{\partial x}\right)^2+\left(\frac{\partial u}{\partial y}\right)^2+\epsilon^2}}\right)+\frac{\partial}{\partial y}\left(\frac{\frac{\partial u}{\partial y}}{\sqrt{\left(\frac{\partial u}{\partial x}\right)^2+\left(\frac{\partial u}{\partial y}\right)^2+\epsilon^2}}\right) ∇⋅(∣∇u∣+ϵ∇u)≈∂x∂((∂x∂u)2+(∂y∂u)2+ϵ2∂x∂u)+∂y∂((∂x∂u)2+(∂y∂u)2+ϵ2∂y∂u)
其中 Δ x \Delta x Δx和 Δ y \Delta y Δy表示图像中相邻像素之间的距离。这些近似式可以通过中心差分、前向差分或后向差分等方法来计算。
通过不断迭代以上更新公式,可以逐渐优化 u u u,使得它同时接近 f f f和具有平滑性。需要注意的是,这个优化问题是一个非凸优化问题,因此可能会收敛到局部最优解而不是全局最优解。尝试使用不同的初始值、学习率和正则化参数来进行多次迭代,并选择最终结果最好的一个。
代码解析
‘’’ matlab
% 设置参数
lambda = 0.1;
mu = 0.5;
epsilon = 1e-5;
niter = 100;
% 初始化u
u = f_noisy; % 噪声图像f_noisy
% 迭代更新u
for i = 1:niter
% 计算梯度
[ux, uy] = gradient(u);
gradmag = sqrt(ux.^2 + uy.^2);
% 计算散度
div = divergence(ux./(gradmag+epsilon), uy./(gradmag+epsilon));
% 更新u
u = u - mu*(2*(u-f_noisy) - lambda*div);
% 显示进度
if mod(i,10)==0
fprintf('Iteration %d\n',i);
imshow(u);
drawnow;
end
end
‘’’