计算机视觉笔记:内容包含深度学习、图像处理、图像特征、图像分类、目标检测、图像分割等基础知识。
Tensorflow:深度学习开源框架,封装了大量深度学习函数。tensorflow系统:tf.data加载数据;tf.deras构建模型;gpu训练模型;tensorflow hub预训练;tensorflow serving部署模型。
张量:多维数组。一维、二维、三维等。
变量:形状不可变的张量。2*2形状就一直是2*2
过程:
导入工具包
数据读取
数据处理:目标值热编码
模型构建
模型训练
模型评估
回调函数(控制训练过程)
模型保存
全连接神经网络
全连接神经网络:输入层、输出层、隐藏层。
激活函数:向神经网络加入非线性因素,可以拟合曲线等任意函数;归一化。
Sigmoid:0-1。会梯度消失=0。y中心不为0。二分类输出层。
Softmax:0-1。多分类输出层。
Tanh:0-1。会梯度消失=0。y中心为0。隐层。
Relu:x<0时,导数=0,权重不更新,神经元死亡。好处是可以缓解过拟合。隐层。
Leakyrelu:x<0时,导数=0.1。防止神经元死亡。隐层。
参数初始化:偏置初始化(0)+权重初始化。权重初始化包括:随机~(正态);标准~(均匀);xavier初始化(正态+均匀);he初始化(正态+均匀)(正向传播时激活值的方差不变,反向传播时梯度的方差不变。区分xavier是方差均不变。)。
正态分布(高斯分布):均值μ,标准差σ。标准正态分布:均值0,标准差1
均匀分布:(a-b)/n
模型的层构建方法
(1)input+layers+model法:
input(shape输入的维度;输入层名字);
x=dense()(input)
x=dense()(x)
model( )
(2)sequential(layers)法:
(3)class mymodel(def init;def call):
损失函数:预测值与真实值之间的差异。分类损失+回归损失。
分类损失:交叉熵损失。多分类、二分类。
多分类损失:0.1是预测属于某类别的预测概率。0,1是目标值。y=1,p越大越好。
二分类损失:y是真实属于某类别的真实概率。y``是预测属于某类别的预测概率。
回归损失:mae(最小绝对误差L1)、mas(最小均方误差L2)、smooth L1(L1和L2的结合,内弯外直,内2外1)。
优化函数:用于优化权重和偏置。
前向传播产生预测结果,计算损失函数。
在损失最小时反向计算导数(反向传播算法=bp算法):根据损失函数对权重和偏置的层层偏导(链 式法则)更新权重和偏置(梯度下降法)。
优化思路:令权重和偏置的更新更加平滑。
优化方法:
修梯度:动量法:梯度使用指数加权平均(当前平滑=历史平滑+当前真实)。
修学习率α:Adagrad:梯度使用累加平方和。
Rmsprop;。梯度使用累加平方和的指数加权平均。
修梯&修α:adam:动量法+Rmsprop。adam思想和梯度下降差不多,但是优化效率更高,如图中的绿色箭头,考虑到红色触底后的惯性方向,绿色箭头能更快达到最优解。
动量让损失函数不容易卡在梯度为0的地方。A引入梯度平方和r(二阶矩)让学习率减小。R引入beta1让r衰减,让学习率变大加快收敛。Ad衰减引入beta2让s(一阶矩)衰减,从而让梯度变小;同时引入t,让t越小的时候,r和s越大。
复习:
1、梯度下降法:损失函数对权重求偏导,损失函数下降的最快的方向。学习率应当先快后慢。
BGD(批量):所有样本的梯度求和
SGD(随机):一个样本的梯度
MBGD(小批量):小部分样本的梯度求和。best
更新后权重=初始权重-学习率*损失函数对权重求偏导
1 -0.1*1 =0.9
Epoch:所有样本送入网络训练的次数=迭代数
Batchsize:每组送入网络训练的样本数量=每组数量。每组数量*组数=n
Iter:训练batch的次数=batch组数*迭代数
鞍点=局部最小值
2、链式传导:将复合导数拆分成一层层的初级导数
学习率退火:学习率衰减的方式。包括:分段常数衰减t;指数衰减e^t;逆时间衰减1/t。
t表示不同迭代次数=时间。
正则化:减少泛化误差;缓解网络过拟合。
泛化误差:新样本上的误差
正则化方法:范数惩罚;提前终止;dropout
(1)范数惩罚:L1&L2正则化。损失函数中加入L1&L2范数,使得权重衰减或变成0,从而让某一项减小或消失,简化模型。超参数lambda
L2正则化:
L1正则化:
(2)dropout正则化:在迭代过程中,随机失活每一层中的部分神经元。
(3)提前停止:将一部分训练集作为验证集,当验证集的loss不再下降了,停止训练。
(4)BN层:网络训练时是一个批次一个批次地输入到网络中。对某一批次的神经元输出(设为m个x)进行标准化+重构,得到最终的输出结果给到下一层(y)。
·标准化:要先求均值和方差。目的:令均值为0。
·重构:gamma放大倍数,beta平移。这两个参数都是通过学习得到。重构是对标准化的结果做进一步处理,令均值不为0,这样有利于训练非线性神经网络。
Bn还可以避免梯度消失。Bn将样本规范化至0均值,1方差。从图中可以看出,sigmoid函数和他对应导数的曲线,可以看出sigmiod函数的梯度在0附近的时候变化是最大的,梯度也是最大的。归一化数据的话,就能让梯度维持在比较大的值和变化率。
卷神经网络CNN
卷神经网络:卷积层CONV、池化层POOL、全连接层FC。CONV特征提取(边缘、方向),POOL降维,FC输出结果。
滤波器=filter=卷积核=过滤器
卷积:滤波器和输入数据的局部区域做点积,最终得到的特征图会缩小。
Padding:零填充。(1)使卷积过程中特征图的大小不变。Padding=1加上一圈0,Padding=2加上一两圈0。(2)边缘信息被遍历的次数不一样,如图,①像素只会被遍历一次,②像素遍历多次,中间像素遍历次数最多。padding后能够使边缘像素多遍历一下,有助于模型提取边缘特征。
stride步长:卷积核的移动步长
多通道卷积:输入多通道图像(如rgb),每一层单独卷积,三层的值相加并放到对应位置
多卷积核卷积:卷积核数=特征图通道数。
输出的特征图尺寸:
Pooling池化层:降维=对特征图进行下采样。3*3最大池化层。
最大池化层:取扫描窗口的最大值最为输出。
平均池化层:取扫描窗口的平均值最为输出。起平滑作用。=GAP。
全连接层:将特征图转换成一维向量,随后进行分类或回归。
卷积(卷积+RELU固定搭配) |
池化(最大、平均) |
1*1 宽高不变,只改变特征的通道数(升维/降维)。卷积核的升降维度取决于1*1卷积核的通道数(几个)。 →假设输入图的尺寸为 32 * 32 * 3, 使用6个 1 * 1的卷积核卷积,得到的输出图大小为32 * 32 * 6。升维。 使用2个 1 * 1的卷积核卷积,得到的输出图大小为32 * 32 * 2,降维。 |
K=2。下采样:特征图shape/2,同时通道 数不变(*2?) |
5*5 = 两个3*3卷积
|
|
7*7 = 三个3*3卷积 |
|
s=2也和pooling一样起到下采样的作用,特征图shape/2,同时通道数*2。 s越大,特征图shape越小,保留的特征越少,但是计算效率高; s越小,特征图shape越大,保留的特征越多,但是计算效率低。 |
|
小卷积核的好处:
(1)多层小卷积核的堆叠(两个3*3卷积)可以达到和单层大卷积核(一个5*5卷积)一样的感受范围。但使用两层3x3卷积核使用的参数量要小于一层5 x 5卷积核。
当使用一层5x5卷积核时:参数量为:C x 5 x 5 x F = 25CF
当使用两层 3 x 3卷积核时:参数量为:(C x 3 x 3 x F) x 2 = 18CF,使用两层3x3卷积核使用的参数量要小
(2)网络加深可以引入更多的“非线性”。神经网络的激活函数可以带来“非线性”。使用多层卷积网络就可以多次使用激活函数,从而引入更多的非线性。
卷积神经网络优势:需要的参数少。
对比全连接层:
如题,有32*32*3的原图,那么10个5*5的卷积核(s=1,p=2),求总参数量?先看一个卷积核的情况:如图所示,左边是H为32的输入图,根据计算可得输出特征图的H’=32。5*5在32*32的输入图上滑动,每个5*5的区域会变为输出图中一个1*1的区域,由于输入有三层,因此每个5*5包含了5*5*3=75个特征,浓缩成输出图中的一格。由于卷积网络,是权重共享的,输入图中所有5*5滑动的区域共享权重,因此一个卷积核下,所需要的采纳数就是5*5*3=75。十个卷积核,总参数就是5*5*3=75。ppt讨论的是一个卷积核(this layer)的情况。
·看一下不共享权重的情况。如题,有32*32*3的原图,那么一个5*5的卷积核,有5*5*3=75个特征,对应到下一层中一个像素。下一层有32*32≈1000个像素,那么下一层接收总参数数量=75*1000*10(通道数10)=750000。参数数量非常多。
卷积层参数计算图解:
参数量为:3*3*3*5+5=135
图像分类:从给定的类别集合(狗、猫、熊猫...)中为图片分配对应的标签。输出:dog:95%, cat:4%, panda:1%
常用数据集:minist数据集(手写数字0-9)。CIFAR-10(10个类别)。CIFAR-100(10个类别)。ImageNet(22000个类别)
Conv2D:(filters卷积核个数,kernel size卷积核大小,strides=4,padding=’valid’,activation=None)
MaxPool2D:(pool size=(2,2)扫描窗口大小, strides=None,padding=’valid’)
keras.layers.Dense:(units, activation=None, use_bias=True, kernel_initializer='glorot_uniform',
输出:Num*H*W*C。
Alexnet:
Input |
CONV |
POOL MAX |
CONV |
POOL MAX |
CONV |
CONV |
CONV |
POOL MAX |
Flatten |
Dense+Dropou(0.5) |
Dense+Dropou(0.5)) |
Output |
227 *227 *3 |
f=96 k=11 s=4 a=relu |
p=3 s=2 |
f=256 k=5 p=same a= |
p=3 s=2 |
f=384 k=3 p= a= |
f=384 k=3 p= a= |
f=256 k=3 p= a= |
p=3 s=2 |
|
u=4096 a=relu
|
u=4096 a=relu
|
u=10 a=softmax
|
VGG16:用统一的3*3小卷积层
Input |
CONV n=2
|
POOL MAX |
CONV n=2
|
POOL MAX |
CONV n=3
|
POOL MAX |
CONV n=3
|
POOL MAX |
CONV n=3
|
POOL MAX |
Flatten |
Dense+Dropou(0.5) |
Dense+Dropou(0.5)) |
Output |
224 *224 *3 |
f=64 k=3 |
p=2 |
f=128 k=3 |
p=2 |
f=256 k=3 |
p=2 |
f=512 k=3 |
p=2 |
f=512 k=3 |
p=2 |
|
u=4096 a=relu
|
u=4096 a=relu
|
u=10 a=softmax
|
GooLeNet:
Inception:6个卷积核+1个池化层。64, (96,128) , (16,32) , 32。
B1 |
B2 |
B3 |
||||||
Input |
CONV
|
POOL MAX |
CONV
|
CONV
|
POOL MAX |
Inception |
Inception |
POOL MAX |
224 *224 *3 |
f=64 k=7 s=2 a=relu |
p=3 s=2 p=sa |
f=64 k=1 s=2 a=relu |
f=192 k=3 s=2 a=relu |
p=3 s=2 p=sa |
64, (96,128), (16,32) 32 |
128, (128,192) (32.96) 64 |
p=3 s=2 p=s |
B4 |
B5 |
||||||||||
Inception |
Aux classifier辅助输出 |
Inception |
Inception |
Inception |
Aux classifier |
Inception |
POOL MAX |
Inception |
Inception |
POOL Avg |
Output |
→c1、c2、c3、c4 192, (96,208), (16,48) 64
P1-1:CONV (c1,k=1) P2-1:CONV (c2[0],k=1) p2-1:CONV (c2 [1,k=3) P3-1:CONV (c3[0]),k=1) p3-1:CONV (c3[1],k=5) P4-1:CONV (c4,k=1) |
→filter size 128,核个数 1024神经元个数
Avg POOL (p=5,s=3) CONV (filter size[0],k=1) Flatten Dense(u=filter size[1]) Dense(u=10)
|
160, (112,224), (24,64) 64 |
128, (128,256), (24,64) 64 |
112, (144,288), (32,64) 64 |
128, 1024 |
256, (160,320), (32,128) 128 |
p=3 s=2 p=sa |
256, (160,320), (32,128) 128 |
384, (192,384), (48,128) 128 |
|
u=10 a=softmax
|
InceptionV2:将5*5的卷积用3*3的卷积替代。
InceptionV3:将3*3的卷积用3*1和1*3的卷积替代。
googlenet的优点:
- 模型又准又轻
- 引入Inception模块,利用不同卷积核提取不同程度的信息
- 采用1x1 卷积进行降维减少了计算量,增加模型深度提高非线性表达能力
- GAP, 每一个通道求平均即平均池化层,不用FC,减少了参数量
- 在训练时有辅助分类器
ResNet:残差网络,即残差模块的串联。ResNet18、34、50、152。
网格退化、网络退化:网络达到一定的深度后再加深,分类性能不会提高,而是会导致网络收敛更缓慢,准确率也随着降低。一般情况下,网络层数越深越容易学到一些复杂特征,理论上模型效果越好,但是由于深层网络中含有大量非线性变化,每次变化相当于丢失了特征的一些原始信息,从而导致层数越深退化现象越严重。
解决网络退化的思路:https://blog.csdn.net/u010879745/article/details/108068652
https://zhuanlan.zhihu.com/p/139772304
解决办法:Resnet block残差模块:相同通道的残差块的串联。
residual残差块:2个卷积层+BN+RELU。可引入1*1卷积层调整维度。
一条路x不变(恒等映射);一条路F(x)负责拟合相对于原始网络的残差。shortcut将Residual block的输入和输出进行跳跃连接。通俗理解:哪科不行补哪科?原来学的好的就保持原样,学之后好就用学之后的。不是训练让预x+残差F(x)逼近真H(x),而是让真H(x)-预x = 残差F(x),F(x)逼近于0,F(x)的优化 会比H(x)简单的多。这个简单的结构并不会给网络增加额外的参数和计算量,同时却可以大大增加模型的训练速度、提高训练效果,并且当模型的层数加深时,解决退化问题。
(理解为什么F(x)的优化会比H(x)简单的多:F(x,w)=H(x)-x,w为残差结构中的参数矩阵。在恒等映射情况下, F(x,w)=0 >> w=0,而参数初始化时一般都在0附近,使其产生恒等映射更加容易。)
经过shortcut后,H(x)=F(x)+x,相加是尺寸一样时才可以相加,尺寸一样时如上图;当尺寸不一样时,常通过1*1的卷积调整通道数。图中的实线、虚线就是为了区分这两种情况的:
实线的Connection部分,表示通道相同,采用计算方式为H(x)=F(x)+x
虚线的的Connection部分,表示通道不同,如第一个绿色矩形和第三个绿色矩形,分别是3x3x64和3x3x128的特征图,通道不同,采用的计算方式为H(x)=F(x)+Wx,其中W是卷积操作,用来调整x维度的。
ResNet34:
输入 |
残差 |
输出 |
|||||
Input |
CONV
|
BatchNormalization |
Activation |
POOL MAX |
Resnet block 1-4 |
POOL Avg |
Dense |
224 *224 *3 |
f=64 k=7 s=2 a=relu |
|
relu |
p=3 s=2 p=sa |
见下方 |
|
u=10 a=softmax |
Resnet block1 |
Resnet block2 |
Resnet block3 |
Resnet block4 |
||||||||||||
Resi =2conv |
Resi |
Resi |
Resi =3conv |
Resi |
Resi |
Resi |
Resi =3conv |
Resi |
Resi |
Resi |
Resi |
Resi |
Resi =3conv |
Resi |
Resi |
f=64 k=3 s=1 p=s |
f=64 k=3 s=1 p=s |
f=64 k=3 s=1 p=s |
f=128 k=3 s=2 p=s + f=128 k=1 s=2
|
f=128 k=3 s=1 p=s |
f=128 k=3 s=1 p=s |
f=128 k=3 s=1 p=s |
f=256 k=3 s=2 p=s + f=256 k=1 s=2 |
f=256 k=3 s=1 p=s |
f=256 k=3 s=1 p=s |
f=256 k=3 s=1 p=s |
f=256 k=3 s=1 p=s |
f=256 k=3 s=1 p=s |
f=512 k=3 s=2 p=s + f=512 k=1 s=2
|
f=512 k=3 s=1 p=s |
f=512 k=3 s=1 p=s |
每个residual中有两个conv卷积层。以上参数是两个conv的。
如层数过多需要调整通道数时,residual中可能另外会在后面加1*1的卷积。
除了first block,其他block的第一个residual另外还要添加1*1卷积,步长为2。
ResNet网络优点
(1)提出residual结构(残差结构),并搭建超深的网络结构(突破1000层)。BN(批量归一化)可以解决网络层数太深而出现的梯度消失问题,但是如果网络层数太多,这个方法也是不太管用的。所以就提出了resnet。
(2)使用batch normalization 加速训练(丢弃dropout)。
(3)学习结果对网络权重的波动变化更加敏感。
(4)相比传统的VGG网络,复杂度降低,所需的参数量下降。
(5)网络深度更深,不会出现梯度消失现象。
图像增强:增加数据的多样性。
方法:
(1)几何变换:翻转;旋转;裁剪;变形;缩放
(2)颜色变换:模糊;颜色变换;擦除;填充
微调:迁移学习。对于目标模型,只训练输出层,其余层的参数都是对源模型的参数微调得到的。
这就是所谓的迁移学习,说的简单一点就是把一个任务训练好的参数,拿到另外一个任务,作为神经网络的初始参数值,这样相比于你直接采用随机初始化的方法,精度可以有很大的提高。
具体步骤:(1)在源数据集(数据量很大的、如imagenet数据集)预训练源模型。
(3)创建目标模型,复制源模型除了输出层外的所有参数。(3)目标模型添加输出层,进行参数随机初始化、
(4)在目标数据集上从头训练输出层。
目标检测:在图中找出指定目标的类别和位置(分类和回归)
Anchor:毛框=先验框。
proposal候选区域:原图上的框
Bbox=矩形框=检测框
detections=预测框=TP+FP
GT框=found truths=真实框=TP+FN=目标的个数
RoI(Region of Interest):是通过不同区域(region)的选择方法,从原始图像(original image)得到的候选区域(proposal region)。但是RoI不等价于Bounding Box,它们可能看起来很像,但是RoI只是为了进一步处理而产生的候选区域。可以简单把RoI理解为“feature map”上的框。
Bounding Box:Bounding Box是指检测目标的边界矩形框。
位置:即bbox的表现形式:
左上角为原点。
极坐标(xmin,ymin,xmax,ymax)
中心点坐标(xcenter,ycenter,w,h)
目标检测开源数据集:PASCAL VOC(含VOC2007和VOC2012)(20类); MS COCO(90类)
PASCAL VOC:
Annotation:xml标注,如位置信息
Imagesets:action人的动作,layout人的肢体,main物体识别类型(负样本),segmentation用于分割的数据
Jpegimages:图片
Segmentationclass
Segmentationobject
MS COCO:每个segmentation+bounding box的精确坐标
常用的评价指标:定位——IOU,分类——mAP
(1)IOU交并比:两个矩形框(真实框pk检测框)的 相交面积/相并面积。IOU越大越相似。阈值一般为0.5,即iou大于0.5时,认为检测到目标物体。
计算IOU的流程:
·先获取两个bbox的坐标,找到其中左上(xmin,ymin)和右下(xmax,ymax)的坐标。计算两个矩形框面积。
·获取交集框的左上(xxmin,yymin)和右下(xxmax,yymax)的坐标。如xxmin=np,max( [xmin1,ymin2] )。计算交集面积
·Iou=交集面积/(area1+area2-并集面积)
(2)mAP:所有类别的PR曲线线下面积。AP是某一类PR曲线线下面积。
计算流程:
·标注TP、FP。P代表检测到了目标、没检测到的目标N在这里不论。每个GT框只会有一个TP(IOU>0.5),其他皆为FP(IOU<0.5或重复检测的)。
·根据不同检测框的置信程度从大到小排列。从上到下加和ACCTP、ACCFP。
·用ACCTP和ACCFP来计算P和R:
P=ACCTP/(ACCTP+ACCFP) 查准率=精度,
R=ACCTP/(ACCTP+ACCFN) 查全率=recall。每个预测框都可以根据累计值来计算P和R,形成PR。
·2010年后的,选择每个R点以后P的最大值作为该R点的P。
n 为什么不用精度(检测的好不好=p)和recall(有没有检测到目标物体)、而用map指标?因为精度和recall往往一个高,一个就会低,(如上图④所示)没有办法看到综合的检测效果。
n 已知条件:班级总人数100人,其中男生80人,女生20人。
目标:找出所有的女生
结果:从班级中选择了50人,其中20人是女生,还错误的把30名男生挑选出来了。TP=20;FP=30;FN=0;TN=50;
预 真 |
P女 |
N男 |
T对 |
本来是女,判断为女=20 |
本来是男,判断为男=50 |
F错 |
本来是女,判断为男=30 |
本来是男,判断为女=0。没有检测到目标物体,当成了背景 |
n 例题:人脸检测中检测出三张人脸,绿框是检测框,蓝框是真实框。三张图的置信度分别为0.9、0.8、0.7。阈值为0.9。求p和r。解:0.8、0.7的置信度低于阈值,被过滤掉,留下第一张预测为人脸,TP=1。另外两张没有检测到,属于检测漏了,因此本例中召回率很低。
1.2.3 F1 score指标
P和R指标有时候会出现的矛盾的情况,这样就需要综合考虑他们,最常见的方法就是F-Score。F-Measure是Precision和Recall加权调和平均:当参数α=1时,就是最常见的F1。F1综合了P和R的结果,当F1较高时则能说明试验方法比较有效。
NMS:非极大值抑制。去除冗余的检测框,保留分数最高的那一个。
选择具有最大置性度score的检测框M,将剩余检测框中与M相似(IOU>0.5)的框从列表B中移除至结果列表D。重复这个过程,直到检测框列表B为空。
第一轮:B分数最高,B放入D中。接着由于D、E与B的IOU>0.5,删除D、E。
第二轮:A分数最高,A放入D中。接着由于C与A的IOU>0.5,删除C。
目标检测方法:
two-stage算法:需要在多个预选框中筛选。更准。代表:RCNN、Fast RCNN、Faster RCNN
one-stage算法。不需要在多个预选框中筛选,直接输出目标检测结果。更快。YOLO
逻辑回归和线性回归的-
联系:逻辑回归可以理解为在线性回归后加了一个sigmoid函数。将线性回归变成一个0~1输出的分类问题。
区别:
1.线性回归用来预测连续的变量(房价预测),逻辑回归用来预测离散的变量(分类,癌症预测)
2. 线性回归是拟合函数,逻辑回归是预测函数
3. 线性回归的参数计算方法是最小二乘法,逻辑回归的参数计算方法是似然估计(梯度下降)的方法
softmax和svm的区别:都是分类器
softmax是典型的logistic regrssion分类器,其数出结果绝对值的大小即是该类别的概率,也就是说起直接输出概率,当然只是因为其数出结果恰好在0-1之间,我们可以当概率看待。
svm是广泛使用的一类分类器,可以实现线性可分到线性不可分的问题,svm下,我们可以完成类别的判定,但实际上我们得到的是类别的得分,而得分是按照所属可能的类别进行排序,但是得分绝对值的效果并没有什么特殊的含义,但在soft max里面,就可以直接输出所属类别概率值了。
Overfeat:滑动窗口+CNN+SVM+Regression回归
用滑动窗口获取检测框。穷尽不同的固定宽高比来适应目标。最后选择分类和定位结果最好的检测框。
CNN进行特征提取
使用支持向量机SVM进行分类,使用线性回归Regression返回框的结果
RCNN: SS+按候选区域CNN+按类别SVM+按类别Regression+按类别NMS
改进:
- 使用选择性搜索SS来获取候选区域:通过语义分割(相同颜色、边界、纹理会合并)进行候选区域的获取。
通常一张图片获取2000个候选区域,将这2000个区域送入CNN。
- 使用CNN网络进行特征提取。
- 固定输入到CNN中的候选区域大小(224*224);
- 微调:
·ImageNet ILSVRC2012。1000类,1000万张图。→预训练(有监督)。直接用AlexNet或VGG16网络,初始参数值不变。ILSVRC中有1000类,因此预训练阶段cnn模型的输出是1000个神经元。
·PASCAC VOC 2007。20类,1万张图。→复制预训练模型的参数作为初始化,微调调优参数。
换掉预训练的CNN模型的最后一层(全连接层),输出换成N+1个神经元(N个目标类别,1个背景类)(20+1=21)。并对最后一层采用参数随机初始化,其他层参数不变,进行训练(正样本IOU>0.5,负样本IOU<0.5)。获取每个候选区域特征的是4096维,一幅图像是2000*4096维特征。
- 使用SVM进行分类。多分类时,如果有N个类别的检测任务,就要使用N个SVM分类器。是猫&不是猫的概率,是狗&不是狗的概率...。。。每个分类器输出2000*4096→2000*2。
- 使用线性回归Regression进行boundingbox位置的修正定位。使红框更加接近绿框。即,使得检测框(px,py,pw,ph)通过参数学习(wx,wy,ww,wh),更加接近于真实框(tx,ty,tw,th)。
- NMS。在2000个候选区域中,每个类别计算IOU,保留一个最优检测框。
总结:
1.训练阶段多
2.训练耗时长,占用磁盘空间大。
3.VGG16模型处理时间长
4.图片形状在输入CNN网络时要固定大小,无法保证图片不变形(227*227 resize)
FastRCNN: CONV+ROI pooling+FC+Softmax目标分类& layer目标回归 = 一整套CNN
- 将整张图输入到CNN网络中获取整张图的特征图。使用SS获取候选区域(的坐标)。将候选区域映射到特征图中(在特征图中找到每一个候选区域对应的区域并截取【区域特征图】)。
- ROI pooling。固定特征图大小。
原先,224*224经过5次VGG16 pooling变为7*7。
现在,800*800经过5次VGG16 pooling变为25*25,25*25经过ROI pooling变为7*7(超参数H*W)。
- FC+Softmax目标分类。K+1个输出的概率值:P0、P1、...Pk。使用softmax代替了RCNN里面的多个SVM分类器。
- FC layer目标回归。K个输出的偏移量t^k:相对于候选框bbox的高度/宽度移位。
- 计算分类和回归的损失函数。k=u。
总结:
将RCNN中的CNN、SVM、Regression三个模块进行了整合,加快计算速度
候选区域映射。
ROI pooling克服了变形,能够固定尺寸。
FasterRCNN: backbone特征提取(ResNet+FPN深浅融合)→anchors先在特征图上滑动再对应到原图anchors。然后,anchors回归分类选择前6000个作为原图上的proposal(RPN网络)→原图上的proposal对应取特征图上的特征再固定维度(roipooling)→送入fasterrcnn对框出来的东西做识别的分类和回归(通常最后一步会有NMS,让每一类别只保留一个检测框)。
零、模型搭建前的准备
pascal = pascal_voc.pascal_voc("train") # 实例化voc数据集的类,选择训练集数据
model = faster_rcnn.FasterRCNN(num_classes=len(classes)) ## 实例化faster_rcnn模型,将预训练输出的类别长度作为参数传进去即可。因为预训练模型的输出类别和最终目标模型的类别数量必须一致
model((image,imagemeta,bbox,label),training=True) #传入要训练的图片信息
model.load_weights("weights/faster_rcnn.h5") # 加载训练好的weights。预训练是加载已经训练好的权重,不用自己重新训练
一、backbone特征提取网络(ResNet+FPN)。FPN:融合后特征P=当前层特征C+未来层特征的上采样M。
P2、3、4、5层特征传入后续网络。
二、训练RPN网络:从众多anchors中提取包含目标、且经过回归调整的候选区域proposal。(先把框给框出来)
·按原图尺寸(如尺度=面积=128)生成一组长宽比固定(1:1, 1:2, 2:1)参考框anchors,在特征图上逐点滑动(如FPN产生了128、64、32三种面积的特征图)(区分overfeat在原图滑动,步数更多),然后再对应回原图,得到原图上每个像素点生成9个anchors(k=9时),[H,W,9]。
·anchor的分类和回归结果:
1、分类:1*1卷积改变通道数为[H,W,18],然后reshape成9*[H,W,2],因为softmax需要输入和输出值都是2个通道。输出后再次通过reshape变成[H,W,18]
2、回归:1*1卷积改变通道数为[H,W,9*4] = [H,W,36]
·proposal层利用回归结果对anchors位置进行修正,对softmax概率值从大到小排序后选取前6000个anchor作为候选区域proposal。
三、ROIPooling:RPN产生的原图候选区域proposal属于FPN产生的多个尺度特征图的哪一层?
确定ROI(候选区域)所在的特征层第k层:。层数越高,特征图越小,越能容纳大尺寸ROI。
输出:候选区域映射的特征图,且特征图尺寸固定为7*7大小
四、FasterRCNN网络:将第一步生成的候选区域映射到的特征图传入,完成对候选区域的分类和回归(此时的候选区域也叫bbox)。(对框出来的东西做识别)
·通过全连接和softmax对候选区域进行分类
·再次对候选区域进行回归修正,获取更高精度的检测框
训练过程:
一、训练RPN网络:
·随机采样256个anchor ,计算损失函数,其中采样的正负anchor(与GT的IOU>或<0.5)的比例尽可能是1:1(29正+227负)。
·通过从零均值标准差为0.01的高斯分布中获取的权重来随机初始化所有新层(最后一个卷积层其后的层)。所有其他层(即共享的卷积层)是通过对ImageNet分类预训练的模型来初始化的。
·采用带动量的随机梯度下降算法对网络进行训练
二、训练FasterRCNN网络
·将第一步生成的候选区域映射到特征图中。对所有正负样本根据IOU值进行排序,每张图片取前256个区域,将这些区域的坐标保存下来,作为该图片的训练样本,正负proposal(与GT的IOU>或<0.5)的比例尽可能是1:1(64正+192负)。
·用于Softmax分类和检测框回归的全连接层的权重分别使用具有方差0.01和0.001的零均值高斯分布初始化,偏置初始化为0。特征提取网络使用ImageNet预训练的模型初始化
·使用梯度下降算法进行优化
三、训练RPN网络:用第二步中的bb参数来训练RPN
四、训练FasterRCNN网络:用第三步中再根据第三步的bb参数微调一下
RPN Loss与Fast RCNN loss相加,然后进行梯度下降优化,更新参数。
总结:
1、多尺度目标:通过RPN网络候选区域,并使用不同大小和长宽比的anchors来解决多尺度问题。anchor技术将检测问题转换为“这个固定参考框中有没有目标,目标框偏离参考框多远”,不再需要多尺度遍历滑窗
2、通过计算anchors与真实框的交并比IOU,并通过阈值建立正负样本
3、样本不平衡:每批次随机采样256个anchors进行边框回归训练,并尽可能保证正负样本数相同,避免负样本过多导致的梯度统治问题
4、两个网络的训练过程中,都是只有正样本有回归损失,负样本不参与计算回归损失。
YOLO系列
端到端的单阶段目标的检测网络:YOLO系列、SSD。
目标检测选择yolo还是maskrcnn?
onestage是直接用一个cnn网络提取特征并完成分类回归x,y,w,h。速度快(FPS高),适用于视频检测。
两阶段多了一个预选候选区域的阶段。效果好(map高)。
YOLOV1:
思想:将图像分割成7*7的网格,每个网格生成两个bbox(按照感觉设立),一共是7*7*2=98个边框,对这98个bbox进行分类和回归。即对bbox的x,y,w,h进行微调,以适应检测目标。返回的定位结果是归一化的相对位置,
网络架构:使用GoogleNet网络。预训练前20层(ImageNet,224*224)——训练所有层(VOC,488*488)
输入:448*448*3的图像(有fc层,因此有大小限制)
添加卷积conv、pooling(GoogleNet)
全连接fc:输出层使用线性函数作为激活函数,其余全部用leaky relu。全连接层用dropout防止过拟合
输出:所有网格可能包含对象的概率+2个位置及位置的可能性。之后用NMS选出最有可能的结果。
7*7*30。=7*7*(20+(1+1)+(4+4))。voc有20类+两个置信度+两个坐标,最后只保留置信度大的框。voc的20类是跟采用的数据集有关,voc就是20类。
置信度含义:框画的准不准。
如猫的中心点落在哪一个,哪一格负责检测猫这个目标,20个类中“猫”的标签值为1。两个
bbox,iou大的那个置信度为1,iou小的那个置信度为0。如果非中心点,两个置信度均为0
缺点:一个网格只能检测一个目标,如有狗和猫的中心点落在一个框里,只能检测为狗或猫之一。
训练:令7*7*30的输出最接近真实的7*7*30,即令其损失最小。
MSE损失=位置误差(中心点+宽度+高度误差)+置信度误差+分类误差。只有置信度需要考虑不负责检测目标的bbox(背景的置信度越接近0越好,前景的置信度越接近1越好),其他损失不需要。背景的置信度的重要性没有前景的置信度重要,因此可通过设置λ=0.1来调节,否则大部分损失可能都由背景影响了。
n 解释:为什么位置误差的w、h要加根号?如图蓝笔所示,根号下x的变化,在x小的时候y变化剧烈,在x大的时候y变化平缓。加了根号能促进小目标(h、w也小)的检测效果。
n Yolov1缺点:一个网格只能检测一个目标。如果数据集中有狗、斑点狗、芭比狗等包含关系的标签,softmax不能分类。
YoloV2:
网络架构:使用Darknet-19网络。
预训练前20层(ImageNet,224*224)——微调(ImageNet,488*488)——训练所有层(VOC+COCO,488*488)
输入:416*416*3的图像(v1版本:448,不能被32整除,影响下采样)。可以输入任何尺寸的图像。
添加卷积conv、pooling(Darknet-19=32倍下采样=5次卷积=2^5=32)
去掉全连接fc、dropout。只要确保输入416*416*3,最后提取的特征格式是13*13*5*25即可。
输出:13*13*5*25。5个先验框,voc有20类+一个置信度+一个边框坐标。(yolov1:7*7*30)
- BN层:v2放弃dropout。解决反向传播中梯度消失和梯度爆炸的问题。卷积→激活 变为 卷积→批标准化→激活。每过一次卷积就做一次归一化,让收敛更加容易。(如高中每个月都有月考)
- 使用更高分辨率的图像来训练分类网络。缓解分辨率突然切换造成的影响。
预训练前20层(ImageNet,224*224)——微调(ImageNet,488*488)——训练所有层(VOC+COCO,488*488)
- Anchorbox:每一网格中预设5个先验框anchor。YOLO1的7*7*2个bbox 变为 13*13*5=845个anchor。
- 对训练集中(ImageNet)标注的边框进行聚类分析=统计频率,得到最常见的五种尺寸的anchor。
聚类距离不是欧式距离,因为欧式距离容易造成大框之间的距离大,小框之间的距离小。用的距离是1-iou,两个框重叠度越高,iou越高,1-iou越小。之后又经过分析,发现当k=5时,iou比较高,再往后,iou增长的速度比较慢了,因为100个人,如果分成3组,组与组之间的差异大,如果分成50组,组与组之间的差异就不会特别大了。
因此选择k=5。
- 边框的预测:bx,by,bw,bh。不直接预测边界框,而是预测偏移tx、ty和尺度tw、th。
网络输出t & 先验框p & 基数c → 预测结果b(经过sigmoidσ进行归一化)。返回的定位结果也是归一化的。但是原点bx、by的偏移位置不能超过蓝色阴影框,(yolov1返回的定位结果是归一化的。但原点可能会乱飘到蓝色阴影框外,乱飞,拟合效果不好)。(bx+1和by+1是因为其左上角的格子大小就是1)。
特征图中的位置(bx,by,bw,bh)*32 → 原图中的位置。因为Darknet-19=32倍下采样。
- 细粒度特征融合passthrough:最后一层时感受野太大了,小目标可能丢失了,需融合之前的特征。
如最终的特征图是13*13*1024大小的,将其前一个特征图(感受野较小,有小目标的特征),大小是26x26x512的,对其1拆4。两者叠加到一起作为输出的特征图13*13*3072。(512*4+1024=3072)
拓展:感受野:特征图上的点能看到原始图像多大区域。如下图的感受野为5*5。
感受野越大,浓缩得越多,细节特征缺失得越多,更专注于全局特征。
如果堆叠3个3*3的卷积层,并且保持滑动窗口步长为1,其感受野就是7*7的了。这跟一个使用7*7卷积核的结果是一样的,那为什么非要堆叠3个小卷积呢?
假设输入大小都是h*w*c,并且都是用c个卷积核(得到c个特征图),可以用来计算一下各自所需参数:
1个7*7卷积核所需参数: =CX(7X7xC)=49C^2
3个3*3卷积核所需参数: =3×CX(3x3×C)=27C^2
很明显,堆叠小的卷积核所需的参数更少一些,并且卷积过程越多,特征提取: 也会越细致,加入的非线性变换也随着增多,还不会增大权重参数个数,这就是VGG网络的甚本出发点,用小的卷积核来完成体特征提取操作。
- 多分辨率的图像进行网络训练:多尺度训练。
YOLO2中没有全连接层,可以输入任何尺寸的图像。因为整个网络采用了320,352,…608等10种输入图像的尺寸。训练时每10个batch 就随机更换一种尺寸,使网络能够适应各种大小的对象检测。
- 使用了Darknet-19网络,只有卷积和池化。没有全连接层。卷积为3*3小卷积、1*1卷积调整通道。
3*3为小卷积,使感受野变大;1*1卷积只减少通道,不改变特征图大小,能够节省参数数量。
9、识别对象:使用ImageNet数据集进行辅助训练,使网络可以分辨更多类别的数据
ImageNet:只有分类样本。1000类。用于分类,针对整张图。
COCO:分类&回归样本。80类。用于目标检测,针对某一部分。
VOC:分类&回归样本。20类。用于实例分割,针对像素点。
YoloV3:特征图3类→特征图上的先验框3*3→分类回归结果
网络架构:使用Darknet-53网络。
输入:416*416*3的图像
没有pooling,用s=2的卷积层完成下采样(Darknet-53=32倍)。因为池化会压缩特征,干脆直接全部做卷积,速度更快。
去掉全连接fc
输出:13*13*3*(4+1+80),26*26*3*(4+1+80),52*52*3*(4+1+80)。不同数据集可能不是80。
不同感受野配不同尺寸先验框。3个尺度各有3个先验框,coco有80类+一个置信度+一个边框坐标。logistic
(区分fastrcnn:3*3个框,3类尺寸,3类长宽比。区分yolov1:2个框,yolov2:5个框。Yolov3:9个框)
组件:
1、CBL: 最小组件,由Conv+Bn+Leaky relu激活函数三者组成。
2、Res unit:借鉴Resnet网络中的残差结构,让网络可以构建的更深。
3、ResX:由一个CBL和X个残差组件构成, 是Yolov3中的大组件。每个Res模块前面的CBL都起到下采样的作用,因此经过5次Res模块后,得到的特征是416>208>104>52>26>13大小。
Concat:张量拼接,会扩充两个张量的维度
Add:张量相加,张量直接相加,不会扩充维度
Backbone中卷积层的数量: 每个ResX中包含1+2X个卷积层,因此整个主干网络Backbone中一共包含1+(1+2x1)+(1+2x2)+(1+2x8)+(1+2x8)+(1+2x4) =52。不过在目标检测Yolov3中,去掉FC层,仍然把Yolov.3的主干网络叫做Darknet53结构。
避免越学越差。给原来的浅层特征(如19层)也给一个参数,如果(20、21层)后面几层表现更好,在训练过程中参数会提高,如果后面几层越学越差,19层的参数随着训练提高。思想:至少不比原来差。
一、backbone:darknet53没有池化和全连接层。Darknet-53
二、FPN特征融合:区分:yolov1和yolov2都是直接在最深层的特征图上检测,ssd是在不同层的特征图上检测。
三、为了检测不同大小的物体,输出3个尺度的特征(多尺度特征):x1、x2、x3
FPN:
FBB+FPN+预测:
四、先验框:coco数据集聚类出9种先验框。每个特征尺度分配三种先验框,分别检测大、中、小目标。
特征图分割数越小,感受野越大,检测的目标越大,先验框越大。
特征图分割数越大,感受野越小,检测的目标越小,先验框越小。
下图中蓝框是候选框,黄框是真实GT框 。
五、输出:1x1的卷积层+logistic 激活函数。输出结果y1、y2、y3
区分softmax:都是目标属于20类的概率。但softmax只能根据最大概率判断类别,logistic可以根据阈值判断。人的概率最大,所以一定是人。然后女人的概率是0.4,此时无法判断是不是女人。
Logistic适用于多标签(目标可以既是人,也是女人)分类任务。多个sigmoid二分类器,设定阈值,概率大于阈值0.6则属于该类。人的概率0.7,是人。然后女人的概率是0.9,所以能判断也是女人。
预测对象类别时不使用softmax,而是被替换为一个1x1的卷积层+logistic 激活函数的结构。使用softmax层的时候其实已经假设每个输出仅对应某一个单个的class,但是在某些class存在重叠情况(例如woman和person)的数据集中,使用softmax就不能使网络对数据进行很好的预测。softmax对每个框只产生一个分类,在目标检测任务中,存在多个目标物体重合的情况,也就是存在多个分类,softmax就不适用了,所以在Yolo算法中使用了logistic。
SSD:
和YOLO一样是端到端的单阶段的目标检测网络。
多尺度检测:大尺度特征图可以用来检测小物体;小特征图用来检测大物体。
密集采样:不同尺度和长宽比的先验框。
网络架构:
一、backbone。VGG16网络进行特征提取。
1、conv4-1之前的maxpooling把ceil_mode=True,上取数字
2、最后面的maxpooling改为3*3,s=1的池化层
3、把全连接改为卷积层6、7
4、扩张卷积:卷积层6通过引入“扩张率参数”来扩大感受野
二、Extra:获取多尺度特征图。extra每层有2个卷积,因此会有conv8-1、conv8-2两个结果。
架构图:
流程图:
三、分类和回归:
1、PriorBox层用来生成先验框。
特征图个数m已知。Smax、Smin已知。原图尺度已知。先根据公式1计算出△S,So、再逐层算出各层比例S_k、再乘以原图尺度得到特征图尺度。(m=5。Smax=0.9、Smin=0.2。原图尺度已知300。)
长宽比a^r,1、5、6号特征图不适用3、1/3的长宽比。
2、回归:用一个3*3卷积完成。
3、分类:用一个3*3卷积完成。
四、模型训练
1、正负样本标记:正样本:高于某个阈值即可。其余为负样本。GT框与anchor可以一对多,但一个anchor只能对应一个GT。GT框与anchor不可以多对一,anchor与iou最大的框匹配。
2、损失函数:分类交叉熵+回归SmoothL1。
3、困难样本挖掘。用于解决样本不均衡的问题。具体:将预测错误的负样本放入下一次的负样本集合再继续训练
图像分割:为RGB图像中每一个可能的类创建一个输出通道,通过叠加各个通道的热编码,获得掩膜mask。
图像分割两类任务:语义分割SegmentationClass、实例分割SegmentationObject。
语义分割:将图像的每一个像素分类。共k+1类。人、羊、狗,还多了一个背景(如草地)
实例分割:将图像的每一个像素、按不同个体分类。羊1、羊2、羊3、羊4。
目标检测(框出来)+语义分割(是谁)
数据集:
1、VOC:
2、城市街道风光数据集Cityscape。我们主要使用leftImg8bit、gtFine两个文件夹。leftImg8bit里是图片,gtFine是标注信息。
评价指标
1、像素精度PA:预测正确的像素个数比所有像素个数。不适用样本不均衡的情况。=橙/(红+橙)
2、平均像素精度MPA:各个类别的像素精度PA求平均。
3、IOU:预测值与真实值的交并比。=橙/(红+橙+黄)。(黄是有缺口的圆,红是完整的圆)
4、MIOU:各个类别的IOU求平均。
联想切片:在Python中,切片(slice)是对序列型对象(如list, string, tuple)的一种高级索引方法。
头:尾:步长。 头被省略(冒号不是省略,空才是省略),代表从头;尾被省略,代表导数。当只有一个冒号,代表步数被默认为1。
>>> a # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[:5] # [0, 1, 2, 3, 4]
>>> a[5:] # [5, 6, 7, 8, 9]
>>> a[2:8] # [2, 3, 4, 5, 6, 7]
>>> a[::2] # [0, 2, 4, 6, 8]
>>> a[::-1] # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>>a[2::2] #[2,4,6,8]
>>> a[0:6:2] #[0, 2, 4]
print(a[0:-1]) #[0, 1, 2, 3, 4, 5, 6, 7, 8] 。负数表示从结尾开始,除了最后一个。因为取不到最后一个
print(a[-1:]) # [9] 倒数第一个到结尾
print(a[-3:-1]) # [7, 8] 倒数第3个到倒数第一个
FCN全连接网络:将分类的CNN网络中最后的全连接层更改为卷积层后,输出与原图像大小相同的分割结果
网络架构:
一、全卷积部分:
1、使用预训练的分类网络,(以AlexNet网络为例)。
2、分类网络中的全连接层修改为1*1卷积层,用于提取特征
3、最终得到了一个相对于原图较小的三维的特征图
在传统的AlexNet结构中,前5层是卷积层,第6层和第7层分别是一个长度为4096的一维向量, 第8层是长度为1000的一维向量, 分别对应1000个不同类别的概率。
FCN将最后的3层转换为卷积层,卷积核的大小1*1*4096、1*1*4096、1*1*1000(宽*高*通道数)。这时还可使用预训练模型的参数。
原理:比如1000分类任务,CNN输出的是1000x1,每个维度代表图像属于对应类别的概率。FCN输出的是1000xHxW。H和W代表输入图像的高和宽,相当于对每一个像素进行1000分类,从而实现了图像分割
不含全连接层(fc)的全卷积(fully conv)网络,可适应任意尺寸输入。
二、上采样部分:反卷积法。先按照一定的比例通过补0来扩大输入图像的尺寸,再进行正向卷积即可。
首先,原始图像padding上下左右,然后再用3*3卷积核进行卷积,得输出。
反卷积中的s是指原始图像间隔的行列数+1。不是卷积核行走步长。
网络中需要卷积和池化提取和选择特征。然而,卷积和池化是一个下采样的过程。所以,提取的特征的宽和高小于输入图像为了输出的宽和高恢复到和输入相同。需要进行上采样
FCN中用到的上采样方法是反卷积(转置卷积)
三、跳层连接:将最后一层的预测和更浅层的预测结合起来,进行图像的分割。深层特征分割宽(因为将同类合并起来了),浅层特征分割细
总结:端到端的,可以接受任意大小的输入图像尺寸,比较高效。
局限性:得到的结果还是不够精细;对图像中的细节不敏感;没有考虑像素与像素之间的关系。
Unet:四层下采样+四层上采样。该操作使得我们可以最大程度的学习到之前学得特征,保留更多细节
一、网络架构:编码部分+中间卷积+解码部分
编码部分(左):
1、重复结构:架构中含有着一种重复结构,每次重复中都有2个3×3卷积层、非线性RoLU层和一个2x2 max pooling层(stride为2).
2、编码过程中通道数加倍
3、输出:下采样,送入下一次编码;送入解码阶段,进行特征的融合
解码部分(右):
1、每一步都首先使用反卷积,每次使用反卷积都将特征通道数量减半,特征图大小加倍。
2、反卷积过后,将反卷积的结果与编码部分中对应步骤的特征图拼接起来。编码部分中的特征图尺寸稍大,要将其修剪过后进行拼接。
3、对拼接后的map再进行2次3×3的卷积。
4、最后一层的卷积核大小为1×1,将64通道的特征图转化为特定类别数量(分类数量)的结果。
实例分割:在实现目标检测的同时分割目标像素
MaskRCNN:在FasterRCNN的基础上进行改进:ROIALIGN和Mask。原始Faster-rcnn算法的基础上面增加了FCN来产生对应的MASK分支。Faster-rcnn完成目标检测任务,FCN可以准确完成语义分割的任务。
一、流程:
·输入要处理的图片。
·将图片送入到Resnet+FPN特征提取网络得到特征图。
·然后对特征图的每一个像素位置设定固定个数的ROI,然后将ROI区域送入RPN网络进行二分类(前景和背景)以及坐标回归,以获得精炼后的ROI区域。
·对上个步骤中获得的ROI区域执行ROIAlign操作,得到固定维度的特征图。
·最后对这些ROI区域进行多类别分类,候选框回归和 引入FCN生成Mask,完成实例分割任务。
二、ROIALIGN:没有了取整操作,不会丢失像素信息
区分ROIPooling:狗狗这个目标,在原图上的大小为665*665,经过CNN 32倍下采样,在特征图上得到的尺寸是浮点数,取整会损失一部分像素信息。特征图进一步ROIPooling得到固定维度7*7,得到的尺寸也是浮点数,取整又会损失一部分像素信息。
ROIALIGN:狗狗这个目标,在原图上的大小为665*665,经过CNN 32倍下采样,在特征图上得到的尺寸是浮点数,不取整。特征图进一步ROIALIGN得到固定维度7*7,得到的尺寸也是浮点数,此时用“双线性插值”估计非整数点的像素值。即用浮点数四周真实存在的像素值中,最大的一个,来决定目标中的一个像素值。
双线性插值:
举例场景:将一个2x2的特征汇聚成一个。
常规的取平均值、最大值。这些办法都没有考虑到权重。
RoiAlign中对于区域中心点来说,周围的像素点的权重就不一样。当然,此处不打算涉及RoiAlign,对它不了解也没事。反正就假设,现在要将一个2x2网格分布的4个特征汇聚成一个特征。
网上随便找了张图。我们将四个特征定义为:Q11、Q12、Q21、Q22。P就是采样点位置。
P的位置对应不同的权重情况,就是说:实际场景中,提取特征时,4个特征的权重大小是通过P的位置来体现的。RoiAlign就是对其最直观的体现。
为何能通过位置来体现呢?因为可以用P点离某个特征的距离远近来表示该特征的权重大小。
此点不理解的话,下篇看了RoiAlign就理解了。
既然用距离远近来代表权重大小,那也就是离某个特征越近那这个特征权重越大。你想呐,汇聚像素特征的时候,自然就该离哪个像素近就受其影响大,其权重就高。
那我们现在将问题简化下,现在是二维的,因为图像是二维码的嘛。那我们先假设现在是提取一维的特征。比如:在Q11,Q21这条一维的横线上,提取R1点的特征。那R1取值时,Q11和Q21的权重与其R1的距离成反比。则有公式如下:
R1 = Q11*(x2-x)/(x2-x1) + Q21*(x1-x)/(x2-x1)
其实,就是一条横线上的Q11和Q21,自身的值乘以自身权重再相加。而权重和距离成反比,所以此处用的x1,x2这边坐标轴来计算距离比值。
R1已经计算出来,同理:R2也可计算出来。再同理,R1、R2、P此时处于一条一维竖线上了,就可以再次取值。
所以,顾名思义,双线性插值。就是:P和周围4个点,不在一个维度不好插,那就先把那4个点拍成2个点,这2个点和P在一个维度,然后就好插了。也就是做了两轮线性插值。
不管,双线性插值在数学上如何理解,但在cv上这样理解就足够了。
其本质就是为了–让周围的像素点根据各自权重来发言。以免max取值那种一言堂,或者均值法那种绝对皿煮。
三、头部网络:头部网络包括边界框识别(分类和回归)+mask分割头预测。全卷积网络。使用反卷积进行上采样,获取分割结果,映射回原图的ROI区域,大于阈值是目标像素,其他就不是
FCN算法思想:首先对图像进行卷积和池化,不断减小其feature map,然后进行反卷积操作,即进行插值操作,增大其feature map,最后对每一个像素值进行分类。
mask分支是一个全卷积网络(FCN),实际工作中我们使用右图较多,对图像进行卷积和池化,不断减小其feature map,然后使用2*2的反卷积进行上采样得到像素点级的特征。对于mask产生的二值掩膜输出,对每个像素点应用sigmoid函数,整体损失定义为平均二值交叉损失熵。对于真实类别为k的roi,仅在第k个掩码上计算损失(其他掩码输出不计入)。
四、损失函数。
分类:交叉熵损失
回归:smoothL1损失
分割:根据分类结果,选择相对应的分割结果,进行sigmoid激活,计算二分类交叉熵损失。
联想:
区分Sigmoid和Softmax:
·神经网络的原始输出值,经过Sigmoid函数后,可以计算出各个类别的概率,那么这些概率之间互不影响,他们之和有可能大于1,有可能小于1。由于各个类别概率相互独立,Sigmoid函数可以用于多分类任务问题,比如一张图片里面,既有狗也有猫也有人,那么神经网络训练后,输出的原始值,经过Sigmoid函数,狗、猫、人的概率应该都比较高且接近于1
·神经网络输出的原始值,经过Softmax函数,可以计算出各个类别的概率,且各类别的概率之和为1。由于各个类别概率不是相互独立,概率之和为1,Softmax函数常用于二分类任务问题,比如NLP的情感判别问题,那么神经网络训练后,输出的原始值,经过Softmax函数,正向与负向的概率和为1,那么肯定有一个概率大于0.5,一个概率小于0.5,可以用来判断一个句子的正负向
图像处理opencv
数字图像:每个像素点的亮度值用灰度值表示。我们平常接触的图像都是8位数图像.包含0~255灰度,其中0,代表最黑,255表示最白。
二位数图:每一个像素点的值为0或1。(区分二进制图,如用1000011表示256灰度值)
灰度图:每一个像素点有8位数,每一点的值是0或1。如01001000。一共有2^8=256级灰度。
彩色图:
彩色图:每一像素的颜色,由R、G、B三个分量来表示。每个图像中,三个M*N的二维矩阵分别表示各个像素的R、G、B三个颜色分量。
Opencv
编写的是python,后台工作的是C++。
opencv库的三个模块:
1.core模块实现了基本运算,如数组操作相关函数等。
2.highguit模块实现了视频与图像的读取、显示、存储
3.imgproc模块实现了图像处理的基础方法,包括图像池波、几何变换、平滑、阈值分割、形态学处理、边缘检测、目标检测、运动分析和对象跟踪等。
图像的基本操作:read、show、write、split、merge、cvtcolor、add、addweighted
先将img的BGR通过翻转(img[:,:,::-1]) 变成RGB通道,再imshow显示。
几何变换:
1、平移:平移矩阵
2、旋转:旋转过程中,坐标系首先变成旋转中点①,然后平移到左上角原点的位置②。因此涉及旋转矩阵&平移矩阵。
先旋转:
再平移:
4、仿射变换:原图中所有平行线在结果中同样平行。不改变平行关系,只改变角度。根据3个点在原图像和目标图像中的位置,得到一个2*3的仿射变换矩阵M(线性变换+平移)。再根据矩阵进行旋转。
5、投射变换:将图像投影到一个新的视平面。确定4个点在原图像和目标图像中的位置,通过cv.getPerspectiveTransform找到透视变换矩阵T(线性变换+平移+投射变换)。再根据矩阵进行旋转。
6、构建图像金字塔。多尺度表达。底部是高分辨率,顶部是低分辨率。层级越高,图像越小,分辨率越低。越大越清晰,越小越模糊。
形态学操作:仅仅针对二值图!
1、连通性:两个像素位置邻接,灰度值相等。
·邻接:4邻接,8邻接,D邻接
·联通:4联通,8联通,m联通。
m联通:p和q在各自4邻接中没有联通的情况下,在D邻接中联通。m联通=4联通和D联通的混合联通。
5、腐蚀:去毛边+变细
核结构1遍历图像每个像素,做“与”的操作,如果都为1,则该元素为1,否则为0。
腐蚀是原图中的高亮区域被蚕食,消除物体边界点,使目标缩小,可以消除小于结构元素的噪声点。
6、膨胀:填补、主体修复变粗、变大
核结构1遍历图像每个像素,做“与”的操作,如果都为0,则该元素为0,否则为1。
膨胀就是使图像中高亮部分扩张,与物体接触的所有背景点合并到物体中,使目标增大,可填补目标中的孔洞。
4、开闭运算
开运算:先腐蚀后膨胀=先小后大。其作用是:分离物体,消除小区域。
特点:消除噪点,去除小的干扰块,而不影响原来的图像(消刺、变小)
闭运算:先膨胀后腐蚀=先大后小。其作用是:消除“闭合”物体里面的孔洞。
特点:可以填充闭合区域。(填洞、变大)
5、黑帽和礼帽:
礼帽:取亮= 原图与“开运算”的结果之差。(带刺-不带刺=刺)
其作用是:用来分离比邻近点亮一些的斑块。背景提取。
黑帽:取暗=“闭运算”结果与原图之差。(变大-不变大=轮廓)
其作用是:用来分离比邻近点暗一些的斑块。
cv.morphologyEx(img,op,kernel)
6、梯度运算:先膨胀再腐蚀。先大、再小,大-小得到图形轮廓,即梯度。
图像平滑
1、噪声:
椒盐噪声:一种随机出现的白点或者黑点,噪声的灰度值为0或255。
高斯噪声:噪声密度函数服从高斯分布的一类噪声。噪声的取值不再是0或255,而是服从高斯分布的数。
联想:
高斯分布=正态分布(默认一维)。若随机变量X服从一个数学期望为μ、方差为σ2的正态分布,记为N(μ,σ2)。其概率密度函数为正态分布的期望值μ决定了其位置,其标准差σ决定了分布的幅度。当μ = 0,σ = 1时的N(0,1)正态分布是标准正态分布,若服从标准正态分布,通过查标准正态分布表就可以直接计算出原正态分布的概率值。
一维高斯的概率密度函数:
高斯分布曲线的特征:
·关于μ对称;高斯分布的概率密度函数的积分为1;
·通过公式可以看出,σ越大,x位置的概率密度就越小,曲线越平缓;而σ越小,x的概率密度就越大,曲线越瘦高的,分布比较集中。
二维高斯的概率密度函数:
2、图像平滑:使用滤波器去除噪声
2.1 均值滤波:使用像素邻域m*n内所有像素的平均值替代中心点的像素值
优点:算法简单,计算速度快
缺点:去除细节信息,将图像变得模糊
如:3*3过滤器:
anchor:
2.2 高斯滤波:去除高斯噪声。二维高斯是构建高斯滤波器的基础。
高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。
1.根据高斯分布确定邻域内像素权重,形成权重矩阵。
(此处设σ=1.5,将9个坐标分别代入二维高斯概率密度分布中,求得9个点不同的权重。
权重矩阵含义:中间那一点由周围9个点决定。决定的权重形成“权重矩阵”。)
- 对邻域内的高斯权重进行归一化,令权重之和=1。权重矩阵归一化,将各权重分别除以权重之和。
(此处计算可知权重和为0.4787147,9个值分别除以0.4787147。)
- 利用权重乘以对应的像素值,乘积的总和替代中心点像素。
(将这9个值加起来,就是中心点的高斯模糊的值。对所有点重复这个过程,就得到了高斯模糊后的图像。)
2.3 中值滤波:去除椒盐噪声。使用邻域内像素值的中值替代中心点的像素值
直方图:
1、灰度直方图:统计图像中像素频数分布的直方图结果。0:最暗,255:最亮。
作用:直方图是图像中像素强度分布的图形表达方式;统计了每一个强度值所具有的像素个数;不同的图像的直方图可能是相同的
参数:掩膜mask。掩膜是由0和1(或255)组成的二进制图像,利用掩膜对要处理的图像进行遮挡,用来选择图像中的感兴趣区域,控制图像处理的范围。其中1(或255)代表保留,0值区域代表屏蔽。
·用途: 1.提取感兴趣区域 2.屏蔽作用 3.结构特征提取 4.特殊图像的制作
·位与运算规则:只有两个数同时为1,结果才为1,否则为0。即 0 & 0= 0 ,0 & 1= 0,1 & 0= 0, 1 & 1= 1。
比如某位置的像素值分别为:23,则与像素0或1进行位与运算。
Zeros:23,0的二进制分别为10111,000000,按位与得到000000。
225或1:23,1的二进制分别为10111,11111111,按位与得到10111即其本身。
2、直方图均衡化:对比度增强。将一副图像的直方图分布变得更均匀,从而增强图像的对比度。
对于曝光不足或者是曝光过度(即图片太暗或图片太亮)的图像,把原始图像的灰度直方图进行非线性拉伸,重新分配图像的像素值,提升图像的对比度,使一定灰度范围内的像素数量大致相同。效果:亮变更亮,暗变更暗
2.1 自适应的图像均衡化:每个分块做自己的均衡化
1)把整幅图像划分为多个小块。opencv默认每个小块的大小是8*8,因此对于16*16的原图,会被分为2*2的小块
2)在每一个小块中进行直方图均衡化
3)如果小块中的bins超出对比度限制时,要把它分配到其他的像素点中
4)使用双线性插值,去除这些小块的边界,将小块进行拼接
3、边缘检测。=逐点计算梯度。边缘:灰度突变的位置=导数最大。导数=梯度,通过计算模长的方法计算G。
3.1 边缘检测方法分类:
1)一阶导最大处。Sobel算子和Scharr算子。
2)二阶导=0:表示对一阶导的进一步求导,表示一阶导数的变化率,体现为凹凸性。
3.2 Sobel算子:计算简单,效率较高
3.2.1 导数
水平方向的导数:|右边灰度-左边灰度|。中间x的值主要由两边决定(权重为2),其次由上下两行决定。Gx=K*I。
垂直方向的导数:|下边灰度-上边灰度|。Gy=K’*I。
求模:模长=真实导数G。
当内核大小为3时,sobel内核可能产生比较明显的误差。Scharr函数比sobel更加快,同时结果更加精确。但Scharr函数仅作用于大小为3的内核;Scharr函数的权重不一样。
Sobel函数求完导数后会有负值,还会有大于255的值。而原图像是uint8,即8位无符号数,所以Sobel建立的图像位数不够,会有截断。因此要使用16位有符号的数据类型,即cv2.CV_16S。处理完图像后,再使用cv2.convertScaleAbs(0函数将其转回原来的uint8格式,否则图像无法显示。
Sobel算子是在两个方向计算的,最后还需要用cv2.addWeighted()函数将其组合起来
联想:数据大小。
整型 |
char字符型‘a’ |
xxx个bit=xxx位 =电脑cpu位数 |
1 个字节 =8位=8bit |
-128 到 127 或者 0 到 255 |
|
signed char |
int8_t 有符号8bit整数 |
1 个字节 |
-128 到 127 |
|
|
unsigned char |
uint8_t 8位无符号(负号就是一个符号)整形 |
1 个字节 |
0 到 255(2^8-1) |
opencv显示、分析图像 |
|
short int =signed short int |
int16_t |
2 个字节 |
-32768 到 32767 |
|
|
unsigned short int |
uint16_t |
2 个字节 |
0 到 65,535 |
遥感图像或其他像素深度比较高的图片 |
|
Int整型 =signed int |
int32_t |
4 个字节 |
-2147483648 到 2147483647 |
|
|
unsigned int |
uint32_t |
4 个字节 |
0 到 4294967295 |
|
|
long int =signed long int |
int64_t |
8 个字节 |
-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 |
|
|
unsigned long int |
uint64_t |
8 个字节 |
0 到 18,446,744,073,709,551,615 |
|
|
浮点型 如3.14 |
float科学计数法 |
Float32单精度类型 |
4 个字节 |
精度型占4个字节(32位)内存空间, +/- 3.4e +/- 38 (~7 个数字) |
傅里叶变换 |
|
Float16半精度类型 |
2 个字节 |
半精度型占2个字节(16位)内存空间,
|
|
|
double |
|
8 个字节 |
双精度型占8 个字节(64位)内存空间,+/- 1.7e +/- 308 (~15 个数字) |
|
|
long double |
|
16 个字节 |
长双精度型 16 个字节(128位)内存空间,可提供18-19位有效数字。 |
|
(1)openCV在显示图像(矩阵)的时候,要求矩阵必须为整形int,因此通常的思路肯定是,在显示深度图像的时候,由于不知道读取的深度图像是什么数据类型,我们通过数据类型转换,将其转换为整型。
(2)在默认情况下声明的整型变量都是有符号的类型(char有点特别)
(3)char型从本质上说,也是种整型类型,它是长度为1个字节的整数,通常用来存放字符的ASCII码。比如uint8_t 实际是一个 char,存储的是ascii码,输出uint8_t 类型的变量实际输出的是其对应的字符, 而不是真实数字。
(4)double类型是浮点数,这种类型可以用科学记数法表示,所以表示范围非常大。但是,使用可浮点数的代价就是损失了精度。它把这部分精度用于指数的表示。所以double类型的优点就是数据范围大,缺点是精度不足,大概只有15~16位有效位数。
(5)遥感图像一般像素深度比较高,基本的就是unit16了,但是如果想在OpenCV中正确使用,而且不丢失数据RGB三通道信息,就需要转为unit8才能进行其他分析。
unit16的图像最大值为2^16-1 = 65535,而OpenCV中的图像最大值为2^8-1 = 255,当大于255时会自动变为255,这样数据信息就丢失了。下面代码采用的方式是线性缩放,将0到65535的数值线性缩放到0到255
(6)通常的深度学习预测(inference)的参数,输入输出和运算都是用的4个字节的 float(也叫 float 32)浮点数表示。 如果改成用2个字节的 float 16浮点数来表示,可以节约内存占用、耗电量和运算时间。
3.3 拉普拉斯算子=Laplacian算子。Gx’’=K*I。通过二阶导来进行边缘检测。捕捉轮廓的效果最差。
→ → → →
3.4 canny边缘检测
流程
1.噪声去除:使用高斯滤波(5*5)消除噪声。要先去除噪声,因为噪声就是灰度变化很大的地方,所以容易被识别为伪边缘。
2.计算梯度:使用sobel算子计算Gx和Gy,随后得出综合梯度和梯度的角度。(梯度的角度=梯度的方向)
3.如果某个像素点是边缘,则梯度方向总是与边缘垂直。
4.非极大抑制:抑制掉像素周围同方向的梯度非极大的像素点。如ABC都是同方向的梯度,通过sobel算子比较三者的梯度,保留梯度最大的点。
5.滞后阈值:设置两个阈值。阈值越小,得到的边缘信息越多。
maxval :像素的梯度大于maxval认为是真正的边缘
minval :梯度小于minval不是边缘
在minval和maxval: 如果与真正的边缘相连,就认为他是边缘否则不是边缘。目的是使得边缘尽可能的闭合。
模板匹配:在图像中查找到与模板最相似的位置,如在动物园图像中寻找一个狗头。模板匹配就是在整个图像区域匹配到与给定子图像的小块区域
1、拿模板图像在原图像中进行扫描, 计算相似度,构建相似矩阵R。
2、从相似矩阵中找到最大匹配值的结果。设立阈值。
匹配算法:
cv.TM_SQDIFF:平方。模板与图像直接相减再平方。距离最小是为0的时候。
cv.TM_CCORR:相关性。模板与图像直接相乘,取相乘结果最大的时候。前提:亮度差异不会特别大。
cv.TM_CCOEFF:相关系数。模板与图像间相关系数匹配,[0,1]。越大越相关。
拓展:要求模板与图像中匹配框的大小尺寸完全相同,才可以匹配。模板匹配不适用于尺度变换,视角变换后的图像,这时我们就要使用关健点匹配算法,比较经典的关键点检测算法包括SIFT和SURF等。
图像金字塔
高斯金字塔:上采样;下采样;上+上;上+下(尺度一样,但更模糊)。
下采样=缩小。先用高斯核卷积;再去除偶数行和列
上采样=放大。先行列插空添加0;再用高斯核卷积
拉普拉斯金字塔:下+上。第一层=原-(下+上)。第二层=第一层-(下+上)。
高斯金字塔是通过对一张图逐级下采样获得的。先用高斯核卷积;再去除偶数行和列。
拉普拉斯金字塔:下采样过程丢失的信息不能通过上采样来完全恢复。拉普拉斯金字塔就是记录高斯金字塔每一级下采样后再上采样与下采样前的差异,目的是为了能够完整的恢复出每一层级的下采样前图像。拉普拉斯金字塔可以认为是残差金字塔。
霍夫变换:检测图像中的几何图形-可用表达式表达出的图形。
笛卡尔坐标与霍夫空间的点线对应:笛卡尔坐标系中的一条直线,对应于霍夫空间中的一个点。反过来,霍夫空间中的一条线,对应于笛卡尔坐标系中一个点。笛中点共线,在霍夫中表示为相交。
霍夫变换求解1:(1)是否共线(笛) → 是否相交(霍)。将笛卡尔坐标系转换为霍夫空间。
(2)我们选择尽可能多的直线汇成的点。
霍夫变换求解2:
(1)是否共线(笛) → 是否相交(霍)。
·笛卡尔坐标系(x,y)转换为极坐标(ρ,θ)的公式:
·先将笛卡尔坐标系转换为极坐标,再进行霍夫变换。
实现流程:
(1)将图片转换成值为0、1的二值图像。如令像素值>170的值为1,其余点为0。
(2)将二值图像中非零值的点依次代入ρ=cosθx+sinθy。θ在0-180, ρ在0-图像的对⻆线长度。再根据θ介于0-180求得ρ值。注:ρ值最大值为图片对角线的距离,因此如果希望精度达到像素级别,行数应当与图像的对角线的距离相等。
(3)每个像素点可以求得一条ρ线。若有两条线交于同一点,则该ρ点的计数就+1。最后找计数最大的点,点映射回笛卡尔坐标就是一条共线。
- 霍夫圆检测:圆形可用数学公式表达出来:
1)累加器法:其中α和b表示圆心坐标,r表示圆半径,因此标准的霍夫圆检测就是在这三个参数组成的三维空间累加器上进行圆形检测,此时效率就会很低。不使用!
2)霍夫梯度法:
·霍夫圆检测对噪声比较敏感,所以应先对图像进行中值滤波。
·霍夫梯度法将霍夫圆检测分为两个阶段,第一阶段检测圆心,第二阶段利用圆心推导出圆半径。
圆心检测的原理:圆心是圆周法线的交汇处,设置一个阙值,在某点的相交的直线的条数大于这个阀值就认为该交汇点为圆心。
圆半径确定原理:圆心到圆周上的距离(半径)是相同的,确定一个阈值,只要相同距离的数量大于该阈值,就认为该距离是该圆心的半径。
原则上霍夫变换可以检测任何形状,但复杂的形状需要的参数就多,霍夫空间的维数就多。霍夫梯度法是霍夫变换的改进。
轮廓检测
1、图像的轮廓
轮廓:具有相同颜色或灰度的曲线。
轮廊提取的基本原理:对于一幅背景为黑色、目标为白色的二值图像,如果在图中找到一个白色点,且它的8邻域(或4邻域)也均为白色,则说明该点是目标的内部点、将其置为黑色,视觉上就像内部被掏空一样。一般在寻找轮廊之前要将图像进行阈值化或Canny边缘检测、转换为二值化图像。图像提取的轮廓结果为二维数组。
转换为二值化:如所有非0元素按照1处理
区分边缘提取和轮廊检测: 边缘检测主要是通过梯度变化比较大的像素点检测到边缘。轮廊检测:findContours(0函数会得到每一个轮廓并以点向量方式存储,除此也得到一个图像的拓扑信息,即一个轮廊的后一个轮廓、前一个轮廓等的索引编号。
拓展:拓扑信息是指物体的拓扑元素(顶点Vertex、边Edge和表面Face)的个数、类型以及它们之间的相互关系信息。拓扑着重研究图形内的相对位置关系。例如,某一面与哪些面相邻、某一面由哪些点组成等都属于拓扑信息。表示拓扑信息常用数据结构来实现,采用体、面、环、边和顶点表示,根据这些信息可以确定物体表面的邻接关系。在计算机处理中常采用链表的数据结构记录几何信息和拓扑信息。
hierarchy[Next同级下个轮廓,Previous同级前个轮廓,First-Child第一个子轮廓,Parent父轮廓]:
0的next是1,1的next是2,2在同一级没有next,因此2的next是-1.
1的previous是0,2的previous是1,0在同一级没有previous,因此0的previous是-1.
2的子轮廓是2a。3a有两个子轮廓:4、5,我们取第一个子轮廓:4。
4、5的父轮廓是3a,3a的父轮廓是3。
2、轮廓特征
轮廓近似:轮廊近似是将轮廓形状近似为到另外一种由更少点组成的轮廓形状,新轮廓的点的数目由我们设定的准确度来决定。
凸包:凸包就是将最外层的点连接起来构成的凸多边形
边界矩形:直边界矩形、旋转边界矩形
直边界矩形:一个直矩形,没有进行旋转。它不会考虑对象是否旋转,所以该边界矩形的面积不是最小的。
旋转边角矩形:这个边界矩形是面积最小的,他考虑了对象的旋转。
最小外接圆:包含目标对象的圆中面积最小的
椭圆拟合:将图像中的一组数据以椭圆方程为模型进行拟合。具体:先假设椭圆参数,得到点到假设椭圆的误差,求出使这个和最小的参数。
直线拟合:就是将图像中的点对象拟合成一条直线过程。
3、图像的矩特征
从一幅图像计算出来的矩集,可以描述图像形状的全局特征以及几何特征,如大小,位置、方向和形状等。
图像识别的一个核心问题是图像的特征提取,简单描述即为用一组简单的数据(图像描述量)来描述整个图像,这组数据越简单越有代表性越好。良好的特征不受光线、噪点、几何形变的干扰。图像识别发展几十年,不断有新的特征提出,而图像不变矩就是其中一个。
3.1 矩的概念
关于c点的k阶矩:。
关于c点的k阶原点矩:。一阶原点矩就是期望E(X)。
关于c点的k阶中心矩:。
一阶中心矩μ1=0,二阶中心矩μ2就是X的方差Var(X)。μ3可以去衡量分布是否有偏。 μ4可以去衡量分布(密度)在均值附近的陡峭程度如何。在统计学上,高于4阶的矩 极少使用。
3.2 图像中的矩特征
对于一幅图像,我们把像素的坐标看成是一个二维随机变量(X,Y),一幅灰度图像可以用灰度值二维密度函数来表示。,矩的作用:描述灰度图像的特征。用于训练分类器,完成目标识别。
1.空间矩/几何矩:空间炬的实质是图像的质量。p和q指空间矩的阶数,I(x,y)是对应位置的灰度值。
2.中心矩:中心矩体现的是图像强度的最大和最小方向,具有平移不变性。
3.归一化的中心矩:对中心矩做归一化处理。具有尺度不变性和平移不变性。
4.Hu矩:具有平移、旋转和尺度不变性。Hu矩由二阶中心矩和三阶中心矩构成输入,输出七个不变炬。
两个函数:moments()函数用于计算中心矩,HuMoments函数用于由中心矩计算Hu矩。
imgmn=cv.moments(imgray)
imghu=cv.HuMoments(imgmn)
opencv实现傅里叶变换和逆傅里叶变换
(看的方向)
频率越大,可以看到正弦波(波浪)变动得越快。
傅里叶变换的作用就是把非正余弦周期(请注意必须是周期函数)函数转化为无限个规则的正弦余弦函数。变成规则的函数以后,虽然有无限项,但是工程取前几项精度就够用了。
傅里叶变换在计算机领域中可以帮助我们进行图像去噪:设计一个低通滤波器(高斯函数),去掉图像中的高频噪声
时域分析:第1分钟得3分,第2分钟得2分...
频域分析:得分情况,每隔一分钟就会得3分,每隔一分钟得2分。频域中只关心频率。
高频:变化剧烈的灰度分量,如边界
低频:变化缓慢的灰度分量,如一片大海
滤波
低通滤波器:只保留低频,会使得图像模糊
高通滤波器:只保留高频,会使得图像细节增强
opencv中主要就是cv2.dft()和cv2.idft(),输入图像需要先转换成np.float32 格式。
得到的结果中频率为0的部分会在左上角,通常要转换到中心位置,可以通过shift变换来实现。
cv2.dft()返回的结果是双通道的(实部,虚部),通常还需要转换成图像格式才能展示(0,255)。
# DFT傅里叶变换(得到频率分布)
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT) #傅里叶变换得到频率分布(频谱图),输出复数数组
dft_shift = np.fft.fftshift(dft) #将零频率分量移至频谱中心,为了处理方便
# 得到灰度图能表示的形式
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1])) #将傅里叶变换结果转换到灰度0-255。频谱图像是双通道的,因此有dft_shift[:,:,0],dft_shift[:,:,1]
# 低通滤波(保留低频=取mask)(对比高通滤波:保留高频=取mask以外的区域)
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1 #将全零矩阵(黑)的中心区域设为1(白)。
# IDFT逆傅里叶变换
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1]) #处理实部和虚部
1.opencv实现傅里叶变换
返回结果 = cv2.dft(原始图像,转换标识)
1> 返回结果:是双通道的,第一个通道是结果的实数部分,第二个通道是结果的虚数部分
2> 原始图像:输入图像要首先转换成np.float32(img)格式
3> 转换标识:flags = cv2.DFT_COMPLEX_OUTPUT,输出一个复数阵列
numpy.fft.fftshift:将零频率分量移到频谱中心(将左上角的低频区域,移到中心位置)
返回值 = 20*np.log(cv2.magnitude(参数1,参数2))
调整频谱的范围,将上面频谱图像的复数数组,转换为可以显示的灰度图像(映射到[0,255]区间)
1> 参数1:浮点型X坐标值,也就是实部
2> 参数2:浮点型Y坐标值,也就是虚部
https://blog.51cto.com/u_15127632/4351582
Flask是一个十分优秀的轻量web开发框架,它可以十分迅速的开发出web应用
2.opencv实现逆傅里叶变换
返回结果 = cv2.idft(原始数据)
1> 返回结果:取决于原始数据的类型和大小
2> 原始数据:实数或者复数均可
numpy.fft.ifftshift
fftshift函数的逆函数,将中心位置的低频,重新移到左上角
调整频谱的范围,映射到[0,255]区间
返回值 = cv2.magnitude(参数1,参数2)
1> 参数1:浮点型X坐标值,也就是实部
2> 参数2:浮点型Y坐标值,也就是虚部
实例:通过opencv实现低通滤波,模糊一副图像
获取图像的形状
rows,cols = img.shape
获取图像的中心点
crow,ccol = int(rows/2),int(cols/2)
生成一个原图像大小的全零矩阵(黑色)
mask = np.zeros((rows,cols,2),np.uint8),这里的(rows,cols,2)是因为dftShift频谱图像的形状是(rows,cols,2),双通道的
将全零矩阵(黑色)的中心区域设置为1(白色),也就是mask矩阵
mask[crow-30:crow+30,ccol-30:ccol+30] = 1
频谱图像 = 原频谱图像 * mask矩阵
fShift = dftShift*mask
图像特征提取与描述:获取数据——特征处理——分类器&回归器
1 图像的特征
图像特征要有区分性,容易被比较。一般认为角点是较好的图像特征,角点周围的灰度情况变化最迅速。
特征检测:找到图像中的特征
特征描述:对特征及其周围的区域进行描述
2 Harris算法
2.1 通过图像的局部小窗口观察图像。
角点的特征是窗口沿任意方向移动都会导致灰度明显变化。
△灰度值E(u,v)=像素权重*(移动后灰度值-移动前灰度值),从公式推倒可知椭圆的短轴对应快速变化的方向,而短轴的长短和特征值相关。
2.2 角点响应值R。
当R为大数值的正数时是角点;(R>>0)(可设置阈值)
当R为大数值的负数时是边界;(R<<0)
当R为小数值时时平坦
Cv.cornerHarris(img图像,blocksize角点检测的领域大小,ksize核大小,k自由参数)
要求数据类型为float32的输入图像
优点:旋转不变性;仿射变化具有部分的不变性
缺点:不具备几何尺度不变性;提取的角点是像素级的
3 Shi-Tomasi角点检测
角点响应函数R。。当特征值中较小的一个大于阈值时,是角点。即两个特征值都大于阈值
所有低于质量水平的角度被排除掉,然后把合格的角度按质量排序,然后将质量较好的角点附近(小于最小欧氏距离)的角点删掉,最后找到maxcorners个角点返回。
优点:旋转不变性;计算更加容易
缺点:不具备尺度不变性;
SIFT/SURF算法
SIFT算法的实质是在不同的尺度空间上找关键点(特征点),并计算出关键点的方向。关健点不会因光照,仿射变预和噪音等因素而变化。=找到尺度不变性,旋转不变性的关键点。并根据描述子对两张图进行匹配。
一、尺度空间的极值检测:
1、构建图像的高斯金字塔:这样构建的目的是为了保证图像在不同尺度即不同大小下都可以找到特征点,从而保证了SIFT算法的尺度不变性。
为了尽可能多的保留原始图像信息,一般需对原始图像进行扩大两倍采样,但不是必须的。
每一组由6层尺寸相同但模糊系数(σ)不同的图像组成。越高层,σ↑,size↓
通过高斯模糊获得尺度不同的结果:计算层数(每组6层),尺度因子(6层6个σ),高斯核,每层尺度。
下一组中第一层是由上一层的倒数第三层直接下采样产生,下一组中其他层是由下一组中第一层高斯模糊而来。
2、构建高斯差分金字塔
利用高斯金字塔中每一层进行相减得到高斯差分金字塔。
3、极值点检测。(x,y)
对于某一个像素,比较邻域18个像素值,来获取局部最大值。如果它的值是这个图像比较域内的最大值,则将其作为特征点。
二、关键点筛选:去除低对比度和不稳定的
1.灰度值比较小的关键点去除=去除低对比度的。
2“边缘”的关键点去除。边界的判断条件:曲率比。(区分harris角点的判断规则)
三、关键点方向的确定(θ):利用关键点邻域像素的梯度方向分布特性为每一个关键点指定方向参数,使其具有旋转不变性。具体做法是:在以关键点为中心的邻域窗口内进行采样,并用直方图统计每个邻域像素的方向,直方图的横坐标是像素点相对于关键点的角度位置,纵坐标是像素点的梯度方向值。选取直方图中的峰值作为关键点的方向,然后将坐标轴旋转为关键点的方向
1.在相应的尺度图像中,以r为半径,计算区域(r=4.5σ)内的所有的像素值的梯度方向和大小。
2.构建直方图:以角度0-360为横轴,梯度幅值加在一起为纵轴,构建直方图
3.每个特征点有一个主方向,辅方向是高度大于主方向80%的方向。通过插值可得到更精确的角度信息。
四、关键点描述:对每一个关键点产生128个数据,即形成一个128维的特征向量,将特征向量进行归一化处理,可以进一步防止光照变化的影响。
SIFT描述子 是一个3D梯度位置方向直方图,位置被量化到4×4局部栅格,梯度角度分为8个方向,算子为4×4×8=128维
每个关系点建立一个描述符,对关键点以及其周围区域进行描述。即计算区域内的梯度直方图,,生成特征向量(梯度信息),对图像信息进行描述。
- 以关键点为中心,获取边长为3σ(d+1)范围。
- 将坐标轴旋转到关键点的主方向。
- 利用插值得到(d*d)区域,每个区域中有8个方向的梯度。每个关键点有d*d*8个排序后的梯度信息。
- 将直方图进行串联得到整个关键点的描述结果。光照、视角变化不会影响描述符。
特征匹配:当两幅图像的SIFT特征向量生成后,我们采用关键点特征向量的欧式距离作为两幅图像中关键点的相似性判定度量。即取图像1 中的关键点,并找出其余图像2中欧式距离最近的前两个关键点。在这两个关键点中,如果 最近距离/次近距离 的大小小于某个阈值,则接受这一匹配。
以sift特征为例。可进行一对一,一对二的匹配(一对二时,每个关键点匹配另一张图中另两个关键点)。
匹配方法有crosscheck:特征向量的距离越小,二者越相似。
NORML2:比较归一化的欧氏距离。
随机抽样一致算法RACSAC:
最小二乘:拟合直线要考虑所有的点。会受异常点的影响。
RACSAC:拟合效果好于最小二乘,不受异常点的影响。
每⼀次拟合后,容差范围内都有对应的数据点数,找出数据点个数最多的情况,就是最终的拟合结果
单应性矩阵H:变换矩阵
(1)求8个未知数,需要有8个方程。x、y可构建两个方程,同时代表1个点。构建8个方程,至少需要4个点。即要完成变换矩阵的匹配,至少需要4个点。
(2)4个点计算H,然后代入任意点求loss。不断找到最好的H使得loss最小。
背景建模
帧差法
由于场景中的目标在运动,目标的影像在不同图像帧中的位置不同。该类算法对时间上连续的两帧图像进行差分运算,不同帧对应的像素点相减,判断灰度差的绝对值,当绝对值超过一定阈值时,即可判断为运动目标,从而实现目标的检测功能。
缺点:帧差法非常简单,但是会引入噪音和空洞问题
### 混合高斯模型
在进行前景检测前,先对背景进行训练,对图像中每个背景采用一个混合高斯模型进行模拟,每个背景的混合高斯的个数可以自适应。然后在测试阶段,对新来的像素进行GMM匹配,如果该像素值能够匹配其中一个高斯,则认为是背景,否则认为是前景。由于整个过程GMM模型在不断更新学习中,所以对动态背景有一定的鲁棒性。最后通过对一个有树枝摇摆的动态背景进行前景检测,取得了较好的效果。
在视频中对于像素点的变化情况应当是符合高斯分布
背景的实际分布应当是多个高斯分布混合在一起,每个高斯模型也可以带有权重
混合高斯模型学习方法
1.首先初始化每个高斯模型矩阵参数。
2.取视频中T帧数据图像用来训练高斯混合模型。来了第一个像素之后用它来当做第一个高斯分布。
3.当后面来的像素值时,与前面已有的高斯的均值比较,如果该像素点的值与其模型均值差在3倍的方差内,则属于该分布,并对其进行参数更新。
4.如果下一次来的像素不满足当前高斯分布,用它来创建一个新的高斯分布。
混合高斯模型测试方法
在测试阶段,对新来像素点的值与混合高斯模型中的每一个均值进行比较,如果其差值在2倍的方差之间的话,则认为是背景,否则认为是前景。将前景赋值为255,背景赋值为0。这样就形成了一副前景二值图。
光流估计
光流是空间运动物体在观测成像平面上的像素运动的“瞬时速度”,根据各个像素点的速度矢量特征,可以对图像进行动态分析,例如目标跟踪。
亮度恒定:同一点随着时间的变化,其亮度不会发生改变。
小运动:随着时间的变化不会引起位置的剧烈变化,只有小运动情况下才能用前后帧之间单位位置变化引起的灰度变化去近似灰度对位置的偏导数。
空间一致:一个场景上邻近的点投影到图像上也是邻近点,且邻近点速度一致。因为光流法基本方程约束只有一个,而要求x,y方向的速度,有两个未知变量。所以需要连立n多个方程求解。
标签:计算机,卷积,检测,梯度,笔记,像素,特征,图像,视觉 From: https://www.cnblogs.com/SDoubleJ/p/16797761.html