推荐 最新
清晨我上码

轻量型卷积网络】MobileNet系列:MobileNet V1网络解析

1. 介绍传统卷积神经网络,内存需求大、运算量大导致无法在移动设备以及嵌入式设备上运行。现阶段,在建立小型高效的神经网络工作中,通常可分为两类工作:压缩预训练模型。获得小型网络的一个办法是减小、分解或压缩预训练网络,例如量化压缩(product quantization)、哈希(hashing )、剪枝(pruning)、矢量编码( vector quantization)和霍夫曼编码(Huffman coding)等;此外还有各种分解因子(various factorizations )用来加速预训练网络;还有一种训练小型网络的方法叫蒸馏(distillation) 蒸馏方法解读,使用大型网络指导小型网络,这是对论文的方法做了一个补充,后续有介绍补充。直接训练小型模型。 例如Flattened networks利用完全的因式分解的卷积网络构建模型,显示出完全分解网络的潜力;Factorized Networks引入了类似的分解卷积以及拓扑连接的使用;Xception network显示了如何扩展深度可分离卷积到Inception V3 networks;Squeezenet 使用一个bottleneck用于构建小型网络。本文MobileNet网络架构属于上述第二种,允许模型开发人员专门选择与其资源限制(延迟、大小)匹配的小型模型,MobileNets主要注重于优化延迟同时考虑小型网络,从深度可分离卷积的角度重新构建模型。MobileNet网络是由google团队在2017年提出的,专注于移动端或者嵌入式设备中的轻量级CNN网络。相比传统卷积神经网络,在准确率小幅降低的前提下大大减少模型参数与运算量。(相比VGG16准确率减少了0.9%,但模型参数只有VGG的1/32), 网络主要体现两方面:Depthwise Convolution(大大减少运算量和参数数量)增加了两个超参数α,β,其中 α 控制卷积核个数的超参数,β 控制输入图像大小,这两个参数是人为设定的,并不是网络学习到的。MobileNet是Google提出的一种小巧而高效的CNN模型,MobileNets基于流线型架构(streamlined),使用深度可分离卷积(depthwise separable convolutions, 即Xception变体结构)来构建轻量级深度神经网络。论文测试在多个参数量下做了广泛的实验,并在ImageNet分类任务上与其他先进模型做了对比,显示了强大的性能。论文验证了模型也在其他领域(对象检测,人脸识别,大规模地理定位等)使用的有效性。2. 模型2.1 基本单元:深度可分离卷积(depthwise separable convolution)mobileNet的基本单元是深度可分离卷积(depthwise separable convolution)。深度可分离卷积其实是一种可分解卷积操作(factorized convolutions),其可以分解为两个更小的操作:depthwise convolution(DW 卷积)和pointwise convolution(PW卷积)。2.1.1 DW卷积Depthwise Convolution和传统卷积不同,对于传统卷积其卷积核是用在所有的输入通道上(input channels),而depthwise convolution针对每个输入通道采用不同的卷积核,就是说一个卷积核对应一个输入通道,所以说depthwise convolution是depth级别的操作。传统卷积卷积核的channel=输入特征channel输出特征矩阵的channel=卷积核个数DW卷积卷积核的channel=1输入特征channel=卷积核个数=输出特征channel2.1.2 PW卷积pointwise convolution其实就是普通的卷积,只不过其采用1x1的卷积核。对于depthwise separable convolution,其首先是采用depthwise convolution对不同输入通道分别进行卷积,然后采用pointwise convolution将上面的输出再进行结合,这样其实整体效果和一个标准卷积是差不多的,但是会大大减少计算量和模型参数量。使用depthwise separable convolution(深度可分离卷积),能减少多少参数呢?请看下图对比说明:2.2 网络结构前面讲述了depthwise separable convolution,这是MobileNet的基本组件,但是在真正应用中会加入BN层,并使用ReLU激活函数,所以depthwise separable convolution的基本结构如图4右边所示。标准卷积和MobileNet中使用的深度分离卷积结构对比如下:MobieNet V1网络结构细节如下:mobienet v1 网络结构中第一行Conv/s2表示普通卷积,步距为2.Filter Shape为3x3x3x32表示卷积核大小为3x3,输入为彩色图片3通道,输出为32通道Conv dw/s1表示 DW卷积,步距为1,Filter Shape为3 x 3 x 32表示卷积核大小3x3,dw卷积的channel为1,卷积核的个数为32由于可分离卷积是mobienet v1基本组件,可分离卷积表示为dw +pw,因此dw 和1x1的pw是成对出现的mobienet v1的模型结构有点类似于VGG结构,简单的将一系列卷积进行串行链接。3. 实验3.1 对比大模型对比了 MobieNet 和GoogleNet、VGG16在imageNet数据集上的准确率、运算量和模型参数,可以看到MobieNet相对于VGG16 它的准确率只减少了0.9%,但它的模型参数大概只有VGG网络的1/32。3.2 对比小模型对比了 MobieNet 和squeezenet、AlexNet在imageNet数据集上的准确率、运算量和模型参数,可以看到MobieNet准确率高且模型参数少。3.3 超参数 α 和 βα 是卷积核个数的倍率,控制卷积过程中采用的卷积核个数。看看取不同 α 时网络的效果。α 取1.0的时候,它的准确率是70.6%,当α 取0.75时,即卷积个数缩减为原来的0.75倍的时候,它的准确率为68.4%,同时计算量和参数也不同程度的减少;当α 取0.5时,准确率为63.7%,计算量和参数同时也在减少。可以发现将我们卷积核个数减少之后,准确率上没有太大的变化,但模型参数大幅减少。可以根据自己的项目需求去选择合适的α值。β 是分辨率的参数,输入图像的尺寸对网络的分类准确率,模型计算量、模型参数的对比。可以发现通过适当减低图片尺寸大小,能够保证准确率降低很小的情况下,来大幅减少我们的运算量。根据你自己项目的需求来设置β 参数。4. 总结在mobienet v1网络的实际使用中,很多人发现dw卷积,它在训练完之后部分卷积核容易废掉,即卷积核参数大部分为0。因为你观察DW卷积的参数时,你会发现它的大部分参数都是等于0的,DW卷积核是没有起到作用的。针对这个问题 在mobienet v2中会得到改善。

