当前位置: 首页 > 编程日记 > 正文

卷积神经网络中十大拍案叫绝的操作

640?wx_fmt=jpeg

作者 | Justin ho

来源 | 知乎

CNN从2012年的AlexNet发展至今,科学家们发明出各种各样的CNN模型,一个比一个深,一个比一个准确,一个比一个轻量。下面会对近几年一些具有变革性的工作进行简单盘点,从这些充满革新性的工作中探讨日后的CNN变革方向。

一、卷积只能在同一组进行吗?-- Group convolution

Group convolution 分组卷积,最早在AlexNet中出现,由于当时的硬件资源有限,训练AlexNet时卷积操作不能全部放在同一个GPU处理,因此作者把feature maps分给多个GPU分别进行处理,最后把多个GPU的结果进行融合。

640?wx_fmt=png

Alexnet

分组卷积的思想影响比较深远,当前一些轻量级的SOTA(State Of The Art)网络,都用到了分组卷积的操作,以节省计算量。但题主有个疑问是,如果分组卷积是分在不同GPU上的话,每个GPU的计算量就降低到 1/groups,但如果依然在同一个GPU上计算,最终整体的计算量是否不变?找了pytorch上有关组卷积操作的介绍,望读者解答我的疑问。

640?wx_fmt=jpeg

关于这个问题,知乎用户朋友 @蔡冠羽 提出了他的见解:

https://www.zhihu.com/people/cai-guan-yu-62/activities

我感觉group conv本身应该就大大减少了参数,比如当input channel为256,output channel也为256,kernel size为3*3,不做group conv参数为256*3*3*256,若group为8,每个group的input channel和output channel均为32,参数为8*32*3*3*32,是原来的八分之一。这是我的理解。

我的理解是分组卷积最后每一组输出的feature maps应该是以concatenate的方式组合,而不是element-wise add,所以每组输出的channel是 input channels / #groups,这样参数量就大大减少了。


二、卷积核一定越大越好?-- 3×3卷积核

AlexNet中用到了一些非常大的卷积核,比如11×11、5×5卷积核,之前人们的观念是,卷积核越大,receptive field(感受野)越大,看到的图片信息越多,因此获得的特征越好。虽说如此,但是大的卷积核会导致计算量的暴增,不利于模型深度的增加,计算性能也会降低。于是在VGG(最早使用)、Inception网络中,利用2个3×3卷积核的组合比1个5×5卷积核的效果更佳,同时参数量(3×3×2+1 VS 5×5×1+1)被降低,因此后来3×3卷积核被广泛应用在各种模型中。

640?wx_fmt=jpeg

三、每层卷积只能用一种尺寸的卷积核?-- Inception结构

传统的层叠式网络,基本上都是一个个卷积层的堆叠,每层只用一个尺寸的卷积核,例如VGG结构中使用了大量的3×3卷积层。事实上,同一层feature map可以分别使用多个不同尺寸的卷积核,以获得不同尺度的特征,再把这些特征结合起来,得到的特征往往比使用单一卷积核的要好,谷歌的GoogleNet,或者说Inception系列的网络,就使用了多个卷积核的结构:

640?wx_fmt=jpeg

最初版本的Inception结构

如上图所示,一个输入的feature map分别同时经过1×1、3×3、5×5的卷积核的处理,得出的特征再组合起来,获得更佳的特征。但这个结构会存在一个严重的问题:参数量比单个卷积核要多很多,如此庞大的计算量会使得模型效率低下。这就引出了一个新的结构。

四、怎样才能减少卷积层参数量?-- Bottleneck

发明GoogleNet的团队发现,如果仅仅引入多个尺寸的卷积核,会带来大量的额外的参数,受到Network In Network中1×1卷积核的启发,为了解决这个问题,他们往Inception结构中加入了一些1×1的卷积核,如图所示:

640?wx_fmt=jpeg

加入1×1卷积核的Inception结构

640?wx_fmt=jpeg

根据上图,我们来做个对比计算,假设输入feature map的维度为256维,要求输出维度也是256维。有以下两种操作:

(1)256维的输入直接经过一个3×3×256的卷积层,输出一个256维的feature map,那么参数量为:256×3×3×256 = 589,824
(2)256维的输入先经过一个1×1×64的卷积层,再经过一个3×3×64的卷积层,最后经过一个1×1×256的卷积层,输出256维,参数量为:256×1×1×64 + 64×3×3×64 + 64×1×1×256 = 69,632。足足把第一种操作的参数量降低到九分之一!

