实验:使用tensorflow实现卷积运算(灰度图)

概述

本文通过代码 将 卷积结果 显示成 图片,便于理解卷积层的功能

注意:

卷积结果 可能是 负数、浮点数,而图片是 0-255 之间的 整数,所以 将 卷积结果 显示成图片,肯定会有 偏差

准备图片

以下面 灰度图 为例子做卷积测试:

代码

导入模块

from tensorflow.keras import Sequential
from tensorflow.keras.layers import Conv2D, MaxPool2D
from tensorflow.keras.layers import Activation

import matplotlib.pyplot as plt

from PIL import Image
import numpy as np

读取图片

读取图片

path=r"C:\Users\mym\Desktop\文件接收柜\aodaili.jpg"
im = Image.open(path)
img=np.array(im)
print('输入图shape:',img.shape)
print('输入图:',img)

将图片格式转换成3维

由于是 灰度图,只有 2个维度(即:宽、高)

但tensorflow需要的是 3维 格式,所以要转换成3维,第3维是 通道数,灰度图的通道数是 1

img=img.reshape(img.shape[0],img.shape[1],1)
# img=np.expand_dims(img,-1)
print('输入图shape:',img.shape)
# print('输入图:',img)

建立模型

model = Sequential()
# 第一个参数是卷积核的数量,第二个参数是卷积核的大小
model.add(Conv2D(4, (3, 3), input_shape=img.shape))

model.summary()

查看权重和偏置量

w,b = model.layers[0].get_weights()
print("共有%d层"%len(model.layers))
print("权重 shape:",w.shape)
print("偏置量 shape",b.shape)

print("权重 :",w)
print("偏置量 ",b)

执行结果如下:


权重shape:(3,3,1,4)的解释:

  • 前2个3,3 是 建立模型时设置 卷积核大小;

  • 第3个1是 建立模型时input_shape=img.shape设置的 图片通道数,因为是灰度图所以是1

  • 第4个4是 建立模型时设置的卷积核 数量

偏置量 shape (4,)的解释:

  • 4是 建立模型时设置的卷积核 数量

预测前准备

由于tensorflow预测时,要求数据为4维矩阵,在原图片维度前插入一个维度,表示图片数量,也就是说:

  • 第1维是图片 数量
  • 第2、3维表示图片 宽高
  • 第4维表示图片 通道数

所以要将图片转为4维矩阵

# 多增加一个维度,第一维是图片数量
img_batch = np.expand_dims(img, axis=0)

print('输入图shape:',img_batch.shape)

执行结果:

输入图shape: (1, 300, 300, 1)

进行预测

直接对该图进行预测,输出卷积结果

# 输出特征图
out_img = model.predict(img_batch)

print ("结果类型:",type(out_img))
print ("结果shape:",out_img.shape)
print ("卷积结果",out_img)

执行结果:

注意:

  1. 预测结果的 类型是 numpy类型

  2. shape解释:

    • 第一个元素:表示传入图片 数量是1,所以预测结果的图片 数量也是1
    • 第二、三个元素:表示图片 高、宽
    • 第四个元素:表示 4个卷积核,经过卷积运算后,生成 4个图片

注意 注意 注意:
卷积结果 有 负数、浮点数
为了直观感受卷积结果,下面要将卷积结果显示成图片,图片是 0-255 之间的 整数,所以显示成图片时,并不是真实的

实现函数:显示卷积结果

def show_img(out_img):
    num_pic = out_img.shape[-1]
    print('out_img.shape:',out_img.shape)

    #显示将特征图
    for _ in range(num_pic):
        show_img = out_img[:, :, _]
#         通过matplotlib显示图片,图片大小不准确
        plt.imshow(show_img, cmap='gray')
        plt.axis('off')
        plt.show()
#       根据图片的numpy数组转成图片对象,由于numpy数组是浮点型,且可能有负数,所以要转换成8位像素模式,然后保存图片
        Image.fromarray(show_img).convert('L').save("2-%s.jpeg"%_)

显示卷积结果

show_img(out_img[0])

matplotlib显示卷积结果:

  1. 图片大小与卷积结果 不一致
  2. 显示与卷积结果 不一致,因为卷积结果有负数、浮点数

pil显示图片结果:

  1. 图片大小与卷积结果 一致
  2. 显示与卷积结果 不一致,因为卷积结果有负数、浮点数

总结

  1. 一张图片,经过 n个卷积核 运算,生成n个结果

  2. 不同的卷积核 提取不同的特征

  3. 卷积核越多,提取的特征就越多

练习

设置边缘填充并观察图片 宽、高 结果

参见 api tf.keras.layers.Conv2D ,设置边缘填充,并查看结果


原文出处:/show_1EF4Po2jfC0H.html