0
0
0
浏览量2016
清晨我上码

【轻量型卷积网络】ResNeXt网络解析

1. 介绍在提出 ResNet 网络之后,很多模型都会拿 ResNet 网络作为基准和比对。而ResNeXt 网络可以被视作对 ResNet 的小幅升级,其实不难发现其也参考了 Inception 的思想。其原始论文为 《Aggregated Residual Transformations for Deep Neural Network》,发表于 2017 年的 CVPR。但是这篇论文没有当初的 ResNet 那么惊艳了。论文最大的贡献点就在于更新了 Residual Block,采用 split-transform-merge 策略,本质是分组卷积,但是不需要像 Inception 一样人工设计复杂的结构,也不像 Inception 一样结合不同尺寸感受野的信息,拓扑结构一致的 ResNeXt 对 GPU 等硬件也更友好 (所以这个结构跑得更快)。值得指出的是,split-transform-merge 策略其实在 VGG 堆叠的思想和 Inception 的思想中都有体现,只不过 VGG split 的是变换函数本身,ResNeXt 和 Inception 都是 split 输入特征。2. 模型2.1 组卷积在讲述 ResNeXt 之前,需要先了解一下什么是组卷积 (Group Convolution)。而 分组卷积是介于普通卷积和深度可分离卷积(MobileNet)的一种折中方案,不是彻底的将每个 channel 都要单独赋予一个独立的卷积核,也不是整个 Feature Map 使用同一个卷积核。这就像之前说的 Group Normalization 一样。2.2 ResNeXt—block作者在论文中给出了三种 block 模块,注意,他们在数学计算上完全等价!首先看从 ( c ) 到 ( b )。在 ( c ) 中上面 256 通道特征图通过 1 × 1 卷积变为 128 个通道,每个卷积核大小为 1 × 1 × 256,一共 128 个卷积核。我们考虑将 128 个卷积核 4 个一组,那么就可以成为 32 组。因为卷积核之间是没什么关联的,所以完全可以独立分开,就对应于 ( b ) 的第一行。因为在 ( c ) 中第二行是组卷积,其实也是把 1 × 1 卷积变为 128 个通道独立拆分为 32 组,每组 4 通道,就和 ( b ) 中第二层的输入是一致的。 ( b ) 的第二层其实就是把组卷积给画开了而已。所以 ( b ) 的第二层与 ( c ) 的第二层一致。因此( b ) 和 ( c ) 是完全等价的。然后我们看从 ( b ) 到 ( a )。重点在于为什么 concatenate 之后通过 256 个 1 × 1 × 128 卷积和直接使用 32 组 256 个 1 × 1 × 4 卷积后直接相加是等价的。其实这非常自然,让我们想象一下,最终输出的某个通道的某个元素,其实就是之前 128 个通道那个元素位置元素的加权求和,权就是 1 × 1 × 128 卷积核的参数。那么他可以把 128 个求和元素拆开成先加 4 个,再加 4 个,这样加 32 下,最后再把这 32 个元素加起来。本质就是 256 个 1 × 1 × 128 卷积核可以拆成 32 组 256 个 1 × 1 × 4 卷积核。因此 ( b ) 和 ( a ) 也是等价的。所以为了搭建 ResNeXt 网络,只需简单地将搭建 ResNet 网络中的 block 进行替换就行了。2.3 为什么 group = 32组数 (作者取名为 Cardinality),可以计算出组卷积通道数,使得和原始 ResNet 计算量基本一致(原论文提到尽可能减少训练过程中超参数个数)。参数量计算很简单,参考如下公式,当 C = 32 , d = 4时计算可得参数量为 70k:实践是检验真理的唯一标准,在没有理论的支撑下,作者干脆就是根据实验发现,这样性能好,所以设置为 32。这里,C为设置的组数,d为每组的维度,width of group conv为组卷积的输出维度,也就是C*d2.4 注意最后补充一下,上述 block 都是针对 ResNet50 及以上的网络进行替换的。如果对于浅层的例如 ResNet18 和 ResNet34 怎么替换呢?可以参考下图的结构进行替换即可。————————————————

0
0
0
浏览量2022
清晨我上码

【Opencv--形态学操作】膨胀、腐蚀、开/闭操作:cv2.morphologyEx、cv2.er

