本教程围绕五个核心问题,系统解析目标检测训练样本图像的制作要点,并推荐实用的工具与操作步骤。
一、像元值应如何归一化?
不能简单认为像元值的取值范围就是0到255,尽管普通数码相机拍摄的图像各通道取值确实在0-255之间。实际上,这个0-255的取值是从更大取值范围经过处理得到的。在局部强光、均匀光照、弱光或强光环境下,人眼能感知到相同的颜色,但数码相机的传感器会量化出不同的像元值。RGB取值对应固定的颜色,而不同环境下的传感器量化值怎样才能映射为一致的颜色?这项技术被称为宽动态。为了使宽动态处理结果更细腻,传感器的量化范围通常更大。
由于数码相机已进行宽动态处理,对普通数码照片进行归一化时,可以简单地将0-255线性映射到0-1。而医学图像、遥感图像则不能直接使用最小最大像元值归一化到0-1。因为白噪声的存在,医学图像和遥感图像的直方图通常如下图所示(横轴代表像元值范围,红色纵轴表示归一化后的取值,绿色纵轴表示不同像元值的像素频数,绿色曲线即直方图)。
如果按照红色实线代表的归一化映射进行处理,绝大多数像素取值会集中在0附近,整幅图像一片漆黑(翻转后的绿色虚曲线为归一化后的直方图)。最佳处理方式是采用红色长线段虚线所代表的映射进行归一化,但该映射难以求解,一般按照红色点虚线代表的映射处理即可。
红色点虚线代表的映射原理很简单:选取合适的最小最大值,小于最小值的置为0,大于最大值的置为1,中间部分线性映射。最大最小值的选取方法有均值±x×标准差和排除两端一定占比的像素。排除两端一定占比的像素示意图如下,从两端按百分比排除像素后即可选出新的最小最大值,此时的归一化映射图像即为红色点虚线。
小提示:对于遥感或医学图像,建议先统计整张大图的直方图,采用排除两端像素的方法计算归一化参数,而非每张小图单独计算,否则统计信息不充分。
二、样本图像的尺寸仅取决于内存和显存大小吗?
如果栅格边长减1后不能被stride整除,卷积的降采样过程会丢弃边缘像素,导致特征图像素与输入图像位置映射产生偏移。最终的特征图无法完整映射到输入图像范围,使用错位的特征图像素去预测原图上的目标,显然不可靠。目前所有深度学习框架均未考虑这种映射错位,即便使用Mask-RCNN提供的ROIAlign,错位依然存在。
因此,训练时输入样本图像的大小和检测时切块的大小,必须根据最终特征图的尺寸反推,确保卷积过程中不丢弃边缘。
小提示:计算时,确保输入尺寸满足 H_in - 1 能被所有stride的乘积整除,否则边缘像素会被丢弃,导致定位偏移。
三、网络能检测的目标框范围仅与图像大小有关吗?
感受野是指直接或间接参与计算特征图像素值的输入图像像素范围。直接感受野即卷积核大小,随着卷积层加深,之前层次的感受野会叠加进来。感受野过小会缺乏环境信息,过大则会引入过多环境干扰。因此,网络能检测的目标框范围与特征图像素或特征向量的感受野密切相关,通常可检测的目标框边长范围是感受野边长的0.1至0.5倍。
详细结论请参考论文:Understanding the effective receptive field in semantic image segmentation
https://www.onacademic.com/detail/journal_1000040207575210_3759.html
拿到一个网络后,需要先做感受野分析,确定其能检测多大的目标。实际目标检测任务需综合考虑网络结构设计和图像分辨率选择。如果目标框的像素范围超出了网络感受野,则需将原始图像缩小后再检测。
常见问题:如何计算感受野?
- 手动逐层计算:从输入层开始,每层用公式 $RF_{l} = RF_{l-1} + (k - 1) \times \prod_{i=1}^{l-1} s_i$,其中 $k$ 为卷积核大小,$s_i$ 为步长。
- 也可在网上查找常见网络(如VGG、ResNet、YOLOv3)的现成感受野数值。
四、卷积网络真的具有平移和旋转不变性吗?
直观上,同一个卷积核,只要像素团不是中心对称的,旋转后的卷积值必然不同,也就是说卷积网络显然不具备旋转不变性。那么,卷积是否具有平移不变性呢?似乎有——同一个像素团无论放在哪里,只要卷积核对齐,卷积值相同。但请不要忽略padding。每一层卷积都加padding的话,图像边缘的像素会受到更多padding影响。对于卷积网络,同一个像素团离图像中心的距离不同,卷积值必然不同,因此加了padding的卷积网络也不存在平移不变性。不带padding的网络每层都必须精心设计,如同不带padding的UNet,显然非常麻烦。为了简化网络设计,对训练样本进行平移增广非常必要。
可能还有人记得以前关于CNN具有各种不变性的解释,如果转不过弯来,建议阅读以下论文。CNN其实没有任何不变性,全靠大量数据强力拟合。
- Making Convolutional Networks Shift-Invariant Again
- SiamRPN++: Evolution of Siamese Visual Tracking with Very Deep
- Mind the Pad -- CNNs Can Develop Blind Spots
- On Translation Invariance in CNNs: Convolutional Layers can Exploit Absolute Spatial Location
- How much Position Information Do Convolutional Neural Networks Encode
- Why do deep convolutional networks generalize so poorly to small image transformations
小提示:由于CNN缺乏平移不变性,训练时务必进行平移增广(如随机偏移切图),测试时也建议采用多尺度/多位置滑窗。
五、制作目标检测训练样本的最佳方案是什么?
1. 进行感受野分析,确定能检测的目标边长范围
这一步需要自行计算。现成的网络通常能在网上找到别人算好的结果,直接使用即可。
2. 根据最终特征图的尺寸反推训练样本图像的尺寸
这一步同样需要自己计算。有了目标边长范围后,选择大于目标框最大边长约2倍的训练样本图像尺寸。
3. 对原始样本图像进行旋转和成像效果变换增广
这一步需要编写代码。目前广泛使用的正框样本库,旋转后范围框更加不准,没有意义。如果自己制作样本,务必使用倾斜范围框进行标注,这样才能进行旋转样本增广,从倾斜范围框生成的正框会更准确。旋转增广已有现成工具,但大多基于正框实现。这里有一个基于Python和OpenCV的实现(https://github.com/XuelianZ/augment)。
成像效果变换样本是指通过直方图匹配等算法,模拟夜晚、雾、雨、雪等天气下的成像效果。
为什么这两种增广要放在切图之前? 对于成像效果变换,统计信息越准确越好,切成小图后难以获得良好的算法效果。对于旋转,切完图后再旋转必然需要填充值,填充值属于人为制造的伪显著区域,不符合检测时的实际情况。
4. 对原始样本图像进行切图,切图同时可进行平移样本增广
这一步仍需编写代码。现有工具大多是简单的切图,仅支持0-255的普通数码照片,也未考虑能检测的目标边长范围。如果存在超过检测目标边长范围的范围框,需对图像进行缩小,并记录缩小比率。检测目录时也要按此缩放比率进行检测。 对于医学图像和遥感图像,切图过程中需进行归一化处理。归一化参数应从原始大样本图像上计算,切完的小图统计信息不全面,归一化参数可能不够好。
5. 其他样本增广操作
例如翻转、加噪、拼接、抠洞、缩放等,这些操作可在训练过程中随机执行。个人认为拼接、抠洞、缩放对工程应用意义不大。拼接增广是指随机找几张图各取一部分或缩小后拼在一起作为一幅图,拼接出来的图会有强烈的拼接痕迹。抠洞是指随机将目标的一部分区域扣掉并填充0值。拼接和抠洞属于人为制造的伪显著区域,不符合实际情况,只会白白增加训练量。
拼接的一个作用是增加小目标样本的数量,而平移增广同样可以增加小目标样本数量,因为小目标可以在图像范围内平移的次数更多。
训练过程中随机缩放也没有必要,缩放后的图像可能导致特征图与输入图像映射错位(参考“样本图像的尺寸仅与内存、显存大小有关吗?”);另外,工程应用中控制好成像距离就能控制目标尺寸范围,只需采集符合设计目标尺寸范围的样本图像即可。
强烈推荐的训练样本图像制作工具(切图工具)
这套工具在切图过程中实现了两种归一化方案和平移增广,输出图像可选择0-1或0-255。输出为0-255的图像可用普通看图工具查看;输出为0-1的图像数值精度更高,可能训练效果更好。对于普通数码照片,因原始取值范围就是0-255,仅以0和255作为最小最大值进行线性映射,不会选取新的最小最大值。该工具还包含一个统计范围框宽高范围并确定切图缩放比率的工具。
该工具仅支持YOLO格式的范围框标注,范围框坐标可以是归一化的,也可以是非归一化的。建议制作样本时使用非归一化坐标,整数坐标值更准确,也便于后续处理。
(一)范围框宽高统计工具
这是一个命令行工具,包含6个参数,参数之间用空格分隔。
- 输入目录
- 范围框标注格式 c,cx,cy,w,h
- 输出目录
- 输入文件扩展名,多个扩展名用半角逗号分隔
- 输入影像的比例尺,0表示从影像中读取,没有空间参考的影像比例尺默认为1,普通照片无空间参考,遥感影像才有空间参考
- 输出样本图片边长
- 裁剪出的样本图片上的目标框边长范围,共四个值,用半角逗号分隔。前两个是“按所需缩放比例缩放后最佳目标框边长的范围”,后两个是“按所需缩放比例缩放后有效目标框边长的范围”
“最佳目标框边长的范围”是指需要对图像进行缩放,使所有范围框的边长都能落入该范围。“有效目标框边长的范围”是指按某个比例缩放后,仍有目标框不能落在最佳范围,但只要在有效范围内就保留。
以下是一个运行示例,路径参数中若包含空格,需用半角引号括起来。
sidelen_cwh.exe "D:DOTA v1.5trainimagesimages" D:Test png,jpg 0 576 21,405,10,567
该工具会输出一个文本文件STATS.txt,内容如下:
1.000000,2.000000 1.000000,1.000000 7.162937,487.783206
这里为兼容遥感影像引入了比例尺概念。第一行缩放比例是一个像素对应的地理长度,普通数码照片的比例尺默认为1,还有一个为2的缩放比例,表示将图像宽高都缩小为原来的二分之一。第二行是所有图像的原始比例尺范围,因无空间参考,比例尺均为1。第三行是范围框边长的范围,以地理长度为单位,若无空间参考,即像素单位。
从中可以看出,DOTA数据集范围框边长的最大值达488,对于YOLOv3的感受野来说,并非所有框都能检测出来,除了在原始比例尺检测外,还需在缩小后的图像上检测。当然,训练也需在多个比例尺上进行。
(二)训练样本裁剪工具
这也是一个命令行工具,包含12个参数,参数之间用空格分隔。
- 输入目录
- 范围框标注格式 c,cx,cy,w,h
- 输出目录
- 输入文件扩展名,多个扩展名用半角逗号分隔
- 输入影像的比例尺,0表示从影像中读取,没有空间参考的影像比例尺默认为1
- 输出样本的比例尺(即缩放比例),多个值用半角逗号分隔,通常采用范围框宽高统计工具输出文件的第一行
- 输出样本图像的通道组合,将原始样本图像的多个通道按顺序输出,通道编号从1开始
- 归一化映射参数,有mg、mo、sg、so四种方式,其后跟的数值是相应方式的归一化参数。m表示最大最小值拉伸,其后数值表示像元数目截断的百分比;s表示均值加减标准差拉伸,其后数值表示标准差的倍数;g表示拉伸到0-255,若本来就是8位则不拉伸;o表示拉伸到0-1,若本来就是8位则直接将0-255映射到0-1
- 输出样本图片边长
- 裁剪出的样本图片上的目标框边长范围,与范围框宽高统计工具一致
- 进行样本增广时目标框平移的最小像素数量和平移量占范围框宽高的比值,当比值乘以实际范围框宽高小于最小平移量时,仍按最小平移量移动
- 目标范围框在裁剪图像范围内的部分占比的阈值,超过该值才保留。切图后若范围框跑到图像外,需排除
- 目标框宽高聚类数目
以下是一个运行示例,路径参数中若有空格需用半角引号括起来。
splitimg_cwh.exe "D:DOTA v1.5trainimagesimages" D:Test png,jpg 0 1 1,2,3 sg2.5 576 21,405,10,567 237,0.65 0.67 9
该工具除了输出裁剪出的样本外,还会生成一个文本文件ANCHORS.txt和一个图像HIST.tif。
ANCHORS.txt中的内容为: 20,20, 57,45, 104,78, 150,139, 169,179, 25,89, 30,169, 42,329, 122,407
这是范围框宽高的聚类中心,可直接用作YOLO的锚点框。
HIST.tif是范围框的二维统计直方图,像素值累计了各个宽高范围框的数量。利用该二维累计直方图可加快聚类速度。
裁剪出的样本图像如下所示。
挑选了几个方块图,将范围框叠加显示,可以观察平移增广的效果。
小提示:使用该工具时,建议先运行范围框宽高统计工具获得缩放比例,再运行裁剪工具。如果目标框尺寸跨度较大,可设置多个输出比例尺(如1,2,3),使大目标在缩小的图像上也能被检测。
常见问题:工具只支持YOLO格式吗?能否扩展其他格式?
- 目前仅支持YOLO格式(c,cx,cy,w,h)。如需其他格式,可自行编写脚本转换。
- 建议标注时使用整数坐标(非归一化),因为整数坐标更精确,也便于后续处理。
det_cwh.zip-深度学习文档类资源
