东台哪家专业做网站,门源网站建设公司,平台公司市场化转型,模板网站建设公司电话目录
计算机视觉的发展历程
卷积神经网络
卷积#xff08;Convolution#xff09;
卷积计算
感受野#xff08;Receptive Field#xff09;
步幅#xff08;stride#xff09;
感受野#xff08;Receptive Field#xff09;
多输入通道、多输出通道和批量操作 …
目录
计算机视觉的发展历程
卷积神经网络
卷积Convolution
卷积计算
感受野Receptive Field
步幅stride
感受野Receptive Field
多输入通道、多输出通道和批量操作
卷积算子应用举例 计算机视觉作为一门让机器学会如何去“看”的学科具体的说就是让机器去识别摄像机拍摄的图片或视频中的物体检测出物体所在的位置并对目标物体进行跟踪从而理解并描述出图片或视频里的场景和故事以此来模拟人脑视觉系统。因此计算机视觉也通常被叫做机器视觉其目的是建立能够从图像或者视频中“感知”信息的人工系统。
计算机视觉技术经过几十年的发展已经在交通车牌识别、道路违章抓拍、安防人脸闸机、小区监控、金融刷脸支付、柜台的自动票据识别、医疗医疗影像诊断、工业生产产品缺陷自动检测等多个领域应用影响或正在改变人们的日常生活和工业生产方式。未来随着技术的不断演进必将涌现出更多的产品和应用为我们的生活创造更大的便利和更广阔的机会。 图1计算机视觉技术在各领域的应用
重点介绍计算机视觉的经典模型卷积神经网络和两个典型任务图像分类和目标检测。主要涵盖如下内容
卷积神经网络卷积神经网络Convolutional Neural Networks, CNN是计算机视觉技术最经典的模型结构。本教程主要介绍卷积神经网络的常用模块包括卷积、池化、激活函数、批归一化、丢弃法等。 图像分类介绍图像分类算法的经典模型结构包括LeNet、AlexNet、VGG、GoogLeNet、ResNet并通过眼疾筛查的案例展示算法的应用。 目标检测介绍目标检测YOLOv3算法并通过林业病虫害检测案例展示YOLOv3算法的应用。 计算机视觉的发展历程
计算机视觉的发展历程要从生物视觉讲起。对于生物视觉的起源目前学术界尚没有形成定论。有研究者认为生物视觉产生于距今约5亿年前寒武纪。寒武纪生物大爆发的原因一直是个未解之谜不过可以肯定的是在寒武纪动物具有了视觉能力捕食者可以更容易地发现猎物被捕食者也可以更早的发现天敌的位置。
视觉能力加剧了猎手和猎物之间的博弈也催生出更加激烈的生存演化规则。视觉系统的形成有力地推动了食物链的演化加速了生物进化过程是生物发展史上重要的里程碑。经过几亿年的演化目前人类的视觉系统已经具备非常高的复杂度和强大的功能人脑中神经元数目达到了1000亿个这些神经元通过网络互相连接这样庞大的视觉神经网络使得我们可以很轻松的观察周围的世界如 图2 所示。 图2人类视觉感知 对人类来说识别猫和狗是件非常容易的事。但对计算机来说即使是一个精通编程的高手也很难轻松写出具有通用性的程序比如假设程序认为体型大的是狗体型小的是猫但由于拍摄角度不同可能一张图片上猫占据的像素比狗还多。那么如何让计算机也能像人一样看懂周围的世界呢研究者尝试着从不同的角度去解决这个问题由此也发展出一系列的子任务如 图3 所示。 图3计算机视觉子任务示意图 (a) Image Classification 图像分类用于识别图像中物体的类别如bottle、cup、cube。 (b) Object Localization 目标检测用于检测图像中每个物体的类别并准确标出它们的位置。 © Semantic Segmentation 图像语义分割用于标出图像中每个像素点所属的类别属于同一类别的像素点用一个颜色标识。 (d) Instance Segmentation 实例分割值得注意的是b中的目标检测任务只需要标注出物体位置而d中的实例分割任务不仅要标注出物体位置还需要标注出物体的外形轮廓。
在早期的图像分类任务中通常是先人工提取图像特征再用机器学习算法对这些特征进行分类分类的结果强依赖于特征提取方法往往只有经验丰富的研究者才能完成如 图4 所示。 图4早期的图像分类任务 在这种背景下基于神经网络的特征提取方法应运而生。Yann LeCun是最早将卷积神经网络应用到图像识别领域的
其主要逻辑是使用卷积神经网络提取图像特征
并对图像所属类别进行预测
通过训练数据不断调整网络参数
最终形成一套能自动提取图像特征并对这些特征进行分类的网络如 图5 所示。 图5早期的卷积神经网络处理图像任务示意
这一方法在手写数字识别任务上取得了极大的成功但在接下来的时间里却没有得到很好的发展。其主要原因一方面是数据集不完善只能处理简单任务在大尺寸的数据上容易发生过拟合另一方面是硬件瓶颈网络模型复杂时计算速度会特别慢。
目前随着互联网技术的不断进步数据量呈现大规模的增长越来越丰富的数据集不断涌现。另外得益于硬件能力的提升计算机的算力也越来越强大。不断有研究者将新的模型和算法应用到计算机视觉领域。由此催生了越来越丰富的模型结构和更加准确的精度同时计算机视觉所处理的问题也越来越丰富包括分类、检测、分割、场景描述、图像生成和风格变换等甚至还不仅仅局限于2维图片包括视频处理技术和3D视觉等。 卷积神经网络
卷积神经网络是目前计算机视觉中使用最普遍的模型结构包括
卷积Convolution池化PoolingReLU激活函数批归一化Batch Normalization丢弃法Dropout
我们介绍了手写数字识别任务应用的是全连接网络进行特征提取即将一张图片上的所有像素点展开成一个1维向量输入网络存在如下两个问题
1. 输入数据的空间信息被丢失。 空间上相邻的像素点往往具有相似的RGB值RGB的各个通道之间的数据通常密切相关但是转化成1维向量时这些信息被丢失。同时图像数据的形状信息中可能隐藏着某种本质的模式但是转变成1维向量输入全连接神经网络时这些模式也会被忽略。
2. 模型参数过多容易发生过拟合。 在手写数字识别案例中每个像素点都要跟所有输出的神经元相连接。当图片尺寸变大时输入神经元的个数会按图片尺寸的平方增大导致模型参数过多容易发生过拟合。
为了解决上述问题我们引入卷积神经网络进行特征提取既能提取到相邻像素点之间的特征模式又能保证参数的个数不随图片尺寸变化。
图6 是一个典型的卷积神经网络结构
多层卷积和池化层组合作用在输入图片上
在网络的最后通常会加入一系列全连接层
ReLU激活函数一般加在卷积或者全连接层的输出上
网络中通常还会加入Dropout来防止过拟合。 图6卷积神经网络经典结构 说明
在卷积神经网络中计算范围是在像素点的空间邻域内进行的卷积核参数的数目也远小于全连接层。卷积核本身与输入图片大小无关它代表了对空间邻域内某种特征模式的提取。比如有些卷积核提取物体边缘特征有些卷积核提取物体拐角处的特征图像上不同区域共享同一个卷积核。当输入图片大小不一样时仍然可以使用同一个卷积核进行操作。 卷积Convolution
这一小节将为读者介绍卷积算法的原理和实现方案并通过具体的案例展示如何使用卷积对图片进行操作主要涵盖如下内容 卷积计算 填充padding 步幅stride 感受野Receptive Field 多输入通道、多输出通道和批量操作 卷积算子应用举例 卷积计算
卷积是数学分析中的一种积分变换的方法
在图像处理中采用的是卷积的离散形式。这里需要说明的是在卷积神经网络中卷积层的实现方式实际上是数学中定义的互相关 cross-correlation运算
与数学分析中的卷积定义有所不同这里跟其他框架和卷积神经网络的教程保持一致都使用互相关运算作为卷积的定义具体的计算过程如 图7 所示。 图7卷积计算过程 说明
卷积核kernel也被叫做滤波器filter假设卷积核的高和宽分别为kh和kw则将称为kh×kw卷积比如3×5卷积就是指卷积核的高为3, 宽为5。 【思考】 当卷积核大小为3×33 \times 33×3时bbb和aaa之间的对应关系应该是怎样的 图8图形填充 感受野Receptive Field 输出特征图上每个点的数值是由输入图片上大小为kh×kwk_h\times k_wkh×kw的区域的元素与卷积核每个元素相乘再相加得到的所以输入图像上kh×kwk_h\times k_wkh×kw区域内每个元素数值的改变都会影响输出点的像素值。我们将这个区域叫做输出特征图上对应点的感受野。感受野内每个元素数值的变动都会影响输出点的数值变化。比如3×33\times33×3卷积对应的感受野大小就是3×33\times33×3如 图10 所示。 图10感受野为3×3的卷积 而当通过两层3×33\times33×3的卷积之后感受野的大小将会增加到5×55\times55×5如 图11 所示。 步幅stride
图8 中卷积核每次滑动一个像素点这是步幅为1的特殊情况。图9 是步幅为2的卷积过程卷积核在图片上移动时每次移动大小为2个像素点。 图9步幅为2的卷积过程 当宽和高方向的步幅分别为shs_hsh和sws_wsw时输出特征图尺寸的计算公式是
HoutH2ph−khsh1H_{out} \frac{H 2p_h - k_h}{s_h} 1HoutshH2ph−kh1
WoutW2pw−kwsw1W_{out} \frac{W 2p_w - k_w}{s_w} 1WoutswW2pw−kw1
假设输入图片尺寸是H×W100×100H\times W 100 \times 100H×W100×100卷积核大小kh×kw3×3k_h \times k_w 3 \times 3kh×kw3×3填充phpw1p_h p_w 1phpw1步幅为shsw2s_h s_w 2shsw2则输出特征图的尺寸为
Hout1002−32150H_{out} \frac{100 2 - 3}{2} 1 50Hout21002−3150
Wout1002−32150W_{out} \frac{100 2 - 3}{2} 1 50Wout21002−3150 感受野Receptive Field
输出特征图上每个点的数值是由输入图片上大小为kh×kwk_h\times k_wkh×kw的区域的元素与卷积核每个元素相乘再相加得到的所以输入图像上kh×kwk_h\times k_wkh×kw区域内每个元素数值的改变都会影响输出点的像素值。我们将这个区域叫做输出特征图上对应点的感受野。感受野内每个元素数值的变动都会影响输出点的数值变化。比如3×33\times33×3卷积对应的感受野大小就是3×33\times33×3如 图10 所示。 图10感受野为3×3的卷积 而当通过两层3×33\times33×3的卷积之后感受野的大小将会增加到5×55\times55×5如 图11 所示。 图11感受野为5×5的卷积 因此当增加卷积网络深度的同时感受野将会增大输出特征图中的一个像素点将会包含更多的图像语义信息。 多输入通道、多输出通道和批量操作
前面介绍的卷积计算过程比较简单实际应用时处理的问题要复杂的多。例如对于彩色图片有RGB三个通道需要处理多输入通道的场景。输出特征图往往也会具有多个通道而且在神经网络的计算中常常是把一个批次的样本放在一起计算所以卷积算子需要具有批量处理多输入和多输出通道数据的功能下面将分别介绍这几种场景的操作方式。 图12多输入通道计算过程 多输出通道场景
一般来说卷积操作的输出特征图也会具有多个通道CoutC_{out}Cout这时我们需要设计CoutC_{out}Cout个维度为Cin×kh×kwC_{in}\times{k_h}\times{k_w}Cin×kh×kw的卷积核卷积核数组的维度是Cout×Cin×kh×kwC_{out}\times C_{in}\times{k_h}\times{k_w}Cout×Cin×kh×kw如 图13 所示。
对任一输出通道cout∈[0,Cout)c_{out} \in [0, C_{out})cout∈[0,Cout)分别使用上面描述的形状为Cin×kh×kwC_{in}\times{k_h}\times{k_w}Cin×kh×kw的卷积核对输入图片做卷积。将这CoutC_{out}Cout个形状为Hout×WoutH_{out}\times{W_{out}}Hout×Wout的二维数组拼接在一起形成维度为Cout×Hout×WoutC_{out}\times{H_{out}}\times{W_{out}}Cout×Hout×Wout的三维数组。 说明
通常将卷积核的输出通道数叫做卷积核的个数。 图13多输出通道计算过程 批量操作
在卷积神经网络的计算中通常将多个样本放在一起形成一个mini-batch进行批量操作即输入数据的维度是N×Cin×Hin×WinN\times{C_{in}}\times{H_{in}}\times{W_{in}}N×Cin×Hin×Win。由于会对每张图片使用同样的卷积核进行卷积操作卷积核的维度与上面多输出通道的情况一样仍然是Cout×Cin×kh×kwC_{out}\times C_{in}\times{k_h}\times{k_w}Cout×Cin×kh×kw输出特征图的维度是N×Cout×Hout×WoutN\times{C_{out}}\times{H_{out}}\times{W_{out}}N×Cout×Hout×Wout如 图14 所示。 图14批量操作 卷积算子应用举例
下面介绍卷积算子在图片中应用的三个案例并观察其计算结果。
案例1——简单的黑白边界检测
下面是使用Conv2D算子完成一个图像边界检测的任务。图像左边为光亮部分右边为黑暗部分需要检测出光亮跟黑暗的分界处。
设置宽度方向的卷积核为[1,0,−1][1, 0, -1][1,0,−1]此卷积核会将宽度方向间隔为1的两个像素点的数值相减。当卷积核在图片上滑动时如果它所覆盖的像素点位于亮度相同的区域则左右间隔为1的两个像素点数值的差为0。只有当卷积核覆盖的像素点有的处于光亮区域有的处在黑暗区域时左右间隔为1的两个点像素值的差才不为0。将此卷积核作用到图片上输出特征图上只有对应黑白分界线的地方像素值才不为0。具体代码如下所示结果输出在下方的图案中。
import matplotlib.pyplot as plt
import numpy as np
import paddle
from paddle.nn import Conv2D
from paddle.nn.initializer import Assign
%matplotlib inline# 创建初始化权重参数w
w np.array([1, 0, -1], dtypefloat32)
# 将权重参数调整成维度为[cout, cin, kh, kw]的四维张量
w w.reshape([1, 1, 1, 3])
# 创建卷积算子设置输出通道数卷积核大小和初始化权重参数
# kernel_size [1, 3]表示kh 1, kw3
# 创建卷积算子的时候通过参数属性weight_attr指定参数初始化方式
# 这里的初始化方式时从numpy.ndarray初始化卷积参数
conv Conv2D(in_channels1, out_channels1, kernel_size[1, 3],weight_attrpaddle.ParamAttr(initializerAssign(valuew)))# 创建输入图片图片左边的像素点取值为1右边的像素点取值为0
img np.ones([50,50], dtypefloat32)
img[:, 30:] 0.
# 将图片形状调整为[N, C, H, W]的形式
x img.reshape([1,1,50,50])
# 将numpy.ndarray转化成paddle中的tensor
x paddle.to_tensor(x)
# 使用卷积算子作用在输入图片上
y conv(x)
# 将输出tensor转化为numpy.ndarray
out y.numpy()
f plt.subplot(121)
f.set_title(input image, fontsize15)
plt.imshow(img, cmapgray)
f plt.subplot(122)
f.set_title(output featuremap, fontsize15)
# 卷积算子Conv2D输出数据形状为[N, C, H, W]形式
# 此处N, C1输出数据形状为[1, 1, H, W]是4维数组
# 但是画图函数plt.imshow画灰度图时只接受2维数组
# 通过numpy.squeeze函数将大小为1的维度消除
plt.imshow(out.squeeze(), cmapgray)
plt.show()
# 查看卷积层的权重参数名字和数值
print(conv.weight)
# 参看卷积层的偏置参数名字和数值
print(conv.bias)
案例2——图像中物体边缘检测
上面展示的是一个人为构造出来的简单图片使用卷积网络检测图片明暗分界处的示例。对于真实的图片也可以使用合适的卷积核(3*3卷积核的中间值是8周围一圈的值是8个-1)对其进行操作用来检测物体的外形轮廓观察输出特征图跟原图之间的对应关系如下代码所示
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
import paddle
from paddle.nn import Conv2D
from paddle.nn.initializer import Assign
img Image.open(./work/images/section1/000000098520.jpg)# 设置卷积核参数
w np.array([[-1,-1,-1], [-1,8,-1], [-1,-1,-1]], dtypefloat32)/8
w w.reshape([1, 1, 3, 3])
# 由于输入通道数是3将卷积核的形状从[1,1,3,3]调整为[1,3,3,3]
w np.repeat(w, 3, axis1)
# 创建卷积算子输出通道数为1卷积核大小为3x3
# 并使用上面的设置好的数值作为卷积核权重的初始化参数
conv Conv2D(in_channels3, out_channels1, kernel_size[3, 3], weight_attrpaddle.ParamAttr(initializerAssign(valuew)))# 将读入的图片转化为float32类型的numpy.ndarray
x np.array(img).astype(float32)
# 图片读入成ndarry时形状是[H, W, 3]
# 将通道这一维度调整到最前面
x np.transpose(x, (2,0,1))
# 将数据形状调整为[N, C, H, W]格式
x x.reshape(1, 3, img.height, img.width)
x paddle.to_tensor(x)
y conv(x)
out y.numpy()
plt.figure(figsize(20, 10))
f plt.subplot(121)
f.set_title(input image, fontsize15)
plt.imshow(img)
f plt.subplot(122)
f.set_title(output feature map, fontsize15)
plt.imshow(out.squeeze(), cmapgray)
plt.show()Figure size 1440x720 with 2 Axes