1. 介绍在使用opencv做图像处理的时候,我们经常会需要用到一些基础的图像形态学操作腐蚀、膨胀。通过这些基本的形态学操作我们可以实现去噪以及图像的切割等。形态学变换是基于图像形状的基础变换,它只能在二值图像上做处理。形态学操作需要两个输入:输入图像和structuring element(kernel),structuring element(kernel)决定我们做何种形态学处理的操作。腐蚀和膨胀是形态学处理的基础操作,而开/闭运算、礼帽黑帽是基于腐蚀和膨胀的变种操作。2. 形态学操作2.1 腐蚀和膨胀腐蚀和膨胀是最基本的形态学操作,腐蚀和膨胀都是针对白色部分(高亮部分)而言的。    膨胀就是使图像中高亮部分扩张,效果图拥有比原图更大的高亮区域;    腐蚀是原图中的高亮区域被蚕食,效果图拥有比原图更小的高亮区域。    总结就是:膨胀是求局部最大值的操作,腐蚀是求局部最小值的操作。2.1.1 腐蚀用一个结构元素扫描图像中的每一个像素,用结构元素中的每一个像素与其覆盖的对应像素做“与"操 作,如果都为1,则该像素为1,否则为0。如下图所示,结构A被结构B腐蚀后:作用:消除物体边界点,使目标缩小,可以消除小于结构元素的噪声点。函数:cv.erode(img,kernel,iterations)参数:img:要处理的图像kernel:核结构(上图结构B)iterations:腐蚀的次数,默认是1。2.1.2 膨胀用一个结构元素扫描图像中的每一个像羹,用结构元素中的每一个像素与其覆盖的对应像素做 “与"操作,如果都为0,则该像素为0,否则为1。如下图所示,结构A被结构B膨胀后:作用:将与物体接触的所有背景点合并到物体中,使目标增大,可填补目标中的孔洞。函数:cv.dilate(img,kernel,iterations)参数:img:要处理的图像kernel:核结构iterations:腐蚀的次数,默认是1。2.1.3 代码示例import numpy as np import cv2 as cv img = cv.imread("./img/1.jpg") # 创建核结构 kernel = np.ones((5,5),np.uint8) # 腐蚀和膨胀 erosion = cv.erode(img,kernel) #腐蚀 dilate = cv.dilate(img,kernel) #膨胀 cv2.imshow('1', img) # 原图 cv2.imshow('2', erosion) # 腐蚀后 cv2.imshow('3', dilate) # 膨胀后2.2 开/闭操作开运算和闭运算是将腐蚀和膨胀按照一定的次序进行处理。但这两者并不是可逆的,即先开后闭(先闭后开)并不能得到原来的图像。2.2.1 开操作先腐蚀后膨胀。作用:分离物体,消除小区域。特点:消除噪点,去除小的干扰块,而不影响原来的图像。2.2.2 闭操作先膨胀后腐蚀。作用:消除"闭合"物体里面的孔洞。特点:可以填充闭合区域。2.2.3 代码示例函数:cv.morphologyEx(img, op, kernel)参数:img:要处理的图像。op(处理方式):若进行开运算,则设为cv.MORPH_OPEN,若进行闭运算,则设为cv.MORPH_CLOSEKernel(核结构):按照该核结构(模板)去进行运算,上述的结构B。import numpy as np import cv2 as cv import matplotlib.pyplot as plt img = cv.imread("./img/1.jpg") # 创建核结构 kernel = np.ones((5,5),np.uint8) #图像的开闭运算 cvOPen = cv.morphologyEx(img,cv.MORPH_OPEN,kernel) #开运算 cvClose = cv.morphologyEx(img,cv.MORPH_CLOSE,kernel) #闭运算 #图像展示 fig,axes=plt.subplots(nrows=1,ncols=3,figsize=(15, 10)) axes[0].imshow(img[:,:,::-1]), axes[0].set_title("原图") axes[1].imshow(cvOPen[:,:,::-1]), axes[1].set_title("开运算") axes[2].imshow(cvClose[:,:,::-1]), axes[2].set_title("闭运算") plt.show()2.3 礼帽和黑帽2.3.1 礼帽运算原图像与开运算结果之差,如下式计算:由于开运算可能会放大了裂缝或者局部低亮度的区域。因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作和选择的核的大小相关。礼帽运算用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。2.3.2 黑帽运算“闭运算“的结果图与原图像之差,如下式计算:黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。黑帽运算可以用来分离比邻近点暗一些的斑块。2.3.3 函数cv.morphologyEx(img, op, kernel) 参数: img:要处理的图像 op:处理方式 闭运算:cv.MORPH_CLOSE 开运算:cv.MORPH_OPEN 礼帽运算:cv.MORPH_TOPHAT 黑帽运算:cv.MORPH_BLACKHAT Kernel:核结构3. 总结腐蚀和膨胀∶      腐蚀:求局部最大值      膨胀:求局部最小值开闭运算:       开:先腐蚀后膨胀      闭:先膨胀后腐蚀礼帽和黑帽:       礼帽:原图像与开运算之差        黑帽:闭运算与原图像之差4. 参考【1】https://blog.csdn.net/qq_50620084/article/details/124526983

0
0
0
浏览量1994
清晨我上码

【图像分割】Unet系列深度讲解(FCN、UNET、UNET++)

