ArrayFire中卷积后反卷积无法还原原图的原因探究
图像反卷积结果偏差问题分析与解决
问题描述
使用C++ ArrayFire库开发图像去模糊应用,测试场景为5×5原图与3×3全1归一化核:
- 通过
af::convolve2完成卷积 - 调用
af::iterativeDeconv分别用Richardson-Lucy(RL)和Landweber算法反卷积 - 结果与原图差异明显,Landweber算法偏差远大于RL;增加迭代次数未达到预期收敛效果
测试代码
// Create a simple 5x5 input image float h_image[25] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 3, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, }; af::array image(5, 5, h_image); // Create a simple 3x3 kernel (normalized such that sum == 1)for convolution float h_kernel[9] = { 0.111, 0.111, 0.111, 0.111, 0.111, 0.111, 0.111, 0.111, 0.111, }; af::array kernel(3, 3, h_kernel); // Perform convolution af::array convolved = af::convolve2(image, kernel); // Perform deconvolution float relaxation_factor = 0.64; int num_iterations = 128; af::array deconvolved_richardson_lucy = af::iterativeDeconv(convolved, kernel, num_iterations, relaxation_factor, AF_ITERATIVE_DECONV_RICHARDSONLUCY); af::array deconvolved_landweber = af::iterativeDeconv(convolved, kernel, num_iterations, relaxation_factor, AF_ITERATIVE_DECONV_LANDWEBER); // Output results af::print("Original Image", image); af::print("Convolved Image", convolved); af::print("Deconvolved Image - Richardson Lucy", deconvolved_richardson_lucy); af::print("Deconvolved Image - Landweber", deconvolved_landweber);
输出结果
Original Image [5 5 1 1] 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 2.0000 2.0000 2.0000 1.0000 1.0000 2.0000 3.0000 2.0000 1.0000 1.0000 2.0000 2.0000 2.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 Convolved Image [5 5 1 1] 0.5550 0.8880 0.9990 0.8880 0.5550 0.8880 1.5540 1.7760 1.5540 0.8880 0.9990 1.7760 2.1090 1.7760 0.9990 0.8880 1.5540 1.7760 1.5540 0.8880 0.5550 0.8880 0.9990 0.8880 0.5550 Deconvolved Image - Richardson Lucy [5 5 1 1] 0.3774 0.5695 1.0053 0.5695 0.3774 0.5695 1.2211 2.2630 1.2211 0.5695 1.0053 2.2630 4.7015 2.2630 1.0053 0.5695 1.2211 2.2630 1.2211 0.5695 0.3774 0.5695 1.0053 0.5695 0.3774 Deconvolved Image - Landweber [5 5 1 1] 23.2821 32.3862 71.3124 32.3862 23.2820 32.3862 80.7867 151.3048 80.7867 32.3862 71.3124 151.3049 276.6479 151.3048 71.3124 32.3862 80.7867 151.3048 80.7867 32.3862 23.2821 32.3862 71.3124 32.3862 23.2820
问题原因分析
1. 卷积边界填充带来的误差放大
af::convolve2默认使用零填充(zero-padding),导致图像边缘区域的卷积结果与真实值偏差显著(比如原图左上角1,卷积后得到0.555,是因为边缘只有5个像素被核覆盖,其余4个是0)。反卷积本身是病态问题,这种边界误差会被迭代过程不断放大,Landweber算法对这类误差的敏感度远高于RL算法,直接导致结果发散。
2. Landweber算法参数设置不合理
Landweber算法收敛的前提是松弛因子小于2/L(L为卷积算子的最大特征值)。对于全1归一化核,L=1(核的和为1,对应最大特征值),理论上松弛因子应小于2,但实际中过大的松弛因子(如0.64)加上128次迭代,会导致算法偏离收敛方向,最终数值爆炸。
3. 核的精度不足
手动设置的0.111与真实值1/9≈0.111111...存在精度误差,卷积后会引入微小偏差,在反卷积的迭代过程中被累积放大。
4. 反卷积的固有病态性
反卷积是典型的不适定问题,即使无噪声,微小的输入误差(如边界填充、核精度)也会被迭代过程放大,导致结果偏离原图。
解决建议
1. 调整边界填充模式
将卷积和反卷积的边界模式改为对称填充(AF_PAD_SYM)或复制填充(AF_PAD_REPLICATE),减少边缘区域的不连续性误差:
// 卷积时指定边界模式 af::array convolved = af::convolve2(image, kernel, AF_CONV_DEFAULT, AF_PAD_SYM);
2. 优化Landweber算法参数
- 降低松弛因子:比如设置为0.1,避免迭代发散
- 减少迭代次数:从128次降至10-20次,观察收敛情况
float relaxation_factor = 0.1; int num_iterations = 15; af::array deconvolved_landweber = af::iterativeDeconv(convolved, kernel, num_iterations, relaxation_factor, AF_ITERATIVE_DECONV_LANDWEBER);
3. 提高核的精度
使用精确的归一化值代替手动输入的0.111:
float h_kernel[9]; float kernel_val = 1.0f / 9.0f; std::fill(h_kernel, h_kernel+9, kernel_val); af::array kernel(3, 3, h_kernel);
4. 加入正则化约束
对于RL算法,可通过调整松弛因子实现隐式正则化;Landweber可考虑使用带正则化的版本,或在迭代过程中加入梯度裁剪,抑制误差放大。
内容的提问来源于stack exchange,提问作者speca
相关产品推荐
相关产品推荐