1×1卷积核也被认为是影响深远的操作,往后大型的网络为了降低参数量都会应用上1×1卷积核。


五、越深的网络就越难训练吗?-- Resnet残差网络

640?wx_fmt=jpegResNet skip connection

传统的卷积层层叠网络会遇到一个问题,当层数加深时,网络的表现越来越差,很大程度上的原因是因为当层数加深时,梯度消散得越来越严重,以至于反向传播很难训练到浅层的网络。为了解决这个问题,何凯明大神想出了一个“残差网络”,使得梯度更容易地流动到浅层的网络当中去,而且这种“skip connection”能带来更多的好处,这里可以参考一个PPT《极深网络(ResNet/DenseNet): Skip Connection为何有效及其它》[1],以及我的一篇文章:为什么ResNet和DenseNet可以这么深?一文详解残差块为何能解决梯度弥散问题[2], 大家可以结合下面的评论进行思考。
[1]张俊林博客:
https://blog.csdn.net/malefactor/article/details/67637785 [2]https://zhuanlan.zhihu.com/p/28124810?group_id=883267168542789632


六、卷积操作时必须同时考虑通道和区域吗?-- DepthWise操作

640?wx_fmt=jpeg

标准的卷积过程可以看上图,一个2×2的卷积核在卷积时,对应图像区域中的所有通道均被同时考虑,问题在于,为什么一定要同时考虑图像区域和通道?我们为什么不能把通道和空间区域分开考虑?

640?wx_fmt=jpeg

Xception网络就是基于以上的问题发明而来。我们首先对每一个通道进行各自的卷积操作,有多少个通道就有多少个过滤器。得到新的通道feature maps之后,这时再对这批新的通道feature maps进行标准的1×1跨通道卷积操作。这种操作被称为 “DepthWise convolution” ,缩写“DW”。

这种操作是相当有效的,在imagenet 1000类分类任务中已经超过了InceptionV3的表现,而且也同时减少了大量的参数,我们来算一算,假设输入通道数为3,要求输出通道数为256,两种做法:

1.直接接一个3×3×256的卷积核,参数量为:3×3×3×256 = 6,912
2.DW操作,分两步完成,参数量为:3×3×3 + 3×1×1×256 = 795,又把参数量降低到九分之一!

因此,一个depthwise操作比标准的卷积操作降低不少的参数量,同时论文中指出这个模型得到了更好的分类效果。

本文在发出12小时后,一位网友私信了我,向我介绍了Depthwise和Pointwise的历史工作,而Xception和Mobilenet也引用了他们16年的工作,就是Min Wang et al 的Factorized Convolutional Neural Networks,这篇论文的Depthwise中,每一通道输出的feature map(称为“基层”)可以不止一个,而Xception中的Depthwise separable Convolution, 正是这篇工作中“单一基层”的情况。推荐有兴趣的读者关注下他们的工作,这里有篇介绍博文:【深度学习】卷积层提速Factorized Convolutional Neural Networks。而最早关于separable convolution的介绍,Xception作者提到,应该追溯到Lau- rent Sifre 2014年的工作 Rigid-Motion Scattering For Image Classification 6.2章节。


七、分组卷积能否对通道进行随机分组?-- ShuffleNet

在AlexNet的Group Convolution当中,特征的通道被平均分到不同组里面,最后再通过两个全连接层来融合特征,这样一来,就只能在最后时刻才融合不同组之间的特征,对模型的泛化性是相当不利的。为了解决这个问题,ShuffleNet在每一次层叠这种Group conv层前,都进行一次channel shuffle,shuffle过的通道被分配到不同组当中。进行完一次group conv之后,再一次channel shuffle,然后分到下一层组卷积当中,以此循环。

640?wx_fmt=jpeg
来自ShuffleNet论文

经过channel shuffle之后,Group conv输出的特征能考虑到更多通道,输出的特征自然代表性就更高。另外,AlexNet的分组卷积,实际上是标准卷积操作,而在ShuffleNet里面的分组卷积操作是depthwise卷积,因此结合了通道洗牌和分组depthwise卷积的ShuffleNet,能得到超少量的参数以及超越mobilenet、媲美AlexNet的准确率!