1. 介绍1.1 背景介绍:自2015年以来,在生物医学图像分割领域,U-Net得到了广泛的应用,目前已达到四千多次引用。至今,U-Net已经有了很多变体。目前已有许多新的卷积神经网络设计方式,但很多仍延续了U-Net的核心思想,加入了新的模块或者融入其他设计理念。编码和解码,早在2006年就发表在了nature上.当时这个结构提出的主要作用并不是分割,而是压缩图像和去噪声,后来把这个思路被用在了图像分割的问题上,也就是现在我们看到的FCN或者U-Net结构,在它被提出的三年中,有很多很多的论文去讲如何改进U-Net或者FCN,不过这个分割网络的本质的结构是没有改动的, 即下采样、上采样和跳跃连接。1.2 医学图像特点图像语义较为简单、结构较为固定。我们做脑的,就用脑CT和脑MRI,做胸片的只用胸片CT,做眼底的只用眼底OCT,都是一个固定的器官的成像,而不是全身的。由于器官本身结构固定和语义信息没有特别丰富,所以高级语义信息和低级特征都显得很重要。数据量少。医学影像的数据获取相对难一些,很多比赛只提供不到100例数据。所以我们设计的模型不宜多大,参数过多,很容易导致过拟合。原始UNet的参数量在28M左右、上采样带转置卷积的UNet参数量在31M左右,而如果把channel数成倍缩小,模型可以更小。缩小两倍后,UNet参数量在7.75M。缩小四倍,可以把模型参数量缩小至2M以内)非常轻量。个人尝试过使用Deeplab v3+和DRN等自然图像语义分割的SOTA网络在自己的项目上,发现效果和UNet差不多,但是参数量会大很多。多模态。相比自然影像,医疗影像是具有多种模态的。以ISLES脑梗竞赛为例,其官方提供了CBF,MTT,CBV,TMAX,CTP等多种模态的数据。比如CBF是脑血流量,CBV用于检测巨细胞病毒的。1.3 图像分割是什么简单的来讲就是给一张图像,图像分割出一个物体的准确轮廓。也这样考虑,给出一张图像 I,这个问题就是求一个函数,从I映射到Mask。求这个函数有很多方法,但是第一次将深度学习结合起来的是全卷积网络(FCN),利用深度学习求这个函数。2. Unet发展历程(FCN、Unet、Unet++)2.1 全卷积网络-FCN很多分割网络都是基于FCN做改进,我们先介绍FCN的内容。2.1.1 FCN介绍:FCN是深度学习在图像分割的开山之作。在此之前深度学习一般用在分类和检测问题上。由于用到CNN,所以最后提取的特征的尺度是变小的。和我们分割任务要求的函数不一样,我们要求的函数是输入多大,输出有多大。经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类(全联接层+softmax输出)。基于此,FCN的设计使得可以接受任意尺寸的输入图像,采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸,最后在上采样的特征图上进行逐像素分类。解决了语义级别的图像分割问题。由于网络中只有卷积没有全连接,所以这个网络又叫全卷积网络。2.1.2 FCN框架输入原图,得到五次池化后的特征图,然后将特征map上采样回去。再将预测结果和ground truth每个像素一一对应分类,做像素级别分类。也就是说将分割问题变成分类问题,而分类问题正好是深度学习的强项。如果只将特征map直接上采样或者反卷积,明显会丢失很多信息。FCN采取解决方法是将pool4、pool3、和特征map融合起来,由于pool3、pool4、特征图大小尺寸是不一样的,所以融合前应该上采样到同一尺寸。这里的融合对应元素相加。2.1.3 反卷积层反卷积层也是卷积层。乍看一下好像反卷积和卷积的工作过程差不多,主要的区别在于反卷积输出图片的尺寸会大于输入图片的尺寸,通过增加padding来实现这一操作。这里可以参考:卷积和逆卷积(转置卷积)详解卷积和逆卷积-nn.Conv2d与nn.ConvTranspose2d参数理解2.1.4 输入图像大小FCN的输入图片大小任意。首先,我们来看传统CNN为什么需要固定输入图片大小。对于CNN,一幅输入图片在经过卷积和 pooling 层时,这些层是不关心图片大小的。比如对于一个卷积层,它并不关心inputsize多大,pooling层同理。但是在进入全连接层时,feature map(假设大小为n×n)要拉成一条向量,而向量中每个元素(共n×n个)作为一个结点都要与下一个层的所有结点(假设4096个)全连接,这里的权值个数是4096×n×n,而我们知道神经网络结构一旦确定,它的权值个数都是固定的,所以这个n不能变化,n是conv5的outputsize,所以层层向回看,每个outputsize都要固定,因此输入图片大小要固定。而FCN的全卷积是没有全连接层的,所以不要求输入图片大小固定。2.1.5 分割效果FCN优点是实现端到端分割。输入是原始数据输出是最终结果,缺点是分割结果细节不够好,可以看到FCN8s是上面讲的pool4、pool3和特征图融合,FCN16s是pool4和特征map融合,FCN32s是只有特征map,得出结果都是细节不够好,具体可以看自行车。此外,作者还尝试了结合pool2发现效果并没有提升。2.2 UNET2.2.1 网络架构Unet包括两部分:第一部分,特征提取,VGG类似。第二部分,上采样部分。由于网络结构像U型,所以叫Unet网络。特征提取部分,每经过一个池化层就一个尺度,包括原图尺度一共有5个尺度。上采样部分,每上采样一次,就和特征提取部分对应的通道数相同尺度融合,但是融合之前要将其crop。这里的融合是拼接。可以看到,输入是572x572的,但是输出变成了388x388,这说明经过网络以后,输出的结果和原图不是完全对应的。图中,蓝色箭头代表3x3的卷积操作,并且stride是1,padding策略是vaild,因此,每个该操作以后,featuremap的大小会减2。红色箭头代表2x2的maxpooling操作,需要注意的是,此时的padding策略也是vaild,这就会导致如果pooling之前featuremap的大小是奇数,会损失一些信息 。所以要选取合适的输入大小,因为2*2的max-pooling算子适用于偶数像素点的图像长宽。绿色箭头代表2x2的反卷积操作,这个只要理解了反卷积操作,就没什么问题,操作会将featuremap的大小乘2。- 卷积和逆卷积(转置卷积)详解、 卷积和逆卷积-nn.Conv2d与nn.ConvTranspose2d参数理解灰色箭头表示复制和剪切操作,可以发现,在同一层左边的最后一层要比右边的第一层要大一些,这就导致了,想要利用浅层的feature,就要进行一些剪切。输出的最后一层,使用了1x1的卷积层做了分类。最后输出了两层是前景和背景。2.2.2 valid卷积这三种不同模式是对卷积核移动范围的不同限制。full mode,橙色部分为image,蓝色部分为filter。full模式的意思是,从filter和image刚相交开始做卷积,白色部分为填0。same mode,当filter的中心(K)与image的边角重合时,开始做卷积运算,可见filter的运动范围比full模式小了一圈。注意:这里的same还有一个意思,卷积之后输出的feature map尺寸保持不变(相对于输入图片)。当然,same模式不代表完全输入输出尺寸一样,也跟卷积核的步长有关系。same模式也是最常见的模式,因为这种模式可以在前向传播的过程中让特征图的大小保持不变,调参不需要精准计算其尺寸变化(因为尺寸根本就没变化)。valid mode,当filter全部在image里面的时候,进行卷积运算,可见filter的移动范围较same更小了。2.2.3 overlap-tile策略医学图像是一般相当大,分割时候不可能将原图直接输入网络。所以需要用一个滑动窗口把原图扫一遍,使用原图的切片进行训练或测试。如下图,红框是要分割区域。但是在切图时要包含周围区域,overlap另一个重要原因是周围overlap部分可以为分割区域边缘部分提供纹理等信息。这样的策略会带来一个问题,图像边界的图像块没有周围像素,卷积会使图像边缘处的信息丢失。因此作者对周围像素采用了镜像扩充。下图中红框部分为原始图片,其周围扩充的像素点均由原图沿白线对称得到。这样,边界图像块也能得到准确的预测。另一个问题是,这样的操作会带来图像重叠问题,即第一块图像周围的部分会和第二块图像重叠。因此作者在卷积时只使用有效部分。可能的解释是使用valid卷积和crop裁剪,最终传到下一层的只有中间原先图像块(黄色框内)的部分。2.2.4 弹性变换由于深度神经网络具有非常强的学习能力,如果没有大量的训练数据,会造成过拟合,训练出的模型难以应用。因此对于一些没有足够样本数量的问题,可以通过已有的样本,对其进行变换,人工增加训练样本。常用的增加训练样本的方法主要有对图像进行旋转、位移等仿射变换,也可以使用镜像变换。这里介绍弹性变换。该算法最开始应用在mnist手写体数字识别数据集中,发现对原图像进行弹性变换的操作扩充样本以后,对于手写体数字的识别效果有明显的提升。因为unet论文的数据集是细胞组织的图像,细胞组织的边界每时每刻都会发生不规则的畸变,所以采用弹性变形的增广是非常有效的。下面来详细介绍一下算法流程:弹性变化是对像素点各个维度产生(-1,1)区间的随机标准偏差,用高斯滤波对各维度的偏差矩阵进行滤波,最后用放大系数控制偏差范围。因而由A(x,y)得到的A’(x+delta_x,y+delta_y)。A‘的值通过在原图像差值得到,A’的值充当原来A位置上的值。下图显示的是在固定的n下不同高斯标准差的结果,第二个图的形变效果是最合适的。2.4.5 损失函数损失函数首先是用了个pixel-wise softmax,就是每个像素对应的输出单独做softmax,也就是做了w*h个softmax。其中,x可以看作是某一个像素点, l(x)表示x这个点对应的类别label,pk​(x)表示在x这个点的输出在类别k的softmax的激活值。那么pl(x)​(x)代表什么呢?根据前面的说明就可以推断出来:点x在对应的label给出的那个类别的输出的激活值。正常的交叉熵定义如第一个公式,可以发现两个公式的意义其实是相同的,后面的公式在外面把非label对应的结果乘0了。然后是w(x)定义的式子,d1,d2分别是像素点最近和第二近的细胞的距离。这个权重可以调整图像中某个区域的重要程度。细胞组织图像的一大特点是,多个同类的细胞会紧紧贴合在一起,其中只有细胞壁或膜组织分割。因此,作者在计算损失的过程中,给两个细胞重合的边缘部分增加了损失的权重,以此让网络更加注重这类重合的边缘信息。实际情况中,是需要自己根据应用情况来设计或调整这个权重的。下图中的a是raw image,b是ground truth segmentation,c 是生成的分割掩码,白色是前景,黑色是背景。d是增加了像素级的loss权重后,让网络对边界像素进行了更好的学习的结果。2.3 UNET++2.3.1 存在的问题第一个问题:既然输入和输出都是相同大小的图,为什么要折腾去降采样一下再上采样呢?降采样的理论意义是,它可以增加对输入图像的一些小扰动的鲁棒性,比如图像平移,旋转等,减少过拟合的风险,降低运算量,增加感受野的大小。上采样的最大的作用其实就是把抽象的特征再还原解码到原图的尺寸,最终得到分割结果。对于特征提取阶段,浅层结构可以抓取图像的一些简单的特征,比如边界,颜色,而深层结构因为感受野大了,而且经过的卷积操作多了,能抓取到图像的一些抽象特征。第二个问题:既然unet每一层抓取的特征都很重要,为什么非要降四次之后才开始上采样回去呢?2.3.2 网络深度提出疑问后, 为了验证多深才好,每加一个深度就训练一个网络,分别用了两个数据集:Electron Microscopy 和 Cell然后测它们各自的分割表现,先不要看后两个UNet++,就看这个不同深度的U-Net的表现(黄色条形图)。我们可以看出,不是越深越好,它背后的传达的信息就是,不同层次特征的重要性对于不同的数据集是不一样的,并不是说设计一个原论文给出的那个结构,就一定对所有数据集的分割问题都最优。最终得出的结论是,不同数据集的最优的深度是不一样的, 但是总不能把所有不同深度的U-Net都训练一遍,太耗时间了,于是提出unet++ 。2.3.3 模型架构这个综合长连接和短连接的架构就是UNet++。UNet++的优势是可以抓取不同层次的特征,将它们通过特征叠加的方式整合,加入更浅的U-Net结构,使得融合时的特征图尺度差异更小。UNet++同时也引进了很多参数,占用内存也变大。3. 参考【1】https://blog.csdn.net/a8039974/article/details/109645616

