两种移动端可以实时运行的网络模型

Posted OpenCV学堂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两种移动端可以实时运行的网络模型相关的知识,希望对你有一定的参考价值。

概述

我们常见的网络模型比如AlexNet、GoogleNet、VGG都因为权重文件太大无法在移动端直接运用,而且因为计算浮点参数过多无法实时运行,所以针对这种情况先后出现了SqueezeNet与MobileNet两种权重参数和文件大小都得到优化的可以在嵌入式边缘设备上运行的网络模型,两种模型都可以通过tensorflow Lite被压缩到2MB大小左右,还依然可以实现比较好的分类与图像检测效果。

SqueezeNet模型

SqueezeNet模型可以达到跟AlexNet相同的图像分类精度,但是文件大小却可以下降50倍以上,SqueezeNet模型有如下三个架构策略:

  • 替换3x3的卷积为1x1的卷积,这个替换步骤可以节省9倍的浮点数参数

  • 对3x3的输入层卷积,通过fire module修改输入层的通道数目,减少3x3卷积的参数

  • 延时下采样,获取更多的激活特征map,从而提高图像分类精度

其中第二个策略fire module的结构如下:

通过1x1与3x3的filter组合有效减少参数,最终通过填充使得1x1与3x3输出feature maps大小一致,叠加输出到下一层。SqueezeNet的网络结构如下:

两种移动端可以实时运行的网络模型

各层参数与filter的详细说明

两种移动端可以实时运行的网络模型

另外一个跟AlexNet不一样的地方是,Squeeze是一个全卷积图像分类网络,它去掉全连接层,这样就可以避免更多参数产生。

MobileNet模型

MobileNet网络模型是谷歌提出了适用于移动端应用的深度学习模型,MobileNet采用跟SqueezeNet不一样的机制来降低网络的参数总数,这种技术被称为深度可分离卷积(Depth-Wise Separable Convolution)。MobileNet正式通过这个方法达到减少权重参数,压缩模型体积大小的目标,实现了快速实时的网络模型。两种移动端可以实时运行的网络模型

其中a是标准的卷积操作,b是深度分离的卷积操作,c是1x1的卷积操作,标准卷积操作可以拆分为b, c两步完成,这样就可以极大的减少参数总数。假设原图中有10个通道,filter为3x3, 则对于输入N=5, 总的参数为5x3x3x10 = 450参数,采用深度可分离卷积则为
5x3x3+10x1x1x5 =95总的参数下降为95个。最终的MobileNet body的网络结构如下:

两种移动端可以实时运行的网络模型值得一提的是两个网络在最后输出层之前都采用了均值池化,而不同于常见网络的最大池化的方法。

预训练的基于SqueezeNet的对象检测模型下载

https://github.com/kvmanohar22/opencv_extra/tree/a0b59f565efd21882dbbf6e84f7183df88cd4e66/dnn_objdetect

OpenCV DNN模块已经支持这两种网络的加载与使用,以MobileNet网络为例

import cv2 as cv

model_bin = "D:/projects/opencv_tutorial/data/models/ssd/MobileNetSSD_deploy.caffemodel";
config_text = "D:/projects/opencv_tutorial/data/models/ssd/MobileNetSSD_deploy.prototxt";
objName = ["background",
"aeroplane""bicycle""bird""boat",
"bottle""bus""car""cat""chair",
"cow""diningtable""dog""horse",
"motorbike""person""pottedplant",
"sheep""sofa""train""tvmonitor"];

# load caffe model
net = cv.dnn.readNetFromCaffe(config_text, model_bin)
image = cv.imread("D:/images/dog.jpg")
h = image.shape[0]
w = image.shape[1]

# 获得所有层名称与索引
layerNames = net.getLayerNames()
lastLayerId = net.getLayerId(layerNames[-1])
lastLayer = net.getLayer(lastLayerId)
print(lastLayer.type)

# 检测
blobImage = cv.dnn.blobFromImage(image, 0.007843, (300300), (127.5127.5127.5), TrueFalse);
net.setInput(blobImage)
cvOut = net.forward()
print(cvOut)
for detection in cvOut[0,0,:,:]:
    score = float(detection[2])
    objIndex = int(detection[1])
    if score > 0.5:
        left = detection[3]*w
        top = detection[4]*h
        right = detection[5]*w
        bottom = detection[6]*h

        # 绘制
        cv.rectangle(image, (int(left), int(top)), (int(right), int(bottom)), (25500), thickness=2)
        cv.putText(image, "score:%.2f, %s"%(score, objName[objIndex]),
                (int(left) - 10, int(top) - 5), cv.FONT_HERSHEY_SIMPLEX, 0.7, (00255), 28);

cv.imshow('mobilenet-ssd-demo', image)
cv.waitKey(0)
cv.destroyAllWindows()

运行结果:

博观而约取
厚积而薄发

推荐阅读






DNN模块学习分享
欢迎扫码加入【OpenCV研习社】


以上是关于两种移动端可以实时运行的网络模型的主要内容,如果未能解决你的问题,请参考以下文章

opencv学习-OpenCV与YOLO之间的关系

是否可以将从移动设备获取的音频实时传输到网络服务器?

是否有一种方法可以将实时记录的音频片段连续发送到Flutter.io中的后端服务器?

shader之——移动端阴影实现

移动端实时阴影+自投影技术实现

浅析即时通讯开发中移动端实时消息推送技术