另外值得一提的是,微软亚洲研究院MSRA最近也有类似的工作,他们提出了一个IGC单元(Interleaved Group Convolution),即通用卷积神经网络交错组卷积,形式上类似进行了两次组卷积,Xception 模块可以看作交错组卷积的一个特例,特别推荐看看这篇文章:王井东详解ICCV 2017入选论文:通用卷积神经网络交错组卷积。

要注意的是,Group conv是一种channel分组的方式,Depthwise +Pointwise是卷积的方式,只是ShuffleNet里面把两者应用起来了。因此Group conv和Depthwise +Pointwise并不能划等号。

八、通道间的特征都是平等的吗?-- SEnet

无论是在Inception、DenseNet或者ShuffleNet里面,我们对所有通道产生的特征都是不分权重直接结合的,那为什么要认为所有通道的特征对模型的作用就是相等的呢? 这是一个好问题,于是,ImageNet2017 冠军SEnet就出来了。

640?wx_fmt=jpeg
SEnet 结构

一组特征在上一层被输出,这时候分两条路线,第一条直接通过,第二条首先进行Squeeze操作(Global Average Pooling),把每个通道2维的特征压缩成一个1维,从而得到一个特征通道向量(每个数字代表对应通道的特征)。然后进行Excitation操作,把这一列特征通道向量输入两个全连接层和sigmoid,建模出特征通道间的相关性,得到的输出其实就是每个通道对应的权重,把这些权重通过Scale乘法通道加权到原来的特征上(第一条路),这样就完成了特征通道的权重分配。

九、能否让固定大小的卷积核看到更大范围的区域?-- Dilated convolution


标准的3×3卷积核只能看到对应区域3×3的大小,但是为了能让卷积核看到更大的范围,dilated conv使其成为了可能。dilated conv原论文中的结构如图所示:

640?wx_fmt=png

上图b可以理解为卷积核大小依然是3×3,但是每个卷积点之间有1个空洞,也就是在绿色7×7区域里面,只有9个红色点位置作了卷积处理,其余点权重为0。这样即使卷积核大小不变,但它看到的区域变得更大了。详细解释可以看这个回答:如何理解空洞卷积(dilated convolution)?

十、卷积核形状一定是矩形吗?-- Deformable convolution 可变形卷积核

640?wx_fmt=jpeg
图来自微软亚洲研究院公众号

传统的卷积核一般都是长方形或正方形,但MSRA提出了一个相当反直觉的见解,认为卷积核的形状可以是变化的,变形的卷积核能让它只看感兴趣的图像区域 ,这样识别出来的特征更佳。

640?wx_fmt=jpeg
图来自微软亚洲研究院公众号

要做到这个操作,可以直接在原来的过滤器前面再加一层过滤器,这层过滤器学习的是下一层卷积核的位置偏移量(offset),这样只是增加了一层过滤器,或者直接把原网络中的某一层过滤器当成学习offset的过滤器,这样实际增加的计算量是相当少的,但能实现可变形卷积核,识别特征的效果更好。详细MSRA的解读可以看这个链接:可变形卷积网络:计算机新“视”界。

启发与思考

现在越来越多的CNN模型从巨型网络到轻量化网络一步步演变,模型准确率也越来越高。现在工业界追求的重点已经不是准确率的提升(因为都已经很高了),都聚焦于速度与准确率的trade off,都希望模型又快又准。因此从原来AlexNet、VGGnet,到体积小一点的Inception、Resnet系列,到目前能移植到移动端的mobilenet、ShuffleNet(体积能降低到0.5mb!),我们可以看到这样一些趋势:

卷积核方面:

  • 大卷积核用多个小卷积核代替;
  • 单一尺寸卷积核用多尺寸卷积核代替;
  • 固定形状卷积核趋于使用可变形卷积核;
  • 使用1×1卷积核(bottleneck结构)。

卷积层通道方面:

  • 标准卷积用depthwise卷积代替;
  • 使用分组卷积;
  • 分组卷积前使用channel shuffle;
  • 通道加权计算。

卷积层连接方面:
  • 使用skip connection,让模型更深;

  • densely connection,使每一层都融合上其它层的特征输出(DenseNet)


启发

类比到通道加权操作,卷积层跨层连接能否也进行加权处理?bottleneck + Group conv + channel shuffle + depthwise的结合会不会成为以后降低参数量的标准配置?