0
0
0
浏览量2025
清晨我上码

图像增广与扩充---带有噪声的黑白裂缝图像扩充,用于裂缝检测训练

图像增广与扩充—带有噪声的黑白裂缝图像扩充,用于裂缝检测训练1. 初始数据获得初始的裂缝数据,可以从github上搜索crack以及其他资源去获得。我这里只在github上找了一些就够了。然后对这些图像基于opencv去转化为黑白图像。然后截图处理,使裂缝可以占满它所在的图像。因为到时候还要贴图,为之后获得标签(位置信息)做铺垫。然后初始的数据就获得了。注意此时的数据是,黑白的图像,并且裂缝占满他所在的图像,每张图像的像素大小大概率是不一样的。2. 传统图像扩充、基于深度学习的图像扩充(GAN网络)传统方法:这里只使用了旋转和尺寸变换(resize)。裁剪等其他的方法没用的必要其实。GAN深度扩充:生成器使用反卷积,判别器使用卷积即可。详细可见:     使用GAN(生成对抗网络)进行图像生成3. 将生成的裂缝图像和黑色背景融合融合时,也可以对裂缝图像(假设原尺寸为256*256)尺寸变换和旋转,之后直接融合到黑色背景(1024*1024)上去即可。def add_obj(background, img, x, y): '''' 将img融合到background上去 background: 背景 img: 要融合的裂缝图像 x,y: 要融合的位置 ''' bg = background.copy() h_bg, w_bg = bg.shape[0], bg.shape[1] h, w = img.shape[0], img.shape[1] # Calculating coordinates of the top left corner of the object image to the background x_tl = x - int(w/2) y_tl = y - int(h/2) # Calculating coordinates of the bottom right corner of the object image to the background x_br = x + int(w/2) y_br = y + int(h/2) w1 = x_br - x_tl h1 = y_br - y_tl if (x_tl >= 0 and y_tl >= 0) and (x_br < w_bg and y_br < h_bg): a = bg[y_tl:y_br, x_tl:x_br] b = img[0:h1, 0:w1] c = np.where(b>50, b, a) bg[y_tl:y_br, x_tl:x_br] = c bg[bg>50] = 255 bg[bg<=50] = 0 return bg, x_tl, y_tl, x_br, y_br else: return None4. 添加噪声''' 生成黑白背景并随机生成噪声 ''' def add_small(w, h): root_path = 'noise/small' files_list = os.listdir(root_path) n = len(files_list) k = np.random.randint(0, n) img = cv2.imread(os.path.join(root_path, files_list[k]), 0) img = cv2.resize(img, (h, w)) return img def add_big(w, h): root_path = 'noise/big' files_list = os.listdir(root_path) n = len(files_list) k = np.random.randint(0, n) img = cv2.imread(os.path.join(root_path, files_list[k]), 0) img = cv2.resize(img, (h, w)) return img def get_xy(w, h, w1, h1): a = w - w1 - 1 b = h - h1 - 1 x = np.random.randint(0, a) y = np.random.randint(0, b) return x, y def add_noise(img): w = img.shape[1] h = img.shape[0] # 小斑点 count = np.random.randint(100, 300) for _ in range(0, count): w1 = np.random.randint(10, 15) h1 = np.random.randint(10, 15) x, y = get_xy(w, h, w1, h1) img[x:x+w1, y:y+h1] = add_small(w1, h1) # 方形 count = np.random.randint(3, 5) for _ in range(0, count): w1 = np.random.randint(30, 50) h1 = np.random.randint(30, 50) x, y = get_xy(w, h, w1, h1) img[x:x+w1, y:y+h1] = add_small(w1, h1) # 长形 count = np.random.randint(3, 5) for _ in range(0, count): w1 = np.random.randint(10, 15) h1 = np.random.randint(30, 50) x, y = get_xy(w, h, w1, h1) img[x:x+w1, y:y+h1] = add_small(w1, h1) # 扁形 count = np.random.randint(3, 5) for _ in range(0, count): w1 = np.random.randint(30, 50) h1 = np.random.randint(10, 15) x, y = get_xy(w, h, w1, h1) img[x:x+w1, y:y+h1] = add_small(w1, h1) return img5. 最终得到裂缝图像以及对应的label(记录着裂缝的位置)最终得到crack文件夹,img是扩充生成的图片,label是对应的裂缝位置信息(保存为xml格式),可以用来训练。生成图像示例:对应label示例(xml文件):

