计算机视觉技术是一门包括计算机科学与工程、神经生理学、物理学、信号处理、认知科学、应用数学与统计等多学科的综合性科学技术, 是人工智能的一个重要分支, 目前在智能安防、自动驾驶汽车、医疗保健、生成制造等领域具有重要的应用价值。
计算机视觉包括了诸多不同的研究方向,比较基础和热门的方向有物体识别和检测(Object Detection)、语义分割(Semantic Segmentation)、运动和跟踪(Motion & Tracking)、视觉问答(Visual Question & Answering)等 。
- 对于计算机视觉的分类任务,很长一段时间里流行研究者通过经验与智慧所设计并生成的手工特征。图像分类研究的主要流程是:
- 获取图像数据集;
- 使用已有的特征提取函数生成图像的特征;
- 使用机器学习模型对图像的特征分类。
卷积神经网络就是含有卷积层的神经网络,深度卷积神经网络的兴起改变了计算机视觉任务中手工设计特征的传统,引领了诸多影响深远的研究。
图像
我们在进行图像任务时,需要了解图像的基础知识。图像是由像素点组成的,每个像素点的值范围为: [0, 255], 像素值越大意味着较亮。比如一张 200x200 的图像, 则是由 40000 个像素点组成, 如果每个像素点都是 0 的话, 意味着这是一张全黑的图像。
我们看到的彩色图一般都是多通道的图像, 所谓多通道可以理解为图像由多个不同的图像层叠加而成, 例如我们看到的彩色图像一般都是由 RGB 三个通道组成的。
像素和通道的理解
import numpy as np
import matplotlib.pyplot as plt
# 1. 图像基本理解
def test01():
img = np.zeros([200, 200])
print(img)
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.show()
img = np.full([255, 255], 255)
print(img)
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.show()
# 2. 图像的通道
def test02():
img = plt.imread('data/彩色图片.png')
# 修改数据的维度
img = np.transpose(img, [2, 0, 1])
# 打印所有通道
for channel in img:
print(channel)
plt.imshow(channel)
plt.show()
# 修改透明度
img[3] = 0.05
img = np.transpose(img, [1, 2, 0])
plt.imshow(img)
plt.show()
在计算机视觉领域, 往往我们输入的图像都很大,使用全连接网络的话,计算的代价较高. 另外图像也很难保留原有的特征,导致图像处理的准确率不高,卷积神经网络(Convolutional Neural Network)是含有卷积层的神经网络. 卷积层的作用就是用来自动学习、提取图像的特征。
CNN网络主要有三部分构成:卷积层、池化层和全连接层构成,其中卷积层负责提取图像中的局部特征;池化层用来大幅降低参数量级(降维);全连接层类似人工神经网络的部分,用来输出想要的结果。
全连接神经网络的2大缺陷
首先是原理上的缺陷:BP神经网络仍然是有监督的传统机器学习方法,会一定程度上丢失了图像中的结构信息,从而丢失了一些对旋转扭曲等的不变性。而且要求输入的大小是固定的,为了学习到如偏移等微小的变化,需要有足够多的参数和足够多丰富的样本。
还有一个就是结构上的缺陷:参数非常多,容易丢失空间信息。如果一个隐藏层特征图像大小为100×100,输入层的特征图像大小为100×100,这意味着学习这一层需压要108108的参数。如果以32位的浮点数进行存储,就需要4×1084×108的字节的存储量,约等于400MB的参数量。
卷积在工程和数学上有非常多的应用,在信号处理领域中,任意一个线性系统的输出,就是输入信号和系统激励函数的卷积。放到数字图像处理领域,卷积操作一般指图像领域的二维卷积。
卷积神经网络基本原理
- 二维互相关(cross-correlation)运算的输入是一个二维输入数组和一个二维核(kernel)数组,输出也是一个二维数组,其中核数组通常称为卷积核或过滤器。卷积核的尺寸通常小于输入数组,卷积核在输入数组上滑动,在每个位置上,卷积核与该位置处的输入子数组按元素相乘并求和,得到输出数组中相应位置的元素。
- 二维卷积层将输入和卷积核做互相关运算,并加上一个标量偏置来得到输出。卷积层的模型参数包括卷积核和标量偏置。
- 卷积层得名于卷积运算,但卷积层中用到的并非卷积运算而是互相关运算。我们将核数组上下翻转、左右翻转,再与输入数组做互相关运算,这一过程就是卷积运算。由于卷积层的核数组是可学习的,所以使用互相关运算与使用卷积运算并无本质区别。
- 二维卷积层输出的二维数组可以看作是输入在空间维度(宽和高)上某一级的表征,也叫特征图。
- 填充(padding)是指在输入高和宽的两侧填充元素(通常是0元素)
import torch
from torch import nn
def corr2d(X, K): # X 是输入,K是卷积核
h, w = K.shape # 获取卷积核的大小
Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
for i in range(Y.shape[0]):
for j in range(Y.shape[1]):
Y[i, j] = (X[i: i + h, j: j + w] * K).sum() # 累加
return Y
X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) # 模拟一个输入
K = torch.tensor([[0, 1], [2, 3]]) # 模拟一个卷积核
corr2d(X, K)
用卷积来学习
图像都是用方形矩阵来表达的,学习的本质就是要抽象出特征,以边缘检测为例。它就是识别数字图像中亮度变化明显的点,这些点连接起来往往是物体的边缘。传统的边缘检测常用的方法包括一阶和二阶导数法,本质上都是利用一个卷积核在原图上进行滑动,只是其中各个位置的系数不同,如果要用sobel算子完成一次完整的边缘检测,就要同时检测x方向和y方向,然后进行融合。这就是两个通道的卷积,先用两个卷积核进行通道内的信息提取,再进行通道间的信息融合。 这就是卷积提取特征的本质,而所有基于卷积神经网络来学习的图像算法,都是通过不断的卷积来进行特征的抽象,直到实现网络的目标。
卷积神经网络的优势
- 卷积神经网络不再是有监督学习了,不需要从图像中提取特征,而是直接从原始图像数据进行学习,这样可以最大程度的防止信息在还没有进入网络之前就丢失。
- 能更好的学习,参数低