原文链接:
https://zhuanlan.zhihu.com/p/28749411

(*本文为AI科技大本营转载文章,转载请联系作者)

推荐阅读
  • 谷歌NIPS论文Transformer模型解读:只要Attention就够了

  • 阿里云弹性计算负责人蒋林泉:亿级场景驱动的技术自研之路

  • 开源sk-dist,超参数调优仅需3.4秒,sk-learn训练速度提升100倍

  • 你在北边的西二旗被水淹没,我在东边的八通线不知所措

  • 为什么说边缘计算的发展比5G更重要?

  • C/C++ 最易受攻击、70% 漏洞无效,揭秘全球开源组件安全现状

  • 首批共享单车死于 2019

  • 公钥加密、加密Hash散列、Merkle树……区块链的密码学你知多少?


640?wx_fmt=png
你点的每个“在看”,我都认真当成了喜欢

相关文章:

windows7下解决caffe check failed registry.count(type) == 1(0 vs. 1) unknown layer type问题

在Windows7下调用vs2013生成的Caffe静态库时经常会提示Check failed: registry.count(type) 1 (0 vs. 1) Unknown layer type的错误,如下图:这里参考网上资料汇总了几种解决方法:1. 不使用Caffe的静态库,直接将Caffe的sourc…

js 变量提升 和函数提升

2019独角兽企业重金招聘Python工程师标准>>> 创建函数有两种形式,一种是函数声明,另外一种是函数字面量,只有函数声明才有变量提升 console.log(a) // f a() { console.log(a) } console.log(b) //undefinedfunction a() {consol…

.net_ckeditor+ckfinder的图片上传配置

CKEditor和CKFinder的最新版可以到官方网站&#xff08;http://cksource.com&#xff09;上下载获得。 把以上两个资源放到网站的根目录&#xff1a; /CKEditor 和 /CKFinder (不区分大小写) 在页面使用 CKEditor&#xff1a; <textarea cols"80" id"prcont…

VS2013在Windows7 64位上变慢的解决方法

重装了windows7系统&#xff0c;又重装了vs2013&#xff0c;发现在打开vs2013、编译工程及调试的时候&#xff0c;vs2013都会变的比较慢&#xff0c;参考网上资料&#xff0c;这里列出几种可能的解决方法&#xff1a; 1. 打开工具--> 选项 --> 源代码管理 --> 插件选…

Key-Value数据库:Redis与Memcached之间如何选择?

华为云分布式缓存Redis5.0和Memcached都是华为云DCS的核心产品。 那么在不同的使用场景之下&#xff0c;如何选择Redis5.0和Memcached呢&#xff1f; 就由小编为大家进行详细的数据对比分析吧Redis和Memcached都是非常受欢迎的开源内存数据库&#xff0c;相对关系型数据库&…

裴健等9名华人当选加拿大皇家学会院士

【导读】近日&#xff0c;加拿大皇家学会&#xff08;RSC&#xff0c;The Royal Society of Canada&#xff09;官网宣布已评选出今年的新增院士。其中&#xff0c;京东副总裁、加拿大西蒙弗雷泽大学计算科学学院教授裴健和其他 8 名华人学者均在这份名单之中&#xff0c;而裴健…

Linux中shell命令的用法和技巧

使用Linux shell是我每天的基本工作&#xff0c;但我经常会忘记一些有用的shell命令和l技巧。当然&#xff0c;命令我能记住&#xff0c;但我不敢说能记得如何用它执行某个特定任务。于是&#xff0c;我开始在一个文本文件里记录这些用法&#xff0c;并放在我的Dropbox里&#…

Caffe中Layer注册机制

Caffe内部维护一个注册表用于查找特定Layer对应的工厂函数(Layer Factory的设计用到了设计模式里的工厂模式)。Caffe的Layer注册表是一组键值对(key, value)( LayerRegistry里用map数据结构维护一个CreatorRegistry list, 保存各个Layer的creator的函数句柄)&#xff0c;key为L…

自动驾驶行业观察 | 停车不再难,L2到L4的泊车辅助系统技术剖析

作者 | 陈光来源 | 自动驾驶干货铺&#xff08;ID:IntelligentDrive&#xff09;【导读】在汽车智能化的浪潮中&#xff0c;车载传感器发展迅速&#xff0c;越来越多搭载了先进传感器的汽车进入了我们的视野。比如能够在高速公路上实现单车道巡航的凯迪拉克CT6&#xff0c;以及…

