主要参考资料:《神经网络和深度学习》— 邱锡鹏
所用测试图片来源于公开网络,无意侵犯创作权益,如涉及侵权,请联系删除。
概念总结
CNN的结构和各层次功能
卷积层:提取特征
池化层:特征压缩/降维
全连接层:结果预测
卷积
卷积是一个数学概念,在CNN中表示:图像当中数据窗口的数据和卷积核作内积运算的操作,是一种互相关运算。
该操作也被称为滤波(filter),主要作用是提取图象在不同维度的特征。
卷积核
也称为滤波器,是定义一系列权值的函数,
可以将输入图像的各个区域的像素点加权平均,得到输出图像的各个像素点,
不同的卷积核可以输出不同风格的图像。图像与卷积核运算,可以提取图像特征。
与全连接相比,卷积核仅关注输入数据的局部特征。
特征图(feature map)
图像和卷积核完成加权累加后,即原图像作为输入经卷积核滤波后,得到的结果就是特征图。
卷积层的输入往往是多层的,输出也往往由多个特征图叠加而成。
特征选择
选择一组较好的特征,由这些低层次的特征,通过更多的卷积层的组合,来表示高层次的特征,能够更好的进行图像识别,使得模型更具针对性和准确度。
池化(Pooling)
又称为下采样(Dwon Sampling),卷积得到的特征图数据量较大,要利用池化层对其进行数据降维。
使用一定大小的滑动窗口和步长,采用一定规则将该区域降维。
可以采用不同的方式进行池化:
需要注意的是,
过大的采样区域容易导致信息丢失。
一般使用非线性激活函数(ReLU)修正负数为0,避免梯度消失。
相关参数:窗口大小,步幅。
多通道
神经层深度
神经元常被组织为三维结构,M x N x D (长 x 宽 x 深度)
特征映射
CNN中的图像处理,往往是同时对多通道的处理,
特征映射为图像经过卷积提取到的特征,每一层可以包含多个特征映射,如一个输入层可以由D个M x N的特征映射组成,
对于单通道图像,其输入层深度为1;多通道下,如RGB,其具有多个特征映射,输入层深度为3。
总结计算机中的色彩空间
位图模式,仅支持一位色深的图像,只包含黑白两种颜色。
GRAY灰度颜色空间,仍是显示全黑和全白之间的颜色,8bit色深下可包含256种颜色。
RGB颜色空间,是三通道色彩表示方式,由三种通道不同组合来表示各种颜色,8bit下有1677万色,而10bit下则有10亿色。还包含RGBA模式,A表示的是Alpha,即透明度。
HSL颜色空间,色调(H)、饱和度(S)、亮度(L),L=100时显示白色,L=0显示黑色。
HSV颜色空间,色调(Hue)、饱和度Saturation、明度(Value),V=100时显示光谱色,V=0显示黑色。
常见卷积核类型
锐化卷积核
该卷积核就是计算中心位置像素与周围像素的差值,
差值越大则表示该元素附近的变化越大(频率越大),输出值也就越大,因此是高频滤波器的一种。
锐化卷积核元素总和如果是0,则有提取图像边缘信息的效果。
轮廓检测卷积核
原理近似上者,
高斯卷积核
元素总和为1,但每个位置的权重不一样,权重在行和列上的分布均服从高斯分布,故称高斯滤波器。
高斯分布的标准差越大,则模糊程度越大。一个3 × 3标准差为1的高斯滤波器如下所示:
水平边缘检测卷积核
元素总和为0,在纵向变化较大,因此可以用于检测水平边缘。
垂直边缘检测卷积核
元素总和为0,在横向变化较大,因此可以用于检测垂直边缘。
编程实现
经典卷积核测试
所用代码借鉴自
import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
from PIL import Image
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 #有中文出现的情况,需要u'内容
file_path = 'demo1.png'
im = Image.open(file_path).convert('L') # 读入一张灰度图的图片
im = np.array(im, dtype='float32') # 将其转换为一个矩阵
print(im.shape[0], im.shape[1])
plt.imshow(im.astype('uint8'), cmap='gray') # 可视化图片
plt.title('原图')
plt.show()
im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))
conv1 = nn.Conv2d(1, 1, 3, bias=False) # 定义卷积
sobel_kernel = np.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]], dtype='float32') # 定义轮廓检测算子
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3)) # 适配卷积的输入输出
conv1.weight.data = torch.from_numpy(sobel_kernel) # 给卷积的 kernel 赋值
edge1 = conv1(Variable(im)) # 作用在图片上
x = edge1.data.squeeze().numpy()
print(x.shape) # 输出大小
plt.imshow(x, cmap='gray')
plt.show()
边缘检测
锐化
模糊
调整经典卷积核参数
测试两种锐化卷积核的效果差异,
肉眼观察,可以看出,左边的卷积核处理的图片(上方的),锐化效果更明显,由卷积和的作用原理可以分析:锐化卷积核就是计算中心位置像素与周围像素的差值,差值越大则表示该元素附近的变化越大(频率越大),锐化效果越强。
不同尺寸图片测试
前面所用图片的分辨率为,
改变所用图像,
进行锐化操作,
发现效果并不理想,这主要是因为大的图片细节更多,需要使用更大的卷积核进行滤波,小卷积核在小尺寸图片的效果更好。
大的卷积核有利于增大感受野,获得更好的全局特征,但是卷积核并不是越大越好的,更大的卷积核,会导致计算量暴增,不利于模型深度的增加,会导致计算负荷增大。
更多类型卷积核
再尝试下浮雕特色的卷积核的效果,
浮雕效果明显,在小尺寸图像下效果还是明显的,
尝试彩色图片边缘检测
色彩空间转换
以防万一,先对图片进行色彩空间转换,
import cv2
# 读取图片,以rgba向rgb转换为例
rgba = cv2.imread("source_rgba.jpg")
# 图像类型转换函数
rgb = cv2.cvtColor(rgba, cv2.COLOR_RGBA2RGB)
# 保存图片
cv2.imwrite('output_rgb.jpg', rgb)
原图像
色彩空间大概率为RGBA,将其转换为RGB三通道,
方法-Canny边缘检测算法
区别于将三通道割裂的进行边缘检测,Canny算法使用了多步处理的方式,利用高斯滤波器和滞后阈值方法,偏向计算整体的梯度变化,效果更好,
可以参考资料:什么是 Canny 边缘检测算法?
幸运的是,在OpenCV
当中支持了该方法,
import cv2
edges = cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
尝试进行边缘检测
# # -*- coding = utf-8 -*-
# @time:2022/5/12 11:26
# Author:Heph4es
# @File:彩色边缘检测.py
# @Software:PyCharm
import cv2
rgb = cv2.imread("5_RGB.png")
# 设置上下阈值
edge = cv2.Canny(rgb, 32, 128)
cv2.imshow("origin", rgb)
cv2.imshow("result", edge)
cv2.waitKey()
cv2.destroyAllWindows()
效果还是相当不错的。
收获总结
收获满满啊!