精华内容
下载资源
问答
  • 和声连接的规则
    千次阅读
    2019-02-15 21:34:14

    阅读这篇文章你可以了解到:
    1、无线摄像头声波配置网络的原理
    2、声波配置是否会受到环境噪声音、传输距离影响;

    首先了解一下声波配置传输原理,详细如下:
    【理论基础】:
    利用声波传输信息,和无线电的通信本质上是一样的。其大致流程如下:
    在这里插入图片描述
    发射端对信源进行编码,转化为声音信号(PCM),然后将声音信号通过音频模块播放出来。同时接收端采集声音,并用相对应的方式进行解码,还原出信息。

    【编码原理】:
    声波配置通过声音传播wifi信息,设备端解析获取信息,传输的准确性与成功率都是取决于编码、解码的规则,举例具体如下:
    编码规则:每4帧表示一个字符,一个ASCLL码有8个比特位,即1帧为2个比特位,那么就存在4种频率模式(00、11、10、01),每种不同的频率模式有三种频率组成;(单位:Hz)
    即:若编码为00,发射端会发出3000 Hz + 4172 Hz + 5343 Hz这三种频点的声音,其他模式01、10、11类似;
    在这里插入图片描述
    解码规则:设备端接受到此时段的环境音频、统计各频点的能量值,会比较各个频点能量之和,分别求出代表00的三个频点的能量和,代表01的三个频点的能量和等等
    再取其中最大值作为当前音频帧的输出结果。对于每一帧音频来说,一定会根据最大值输出00,01,10,11中的一个,但是最后ASCLL码结果需要根据连续4帧的结果综合判定。

    【传输格式】:
    声波配置除了携带wifi信息,还会携带一些特征字符用来标记,便于准确识别有效数据,一整套数据格式如下;
    信息头部:特定编码代表标志开始
    间隔符:区分SSID与密码的间隔符;
    结束符:特定编码代表标志结束
    校验位:用于校验错误,重传;

    【准确性/抗干扰性】:
    关于声波配置的准确性多大以及抗干扰能力,可以从理论和实测来整体看:
    1、因为生活中声源,频率常在中低频以下,所以编码时多采用中高频甚至超声波的频率,以提高对干扰的抵抗,我司采用的是3K Hz ~ 7K Hz范围,受一般声音干扰小;
    2、编码采用多频组合表示,比单频受干扰的程度减小了很多,只要不是我们对应的频点就没啥关系,除非是与我们某个频点一样,导致含那个频点的能量增大,导致误解析成错的码;
    3、对于特定频率的噪声容易造成错误或者错位,这时CRC会校验失败,需要重新发送。
    4、设备加入去噪处理,会提高算法的准确度;

    主要影响测试结果的因素为:距离、角度、环境干扰;
    距离:3m内比较推荐;
    角度:手机speaker对着mic时,即0°条件下,算法可稳定识别的距离是3m,mic偏转后,不同手机播放,表现不同。但基本在1.5m左右可稳定识别;
    环境干扰:如上述2,若环境里存在某种我们对应的频点,会导致含那个频点的能量增大,可能出现误解析问题。加入去噪处理,会提供识别的准确性。

    更多相关内容
  • 最近的研究表明,如果卷积网络包含接近输入的层接近输出的层之间的较短连接,则卷积网络可以更深入,更精确更有效地进行训练。在本章中,论文首先研究密集卷积网络(DenseNet)的结构工作原理,随后本人提出...

    第三章 基于密集连接卷积网络改进的目标分类算法

    最近的研究表明,如果卷积网络包含接近输入的层和接近输出的层之间的较短连接,则卷积网络可以更深入,更精确和更有效地进行训练。在本章中,论文首先研究密集卷积网络(DenseNet)的结构和工作原理,随后本人提出一些改进意见,包括增加密集块中的层数、使用复合型综合函数、使用不同尺寸的卷积核和池化核、使用变化的增长率、压缩模型使其紧凑等方式对网络进行了改进。实验表明改进后的网络在物体分类任务上表现更好。DenseNet以前馈的方式将每层连接到每个其他层。传统的具有L层的卷积网络具有L个连接,每个层与其后一个层之间,DenseNet具有 个直接连接。对于每一层,前面所有图层的特征映射都被用作输入,并且它自己的特征映射被用作所有后续图层的输入。DenseNet有几个引人注目的优点:它们可以缓解消失梯度问题,加强特征传播,鼓励特征重用以及大幅减少参数数量。论文在识别基准任务(CIFAR-10,CIFAR-100,SVHN)的上验证了改进后网络的准确率。 DenseNet在其中大部分技术上都取得了显着的改进,同时需要较少的计算来实现高性能。

    3.1 DenseNet基本原理

    3.1.1 DenseNet结构

    近几年, 卷积神经网络(CNN)已经成为视觉对象识别的主要机器学习方法。虽然它们最初是在20多年前推出的,但计算机硬件和网络结构的改进使得最近才开始真正深入CNN。最初的LeNet5由5层组成,而VGG有19层,仅Highway网络和残差网络(ResNet)超过了100层网络结构。

    随着CNN网络结构的日益加深,出现了一个新的研究问题:随着有关输入或梯度的信息经过许多层,在到达网络的末端(或开始)时,它可能损耗或者消失。许多最近的论文解决了这个以及相关问题。ResNets和Highway Networks通过跳跃连接将来自一个层的信号传递给下一层。随机深度通过在训练期间随机丢弃一些层来缩短ResNets结构以保证更好的信息和梯度传递。 FractalNet通过多次合并具有不同数量的卷积块的并行层序列以获得大的标称深度,同时在网络中保持许多短路径。虽然这些不同的方法在网络拓扑和训练过程中各不相同,但是它们都具有一个关键特征:它们创建从早期层到后期层的短路径。

    在本章中,我们对这种将这种见解提炼成简单连接模式的体系结构加以验证,并尝试改进策略。为了确保网络中各层之间的最大信息流,直接连接所有的网络层。为了保留前馈特性,每一层都从前面的所有层获得附加输入,并将其自身的特征映射传递到所有后续层。图3-1示意性地说明了这种布局。最重要的是,与ResNets相比,DenseNet从未将特征通过求和组合到一个层中,相反地,DenseNet通过连接它们来组合特征。因此,第 层有l个输入,由前面所有卷积块的特征映射组成。它自己的特征映射被传递给所有的 后续层。这在一个L层网络中引入了 个连接,而不仅仅是像在传统架构中一样的L个连接。由于其密集的连接性模式,我们将这种方法称为密集卷积网络(DenseNet)。
    在这里插入图片描述
    图3-1 DenseNet(左)与ResNet(右)部分结构对比

    这种密集连接可能是反直觉效应模式是它比传统需要更少的参数卷积网络,因为不需要重新学习多余的特征图(feature maps)。传统的前馈架构可以被看作是具有状态的算法,其中信息从一层到下一层进行传递,每层从它的前一层读取状态然后写入后续层。这种节后改变了状态,但也传递了需要被保存的信息。ResNets通过增加性标识转换使得信息被保留。ResNets最近的变化显示了许多层次贡献很小,并且事实上可以在训练中随机丢弃。这使ResNets的状态类似到递归神经网络,但ResNets的参数数量要大得多,因为每一层都有自己的权重。DenseNet架构明确区分被添加到网络中的信息和保留的信息。DenseNet的层非常狭窄(例如,每一层有12个特征图),通过向网络中增加一小部分特征图,并保持其余特征映射不变,最后的分类器基于网络中所有的特征图做决策。

    除了更好的参数使用效率外,DenseNet还有一大优势就是他们改进的信息流和梯度流经整个网络,这使得他们很容易训练。每个层都可以直接访问损失函数的梯度和原始输入信号,使得网络包含了隐式的深度监督。这有助于训练更深的网络架构。此外,我们还观察到密集的连接具有正则化效果,这减轻了训练集规模较小时产生的过度拟合问题。

    论文使用几个标准数据集(CIFAR-10,CIFAR-100,SVHN)来评估DenseNet。实验达到了与现有算法相媲美的准确性,而且往往需要更少的参数。并且,性能优于目前的最新技术水平大部分基准测试任务的结果。

    3.1.2 相关研究

    自神经网络问世以来,网络架构的探索一直是其中重要的一部分。最近神经网络的普及也恢复了这一研究领域。层数越来越多在现代网络中放大了网络之间的差异架构,并激发对不同连接性的探索模式和对旧研究思路的重新审视。

    级联结构类似于密集网络布局,该结构自20世纪80年代起已经在神经网络中进行了研究贡献。他们的开创性工作侧重于完全连接的多层感知器在层与层之间训练。最近,完全连接的级联网络受到批梯度下降训练算法的影响。尽管对小数据集有效,但这一方法只能扩展到具有几百个参数的网络。利用多级特征在CNN通过跳跃连接(skip-connnections)被证明是适用于各种视觉任务的。

    Highway Networks是提出训练端到端网络最早的架构之一,网络首次超过100层。通过使用绕过路径与门控单元,Highway Networks网络有效地使用SGD优化数百个图层。被绕过的路径被认为是简化了这些非常深的网络训练的关键因素。这一点在ResNet中得到进一步支持,ResNet在挑战图像识别,定位和检测任务等方面取得了令人印象深刻的创纪录的表现,如ImageNet和COCO目标检测。最近,随机深度作为一种成功的方法训练了一个1202层深的ResNet网络结构。随机深度通过随机丢弃一些层(Dropout机制)来改善深度残留网络的训练。这表明不是所有层都是必须的,并强调在深度(残差)网络中存在着比较大的冗余量。DenseNet正是受到这一观点的启发。

    一种使网络层数更深的正交方法(例如,在跳过连接的帮助下)是增加网络宽度。 GoogLeNet使用了“Inception module”。该模块连接了由不同大小的过滤器生成的特征映射。ResNet的一个变种提出了更广泛的残差块。在实际上,简单的增加ResNet每一层的过滤器数量能提升网络的表示能力。

    DenseNet通过特征重用(feature reuse)来探索网络的潜力,以产生易于训练和高参数效率的密集模型,而不是从极端的图形表示力深层或广泛的架构。通过连接不同的层中学习到的特征映射会增加后续层输入的变化并提高效率,这形成了DenseNet和ResNet之间的一个主要区别。与同样也是连接由不同层提取的特征的InceptionNet相比,DenseNets更简单,更高效。

    还有其他值得注意的网络体系结构创新,他们同样取得了有竞争力的结果。Network In Network(NIN)结构包括微型多层感知器进入卷积层的滤波器中以提取更复杂的特征。在深度监督网络(DSN)中,内部层直接受到辅助分类器的监督,这可以加强由较早的层传递来的梯度。Ladder Network引入横向连接到自动编码器(autoencoder),获得了在半监督学习任务方面较高的准确性。Deeply-Fused Net(DFNs)被引出的目的是为了提升信息的流动,通过组合中间层不同的基础网络。通过增加路径来减少重建损失的网络也被证明可以改善图像分类模型。

    3.2 改进的DenseNet结构

    现在考虑一个通过卷积网络传递的单个图像 。这个网络包含L层,每一层实现一个非线性变换 ,其中l表示层数。 可以是一个符合函数,诸如批量标准化(Batch Normalization)、整流线性单元(ReLU)、卷积(Conv)或者赤化(Pooling)。定义 层的输出为 。DenseBlock的结构如图3-2所示:
    在这里插入图片描述
    图3-2 一个5层Dense Block模型

    传统前馈卷积网络将 层的输出直接作为 层的输入,得到这个传递函数: 。而ResNet在进行非线性转换时添加了跳跃连接(skip-connection),得到下面的转换方程: 。ResNet的一个明显优点就是梯度直接从后面的层流向前面的层。然而,非线性变换及其输出是以加法结合在一起,这将影响网络中信息的流动。

    3.2.1 密集连接(Dense connectivity)

    为了进一步提升网络中信息的流动性,模型使用一种不同的连接方式:将每一层直接与后面的每一层相连接。因此,第 层会获取前面所有层的特征图,公式如下,其中 表示由第0,1, ,l-1层产生的特征图组成的向量。
    (3-1)
    因为使用了密集连接(Dense connectivity),这种网络结构称之为Dense Convolution Network(DenseNet)。为了便于实施,合并多输入的 为一个简单向量。

    3.2.2 综合函数(Composite function)

    定义 为一个包含了三个连续操作的复合函数:批量标准化(Batch Normalization),整流线性单元(ReLU)和一个 卷积(Conv)。

    3.2.3 池化层(Pooling layer)

    图3-2中使用的级联操作在特征映射的大小发生变化时变得不可行。但是,卷积网络的一个重要组成部分是汇集可改变特征映射大小的层。为了便于在体系结构中合并,将网络分成多个密集连接的密集块(dense blocks)。密集块之间的层称为过渡层,它们进行卷积和池化操作。 在我们的实验中使用的过渡层包括批量标准化层和1×1卷积层,然后是2×2平均池化层。

    3.2.4 增长率(Growth rate)

    如果每一层的函数 生成k个特征图作为输出,那么第 层有 个输入特征图,其中 是原始输入图像的通道数。为了防止网络增长太宽,并改善参数效率,限制k为一个小的整数,例如k=12。我们引入超参数k作为网络的增长率,并且相对较小的增长率就足够了在我们测试的数据集上获得最新的结果。对此的一种解释是每个层都有到其他密集块特征映射的访问权限,另一种解释是将特征图看做网络的全局状态,即每一层为自己增加k个特征图。增长率调节每一层贡献给全局状态的新信息量。全局状态一旦写入,就可以从网络的任何地方访问它,这与传统网络体系结构不同,我们不需要一层一层地复制它。

    3.2.5 瓶颈层(Bottleneck layers)

    尽管每一层只产生k个输出特征图,它通常有更多的输入。前面我们提到,可以引入1×1卷积作为每次3×3卷积之前的瓶颈层(Bottleneck layer),以减少输入特征图的数量,从而减少输入特征图的数量,提高计算效率。我们发现这个设计对DenseNet非常有效,并将Bottleneck layer引入我们的网络,即BN-ReLU-Conv(1×1)-BN-ReLU-Conv(3×3)版本的综合函数,作为DenseNet-B。除非另有规定,每个1×1卷积减少在所有实验中输入到4k特征映射。

    3.2.6 压缩(Compression)

    为了进一步提高模型的紧凑性,我们可以减少过渡时的特征映射的数量层。 如果密集块包含m个特征映射,我们让下一个过渡层生成不超过 的最大整数个输出特征图,其中 被称为压缩因子。当 时,转换过程中的特征映射的数量保持不变。我们称DenseNet当 时为DenseNet-C,我们在实验中设定 。当同时使用了瓶颈层(Bottleneck layers)和压缩(Compression)方法时,我们称我们的模型为DenseNet-BC。
    在这里插入图片描述
    图3-3 包含3个Dense Block的DenseNet结构

    3.3 DenseNet卷积网络的实现与测试

    3.3.1 Tensorflow框架

    TensorFlow是Google推出的一套机器学习系统,使用其简单灵活的架构可以轻松构建各种复杂的算法模型。其高效的执行系统和分布式架构保证了在模型训练和执行时的高性能。再加上其跨平台可移植性及实验可复现,支持快速产品化等特点,逐渐成为主流的机器学习平台。

    TensorFlow是一个基于计算图(Computational Graph)的数值计算系统。计算图是一个有向图,图中的节点表示数学计算操作的算子(operations)。节点之间的连接的边代表参与计算的高维数组,成为tensor。计算图的执行可以看做数据tensor按照计算图的拓扑结构顺序,从输入节点逐步流过所有中间节点,最后到达输出节点的过程。Session(会话)系统执行的入口,其负责完成节点布置和传输节点的添加等任务。

    本节DenseNet的结构正是用到了TensorFlow来实现。

    3.3.2 DenseNet网络实现

    DenseNet网络的结构如图3-3所示,其中N表示 卷积和 卷积的组合。我们可以看到,具有不同层的网络也有一个大致相似的结构。网络首先在输入图像上做一次卷积和池化操作,然后进入第一个DenseBlock,DenseBlock里面就是在做密集的连接运算。第一个DenseBlock后是一个Transition Layer,同样还是一个卷积和池化操作。再往后就是与前面类似的结构,只不过通过卷积得出的特征图尺寸越来越小,深度越来越大。网络的最后一层就是分离N类的Softmax层,采用全连接结构。

    网络结构代码由TensorFlow框架实现。和通常使用一样,我们从输入图像开始一步一步构建网络的拓扑结构。代码实现的关键点在于如何实现“跳跃连接”,在DenseBlock中,我们将前面层的特征图全都传到后面层中。我们注意到,不同尺寸的特征图进入DenseBlock,每一个DenseBlock中的特征图的尺寸是一样的,我们使用框架提供的一个合并函数:tf.concat(concat_dim, values, name=’concat’)。该函数的第一个参数concat_dim必须是一个数,表明在哪个维度上进行连接操作,第二个参数values就是两个或者一组待连接的tensor。举个例子,DenseBlock中的第一层特征图a是一个[16,32,32,16]维的数组,经过一次卷积得到中间特征图b是一个[16,32,32,6]维的数组,调用函数c= tf.concat(3, (a,b))得到一个[16,32,32,22]维的向量,作为第二层的输入特征图。在DenseBlock中,每一层都调用该函数将上一层的特征图和本层产生的特征图进行合并,最终DenseBlock中最后一层就得到前面多有特征图的组合。

    表3-1 DenseNet网络结构图
    Layer Feature Size DenseNet-121 DenseNet-169 DenseNet-201 DenseNet-161
    Conv 112×112 7×7 conv
    Pooling 56×56 3×3 max pool
    DenseBlock1 56×56 N×6
    N×6
    N×6
    N×6

    L1 56×56 1×1 conv
    28 × 28 2×2 avg pool
    DenseBlock2 28 × 28 N×12 N×12 N×12 N×12
    L2 28 × 28 1×1 conv
    14 × 14 2×2 avg pool
    DenseBlock3 14 × 14 N×24 N×32 N×48 N×36
    L3 14 × 14 1×1 conv
    7 × 7 2×2 avg pool
    DenseBlock4 7 × 7 N×16 N×32 N×32 N×24
    Classification 7 × 7 ,Average Pooling
    1000D full connection

    3.3.3 网络训练

    我们凭经验证明了它的有效性,DenseNet在几个基准数据集上进行比较具有最先进的网络架构,尤其是与ResNet及其变体相比。

    1、数据库
    模型训练使用CIFAR-10数据集。CIFAR-10数据集是一个经典的物体识别数据集,该数据集是由60000张 的RGB彩色图片构成,共有10个分类,每一类有6000张图像。其中包含50000张训练图片和10000张测试图片。

    数据集被分为5个Training Batch和1个Test Batch,每个Batch有10000张图像。测试批次包含来自每个类的恰好1000个随机选择的图像。训练批次以随机顺序包含剩余图像,但一些训练批次可能包含来自一个类的图像比另一个更多。这10类物体分别是:飞机,汽车,鸟,猫,麋鹿,狗,青蛙,马,船和卡车。这些分类完全互斥,汽车和卡车之间没有重叠。汽车包括轿车、SUV等,卡车只包括大卡车。两者都不包含皮卡车。

    2、开始训练
    所有的网络均使用随机梯度下降算法(SGD)进行训练。在CIFAR数据集上我们使用小批量训练大小为64,并使用300和40作为训练周期。初始学习率设为0.1,并且在训练周期的50%和75%阶段再除以10。在ImageNet上,我们使用256的小批量训练集和90个训练周期。初始学习率设为0.1,并且在训练周期为30和60的阶段再除以10。由于GPU内存的限制,我们使用的小批量训练尺寸为128,作为补偿,我们训练100个周期,并且在90周期时将学习率除以10。

    随后,我们使用一个 的权重衰减,并使用高斯分布来初始化权重。在没有数据增量的三个数据集里,我们在每一个卷积层(除了第一个)后加上一个Dropout层,并设随机丢弃率(dropout rate)为0.2。测试误差仅对一项任务进行一次评估。

    3、训练结果
    我们使用不同的深度L和不同的增长率k。在CIFAR和SVHN数据集上的主要测试结果图表3-2所示。

    表3-2 CIFAR和SVHN数据集上的错误率
    Method Depth Params C10 C10+ C100 C100+ SVHN
    ResNet 110 38.6M — 6.61 — — —
    ResNet2 164 1.7M 11.26 5.46 35.58 24.33 —
    DenseNet(k=12) 40 1.0M 7.00 5.24 27.55 24.42 1.79
    DenseNet(k=12) 100 7.0M 5.77 4.10 23.79 20.20 1.67
    DenseNet(k=24) 100 27.2M 5.83 3.74 23.42 19.25 1.59
    DenseNet-B(k=12) 100 0.8M 5.92 4.51 24.15 22.27 1.76
    DenseNet-B(k=24) 250 15.3M 5.19 3.62 19.64 17.60 1.74
    DenseNet-B(k=40) 190 25.6M — 3.46 — 17.18 —

    首先来看准确率。可能最引人注目的是表3-2最下面的一行,可以看出当L=190,k=40时的DenseNet-BC在CIFAR数据库上表现地比现有的最好的算法还要出色。最终的错误率是3.46%(C10+)和17.18%(C100+),这一结果明显低于宽度ResNet架构得到的错误率。我们在C10和C100(均没有图像增量)上的最好结果甚至有更多令人鼓舞的地方:两者都以丢弃路径的正则化方式得到比FractalNet低30%的结果。DenseNet在SVHN数据集上以L=100,k=24的结构超过了ResNet取得最好成绩。然而,250层的DenseNet-BC并不能进一步改进短连接带来的变现,可能是由于SVHN是个比较容易解释的任务,并且及其深的模型容易过拟合。

    再来看参数量,如果没有压缩层或者瓶颈层的话,网络会有一个趋势就是性能会随着L和k的增加而变现更好。我们将此归因于相应的模型容量的增长。最好的证明就是在C10数据集上随着错误率从5.24%下降到4.10%,最后降到3.74%,参数的数量从1.0M到7.0M,再到27.2M。在C100数据集上也能观察到这一趋势。这表明DenseNet可以利用更大更深层模型的持续增长的变现力。也表明网络不会受到ResNet中过拟合或者优化难等问题的困扰。

    表中的结果表明DenseNet比其他架构模型(尤其是对比了ResNet)有更高效的参数利用率。具有Bottleneck结构的DenseNet-BC结构具有显著的参数利用率。比如,最深的模型仅有15.3M的参数量,但它始终优于其他模型,比如ResNet的参数量超过了30M。需要强调的是,超参数L=100和k=12的DenseNet-BC结构能达到与1001层的ResNet相当的性能(C10错误率4.51%vs 4.62%,C100错误率22.27%vs22.71%),但是参数量却少了90%。图3-4表明了两种网络在C10数据集上的训练损失(Training loss)和测试误差(Test Error)。

    最后研究一下过拟合现象。高效利用参数的一个积极的作用就是能够减轻过拟合现象。我们注意到,在没有进行增强的数据集上,DenseNet架构相比于之前的工作的改进尤为明显。在C10上,改进意味着相对误差从7.33%降至5.19%,相对减少29%。在C100上,减小幅度为30%,从28.2%降至19.64%。在我们的实验中,我们观察到潜在的过拟合出现在一个单一的设置:在C10中,通过增加k=12到k=24所产生的参数4倍增长导致误差从5.77%小幅增加到5.83%。DenseNet-BC的Bottleneck层和压缩层是对付这种趋势的有效方法。
    在这里插入图片描述
    图3-4 DenseNet测试图

    3.3.4 与同类方法对比

    从表面看,DenseNet网络与ResNet非常相似,只有功能函数由 变成了加法。然而,这个看起来很小的修改的影响导致两种网络架构的行为大不相同。
    在这里插入图片描述
    图3-5 DenseNet与ResNet错误率比较

    1、模型紧凑
    作为输入级联的直接结果,DenseNet任何层获得的特征映射可以被所有后续层访问。这鼓励了整个网络中的特征重用,并导致更紧凑的模型。图3-5中的图显示了这是一个旨在比较所有DenseNet参数效率和一个可比较的ResNet体系结构的实验结果。模型在C10上训练多个不同深度的小网络,并将它们的测试精度作为网络参数的一个函数。与其他流行的网络结构(比如AlexNet和VGGNet)相比,带有预激活的ResNet使用较少的参数,同时通常可获得更好的结果。因此,我们比较DenseNet(k=12)与ResNet。DenseNet的训练参数设置与上一节保持一致。

    图3-5显示DenseNet-BC始终是DenseNet的最高参数的有效变体。此外,为了达到相同的准确度,DenseNet-BC只需要ResNet大约1/3的参数量。这一结果与我们在表3-2中呈现的ImageNet上的结果一致。表3-2显示一个仅有0.8M可训练的DenseNet-BC就能够实现与1001层ResNet相当的准确度,后者具有10.2M的参数量。

    2、隐含的深度监督。
    提高密集卷积网络准确性的一个解释可能是单个层通过较短的连接从损失函数外接收额的监督。可以理解为DenseNets在进行一种“深度监督”。前面在深度监督网络中展示了“深度监督”的好处,它们将分类器附加到每个隐藏层,强制中间层学习判别特征。

    DenseNet以隐含的方式执行类似的深层监督:网络顶部的单个分类器通过至多两个或三个过渡层直接监督所有层。然而,DenseNets的损失函数和梯度实质上并不复杂,因为所有层之间共享相同的损失函数。

    3、随机连接与确定性连接。
    密集卷积网络和残余网络的随机深度正则化之间有一定的联系。在随机深度中,ResNet中的层随机丢弃,从而在周围层之间建立直接连接。由于池化层永远不会被丢弃,因此网络会产生与DenseNet类似的连接模式:如果所有中间层都是随机丢弃的,则在任何两层之间有一个小概率可以直接连接。 尽管这些方法与以往完全不同,但DenseNet对随机深度的解释可能会提供正规化一种正确的启示。

    4、特征重用
    按照设计,DenseNet允许每层访问来自其前面所有层的特征图(尽管有时会通过过渡层)。我们进行一项实验来验证一个被训练过的网络是否利用了这一优势。我们首先在C10上训练一个DenseNet,令L=40和k=12。对于密集块中的每一个卷积层l,我们计算分配给层s连接的平均绝对权重。平均绝对权重充当卷积层所依赖的前面层的替代物。位置 处的点表示层l使用前面s层生成的特征图的平均情况。可以得到以下观测结果:

    (a)所有图层将其权重分布在同一个块内的许多输入上。 这表明非常早期的层提取的特征实际上直接被整个同一密集块中的深层使用。

    (b)过渡层的权重也将它们的权重分散到前一个密集块内的所有层上,从而通过少量间接指示从DenseNet的第一层到最后一层的信息流。

    (c)第二个和第三个密集块内的图层始终将最小权重分配给过渡图层(三角形顶部行)的输出,表明过渡图层输出许多冗余特征(平均具有低权重)。 这与DenseNet-BC的强大结果保持一致,在这些结果中正好压缩了这些输出。

    (d)尽管最右侧的分类层也使用了整个密集块中的权重,但似乎还是会集中在最终的特征图上,这表明网络后期可能会产生更多的高级特征。

    3.3.5 DenseNet小结

    DenseNet将具有相同特征图大小的任何两个图层之间进行直接连接。我们发现DenseNet可以自然扩展到数百层,同时不会出现优化问题。在实验中,随着参数数量的增加,DenseNet倾向于提高准确度的一致性,没有任何性能下降或过度拟合的迹象。在多个设置下,它在多个高度竞争的数据集上实现了最先进的结果。而且,DenseNet需要实质上更少的参数和更少的计算来实现最新的性能。因为本研究中采用了针对残留网络优化的超参数设置,所以我们相信通过更详细地调整超参数和学习速率计划,可以获得DenseNet准确性的进一步提高。

    在遵循简单的连接规则的同时,DenseNets自然地整合了身份映射的属性,深度监督和多样化的深度。它们允许在整个网络中重用特征,并因此可以学习更紧凑。由于其紧凑的内部表示和减少的特征冗余,DenseNet可能是用于构建在卷积特征上的各种计算机视觉任务的良好特征提取器。

    3.4 本章小结

    本章首先讲述了密集卷积网络(DenseNet)的结构和原理,并通过组合优化策略将其改造成高质量的特征提取器。实验表明经过不断地增加层数可以有效提高准确率,并且不会产生过拟合的现象。实验成功将算法应用在分类问题上,下一章我们将该网络作为基础网络用于图像检测。

    展开全文
  • Arduino智能小车——超声波避障

    万次阅读 多人点赞 2017-09-01 21:17:36
    超声波接线   估计不少朋友早已经发现板子上的“+5V”“GND”引脚已经不够用了,这个时候你们可以向我这样焊一个扩展板出来,上面固定两排排针,一排用来扩展“+5V”,一边用来扩展“GND”引脚。   超声波...

    Arduino智能小车——超声波避障

    Arduino智能小车系列教程时空门:

    1. Arduino智能小车——拼装篇 点击跳转
    2. Arduino智能小车——测试篇 点击跳转
    3. Arduino智能小车——调速篇 点击跳转
    4. Arduino智能小车——超声波避障 点击跳转
    5. Arduino智能小车——蓝牙小车 点击跳转
    6. Arduino智能小车——循迹篇 点击跳转
    7. Arduino智能小车——小车测速 点击跳转

      经过前几篇的测试大家应该对小车有一定的认识了,在实际的操作过程中经常会由于操作不当各种碰壁吧?那这次我们将给小车装上一只“眼睛”,让小车看到障碍,躲避障碍。

    准备材料

    超声波模块HC-SR04

      在这里简单说下超声波测距的原理,相信大家也都知道。超声波发射装置发出超声波,它的根据是接收器接到超声波时的时间差,与雷达测距原理相似。 超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。

    1. 采用Trig引脚触发,给至少10us的高电平脉冲信号
    2. 模块自动发送8个40kHz的方波,自动检测是否有信号返回
    3. 有信号返回,通过Echo引脚输出一个高电平脉冲,高电平脉冲持续的时间就是超声波从发射到反射返回的时间。距离=(高电平脉冲时间*340)/2。(声音在空气中传播速度为340m/s)
    主要技术参数
    工作电压DC5V
    静态电流<2mA
    输出电平0-5V
    感应角度≤15度
    探测距离2cm-450cm
    最高精度0.3cm

    ###舵机
      在这里推荐9G舵机SG90,或者其他类似的舵机,这种舵机体积比较小,扭矩虽然不是大, 但是足够带动简易云台,很方便在小车上使用,大家购买时注意舵机的转动角度,有55度的,180度的等等,大家可以根据需要购买。

    舵机固定架

      舵机固定架的购买一定要配合舵机,所以大家购买的时候注意尺寸哦!!~

    舵机安装

      舵机在安装之前大家一定要记得校准,为什么要校准那,这个跟舵机的工作原理有关。控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压。它内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。最后,电压差的正负输出到电机驱动芯片决定电机的正反转。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。
      舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分,总间隔为2ms。以180度角度伺服为例,那么对应的控制关系是这样的:

    高电平时间对应位置
    0.5ms0度
    1.0ms45度
    1.5ms90度
    2.0ms135度
    2.5ms180度

      也就是说当对舵机输入相同控制信号时,舵机会运动到固定位置,他的动作不是做圆周运动,而是在运动范围内,每一个位置对应一个控制信号。

      因此我们需要在将舵机安装在固定架上之前,需要先将舵机初始化好,舵机一般为三根线:棕色——GND,红色——VCC,橙色——控制信号。因此我们将棕色线接到GND,红色线接到“+5V”引脚,橙色线接到“9”引脚,初始化程序如下:

    #include <Servo.h>  //加入含有舵机控制库的头文件
    
    #define PIN_SERVO 9  //舵机信号控制引脚
    Servo myservo;  
      
    void setup()  
    {  
      myservo.attach(PIN_SERVO);  //舵机初始化
    }  
      
    void loop()  
    {  
      myservo.write(90);  //PWM输出
    } 
    

      在舵机初始化好之后将其安装在固定架上,然后装配在小车上,此时保证超声波模块超前。

    超声波接线

      估计不少朋友早已经发现板子上的“+5V”和“GND”引脚已经不够用了,这个时候你们可以向我这样焊一个扩展板出来,上面固定两排排针,一排用来扩展“+5V”,一边用来扩展“GND”引脚。

      超声波模块有四个引脚,“VCC”接到Arduino UNO开发板的“+5V”引脚,“GND”接到开发板“GND”引脚,“Trig”引脚接到开发板“8”引脚,“Echo”引脚接到开发板“7”引脚

      线太乱了,真的没办法整理,我自己都没眼看。

    代码测试

    #include <Servo.h>
    
    #define STOP      0
    #define FORWARD   1
    #define BACKWARD  2
    #define TURNLEFT  3
    #define TURNRIGHT 4
    
    int leftMotor1 = 16;
    int leftMotor2 = 17;
    int rightMotor1 = 18;
    int rightMotor2 = 19;
    
    int leftPWM = 5;
    int rightPWM = 6;
    
    Servo myServo;  //舵机
    
    int inputPin=7;   // 定义超声波信号接收接口
    int outputPin=8;  // 定义超声波信号发出接口
    
    void setup() {
      // put your setup code here, to run once:
      //串口初始化
      Serial.begin(9600); 
      //舵机引脚初始化
      myServo.attach(9);
      //测速引脚初始化
      pinMode(leftMotor1, OUTPUT);
      pinMode(leftMotor2, OUTPUT);
      pinMode(rightMotor1, OUTPUT);
      pinMode(rightMotor2, OUTPUT);
      pinMode(leftPWM, OUTPUT);
      pinMode(rightPWM, OUTPUT);
      //超声波控制引脚初始化
      pinMode(inputPin, INPUT);
      pinMode(outputPin, OUTPUT);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      avoidance();
    }
    void motorRun(int cmd,int value)
    {
      analogWrite(leftPWM, value);  //设置PWM输出,即设置速度
      analogWrite(rightPWM, value);
      switch(cmd){
        case FORWARD:
          Serial.println("FORWARD"); //输出状态
          digitalWrite(leftMotor1, HIGH);
          digitalWrite(leftMotor2, LOW);
          digitalWrite(rightMotor1, HIGH);
          digitalWrite(rightMotor2, LOW);
          break;
         case BACKWARD:
          Serial.println("BACKWARD"); //输出状态
          digitalWrite(leftMotor1, LOW);
          digitalWrite(leftMotor2, HIGH);
          digitalWrite(rightMotor1, LOW);
          digitalWrite(rightMotor2, HIGH);
          break;
         case TURNLEFT:
          Serial.println("TURN  LEFT"); //输出状态
          digitalWrite(leftMotor1, HIGH);
          digitalWrite(leftMotor2, LOW);
          digitalWrite(rightMotor1, LOW);
          digitalWrite(rightMotor2, HIGH);
          break;
         case TURNRIGHT:
          Serial.println("TURN  RIGHT"); //输出状态
          digitalWrite(leftMotor1, LOW);
          digitalWrite(leftMotor2, HIGH);
          digitalWrite(rightMotor1, HIGH);
          digitalWrite(rightMotor2, LOW);
          break;
         default:
          Serial.println("STOP"); //输出状态
          digitalWrite(leftMotor1, LOW);
          digitalWrite(leftMotor2, LOW);
          digitalWrite(rightMotor1, LOW);
          digitalWrite(rightMotor2, LOW);
      }
    }
    void avoidance()
    {
      int pos;
      int dis[3];//距离
      motorRun(FORWARD,200);
      myServo.write(90);
      dis[1]=getDistance(); //中间
      
      if(dis[1]<30)
      {
        motorRun(STOP,0);
        for (pos = 90; pos <= 150; pos += 1) 
        {
          myServo.write(pos);              // tell servo to go to position in variable 'pos'
          delay(15);                       // waits 15ms for the servo to reach the position
        }
        dis[2]=getDistance(); //左边
        for (pos = 150; pos >= 30; pos -= 1) 
        {
          myServo.write(pos);              // tell servo to go to position in variable 'pos'
          delay(15);                       // waits 15ms for the servo to reach the position
          if(pos==90)
            dis[1]=getDistance(); //中间
        }
        dis[0]=getDistance();  //右边
        for (pos = 30; pos <= 90; pos += 1) 
        {
          myServo.write(pos);              // tell servo to go to position in variable 'pos'
          delay(15);                       // waits 15ms for the servo to reach the position
        }
        if(dis[0]<dis[2]) //右边距离障碍的距离比左边近
        {
          //左转
          motorRun(TURNLEFT,250);
          delay(500);
        }
        else  //右边距离障碍的距离比左边远
        {
          //右转
          motorRun(TURNRIGHT,250);
          delay(500);
        } 
      }
    }
    int getDistance()
    {
      digitalWrite(outputPin, LOW); // 使发出发出超声波信号接口低电平2μs
      delayMicroseconds(2);
      digitalWrite(outputPin, HIGH); // 使发出发出超声波信号接口高电平10μs,这里是至少10μs
      delayMicroseconds(10);
      digitalWrite(outputPin, LOW); // 保持发出超声波信号接口低电平
      int distance = pulseIn(inputPin, HIGH); // 读出脉冲时间
      distance= distance/58; // 将脉冲时间转化为距离(单位:厘米)
      Serial.println(distance); //输出距离值
     
      if (distance >=50)
      {
        //如果距离小于50厘米返回数据
        return 50;
      }//如果距离小于50厘米小灯熄灭
      else
        return distance;
    }
    

    代码详解

    “Trig”引脚控制超声波发出声波,对应int outputPin=8;
    “Echo”引脚反应接收到返回声波,对应int inputPin=7;

    int inputPin=7;   // 定义超声波信号接收接口
    int outputPin=8;  // 定义超声波信号发出接口
    

    int getDistance()函数解析

    超声波发出引脚“Trig”为高时对外发出超声波,为保证发出10μs声波,因此在发送之前需要将该引脚拉低,并给他一定反应时间。

    digitalWrite(outputPin, LOW); // 使发出发出超声波信号接口低电平2μs
    delayMicroseconds(2);
    

    之后发送10μs超声波

    digitalWrite(outputPin, HIGH); // 使发出发出超声波信号接口高电平10μs,这里是至少10μs
    

    声波发送之后禁止其继续发送,同时开始检测是否反射回来的声波

    digitalWrite(outputPin, LOW); // 保持发出超声波信号接口低电平
      int distance = pulseIn(inputPin, HIGH); // 读出脉冲时间
    

    pulseIn()单位为微秒,声速344m/s,所以距离cm=344100/1000000pulseIn()/2约等于pulseIn()/58.0distance= distance/58; // 将脉冲时间转化为距离(单位:厘米)
    超声波模块工作受物体表面反射程度影响,并且在传播过程中信号强度容易衰减,因此该模块适用的检测距离有限,一般在50cm以内相对正确,而且我们在避障时不需要检测太远的距离,因此超过50cm以上的都按50cm计算

    if (distance >=50)
      {
        //如果距离小于50厘米返回数据
        return 50;
      }//如果距离小于50厘米小灯熄灭
      else
        return distance;
    

    void avoidance()函数解析

    小车前进过程中只检测前方距离障碍的距离,并且控制舵机,保持超声波模块位于正前方。

    motorRun(FORWARD,200);
      myServo.write(90);
      dis[1]=getDistance(); //中间
    

    当检测到小车前方距离障碍距离小于30cm时停车,检测两边距离。

    motorRun(STOP,0);
    

    控制舵机每次运动一个周期后都返回正前方位置。由于舵机运动需要一定的时间,因此在每转过一个角度的时候都延时delay(15),供其运动。

    for (pos = 90; pos <= 150; pos += 1) 
    {
          myServo.write(pos);              // tell servo to go to position in variable 'pos'
          delay(15);                       // waits 15ms for the servo to reach the position
    }
    

    当运动到最左边时检测小车左边距离障碍的距离

    dis[2]=getDistance(); //左边
    

    向右边运动,检测右边距离

    for (pos = 150; pos >= 30; pos -= 1) 
    {
      myServo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(15);                       // waits 15ms for the servo to reach the position
      if(pos==90)
        dis[1]=getDistance(); //中间
    }
    dis[0]=getDistance();  //右边
    

    将前边、左边、右边距离障碍的距离都检测结束之后,舵机回到最初位置。

    for (pos = 30; pos <= 90; pos += 1) 
    {
      myServo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(15);                       // waits 15ms for the servo to reach the position
    }
    

    注意事项

    1.舵机使用时要防止其堵转,因为点击堵转时电流会增大,很容易烧坏舵机。
    2.舵机的红色电源线接入电压一般要大于等于其工作电压,供电不足会导致舵机不停自传。
    3.Arduino 《Servo.h》库里提供的write()函数输出的PWM即为舵机专用的20ms为周期的PWM波,如果使用其他开发板或者函数的话,请务必保证输出方波周期为20ms,否则舵机不会受控制

    总结

      这一篇讲解了舵机和超声波模块的使用方法,舵机在大家以后的开发生涯中应该会经常用到,因此舵机的使用规则(控制周期为20ms)请大家一定要记清楚,在舵机不受控制的时候建议大家可以购买一个舵机测试仪来测试舵机。

    欢迎各位有兴趣的朋友加入Q群1:789127261 点评、交流

    展开全文
  • C/C++头文件include规则

    千次阅读 2021-04-14 16:29:17
    计算机不能直接识别执行用高级语言写的指令,必须用编译程序(也称编译器)把C源程序翻译成二进制形式的目标程序,然后再将该目标程序与系统的函数库以及其他目标程序连接起来,形成可执行的目标程序。 编译器的...

    编译原理基础知识

    计算机不能直接识别和执行用高级语言写的指令,必须用编译程序(也称编译器)把C源程序翻译成二进制形式的目标程序,然后再将该目标程序与系统的函数库以及其他目标程序连接起来,形成可执行的目标程序。

    编译器的工作过程,一般说来编译器会做以下几个过程:
    1.预处理阶段:负责将源程序聚合在一起,将那些称为宏的缩写形式转换为源语言的语句;其中包括查找.h文件,去处理宏,变量,函数声明,嵌套的.h文件包含等,检测依赖关系,进行宏替换,看是否有重复定义与声明的情况发生,最后将那些文件中 所有的东东全部扫描进这个当前的C文件中,形成一个中间“C文件”;

    2.编译阶段:经过词法与语法分析器,生成一个类机器语言的中间表示形式作为输出,并生成可重定位的机器代码;

    3.链接阶段:解决外部内存地址的问题,将可重定位的目标文件以及库文件链接到一起,形成真正在机器上运行的代码;

    4.加载阶段:把所有的可执行目标文件放到内存中执行。
    在这里插入图片描述

    头文件的作用

    内容参考:C语言中 .h文件和.c文件的区别

    理论上来说C文件与h文件里的内容,只要是C语言所支持的,无论写什么都可以的,比如你在h文件中写函数体,只要在任何一个C文件包含此.h文件就可以将 这个函数编译成目标文件的一部分(编译是以C文件为单位的,如果不在任何C文件中包含此.h文件的话,这段代码就形同虚设),你可以在C文件中进行函数声 明,变量声明,结构体声明,这也不成问题!!!那为何一定要分成h文件与C文件呢?又为何一般都在h文件中进行函数,变量声明,宏声明,结构体声明呢?而 在C文件中去进行变量定义,函数实现呢??原因如下:

    1.如果在h文件中实现一个函数体,那么如果在多个C文件中引用它,而且又同时编译多个C文件,将其生成的目标文件连接成一个可执行文件,在每个引用此h 文件的C文件所生成的目标文件中,都有一份这个函数的代码,如果这段函数又没有定义成局部函数,那么在连接时,就会发现多个相同的函数,就会报错;

    2.如果在h文件中定义全局变量,并且将此全局变量赋初值,那么在多个引用此h文件的C文件中同样存在相同变量名的拷贝,关键是此变量被赋了初值,所以编 译器就会将此变量放入DATA段,最终在连接阶段,会在DATA段中存在多个相同的变量,它无法将这些变量统一成一个变量,也就是仅为此变量分配一个空 间,而不是多份空间,假定这个变量在h文件没有赋初值,编译器就会将之放入BSS段,连接器会对BSS段的多个同名变量仅分配一个存储空间;

    3.如果在C文件中声明宏,结构体,函数等,那么我要在另一个C文件中引用相应的宏,结构体,就必须再做一次重复的工作,如果我改了一个C文件中的一个声 明,那么又忘了改其它C文件中的声明,这不就出了大问题了,程序的逻辑就变成了你不可想象的了,如果把这些公共的东东放在一个头文件中,想用它的C文件就 只需要引用一个就OK了!!!这样岂不方便,要改某个声明的时候,只需要动一下h文件就行了;

    4.在h文件中声明结构体,函数等,当你需要将你的代码封装成一个库,让别人来用你的代码,你又不想公布源码,那么人家如何利用你的库呢?也就是如何利用 你的库中的各个函数呢??一种方法是公布源码,别人想怎么用就怎么用,另一种是提供头文件,别人从头文件中看你的函数原型,这样人家才知道如何调用你写的 函数,就如同你调用printf函数一样,里面的参数是怎样的??你是怎么知道的??还不是看人家的头文件中的相关声明啊!!!当然这些东东都成了C标 准,就算不看人家的头文件,你一样可以知道怎么使用.

    一般头文件的include方法

    内容参考:C/C++头文件的引用问题(#include使用)
    在这里插入图片描述
    对于一个工程(如下):

    在base中包含:func3.h,func3.c,文件夹main和文件夹func4;

    在main中包含:main.c,func1.h,func1.c和文件夹func2;

    在func2中包含:func2.h和func2.c;

    在func4中包含:func4.h和func4.c。

    因此:

    Main.c 中需要引用头文件 func1.h:处于同一文件夹下
    #include “func1.h”(直接引用)

    Main.c 中需要引用头文件func2.h:fun2.h处于main的平行子文件夹下
    #include “func2\func2.h”(文件夹func2后再引用)

    Mian.c 中需要引用头文件func3.h:func3.h处于main的上级文件夹下
    #include “…\func3.h”(…后再引用)

    Mian.c 中需要引用头文件func4.h:func4.h处于main的上级文件夹的下一级文件夹下
    #include “…\func4\func4.h”(…和func4后再用)

    Android.bp方式编译代码头文件include方法

    在android build系统中,通常使用Android.bp和Android.mk进行module的定义,进而对cpp进行编译,例如:

    //system/tools/hidl/Android.bp hidl-gen
    cc_binary_host {
         name: "hidl-gen",
         defaults: ["hidl-gen-defaults"],
         srcs: ["main.cpp"],
         static_libs: [
             "libbase",
             "libcrypto",
             "libhidl-gen",
             "libhidl-gen-ast",
             "libhidl-gen-hash",
             "libhidl-gen-host-utils",
             "libhidl-gen-utils",
             "libjsoncpp",
             "liblog",
         ],
     }
    

    hidl-gen的src为同级目录下的main.cpp,其头文件include代码如下:

    //system/tools/hidl/main.cpp
    #include "AST.h"
    #include "Coordinator.h"
    #include "Interface.h"
    #include "Scope.h"
    
    #include <android-base/logging.h>
    #include <hidl-hash/Hash.h>
    #include <hidl-util/FQName.h>
    #include <hidl-util/Formatter.h>
    #include <hidl-util/StringHelper.h>
    #include <stdio.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <iostream>
    #include <set>
    #include <sstream>
    #include <string>
    #include <vector>
    
    system/tools/hidl目录树:
    ├── Android.bp
    ├── AST.cpp
    ├── AST.h 
    ├── Coordinator.cpp
    ├── Coordinator.h
    ├── hashing
    │   ├── Android.bp
    │   ├── Hash.cpp
    │   └── include
    │       └── hidl-hash
    │           └── Hash.h
    ├── host_utils
    │   ├── Android.bp
    │   ├── Formatter.cpp
    │   ├── include
    │   │   └── hidl-util
    │   └── StringHelper.cpp
    ├── Interface.cpp
    ├── Interface.h
    ├── Location.cpp
    ├── Location.h
    ├── main.cpp
    ├── utils
    │   ├── Android.bp
    │   ├── FqInstance.cpp
    │   ├── FQName.cpp
    │   └── include
    │		└── hidl-util
    │    		├── FqInstance.h
    │    		└── FQName.h
    │        ├── FqInstance.h
    │        └── FQName.h   
    │ ......
    

    以main.cpp的头文件#include <hidl-hash/Hash.h>为例:
    <hidl-hash/Hash.h>头文件的代码实现在hashing/Hash.cpp中,而Hash.cpp被编译为libhidl-gen-hash.so被hidl-gen链接,即hidl-gen通过hidl-gen/Hash.h头文件访问libhidl-hash.so库中Hash.cpp的代码实现。

    libhidl-gen-hash的定义在system/tools/hidl/hashing/Android.bp中:

    cc_library {
         name: "libhidl-gen-hash",
         host_supported: true,
         defaults: ["hidl-gen-defaults"],
         srcs: ["Hash.cpp"],
         export_include_dirs: ["include"],
         shared_libs: [
             "libbase",
             "libcrypto",
             "libssl",
         ],
    }
    

    export_include_dirs导出system/tools/hidl/hashing/include,因此hidl-gen在依赖libhidl-gen-hash时,就获得了system/tools/hidl/hashing/include这个路径,只需要以此为相对路径寻找头文件就可以了,即<hidl-hash/Hash.h>.

    因此使用Android.bp进行module定义,所依赖的头文件有相对应的库实现时,头文件include可以以库的export_include_dirs为相对路径进行头文件include,soong编译系统会对include路径进行内部转换,但如果使用gcc直接编译main.cpp,会发生报错的情况。

    展开全文
  • 关联规则(Association Rules)

    千次阅读 2019-10-17 16:12:05
    关联规则反映一个事物与其他事物之间的相互依存性关联性,是数据挖掘的一个重要技术,用于从大量数据中挖掘出有价值的数据项之间的相关关系。本篇的Apriori算法主要是基于频繁集的关联分析。其主要目的就是为了...
  • 竞速比赛规则第十五届竞赛规则导读 参加过往届比赛的队员可以通过下面内容了解第十五届规则主要变化。如果第一次参加比赛,则建议对于本文进行全文阅读。竞速比赛共分为为四个组别。详细情况参加文档...
  • 黑客大曝光:网络安全机密与解决方案:第7版 第7章 远程连接和VoIP攻击 奇 怪的是,时至今日,很多公司依旧使用着各种各样的拨号连接来访问私有网络基础设施。这就像电影《黑客》中的一幕,战争拨号器依旧继续存在...
  • 问题现象:客户在云主机安全组上加入了20/21入规则,客户端可以连接FTP服务器,但是无法传输文件等。 原因:默认FTP连接传输使用被动模式未使用主动模式,防火墙(安全组)未设置正确的出入站规则 解决方法:关闭...
  • 计算机各个接口PCB-Layout 规则要求

    千次阅读 2020-10-17 17:13:19
    各个接口PCB-Layout 规则要求 针对计算机领域常用的各种接口,如USB...是Universal Serial Bus的缩写,即通用串行总线,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在PC领域的接口技术。 PCB-lay
  • “区块链自治规则”是指建立在区块链上的去中心化自治组织系统的运行方式策略安排等规则,为了叙述方便,简称为此。 区块链自治规则是由计算机代码实现,由区块链协议保障其自动运行,根据既定条件自动触发实现。...
  • ALLEGRO的约束规则的设置教程,手把手教你!

    万次阅读 多人点赞 2019-10-15 10:32:19
    约束规则的设置 分三步, 定义规则(一、基本约束规则设置:1、线间距设置;2、线宽设置;3、设置过孔;4、区域约束规则设置;5、设置阻抗;6、设置走线的长度范围;7、设置等长:7.1、不过电阻的NET 等长;7.2、过电阻的XNET ...
  • 阿里的防护等级默认关闭, 第一次需要远程连接开一下防火墙设置, 进去之后修改一下虚拟主机的防火墙配置,这样能用mstsc命令来远程登录 每个人的电脑配置以及网络都不同,解决方案也会是不同的,下面的解决方案都...
  • 计算机网络期末复习题

    万次阅读 2020-12-31 08:48:25
    再设发送方接收方的起始序号分别为200400,试画出连接建立阶段的工作示意图。标注关键字段的取值。 5.用户数据报的首部十六进制表示是:06 32 00 45 00 1C E2 17.试求源端口、目的端口、用户数据报的总长度、...
  • 首先输入命令service iptables stop关闭iptables(注意:iptables可能会有问题,貌似在旧版本中不被认为是一个服务,而是防火墙,这个问题我还没有解决,如果你解决了请告诉我一,谢谢) 限制端口并发数很简单,...
  • App Store审核规则中文版(App审核被拒原因,苹果开发必备) 简介 App Store的指导原则非常简单 - 我们希望为用户获取 app 时提供更安全可靠的体验,并为所有开发者提供借助 app 获得成功的契机。为此,我们精心打造...
  • 需要在防火墙添加新的入站规则: win+x --> 设置 --> 更新安全 -->...另外遇到过发送数据接收不到的一种情况是连接路由器的设备太多,所以遇到数据接收不到的情况时,最好建立手机热点尝试。 ...
  • 计算机网络——网络硬件网络设备及其工作原理

    万次阅读 多人点赞 2018-10-09 01:26:36
    网卡是工作在链路层的网络组件,是局域网中连接计算机传输介质的接口,不仅能实现与局域网传输介质之间的物理连接和电信号匹配,还涉及帧的发送与接收、帧的封装与拆封、介质访问控制、数据的编码与解码以及数据...
  • 2、区分器件等级工作温度 比如TI公司的基准电压芯片TL431,TL431C代表器件的工作温度是0度至70度(民用级),TL431I代表器件的工作温度是-40度至85度(工业级),其中后缀“C”“I”就代表不同的工作温度。...
  • 流式封装可以有TS、FLV等,索引式的封装有MP4,MOV,AVI等, ☞ 主要作用:一个视频文件往往会包含图像音频,还有一些配置信息(如图像音频的关联,如何解码它们等):这些内容需要按照一定的规则组织、封装起来....
  • sonar检查规则指南.docx

    千次阅读 2018-12-18 17:02:17
    1 bug类型 1.1 “.equals()” should not be used to test the values of “Atomic” classes. ...Atomic变量永远只会自身相等,Atomic变量没有覆写equals()方法. 1.2 “=+” should not be used instead...
  • 计算机网络基础知识总结,就这一篇了

    千次阅读 多人点赞 2022-04-18 19:41:18
    进入 21 世纪后,CERNET2 试验网开通,CERNET2 试验网是以 2.5 Gbit/s - 10 Gbit/s 的速度连接北京、上海广州三个 CERNET 核心节点,这标志着我国互联网已经迈入了国际先进水平。 CNNIC(中国互联网络信息中心)...
  • 前言: 在传统APA自动泊车系统中,通常使用超声波雷达进行车辆前后辈避障以及侧向车位探测。目前市场上大多数带有...单组6个雷达探头串联,其中第1第6号雷达为长距LRU雷达,2-4号为短距SRU避障雷达。超声探头均...
  • IEEE(Institute of Electrical and Electronics Engineers,美国电气电子工程师协会)对嵌入式系统的定义:“用于控制、监视或者辅助操作机器设备的装置”。原文为:Devices Used to Control,Monitor or ...
  • airpods自动连接不上Spatial audio brings head tracking and a surround-sound effect to the AirPods Pro with iOS 14. We take it for a test drive to find out what it’s all about.空间音频为iOS 14的AirPods...
  • 关于阿里云服务器ECS实例windows无法远程连接

    万次阅读 多人点赞 2018-04-22 00:15:13
    1、无法远程连接用网页连接阿里云登陆主机,打开服务器管理,选择本地服务器,启用远程管理远程桌面然后登陆阿里云控制台---&gt;管理控制台----&gt;云服务器ECS--&gt;安全组--&gt;快速创建规则...
  • 8000字干货:那些很厉害的人是怎么构建知识体系的

    万次阅读 多人点赞 2019-09-29 11:18:27
    分辨知识知识体系的差别 理解如何用八大问发现知识的连接点; 掌握致用类知识体系的构建方法; 能够应用甜蜜区模型找到特定领域来构建知识体系。 1. 知识体系?有必要吗? 小张准备通过跑步锻炼身体,可因为之前...
  • 计算机网络的 166 个核心概念

    万次阅读 多人点赞 2022-03-17 10:01:43
    针对这种情况,我重新根据不同的章节来进行整理汇总,这篇文章理解起来,应该会舒服很多了。 计算机网络基础概念 主机:计算机网络上任何一种能够连接网络的设备都被称为主机或者说是端系统,比如手机、平板电脑...
  • 第3章 规则

    2020-08-25 18:09:43
    图3-1:Amazon上这个微交互的目标是防止用户购买别人已经为他购买的商品——防止某种情况出现,同时(某种程度上)又不影响惊喜(蒙Artur Pokusin“Little Big Details”惠允使用) 规则的目的虽然是限制用户的...
  • 晶体管的工作原理

    千次阅读 2022-01-15 00:18:21
    如果你有一个0.7V的电池,你可以把它连接到基极发射极之间,晶体管就会打开。 既然我们大多数人没有0.7V的电池,我们怎么打开晶体管? 很简单!晶体管的基极到发射极部分的工作原理是二极管,二极管有一个正向...
  • 前几天我用 ...本文将之前做好的GUI远程连接MySQL数据库,实现远程账户登陆。 目录 1 搭建MySQL环境 1.1 MySQL下载及安装 1.2 远程MySQL数据库配置 1.3 MySQL使用的IDE(Navicat)安装及使用 2.登陆...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 41,617
精华内容 16,646
关键字:

和声连接的规则