0
0
0
浏览量2016
清晨我上码

【轻量型卷积网络】ShuffleNet 网络解析

1. 介绍论文地址:ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile DevicesShuffleNet是Face++(旷视)的一篇关于降低深度网络计算量的论文,号称是可以在移动设备上运行的深度网络。它主要采用channel shuffle、pointwise group convolutions 和 depthwise separable convolution来修改原来的ResNet单元。ShuffleNet可以和MobileNet、Xception和ResNeXt 结合来看,因为有类似的思想。卷积的group操作从AlexNet就已经有了,当时主要是解决模型在双GPU上的训练。ResNeXt借鉴了这种group操作改进了原本的ResNet。MobileNet则是采用了depthwise separable convolution代替传统的卷积操作,在几乎不影响准确率的前提下大大降低计算量。Xception和MobileNet类似,也是主要采用depthwise separable convolution 来 改进Inception v3的结构。上述内容解读,可以参考:ResNeXt:ResNeXt 详细解析MobileNet:MobileNet V1MobileNet V2MobileNet V3Xception:Xception 详细解析2. ShuffleNet 模型ShuffleNet 主要采用channel shuffle、pointwise group convolutions 和 depthwise separable convolution来修改原来的ResNet单元,接下来依次讲解。2.1 channel shuffle其思想如上图 Figure 1。先从group操作说起,一般卷积操作中比如输入feature map的数量是N,该卷积层的filter数量是M,那么M个filter中的每一个filter都要和N个feature map的某个区域做卷积,然后相加作为一个卷积的结果。假设你引入group操作,设group为 g,那么N个输入feature map就被分成g个group,M个filter就被分成g个group,然后在做卷积操作的时候,第一个group的M/g个filter中的每一个都和第一个group的N/g个输入feature map做卷积得到结果,第二个group同理,直到最后一个group,如上图(a)。不同的颜色代表不同的group,图中有三个group。这种操作可以大大减少计算量,因为你每个filter不再是和输入的全部feature map做卷积,而是和一个group的feature map做卷积。但是如果多个group操作叠加在一起,如Figure1(a)的两个卷积层都有 group 操作,显然就会产生边界效应。什么意思呢?就是某个输出channel仅仅来自输入channel的一小部分。这样肯定是不行的,学出来的特征会非常局限。于是就有了channel shuffle来解决这个问题,先看Figure1(b),在进行GConv2之前,对其输入feature map做一个分配,也就是每个group分成几个subgroup,然后将不同group的subgroup作为GConv2的一个group的输入,使得GConv2的每一个group都能卷积输入的所有group的feature map,这和Figure1(c)的channel shuffle的思想是一样的。2.2 pointwise group convolutionspointwise group convolutions 其实就是带group的卷积核为11的卷积,也就是说 pointwise convolution是卷积核为11的卷积。在ResNeXt中主要是对33的卷积做group操作,但是在ShuffleNet中,作者是对11的卷积做group的操作,因为作者认为1*1的卷积操作的计算量不可忽视。可以看Figure2(b)中的第一个11卷积是GConv,表示group convolution。Figure2(a)是ResNet中的bottleneck unit,不过将原来的33 Conv改成3*3 DWConv,作者的ShuffleNet主要也是在这基础上做改动。首先用带group的11卷积代替原来的11卷积,同时跟一个channel shuffle操作,这个前面也介绍过了。然后是3*3 DWConv 表示depthwise separable convolution。其实就是将传统的卷积操作分成两步,假设原来是3 * 3的卷积,那么 depthwise separable convolution就是先用M个3 * 3卷积核一对一卷积输入的M个feature map,不求和,生成M个结果,然后用N个1 * 1的卷积核正常卷积前面生成的M个结果,求和,最后得到N个结果。Figure2(c)添加了一个Average pooling和设置了stride=2,另外原来Resnet最后是一个Add操作,也就是元素值相加,而在(c)中是采用concat的操作,也就是按channel合并,类似googleNet的Inception操作。2.3 depthwise separable convolution可以参考:MobileNet v1 中的解析。2.4 结构 & 实验结果3. 总结ShuffleNet的核心就是用 pointwise group convolution,channel shuffle和depthwise separable convolution 来改进 ResNet block的相应层进而构成了ShuffleNet uint,达到了减少计算量和提高准确率的目的。其中最核心的是 channel shuffle解决了多个group convolution叠加出现的边界效应,而pointwise group convolution和depthwise separable convolution主要减少了计算量。————————————————

