引言

普通图像反卷积,跟深度学习中的反卷积是一回事吗?别傻傻分不清!其实它们根本不是一个概念

图像反卷积

最早支持反卷积是因为图像去噪跟去模糊,知道图像去模糊时候会使用反卷积技术,那个是真正的反卷积计算,会估算核,会有很复杂的数学推导,主要用在图像的预处理与数字信号处理中。本质上反卷积是一种图像复原技术,典型的图像模糊可以看成事图像卷积操作得到的结果,把模糊图像重新复原为清晰图像的过程常常被称为去模糊技术,根据模糊的类别不同可以分为运动模糊与离焦模糊,OpenCV支持对这两张模糊图像进行反卷积处理得到清晰图像。反卷积的基本原理就是把图像转换到频率域,通过估算图像的核函数,在频率域对图像点乘计算之后,重新获取图像信息,转回为空间域。主要操作都在频率域,转换通过离散傅里叶(DFT)变换与反变换,通过维纳滤波处理获取反模糊信息,OpenCV支持反卷积采用维纳滤波方式的去模糊,但是参数调整事一个大坑,基本上每张图像的参数都不一样,很难有相同的结果。最近这些年,图像反模糊逐步被深度学习的方法引领,OpenCV提供的那几个函数越来越少的人知道,主要是通用性很差。

深度学习中的反卷积

深度学习中典型网络就是卷积神经网络,对图像分类,对象检测都可以取得很好的效果。但是在语义分割任务中,网络模型涉及到上采样操作,最常见的就是通过填充0或者最近邻插值的方式来完成上采样。在ICCV 2015年的一篇论文中提出了可学习的反卷积网络,不再通过简单粗暴的填充0或者最近邻插值方法来完成上采样,让整个过程变成可学习,在图像语义分割网络中实现了对上采样过程的训练。论文中提到的反卷积操作实现上采样跟图像处理中反卷积实现图像去模糊有本质区别,这里的反卷积更加准确的说法应该是转置卷积。

卷积操作

图中第二行就是卷积与反卷积的示意图,下面通过一个简单的例子来解释上图的内容。假设有4x4大小的二维矩阵D,有3x3大小的卷积核C,如下:

3 3 2 1
0 0 1 3
3 1 2 2
2 0 0 2
0 1 2
2 2 0
0 1 2

直接对上述完成卷积操作(不考虑边缘填充)输出卷积结果是2x2的矩阵

12 12
10 17

其中2x2卷积的输出结果来自D中第二行第二列像素位置对应输出,相关的卷积核与数据点乘的计算为:

0x3+1x3+2x2+2x0+2x0+0x1+0x3+1x1+2x2=12,可以看出卷积操作是卷积核在矩阵上对应位置点乘线性组合得到的输出,对D=4x4大小的矩阵从左到右,从上到下,展开得到16个维度的向量表示如下:
$$
D^{T} = [3\ 3\ 2\ 1\ 0\ 0\ 1\ 3\ 3\ 1\ 2\ 2\ 2\ 0\ 0\ 2]
$$
我们同样可以把3x3的卷积核表示如下:
20230419155414
为了获得卷积核的4x4的向量表示,我们可以对其余部分填充零,那么卷积核在D上面移动的位置与对应的一维向量表示如下:
20230419155433
考虑到卷积核C与D的点成关系,合并在一起还可以写成如下形式:
20230419155447
把上面卷积核中的字符表示替换为实际卷积核C,得到:
20230419155500
所以上述的卷积操作可以简单的写为:
$$
D^{T}C = [12\ 12\ 10\ 17]
$$
重排以后就得到上面的2x2的输出结果。

反卷积操作

现在我们有2x2的数据块,需要通过卷积操作完成上采样得到4x4的数据矩阵,怎么完成这样的操作,很容易,我们把2x2转换为1x4的向量E,然后对卷积核C转置,再相乘,表示为$EC^{T}$就得到16维度向量,重排以后就得到了4x4的数据块。这个就是深度学习中的卷积与反卷积最通俗易懂的解释。

代码

import torch
import numpy as np
# 输入一维数据
d = torch.tensor([1.,2.])
# 一维卷积核
f = torch.tensor([3.0,4.0])
# 维度转换dd
d = d.view(1,1,2)
f = f.view(1,1,2)
# 一维转置卷积
ct1d = torch.nn.ConvTranspose1d(in_channels=1, out_channels=1, kernel_size=2, stride=2, bias=0)
ct1d.weight = torch.nn.Parameter(f);
# 打印输出
print("输入数据:", d)
print("输出上采样结果:", ct1d(d))

参考

https://blog.csdn.net/qq_42722197/article/details/125076341