Unity Log重新定向

Unity Log重新定向 使用Unity的Log的时候有时候需要封装一下Debug.Log(message)&#xff0c;可以屏蔽Log或者把log内容写到文本中。通过把文本内容传送到服务器中&#xff0c;查找bug出现的原因。但是封装之后的日志系统如果双击跳转的时候&#xff0c;会跳转到自定义的日志系统…

Javascript 检查一组 radio 中的哪一个被勾选

2019独角兽企业重金招聘Python工程师标准>>> 以前检查单选按钮是否被选择时&#xff0c;我使用的是 if else 一个一个的检查其 checked 属性。 这样虽然可以&#xff0c;但是当一组 radio 有很多个时&#xff0c;就很麻烦了。 可以通过 getElementsByName 得到所有…

二维码Aztec简介及其解码实现(zxing-cpp)

Aztec Code是1995年&#xff0c;由Hand HeldProducts公司的Dr. Andrew Longacre设计。它是一种高容量的二维条形码格式。它可以对ASCII和扩展ASCII码进行编码。当使用最高容量和25%的纠错级别的時候&#xff0c;Aztec可以对3000个字符或者3750个数字进行编码。Aztec的矩阵大小在…

顶配12699 元、没有5G,“浴霸三摄”的iPhone你会买吗?

作者 | 屠敏出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;北京时间 9 月 11 日凌晨 1 点&#xff0c;以「Apple 特别活动」为主题的苹果秋季发布会正式于史蒂夫乔布斯剧院拉开帷幕。按照惯例&#xff0c;在发布会之前&#xff0c;业界“毫不留情”地对新品进行了…

阿里P7架构师告诉你Java架构师必须知道的 6 大设计原则

在软件开发中&#xff0c;前人对软件系统的设计和开发总结了一些原则和模式&#xff0c; 不管用什么语言做开发&#xff0c;都将对我们系统设计和开发提供指导意义。本文主要将总结这些常见的原则&#xff0c;和具体阐述意义。 开发原则 面向对象的基本原则(solid)是五个&#…

rhel6用centos163 yum源

cd /etc/yum.repos.d/wget wget http://mirrors.163.com/.help/CentOS6-Base-163.reposed -i "s/\$releasever/6/" CentOS6-Base-163.repo

打破深度学习局限,强化学习、深度森林或是企业AI决策技术的“良药”

算法、算力和数据是人工智能时代的三驾马车&#xff0c;成为企业赋能人工智能的动力&#xff0c;但它们自身的特性也为企业和高校在研究和落地应用过程带来了重重挑战。比如&#xff0c;训练算法的成本高昂&#xff0c;数据从采集、处理到存储已面临瓶颈&#xff0c;目前针对算…

JAVA springboot微服务b2b2c电子商务系统(十三)断路器聚合监控(Hystrix Turbine)

讲述了如何利用Hystrix Dashboard去监控断路器的Hystrix command。当我们有很多个服务的时候&#xff0c;这就需要聚合所以服务的Hystrix Dashboard的数据了。这就需要用到Spring Cloud的另一个组件了&#xff0c;即Hystrix Turbine。一、Hystrix Turbine简介看单个的Hystrix D…

二维码Data Matrix的解码实现(zxing-cpp)

二维码Data Matrix的介绍可以参考http://blog.csdn.net/fengbingchun/article/details/44279967 ,以下是通过zxing-cpp开源库实现的对Data Matrix进行解码的测试代码&#xff1a;#include "funset.hpp" #include <string> #include <fstream> #include &…

PHP mongodb 的使用

mongodb 不用过多的介绍了&#xff0c;NOSQL的一种&#xff0c;是一个面向文档的数据库&#xff0c;以其方便灵活的数据结构&#xff0c;对于开发者来说是比较友好的&#xff0c;同时查询的速度也是比较快的&#xff0c;现在好多网站 开始使用mongodb ,具体的介绍可以网上查找。…

必看,61篇NeurIPS深度强化学习论文解读都这里了

作者 | DeepRL来源 | 深度强化学习实验室&#xff08;ID: Deep-RL&#xff09;NeurIPS可谓人工智能年度最大盛会。每年全球的人工智能爱好者和科学家都会在这里聚集&#xff0c;发布最新研究&#xff0c;并进行热烈探讨&#xff0c;大会的技术往往这未来几年就会演变成真正的研…