0
0
0
浏览量1859
清晨我上码

【轻量型卷积网络】MobileNet系列:MobileNet V3网络解析

1. 介绍1.1 关于v1和v2MobileNet-v1的主要思想就是深度可分离卷积,大大减少了参数量和计算量。可以参考 MobileNet V1网络解析。深度可分离卷积 可理解为 深度卷积 + 逐点卷积。深度卷积:深度卷积只处理长宽方向的空间信息;逐点卷积只处理跨通道方向的信息。能大大减少参数量,提高计算效率。 一个卷积核只处理一个通道,即每个卷积核只处理自己对应的通道。输入特征图有多少个通道就有多少个卷积核。将每个卷积核处理后的特征图堆叠在一起。输入和输出特征图的通道数相同。逐点卷积: 是使用1x1卷积对跨通道维度处理,有多少个1x1卷积核就会生成多少个特征图。用于跨通道扩充维度。MobileNet-v2 使用了逆转残差模块和最后一层采用线性层(而不是relu)。可以参考 MobileNet V2网络解析。输入图像,先使用1x1卷积提升通道数;然后在高维空间下使用深度卷积;再使用1x1卷积下降通道数,降维时采用线性激活函数(y=x)。当步长等于1且输入和输出特征图的shape相同时,使用残差连接输入和输出;当步长=2(下采样阶段)直接输出降维后的特征图。对比 ResNet 的残差结构。输入图像,先使用1x1卷积下降通道数;然后在低维空间下使用标准卷积,再使用1x1卷积上升通道数,激活函数都是ReLU函数。当步长等于1且输入和输出特征图的shape相同时,使用残差连接输入和输出;当步长=2(下采样阶段)直接输出降维后的特征图。1.2 v3の介绍相对于v2,主要有3个变化:block结构发生改变,在v2的bottleneck block里加入了Squeeze-and-Excitation block。算法内部微结构变化,把部分relu6使用hard-swish替换,把全部sigmoid使用hard-sigmoid替换。使用Platform-Aware Neural Architecture Search(NAS)来形成网络结构,并利用NetAdapt技术进一步筛选网络层结构。2. 模型主要有以下改进:(1)添加SE注意力机制;(2)使用新的激活函数;(3)重新设计耗时层结构2.1 添加SE注意力机制先将特征图进行全局平均池化,特征图有多少个通道,那么池化结果(一维向量)就有多少个元素,[h, w, c]==>[None, c]。然后经过两个全连接层得到输出向量。第一个全连接层的输出通道数等于原输入特征图的通道数的1/4;第二个全连接层的输出通道数等于原输入特征图的通道数。即先降维后升维。全连接层的输出向量可理解为,向量的每个元素是对每张特征图进行分析得出的权重关系。比较重要的特征图就会赋予更大的权重,即该特征图对应的向量元素的值较大。反之,不太重要的特征图对应的权重值较小。第一个全连接层使用ReLU激活函数,第二个全连接层使用 hard_sigmoid 激活函数。经过两个全连接层得到一个由channel个元素组成的向量,每个元素是针对每个通道的权重,将权重和原特征图的对应相乘,得到新的特征图数据。以下图为例,特征图经过两个全连接层之后,比较重要的特征图对应的向量元素的值就较大。将得到的权重和对应特征图中的所有元素相乘,得到新的输出特征图。2.2 使用不同的激活函数swish激活函数公式为: ,尽管提高了网络精度,但是它的计算、求导复杂,对量化过程不友好,尤其对移动端设备的计算。h_sigmoid激活函数公式为: ,ReLU6激活函数公式为:激活函数公式为: ,替换之后网络的推理速度加快,对量化过程比较友好。2.3 重新设计耗时层结构减少第一个卷积层的卷积核个数。将卷积核个数从32个降低到16个之后,准确率和降低之前是一样的。减少卷积核个数可以减少计算量,节省2ms时间。简化最后的输出层。删除多余的卷积层,在准确率上没有变化,节省了7ms执行时间,这7ms占据了整个推理过程的11%的执行时间。明显提升计算速度。2.4 总体流程图像输入,先通过1x1卷积上升通道数;然后在高维空间下使用深度卷积;再经过SE注意力机制优化特征图数据;最后经过1x1卷积下降通道数(使用线性激活函数)。当步长等于1且输入和输出特征图的shape相同时,使用残差连接输入和输出;当步长=2(下采样阶段)直接输出降维后的特征图。2.5 网络结构图网络模型结构如图所示。exp size 代表11卷积上升的通道数;#out 代表11卷积下降的通道数,即输出特征图数量;SE 代表是否使用注意力机制;NL 代表使用哪种激活函数;s 代表步长;bneck 代表逆残差结构;NBN 代表不使用批标准化。

0
0
0
浏览量1655
清晨我上码

【Opencv】cv2.connectedComponentsWithStats 计算不规则连通区域

