很多代码中,sobel算子表达式的构造语句如下:
filter = tf.Variable(tf.constant([[-1.0,-1.0,-1.0], [0,0,0], [1.0,1.0,1.0],
[-2.0,-2.0,-2.0], [0,0,0], [2.0,2.0,2.0],
[-1.0,-1.0,-1.0], [0,0,0], [1.0,1.0,1.0]],shape = [3, 3, 3, 1]))
其实你也可以写成:
filter=tf.Variable(tf.constant([-1.0,-1.0,-1.0,0,0,0,1.0,1.0,1.0,-2.0,-2.0,-2.0,0,0,0,2.0,2.0,2.0,-1.0,-1.0,-1.0,0,0,0,1.0,1.0,1.0],shape=3,3,3,1))
结果和意思一样,只不过第一种写法更清晰。
以上语句构造出3个下面的矩阵:这个[3,3,3]矩阵代表具有三个通道的过滤器(或者称为卷积核)
怎么看这个矩阵,展开和表达式里面的元素次序也不一样。要明白上面的语句为什么会生成这种结构的鬼东西,我们先了解一下python读取一个三通道的图片会形成一个什么样的矩阵,或者说,python是怎么读取图像每个像素的数据并形成矩阵的。
我们假设下面一个高度为3像素,宽度为2像素的简单图片如下,每一个图片的像素由(R,G,B)三个颜色构成:
图中每一个红色的格子代表一个像素(题外话:这个结构和液晶显示屏的结构几乎一样)
python在读取像素数据并形成列表的时候,是按照行->列->(RGB)通道的循序进行的。具体说就是:
先读取第一行,再读取第二行。每一行先读取第一列,再读取第二列。每一列先读取R,再依次读取G,B的值。
按照这个顺序,读取的结果就是(下标是像素的坐标值,起始为0)R00G00B00R01G01B01R02G02B02
R10G10B10R11G11B11R12G12B12
形成的矩阵(2x3x3)格式如下:
[
[
[R00,G00,B00]
[R01,G01,B01]
[R02,G02,B02]
]
[
[R10,G10,B10]
[R11,G11,B11]
[R12,G12,B12]
]
]
知道了python怎么读取图像数据,我们再返回来看卷积核的构造。
filter = tf.Variable(tf.constant([[-1.0,-1.0,-1.0], [0,0,0], [1.0,1.0,1.0],
[-2.0,-2.0,-2.0], [0,0,0], [2.0,2.0,2.0],
[-1.0,-1.0,-1.0], [0,0,0], [1.0,1.0,1.0]],shape = [3, 3, 3, 1]))
constant的初始化值是一个列表,每三个元素构成一个像素的RGB值,由于卷积核其实也是一个三通道的图像,所以这个三层的卷积核每一层的元素应该分别从上面的三元组中选取对应的元素,构成纯粹有R或者G,B数值的矩阵。如此:
R通道的sobel算子构造方法如下:
选择第1个元组的第1个元素:-1
选择第2个元组的第1个元素:0
选择第3个元组的第1个元素:1
选择第4个元组的第1个元素:-2
选择第5个元组的第1个元素:0
选择第6个元组的第1个元素:2
选择第7个元组的第1个元素:-1
选择第8个元组的第1个元素:0
选择第9个元组的第1个元素:1
以上9个元素构成R通道的sobel算子:
-1,0,1
-2,0,2
-3,0,3
同理,依次取每个元组的第2,3个元素可以构造G和B通道的sobel算子。