07-09-Exchange Server 2019-配置-Outlook 2019

[在此处输入文章标题] 《系统工程师实战培训》 -07-部署邮件系统 -09-Exchange Server 2019-配置-Outlook 2019 作者&#xff1a;学 无 止 境 QQ交流群&#xff1a;454544014 MSUCDemo01 MSUCDemo02 MSUCDemo03 MSUCDemo04 MSUCDemo05 启用邮箱 MSUCDemo01i-x-Cloud.com MSUCDe…

二维码QR Code简介及其解码实现(zxing-cpp)

二维码QR Code(Quick Response Code)是由Denso公司于1994年9月研制的一种矩阵二维码符号&#xff0c;它具有一维条码及其它二维条码所具有的信息容量大、可靠性高、可表示汉字及图象多种文字信息、保密防伪性强等优点。二维码QR Code呈正方形&#xff0c;常见的是黑白两色。在3…

jQuery学习(一)

因为项目需要&#xff0c;同时也因为兴趣&#xff0c;在近一段时间研究和使用了jQuery&#xff0c;它真的是太强大了&#xff0c;代码非常的优雅和简洁&#xff0c;好后悔现在才开始了解它&#xff0c;虽然目前网络上关于jQuery的资料、学习心得&#xff0c;教程多得你看不完&a…

知乎算法团队负责人孙付伟:Graph Embedding在知乎的应用实践

演讲嘉宾 | 孙付伟出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;9月6-7日&#xff0c;在由CSDN主办的2019中国AI开发者大会&#xff08;AI ProCon 2019&#xff09;的 机器学习专场中&#xff0c;知乎算法团队负责人孙付伟在机器学习专场中分享了《Graph Embedding…

一维码Codabar简介及其解码实现(zxing-cpp)

一维码Codabar&#xff1a;由4条黑色线条&#xff0c;3条白色线条&#xff0c;合计7条线条所组成&#xff0c;每一个字元与字元之间有一间隙Gap做区隔。条形码Codabar包含21个字元&#xff1a;(1)、10个数字0~9;(2)、””, ”-”,”*”, ”/”, ”$”, .”, ”:”等7个特殊符号…

node 压缩模块速成

1. 压缩与解压缩处理可以使用zlib模块进行压缩及解压缩处理,压缩文件以后可以减少体积&#xff0c;加快传输速度和节约带宽 代码2. 压缩对象压缩和解压缩对象都是一个可读可写流方法说明zlib.createGzip返回Gzip流对象&#xff0c;使用Gzip算法对数据进行压缩处理zlib.createGu…

hadoop作业初始化过程详解(源码分析第三篇)

&#xff08;一&#xff09;概述我们在上一篇blog已经详细的分析了一个作业从用户输入提交命令到到达JobTracker之前的各个过程。在作业到达JobTracker之后初始化之前&#xff0c;JobTracker会通过submitJob方法&#xff0c;为每个作业都创建一个JobInProgress对象(本文以后简称…

百度无人车急刹车

导语&#xff1a;没人会怀疑人工智能在未来的地位&#xff0c;也没人会怀疑无人驾驶将改变我们的生活&#xff0c;但百度首次出现亏损&#xff0c;“现金牛”业务遭遇越发严重的挑战&#xff0c;无人驾驶行业的征途却越发漫长且荆棘密布&#xff0c;这个公司该如何走到“流着奶…

STM32中EXTI和NVIC的关系

&#xff08;1&#xff09;NVIC(嵌套向量中断)&#xff1a;NVIC是Cortex-M3核心的一部分&#xff0c;关于它的资料不在《STM32的技术参考手册》中&#xff0c;应查阅ARM公司的《Cortex-M3技术参考手册》Cortex-M3的向量中断统一由NVIC管理。 &#xff08;2&#xff09;EXTI(外部…

一维码Code 93简介及其解码实现(zxing-cpp)

一维码Code 93: Code 93码与Code 39码的字符集相同&#xff0c;但93码的密度要比39码高&#xff0c;因而在面积不足的情况下&#xff0c;可以用93码代替39码。它没有自校验功能,为了确保数据安全性,采用了双校验字符,其可靠性比39条码还要高.一维码Code 39的介绍可以参考&#…