【Opencv】cv2.connectedComponentsWithStats 计算不规则连通区域0. 介绍计算不规则连通区域是指在图像中提取出不规则的、由像素点连接而成的连通区域。OpenCV提供了一种函数叫做cv2.connectedComponents(),用于实现这个功能。原理:首先,将二值化图像中的前景部分(像素值为1)与背景部分(像素值为0)进行标记。然后,使用基于连通性的算法,将像素点进行分组,并给每个组分配一个唯一的标签。最终得到的结果是连通区域的数量和每个像素点所属的标签。应用:目标检测和跟踪:通过计算不规则连通区域,可以实现对目标对象的检测和跟踪,进而进行目标识别、运动分析等应用。图像分割:将图像分割成不同的不规则连通区域,用于图像分析、对象提取和图像处理等任务。图像分析和特征提取:通过计算不规则连通区域的属性,如面积、周长、重心等,可用于分析图像中的形状、纹理、边缘等特征。图像处理和修复:通过计算不规则连通区域,可以定位和修复图像中的缺陷、噪声或损坏部分,如去除图像中的小斑点或孔洞。计算机视觉和机器学习:不规则连通区域的计算可以作为计算机视觉和机器学习算法的预处理步骤,用于提取图像中的特征,构建模型等。需要注意的是,计算不规则连通区域在处理复杂图像时可能会受到噪声和边缘模糊等因素的影响,因此在使用时可能需要进行图像预处理、参数调整等措施来优化结果。1. 函数num, labels, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=8)输入值: image : 是要处理的图片,官方文档要求是8位单通道的图像。connectivity : 可以选择是4连通还是8连通。    输出值:num : 返回值是连通区域的数量。labels : labels是一个与image一样大小的矩形(labels.shape = image.shape),其中每一个连通区域会有一个唯一标识,标识从0开始。stats :stats会包含5个参数分别为x,y,h,w,s。分别对应每一个连通区域的外接矩形的起始坐标x,y;外接矩形的wide,height;s为对应的连通区域的像素个数(也就是      不规则连通区域的面积)。centroids : 返回的是连通区域的质心。

0
0
0
浏览量1618
清晨我上码

【轻量型卷积网络】MobileNet系列:MobileNet V2网络解析

1. 介绍1.1 V1存在的问题MobileNet-v1的主要思想就是深度可分离卷积,可以参考MobileNet V1网络解析。结构问题:MobileNet-v1的结构非常简单,类似于VGGNet,是一个非常复古的直筒结构。这种结构的性价比其实不高,后续一系列的ResNet、DenseNet等结构已经证明通过复用图像特征,使用Concat/Elwise+等操作进行融合,能极大提升网络的性价比。Depthwise convolution存在的问题:Depthwise convolution确实是大大降低了计算量,Depthwise+Pointwise的结构在性能上也能接近普通卷积。但是在实际应用时我们发现Depthwsie部分的kernel比较容易训废掉,训练完之后发现Depthwise训出来的kernel有不少是空的。因为depthwise每个kernel_dim相对于普通卷积要小得多,过小的kernel_dim加上ReLU的激活影响下,使得输出神经元很容易变为0,所以就学废了。ReLU对于0的输出梯度为0,所以一旦陷入0输出,就没法恢复了。1.2 解决方法MobileNet v2网络是由google团队在2018年提出的,相比MobileNet V1网络,准确率更高,模型更小。网络中的亮点 :Inverted Residuals (倒残差结构 ):去掉了小维度输出层后面的非线性激活层,目的是为了保证模型的表达能力。 好处:通过去掉Eltwise+ 的特征去掉ReLU, 减少ReLU对特征的破坏;Linear Bottlenecks(结构的最后一层采用线性层):和residual block中维度先缩减再扩增正好相反,因此shotcut也就变成了连接的是维度缩减后的feature map。好处1: 复用特征。好处2: 旁支block内先通过1x1升维, 再接depthwise conv以及ReLU, 通过增加ReLU的InputDim, 来缓解特征的退化情况。MobileNet-v2的主要思想就是在v1的基础上引入了线性瓶颈 (Linear Bottleneck)和逆残差 (Inverted Residual)来提高网络的表征能力,同样也是一种轻量级的卷积神经网络。ResNet是:压缩”→“卷积提特征”→“扩张”,MobileNetV2则是Inverted residuals,即:“扩张”→“卷积提特征”→ “压缩”。2. 模型2.1 Linear Bottlenecksv1中使用width multiplier参数来做模型通道的缩减,使特征信息集中在缩减后的通道中,其后使用非线性激活ReLU,会产生较大的信息丢失。为了减少信息损失,v2使用linear bottleneck,在bottleneck的输出后接线性激活。2.2 Inverted residuals上图展示了从standard convolution到depthwise separable convolution再到本文中的inverted residual block的差异。标准33卷积操作,若输入channel数量为n,则卷积核的维度为33n(图中红色立方体),将channel和spatial的信息同时进行映射,参数量较大v1中采用的depthwise separable convolution,可分离卷积,解耦了channel和spatial,化乘法为加法在(b)的基础上增加了一个类似bottleneck的操作v2 inverted residual block结构,和ResNet中residual block对维度的操作相反。2.3 网络结构MobieNet V2网络结构细节如下:

0
0
0
浏览量1622
清晨我上码

去噪很有效的代码

去噪很有效的代码1. 原图与效果图 2. 实现代码import cv2 import numpy as np img = cv2.imread("a.jpg", 0) img2 = img.copy() # cv2.erode(img, (3, 3)) # 开操作,稍微去噪 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) # img = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) num, labels, stats, centroids = cv2.connectedComponentsWithStats(img, connectivity=8) img1 = np.zeros_like(img) for i in range(num): if i==0: continue if stats[i][-1] > 50: img1[labels == i] = 255 # 恢复原图的纹理,但是噪声已去除 img1 = np.where(img1>0, img2, 0) img1 = np.array(img1, dtype=np.uint8) img1 = cv2.cvtColor(img1, cv2.COLOR_GRAY2RGB) cv2.imwrite('a.jpg', img1)

0
0
0
浏览量1604