目录
摘要
本周阅读了一篇基于深度卷积神经网络的红外小目标检测的论文,通过窗口滑动将小目标检测问题转化为小目标位置分类问题,减少了工作量。在工程项目上,学习了如何读取文件和使用前端模板。在深度学习上,学习了朴素贝叶斯理论和他的数学推导,以及复现简单的代码。
This week, I read a paper on infrared small target detection based on depth convolution neural network. Through window sliding, the problem of small target detection is transformed into the problem of small target location classification, which reduces the workload.On engineering projects,I learn how to read files and use front-end templates.In terms of deep learning,I learn naive Bayesian theory and its mathematical derivation, as well as the reproduction of simple code.
一、文献阅读
1、题目和摘要
题目:基于深度卷积神经网络的红外小目标检测
doi:10.11972/j.issn.1001-9014.2019.03.019
提出了一种新的用于检测红外图像中小目标的深度卷积网络,将小目标检测问题转化为小目标位置分类问题。首先,全卷积网络用于增强和初步筛选然后,选择原始图像和背景抑制图像作为用于后续筛选的分类网络输入,然后采用SEnet(挤压和激励网络)选择特征图。实验结果表明该检测网络优于多种典型的红外小目标检测方法在不同信噪比、不同场景和运动模糊目标上的出色效果
A new deep convolutional network for detecting small targets in infrared images is proposed. The problem of small targets detection is transformed into the classification of small targets’location distribution. First,a Fully Convolutional Networks is used for enhancing and initially screening the small targets. After that,the original image and the background suppressed image are selected as the inputs for classification network which is used for the follow -up screening,and then the SEnet ( Squeeze-and-Excitation Networks) is used to select the feature maps. The experimental results show that the detection network is superior to multiple typical infrared small target detection methods and has an excellent result on different signal-to-noise ratio,different scenes and motion blur targets.
2、问题的提出
红外图像小目标检测技术一直以来是红外图像处理中所研究的重点。 但是在实际场景中,一方面,红外小目标通常被淹没在复杂的背景和噪声中;另一方面,红外小目标缺少具体的形状和纹理,因此检测过程中缺少显著的特征和纹理信息. 因此红外小目标检测问题是一个具有较大挑战性的课题。
现有的红外小目标检测技术可以分为两大类别: 基于单帧空域和基于时域序列图像的检测方法。 然而基于时域序列图像的检测方法需要更多的先验信息并且通常需要借助于单帧的空域检测方法。 因此对于预警问题来说,基于单帧空域的检测方法显得非常重要。目前的红外小目标检测方法存在着人为调整的参数较多并且需要在线自适应计算的缺点。
本文设立的检测方案的出发点在于深度卷积神经网络通过对训练样本的学习,可以区分出背景图像结构与红外小目标结构特性,进而达到对小目标检测的目的. 针对小目标信噪比太弱难以检测的问题,设计了一种基于全卷积的增强网络对小目标区域进行初步筛选,其后的分类网络利用原始图像中的结构信息来抑制检测中的虚警点,同时利用背景抑制图像中小目标的局部特性提高小目标的检测 率,因此该网络采用了原始图像与背景图像的双输入进行目标的判别。
3、网络结构设计
由于红外小目标形状微小,在一幅较大尺寸的图像中所占像素数目比例非常低,因此利用深度卷积网络直接对一副较大图像进行小目标检测时会造成网络在训练过程中负样本数目远大于正样本数目 的情况,增加了训练难度和准确度. 为了改善这一情 况,本文在提取候选目标点时采用与滑动窗口类似 的方法,不同点在于,滑动步长设为窗口尺寸,同时 为了改善目标被窗口边界切割的情况,将步长设为1,这样可以保留目标的大部分。
搜索计算方式为:
W,H 为图像长宽,S 为窗口大小,stride为搜索步长. 我们选择了 21 * 21 的窗口,步长为20,图像大小为 288 * 384,因此一幅图需要的遍历次数为 266 次,远小于逐像素遍历所需要的 110 592次,因此在检测效率上有很大的提高。
经过滑动后得到的图像后,接下来应当对图像中的目遍进行检测,分为3种情况,目标在图像中间、目标在图像非中间,图像上没有目标。基于此,我们将目标的检测问题转换成目标位置分布的分类问题,当分类结果属于第一类,即目标在图像的中心位置时此时图像的中心坐标即为目标检测的具体位置。 这样做的好处是省去了对目标位置的回归网络,不需要事先标定目标所在区域的坐标进行回归训练,大大简化了网络的设计结构。
增强网络的主要目的是得到概率最大的目标候选位置,从而减少搜索次数,其作用是对目标进行一个粗筛选。利用目标的特性,卷积神经网络能够通过卷积提取目标特征并通过多层卷积对目标的形成一个分类能力,得出目标点的概率大小。增强网络的具体构造:
分类网络主要用来对目标的分布形式进行分类,其设计好坏直接影响到小目标检测率以及虚警率的大小; 分类网络的输入来自于增强网络得到的候选目标位置; 文章采取将原始图像 F 和背景抑制后的图像S同时输入作为输入方式。结构构造:
由于训练集中目标和实际场景中目标的差异,当目标产生不规则的运动模糊时,分类网络在这种情况下检测率有 所下降。采用背景抑制后的图像 S进行分类判断会更加合理,然而有些时候需要利用原始图像F中物体轮廓的连续性和结构性来抑制虚警; 因此,F和S同时输入时,不同情况下 F 和 S 的特征对分类的重要性不同,也就是要求分类网络需要能够对两组特征有一个选择性。
4、数据集制作以及训练方法
在制作训练集的需要考虑红外目标检测问题中的多样性和复杂性。 首先,在训练集中加入了局部信噪比从 1 到 7 变化的目标;目标本身的特性可以近似为服从高斯分布的点扩散; 因此采用方差为的二维高斯分布来近似目标点扩散效应; 目标区域的灰度计算可以用公式表示如下:
其中 I( x,y) 表示在图像区域内相对于中心坐标为 ( x,y) 处的点的灰度值,I( 0,0) 为区域中心点的灰度值,其大小可以根据不同的信噪比进行计算。
为了定量添加SNR不同的目标点,我们选取了目标点为中心 11* 11 的邻域对局部信噪比进行计算,计算公式为:
其中 σ2 bp表示目标所在的 11* 11 像素大小的背景区域的方差。
目标背景大概分为地面背景,天空背景以及天地交接三种类型,对于每一类的背景,选取差别较大的 200 幅添加目标点,图像之间的差异通过对其进行 PCA 分解得 到的特征向量的差值来衡量; 在每幅图像上添加 30个目标点并记录下相应位置; 随机选取其中 500 幅作为训练,其余 100 幅以及含有实际运动目标点的300 幅图像作为测试图像。
在网络训练中,首先对增强网络进行训练; 然后对将所制作的分类训练集输入到分类网络中训练,为了提高模型的泛化能力,在训练中所采用的均为提前中止的方法. 即在每次训练完一个epoch之后,对测试集进行测试,在迭代 500 个epoch之后保存的是在测试集上面表现最好的一次网络模型,并记录下此时的测试误差; 接着再对训练集和测试,集一起进行训练,直到训练的误差小于等于之前所最记录的最小的测试误差。
5、实验结果
按照4:1的比例划分训练集和测试集,选取了含有 3,4,5层卷积的增强网络进行实验对比,其测试误差曲线如下图所示。 从测试误差曲线中可以看到卷积层数为3时,其最终的测试误差与更深的网络层数相比仍相对较高,含有5层卷积的网络虽然误差收敛速度最快,但4层卷积网络最终也达到了几乎相同的测试误差,并且收敛更加稳定,因此出于检测时间上的考虑,最终选取了4层卷积网络。
在目标检测问题上,希望能够尽最大可能地将目标检测到同时不增加虚警,因此我们加入了 SEnet 改进分类网络。在实际分类效果图上,增加了SEnet的有着更好的检测效果。
有无 SEnet 对目标检测率影响:
有无 SEnet 对虚警个数影响:
比较了最终所设计的模型与目前常用的Top-hat,环形去中值滤波,单阈值PDE以及MRF算法在测试集上的检测率和虚警率上的实验结果。表中的 A,B,C,D 分别表示 Top-hat,环形去中值滤波,单阈值PDE以及MRF算法。
不同检测算法在测试集上检测效果比较
不同检测算法在测试集上虚警个数比较
从统计结果中可以看到我们所设计的算法在检测率和虚警率上均优于对比的方法,而且克服了对比算法中所需要的图像分割中的阈值选取以及PDE和MRF中参数的选择问题。文章所设计的网络具有良好的检测率和对虚警率的抑制,对目标信噪比的变化具有相当高的鲁棒性。
二、工程项目
1、读取文件
通过此方法,不需要给于用户绝对路径,通过相对路径展示给用户,起到一定的安全作用。
public ActionResult GetFile()
{
return File(@"G:\大四\屏幕截图 2022-02-14 001447.png", "image/png");
}
<img src="/home/GetFile", alt="Alternate Text" width="100"/>
上传文件到指定的文件夹,较java的io流相比,操作更加简便。
public ActionResult UploadFile(HttpPostedFileBase file)
{
var filename = DateTime.Now.Ticks + file.FileName;
file.SaveAs(basePath + @"\" + filename);
return Content(filename);
}
<form action="/home/UploadFile" method="post" enctype="multipart/form-data">
<input type="file" name="file"/ >
<button>上传</button>
</form>
单独写ActionResult来返回某个Json
public ActionResult GetJosn()
{
return Json(new {di=1,name="张三" },JsonRequestBehavior.AllowGet);
}
返回状态码
public ActionResult GetCode()
{
return new HttpStatusCodeResult(System.Net.HttpStatusCode.InternalServerError);
}
2、Result剃须刀模板
通过模板快速完成数据展示
public ActionResult List()
{
return View(new List<Student>
{
new Student()
{
Id = 1,
Name = "张三",
Age = 12
},
new Student()
{
Id = 2,
Name = "张三2",
Age = 11
},
new Student()
{
Id = 3,
Name = "张三3",
Age = 13
},
});
}
前端代码,在模板中通过@符号可以在前端页面中使用C#语音。
@model List<WebApplication2.Models.Student>属于声明语句,声明传过来的数据是List数据
通过 @Html.Raw方法可以执行在上方写的html语句
@model List<WebApplication2.Models.Student>
@{
ViewBag.Title = "List";
}
@{
string html = @"<span style = 'color:red'>hello</span>";
}
<h2>List</h2>
<ul>
@Html.Raw(html)
@foreach (var stu in Model)
{
<li>@stu.Name</li>
}
</ul>
3、ViewModels
通过Required、RegularExpression等名词,可以提供提示和进行基本的验证,这样不需要到前端进行更改,提高了开发效率。
public class RegisterViewModels
{
[Required(ErrorMessage ="邮箱地址必须填写")]
[RegularExpression("", ErrorMessage = "邮箱地址有误")]
public string Email { get; set; }
[Required]
public string Password { get; set; }
[Required]
[Compare (nameof(Password))]
public string ConfirmPassword { get; set; }
[Display(Name ="年龄")]
[Range(10, 20, ErrorMessage = "年龄必须在0到20之间")]
public int Age { get; set; }
public DateTime? BornData { get; set; }
}
三、深度学习(朴素贝叶斯)
1、朴素贝叶斯的数学理解
朴素贝叶斯是基于贝叶斯定理与特征条件独立假设的分类方法。
朴素贝叶斯通过训练数据学习联合分布P(X,Y)。在贝叶斯中假设的是样本不同特征之间,相互独立的。
数学推导过程
2、三种朴素贝叶斯的实现
三种实现差别主要体现在计算条件概率P(Xj=alj|Y=ck)。
-
伯努利朴素贝叶斯
适用于离散变量,假设各变量取值只有0、1两种,因此首先要对特征值进行二值化处理。
-
多项式朴素贝叶斯
适用于离散变量,其假设各个特征在各个类别下是服从多项式分布的,每个特征值不能是负数。
-
高斯朴素贝叶斯
适用于连续变量,其假定各个特征在各个类别下服从正态分布,通过训练集估计正态分布的参数。
优点:
生成式模型,通过计算概率来进行分类,可以用来处理多分类问题。
对小规模的数据表现很好,适合多分类任务,适合增量式训练,算法也比较简单。
缺点:
对输入数据的表达形式很敏感。
在准确率方面存在缺失问题,分类决策存在错误率。
3、简单的代码例子
对词条进行分类,分为侮辱性和非侮辱性的词语,1代表侮辱、0是侮辱类,通过词条向量训练朴素贝叶斯分类器,训练好分类器后使用分类器进行分类。
import numpy as np
from functools import reduce
"""
函数说明:创建实验样本
Parameters:
无
Returns:
postingList - 实验样本切分的词条
classVec - 类别标签向量
"""
def loadDataSet():
postingList=[['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'], #切分的词条
['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
['stop', 'posting', 'stupid', 'worthless', 'garbage'],
['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
classVec = [0,1,0,1,0,1] #类别标签向量,1代表侮辱性词汇,0代表不是
return postingList,classVec #返回实验样本切分的词条和类别标签向量
"""
函数说明:将切分的实验样本词条整理成不重复的词条列表,也就是词汇表
Parameters:
dataSet - 整理的样本数据集
Returns:
vocabSet - 返回不重复的词条列表,也就是词汇表
"""
def createVocabList(dataSet):
vocabSet = set([]) #创建一个空的不重复列表
for document in dataSet:
vocabSet = vocabSet | set(document) #取并集
return list(vocabSet)
"""
函数说明:根据vocabList词汇表,将inputSet向量化,向量的每个元素为1或0
Parameters:
vocabList - createVocabList返回的列表
inputSet - 切分的词条列表
Returns:
returnVec - 文档向量,词集模型
"""
def setOfWords2Vec(vocabList, inputSet):
returnVec = [0] * len(vocabList) #创建一个其中所含元素都为0的向量
for word in inputSet: #遍历每个词条
if word in vocabList: #如果词条存在于词汇表中,则置1
returnVec[vocabList.index(word)] = 1
else: print("the word: %s is not in my Vocabulary!" % word)
return returnVec #返回文档向量
"""
函数说明:朴素贝叶斯分类器训练函数
Parameters:
trainMatrix - 训练文档矩阵,即setOfWords2Vec返回的returnVec构成的矩阵
trainCategory - 训练类别标签向量,即loadDataSet返回的classVec
Returns:
p0Vect - 非侮辱类的条件概率数组
p1Vect - 侮辱类的条件概率数组
pAbusive - 文档属于侮辱类的概率
"""
def trainNB0(trainMatrix,trainCategory):
numTrainDocs = len(trainMatrix) #计算训练的文档数目
numWords = len(trainMatrix[0]) #计算每篇文档的词条数
pAbusive = sum(trainCategory)/float(numTrainDocs) #文档属于侮辱类的概率
p0Num = np.zeros(numWords); p1Num = np.zeros(numWords) #创建numpy.zeros数组,
p0Denom = 0.0; p1Denom = 0.0 #分母初始化为0.0
for i in range(numTrainDocs):
if trainCategory[i] == 1: #统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···
p1Num += trainMatrix[i]
p1Denom += sum(trainMatrix[i])
else: #统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···
p0Num += trainMatrix[i]
p0Denom += sum(trainMatrix[i])
p1Vect = p1Num/p1Denom #相除
p0Vect = p0Num/p0Denom
return p0Vect,p1Vect,pAbusive #返回属于侮辱类的条件概率数组,属于非侮辱类的条件概率数组,文档属于侮辱类的概率
"""
函数说明:朴素贝叶斯分类器分类函数
Parameters:
vec2Classify - 待分类的词条数组
p0Vec - 侮辱类的条件概率数组
p1Vec -非侮辱类的条件概率数组
pClass1 - 文档属于侮辱类的概率
Returns:
0 - 属于非侮辱类
1 - 属于侮辱类
"""
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
p1 = reduce(lambda x,y:x*y, vec2Classify * p1Vec) * pClass1 #对应元素相乘
p0 = reduce(lambda x,y:x*y, vec2Classify * p0Vec) * (1.0 - pClass1)
print('p0:',p0)
print('p1:',p1)
if p1 > p0:
return 1
else:
return 0
"""
函数说明:测试朴素贝叶斯分类器
arameters:
无
Returns:
无
"""
def testingNB():
listOPosts,listClasses = loadDataSet() #创建实验样本
myVocabList = createVocabList(listOPosts) #创建词汇表
trainMat=[]
for postinDoc in listOPosts:
trainMat.append(setOfWords2Vec(myVocabList, postinDoc)) #将实验样本向量化
p0V,p1V,pAb = trainNB0(np.array(trainMat),np.array(listClasses)) #训练朴素贝叶斯分类器
testEntry = ['love', 'my', 'dalmation'] #测试样本1
thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry)) #测试样本向量化
if classifyNB(thisDoc,p0V,p1V,pAb):
print(testEntry,'属于侮辱类') #执行分类并打印分类结果
else:
print(testEntry,'属于非侮辱类') #执行分类并打印分类结果
testEntry = ['stupid', 'garbage'] #测试样本2
thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry)) #测试样本向量化
if classifyNB(thisDoc,p0V,p1V,pAb):
print(testEntry,'属于侮辱类') #执行分类并打印分类结果
else:
print(testEntry,'属于非侮辱类') #执行分类并打印分类结果
if __name__ == '__main__':
testingNB()
运行结果
这样写的算法无法进行分类,p0和p1的计算结果都是0,后期应该进行相应的修改,采用平滑方法,解决0概率问题。
总结
下周为最后一周学习CNN,下周后开始学习RNN。在工程项目上,开始尝试通过理顺项目的情况下学习框架知识。在深度学习方面本周学习的是朴素贝叶斯,朴素贝叶斯与概率分布息息相关,计划下周学习决策树的相关知识。