带你玩转Jetson之Deepstream简明教程(四)DeepstreamApp如何使用以及用于工程验证。
1.DeepstreamApp是什么?
如果你安装完毕deepstream整体框架,会在你的系统执行目录内有可执行文件,文件名字是deepstream-app。这是一个可执行脚本文件,通过deepstream框架中的代码在安装的时候编译后install到系统根目录内。
此脚本文件可以通过终端命令行使用,使用的同时必须使用txt文本文件作为配置文件。此脚本可以通过txt配置一个“相当简单的”deepstream管道,管道中的视频源可以通过txt文本设置为各种输入,包括但不限于本地视频文件,网络上的rtsp推流等等。管道中的堆叠,一级、二级推理、跟踪、OSD等也可以通过txt文本文件进行相当简单快速的配置。
使用终端输入deepstream-app -h即可查看如何使用此脚本。
这个deepstream-app程序是安装deepstream的时候就已经编译好安装在系统里,可以在任意位置的命令终端进行调用。App分为deepstream-app和deepstream-test5-app两种。两者功能上的差别就是tset5支持类型设置为6的sink,也就是向kafka服务器收发数据的组件。其余二者大致相同。英伟达也附赠了两个app的源代码,基于C++的源代码的位置位于:(可以学习参考)
opt/nvidia/deepstream/deepstream-5.1/sources/apps/sample_apps/deepstream-app
opt/nvidia/deepstream/deepstream-5.1/sources/apps/sample_apps/deepstream-test5
2.Deepstream-App存在的意义?
deepstream-app脚本存在主要有两个意义。
首先第一个,用于工程快速验证性开发。因为deepstream-app是一个通过文本文件就能配置的管道,因此可以在您视频应用的早期阶段进行深度学习网络性能和设备硬件性能的快速测试。譬如您设计、训练了一个网络,要部署到nx上面,需要实时处理8路视频。此时您对nx的性能没有底,或者是并不知道这个网络在nx上能不能跑八路。这时候总不能现用c++或者python开发个系统再去测试吧。代码的时间是宝贵的,为了快速验证可行性,通常会先把网络设计训练完毕,然后通过deepstream-app脚本装载到简单管道里做一下压力测试。这样可以快速验证项目可行性。
其次第二个,deepstream-app可以验证网络性能瓶颈和辅助排除Bug。我之前遇到过一个大学的学生设计制作矿井安全监控,他们在3090上面跑了20多路1080p的视频流,开到22个视频流就开始卡顿,无推理结果,他们使用了c++脚本二次开发。因为他们的代码揉合了自己的代码和deepstream官方代码,有很多自定义的方法和类,短时间摸透他们的代码并不容易,且代码风格一团糟。也没有注释,这时候就开始把他们的网络通过deepstream-app配置一个22路视频同时输入的管道,通过配置发现deepstream-app本身工作正常,并没有出现卡顿无推理的情况。所以基本排除了deepstream本身的关键组件出现问题的可能。将问题锁定在了他们自己的代码位置。最后通过排查发现他们是版本控制太乱,有个学生在管道内通过tee组件插了一个支路,这个支路导致了线程崩溃。再者说,如果您的deepstream工程出现了卡顿、性能瓶颈等,完全可以把网络模型单独拿出来用txt写个简单管道,挨个排查deepstream每个单元可能的问题。如果deepstream-app都没问题,就需要自己排查自己写的部分代码。
3.Deepstream-app怎么用?
Deepstream-app的用法非常简洁。即脚本+配置文件。具体写法如下所示:
deepstream-app -c 您的配置文件.txt
脚本会自动解析您配置文件里面的内容然后组成管道。所以我们的重点应该放在这个配置文件如何写。下面,我贴出来一份以YoloV5m为范例的配置文件,逐行进行分析。
################################################################################
# Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
################################################################################[application]
enable-perf-measurement=1
perf-measurement-interval-sec=5
#gie-kitti-output-dir=streamscl[tiled-display]
enable=1
rows=1
columns=1
width=1920
height=1080[source0]
enable=1
#Type - 1=CameraV4L2 2=URI 3=MultiURI 4=RTSP
type=3
uri=rtsp://admin:HuaWei123@113.128.197.19:54388/LiveMedia/ch1/Media1
#uri=file:///home/jetson/vedio/1.mp4
num-sources=1
gpu-id=0
# (0): memtype_device - Memory type Device
# (1): memtype_pinned - Memory type Host Pinned
# (2): memtype_unified - Memory type Unified
cudadec-memtype=0[sink0]
enable=1
#Type - 1=FakeSink 2=EglSink 3=File 4=RTSPStreaming 5=Overlay 6=send message to cloud(only enable in test5-app)
type=6
msg-conv-config=./MsgConfig/config.txt
msg-conv-payload-type=0
#(0): PAYLOAD_DEEPSTREAM - Deepstream schema payload
#(1): PAYLOAD_DEEPSTREAM_MINIMAL - Deepstream schema payload minimal
#(256): PAYLOAD_RESERVED - Reserved type
#(257): PAYLOAD_CUSTOM - Custom schema payload
msg-broker-proto-lib=/opt/nvidia/deepstream/deepstream-5.1/lib/libnvds_kafka_proto.so
#msg-broker-conn-str=127.0.0.1;9092;RawData
msg-broker-conn-str=192.168.1.104;9092;RawData
topic=RawData[sink1]
enable=1
#Type - 1=FakeSink 2=EglSink 3=File 4=RTSPStreaming 5=Overlay
type=4
#1=h264 2=h265
codec=1
#encoder type 0=Hardware 1=Software
enc-type=0
sync=0
bitrate=4000000
#H264 Profile - 0=Baseline 2=Main 4=High
#H265 Profile - 0=Main 1=Main10
profile=0
# set below properties in case of RTSPStreaming
rtsp-port=8554
udp-port=5400[osd]
enable=1
border-width=2
text-size=15
text-color=1;1;1;1;
text-bg-color=0.3;0.3;0.3;1
font=Serif
show-clock=0
clock-x-offset=800
clock-y-offset=820
clock-text-size=12
clock-color=1;0;0;0[streammux]
##Boolean property to inform muxer that sources are live
live-source=0
batch-size=1
##time out in usec, to wait after the first buffer is available
##to push the batch even if the complete batch is not formed
batched-push-timeout=40000
## Set muxer output width and height
width=1920
height=1080
## If set to TRUE, system timestamp will be attached as ntp timestamp
## If set to FALSE, ntp timestamp from rtspsrc, if available, will be attached
# attach-sys-ts-as-ntp=1# config-file property is mandatory for any gie section.
# Other properties are optional and if set will override the properties set in
# the infer config file.[primary-gie]
enable=1
bbox-border-color0=1;0;0;1
bbox-border-color1=0;1;1;1
bbox-border-color2=0;0;1;1
bbox-border-color3=0;1;0;1
gie-unique-id=1
config-file=./Models/config.txt[tracker]
enable=1
# For the case of NvDCF tracker, tracker-width and tracker-height must be a multiple of 32, respectively
tracker-width=640
tracker-height=384
ll-lib-file=/opt/nvidia/deepstream/deepstream-5.1/lib/libnvds_mot_iou.so
#ll-lib-file=/opt/nvidia/deepstream/deepstream-5.1/lib/libnvds_nvdcf.so
#ll-lib-file=/opt/nvidia/deepstream/deepstream-5.1/lib/libnvds_mot_klt.so
#ll-config-file required for DCF/IOU only
#ll-config-file=tracker_config.yml
#ll-config-file=iou_config.txt
gpu-id=0
#enable-batch-process and enable-past-frame applicable to DCF only
enable-batch-process=1
enable-past-frame=0
display-tracking-id=1[tests]
file-loop=0
让我们逐组件逐行来进行翻译和解释。说在最前面,这份配置文件是通过“#”字符来进行注释的,如果有不需要的设置或者需要更改设置,建议使用“#”来进行无效化,不建议直接删,否则可能会记不住删除了那些东西。
[application]
enable-perf-measurement=1
perf-measurement-interval-sec=5
首先来看application总体配置。enable-perf-measurement的意思是开启每秒帧数测试。是否开启fps帧率检测,0代表不开启1代表开始,下面的perf-measurement-interval-sec参数是多少帧率计算一次用来做数据平滑。
[source0]
enable=1
#Type - 1=CameraV4L2 2=URI 3=MultiURI 4=RTSP
type=3
uri=rtsp://admin:HuaWei123@113.128.197.19:54388/LiveMedia/ch1/Media1
#uri=file:///home/jetson/vedio/1.mp4
num-sources=1
gpu-id=0
# (0): memtype_device - Memory type Device
# (1): memtype_pinned - Memory type Host Pinned
# (2): memtype_unified - Memory type Unified
cudadec-memtype=0
然后来看source0,这个是deepstream的输入源,您可以在这个source组件进行视频流输入的配置。如果您有一个视频流就写[source0],如果有多个就[source1],[source2],[source3]依次往下递增序号即可。enable不用说了还是一个使能设置,0则关闭1则开启。type类型是告诉deepstream-app大概是什么类型的输入,1是V4L2也就是linux硬件设备树上面的摄像头,2是网络URI,3是万能设置,比2更好,可以读取本地文件。4是指定的RTSP视频流。我一般直接用3即可。
然后是Uri链接,如果是网络连接或者是ip摄像头,直接把rtsp地址copy过来即可。就如同上面的:uri=rtsp://admin:HuaWei123@113.128.197.19:54388/LiveMedia/ch1/Media1。如果是本地的视频文件,需要特定的写法。这个我也是论坛查了好久才查到的,具体写法就是uri:///加上文件在系统内的绝对路径加上文件名字。这样写deepstream-app就能直接读取本地视频流进行推理。
[streammux]
##Boolean property to inform muxer that sources are live
live-source=0
batch-size=1
##time out in usec, to wait after the first buffer is available
##to push the batch even if the complete batch is not formed
batched-push-timeout=40000
## Set muxer output width and height
width=1920
height=1080
## If set to TRUE, system timestamp will be attached as ntp timestamp
## If set to FALSE, ntp timestamp from rtspsrc, if available, will be attached
# attach-sys-ts-as-ntp=1
Streammux插件是deepstream的混流插件,比如你输入是30路视频流,需要通过Streammux插件将视频流混流到一起,组成一个视频流。这里需要注意的是batch-size改成了1,还有输入输出的尺寸需要设计好。
[primary-gie]
enable=1
bbox-border-color0=1;0;0;1
bbox-border-color1=0;1;1;1
bbox-border-color2=0;0;1;1
bbox-border-color3=0;1;0;1
gie-unique-id=1
config-file=./Models/config.txt
[primary-gie]插件就是我们需要用到的推理插件,这个插件在deepstream-app的txt配置文件中需要写的东西不多,上面的几个参数分别是使能,bbox框颜色,bbox框是否生成唯一id。后面这个config-file目录才是重点。这里文件目录采用的是和终端命令行相似的相对目录,在deepstream-app的txt配置文件的同级目录下的Models的文件夹内的config文件。这个目录和文件名到时候根据您的项目来随意写。网络推理的相关参数都在这个config文本内。接下来我们看一下这个config.txt文本内到底是什么。
################################################################################
# Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
################################################################################# Following properties are mandatory when engine files are not specified:
# int8-calib-file(Only in INT8), model-file-format
# Caffemodel mandatory properties: model-file, proto-file, output-blob-names
# UFF: uff-file, input-dims, uff-input-blob-name, output-blob-names
# ONNX: onnx-file
#
# Mandatory properties for detectors:
# num-detected-classes
#
# Optional properties for detectors:
# cluster-mode(Default=Group Rectangles), interval(Primary mode only, Default=0)
# custom-lib-path
# parse-bbox-func-name
#
# Mandatory properties for classifiers:
# classifier-threshold, is-classifier
#
# Optional properties for classifiers:
# classifier-async-mode(Secondary mode only, Default=false)
#
# Optional properties in secondary mode:
# operate-on-gie-id(Default=0), operate-on-class-ids(Defaults to all classes),
# input-object-min-width, input-object-min-height, input-object-max-width,
# input-object-max-height
#
# Following properties are always recommended:
# batch-size(Default=1)
#
# Other optional properties:
# net-scale-factor(Default=1), network-mode(Default=0 i.e FP32),
# model-color-format(Default=0 i.e. RGB) model-engine-file, labelfile-path,
# mean-file, gie-unique-id(Default=0), offsets, process-mode (Default=1 i.e. primary),
# custom-lib-path, network-mode(Default=0 i.e FP32)
#
# The values in the config file are overridden by values set through GObject
# properties.[property]
gpu-id=0
net-scale-factor=0.0039215697906911373
#0=RGB, 1=BGR
model-color-format=0
custom-network-config=yolov5s
model-file=yolov5s.wts
model-engine-file=yolov5s_fp16.engine
labelfile-path=labels.txt
int8-calib-file=yolov5s.trt.calib.table
## 0=FP32, 1=INT8, 2=FP16 mode
network-mode=2
num-detected-classes=2
gie-unique-id=1
network-type=0
is-classifier=0
## 0=Group Rectangles, 1=DBSCAN, 2=NMS, 3= DBSCAN+NMS Hybrid, 4 = None(No clustering)
cluster-mode=2
maintain-aspect-ratio=1
parse-bbox-func-name=NvDsInferParseCustomYoloV5
custom-lib-path=libnvdsinfer_custom_impl_yolov5.so
engine-create-func-name=NvDsInferYoloCudaEngineGet
#scaling-filter=0
#scaling-compute-hw=0
首先,前面的大段都是nvidia的版权声明,从poperty这里开始是推理引擎的配置。gpu-id是指定相关gpu,单卡就是0,多卡依次按序号指定。net-scale-factor一般是默认数据。需要注意的是,这里的:
custom-network-config=yolov5s
model-file=yolov5s.wts
model-engine-file=yolov5s_fp16.engine
parse-bbox-func-name=NvDsInferParseCustomYoloV5
custom-lib-path=libnvdsinfer_custom_impl_yolov5.so
engine-create-func-name=NvDsInferYoloCudaEngineGet
几行要合起来看,因为我这里使用的是deepstream的第三方网络也就是yolov5m,deepstream并不能直接加载且解析网络、构建网络的加速引擎、并且对网络推理的后处理bbox进行解析,所以需要你自己编写一个.so来进行上述工作。parse-bbox-func-name就是指出bbox解析的api名称,custom-lib-path是你的.so库名字,engine-create-func-name是你库的解析yolov5模型创建引擎的api名称。需要注意的是,如果你使用的英伟达TAO或者TLT迁移学习,深度学习网络模型是从nvidia官网上下载的resnet19等训练好的etlt模型,可以无缝接入Deepstream不用做这个第三方库。直接就可以简化为:
model-file=resnet19.etlt
model-engine-file=resnet19_fp16.engine
剩下的关于深度学习网络的配置我就不一一介绍了,基本都是推理相关,我等会会把每一条都是什么的官网查询文档贴出来。
接着来看跟踪器相关设置。
[tracker]
enable=1
# For the case of NvDCF tracker, tracker-width and tracker-height must be a multiple of 32, respectively
tracker-width=640
tracker-height=384
ll-lib-file=/opt/nvidia/deepstream/deepstream-5.1/lib/libnvds_mot_iou.so
#ll-lib-file=/opt/nvidia/deepstream/deepstream-5.1/lib/libnvds_nvdcf.so
#ll-lib-file=/opt/nvidia/deepstream/deepstream-5.1/lib/libnvds_mot_klt.so
#ll-config-file required for DCF/IOU only
#ll-config-file=tracker_config.yml
#ll-config-file=iou_config.txt
gpu-id=0
#enable-batch-process and enable-past-frame applicable to DCF only
enable-batch-process=1
enable-past-frame=0
display-tracking-id=1
Tracker组件用于对推理目标进行跟踪,譬如一个摄像头30FPS,但是推理性能不够只有15FPS,需要跳帧推理的时候,中间没有进行推理的帧就通过跟踪器进行追踪,确保不会丢失bbox。或者是针对目标进行单一id化,确保目标识别出来后在画面内始终保持同一个id。在车船人员计数方面还是有一定作用,防止bbox推理丢失后产生多重计数等。
nvidia这边提供了三种跟踪方式,分别是iou、nvdcf、klt光流。iou最简单算力使用最低,但是效果最差劲,klt光流法最好但是最吃算力。nvdcf是英伟达自己开发的算法,通过概率去预测。是一个比较均衡的。此Tracker组件需要根据选用的算法指定具体.so,追踪宽高基本是默认的。
需要注意的是上述追踪算法在jetson平台默认自动运行于VIC内,会减少CPU占用。
[osd]
enable=1
border-width=2
text-size=15
text-color=1;1;1;1;
text-bg-color=0.3;0.3;0.3;1
font=Serif
show-clock=0
clock-x-offset=800
clock-y-offset=820
clock-text-size=12
clock-color=1;0;0;0
OSD插件适用于bbox可视化,基本就是线宽,是否展示id,颜色等等,不做过多赘述。此插件也是在jetson平台用VIC进行硬件加速的,会减少cpu占用。
[sink0]
enable=1
#Type - 1=FakeSink 2=EglSink 3=File 4=RTSPStreaming 5=Overlay 6=msgbroker(only enable in test5-app)
type=6
msg-conv-config=./MsgConfig/config.txt
msg-conv-payload-type=0
#(0): PAYLOAD_DEEPSTREAM - Deepstream schema payload
#(1): PAYLOAD_DEEPSTREAM_MINIMAL - Deepstream schema payload minimal
#(256): PAYLOAD_RESERVED - Reserved type
#(257): PAYLOAD_CUSTOM - Custom schema payload
msg-broker-proto-lib=/opt/nvidia/deepstream/deepstream-5.1/lib/libnvds_kafka_proto.so
#msg-broker-conn-str=127.0.0.1;9092;RawData
msg-broker-conn-str=192.168.1.104;9092;RawData
topic=RawData
sink是管道最后的sink接受终端,enable-1代表开启,type种类非常丰富。1就是假的sink,啥也不干。算法纯在后台运行不做任何显示或者处理。2是图像显示,格式是EGL。3是文件sink,在接收到视频流后直接在本地存文件。4是RTSP推流。5是全屏直接显示,6是服务器收发消息组件,仅在deepstream-test5-app有效。此处选择了6。
msg-conv-config参数是配置摄像头位置信息的,仅仅在360度扭曲变换那个例子有用,这里直接抄过来了怕出错。不过里边的东西没用。msg-conv-payload-type就是每一帧发送什么样的消息,0就是所有的都发,1简短一些,256 257是自定义和预留的参数。msg-broker-proto-lib是选择底层用什么通讯,这里选用了kafka。msg-broker-conn-str参数是服务参数配置,这里nx代表了kafka的producer,需要给一个broker发送消息。Kafka的broker就相当于是个托管服务器,消费者和生产者的消息都要过这个broker中间人。第一个是broker服务的地址,第二个是端口,第三个是Topic。下面的Topic参数和上面的写一致即可。
上面这个主要是为了给kafka服务器发送数据,如果只是做本地显示,改成如下即可。
[sink0]
enable=1
#Type - 1=FakeSink 2=EglSink 3=File 4=RTSPStreaming 5=Overlay 6=msgbroker(only enable in test5-app)
type=2
如果你想通过deepstream-app推流,也可以如下设置sink组件来达到推流效果:
[sink1]
enable=1
#Type - 1=FakeSink 2=EglSink 3=File 4=RTSPStreaming 5=Overlay
type=4
#1=h264 2=h265
codec=1
#encoder type 0=Hardware 1=Software
enc-type=0
sync=0
bitrate=4000000
#H264 Profile - 0=Baseline 2=Main 4=High
#H265 Profile - 0=Main 1=Main10
profile=0
# set below properties in case of RTSPStreaming
rtsp-port=8554
udp-port=5400
sink1是rtsp的推流sink,可以接受管道数据然后在局域网转推出来。Codec是选择编码格式,默认h264。Enc-type是编码器选择,这里肯定选硬件编码器。Sync是同步选择,就是视频源头推送一帧我这个sink就推送一帧,是同步且实时的,但是有点不好的就是读取带有延迟的网络视频流,经过网络的传输实时延迟已经很大了,就会造成sync报错视频卡顿,所以sync还是不开了,给关掉了。Bitrate是编码比特率,默认参数。Profile暂时没搞懂,默认的参数。Rtsp port和udp port都是网络端口信息。这俩都是默认即可,可以根据网络环境更改。最后管道在运行的时候就可以得到一个实时推流地址。
4.实机演示
验证平台:Jetson NX 8 GB 、yolov5m 、deeepstream 5.1
运行效果如上图所示。 如果你还增加了rtsp推流,将结果推出,脚本会输出rtsp地址以供查看。
5.概括Deepstream-app脚本优缺点
优点1.快速搭建用于验证的管道模型。
优点2.通过控制关键组件enable的0、1来排查bug或者性能瓶颈。
缺点:基本就是个直肠子,只能组建source-mux混流-gie推理-(gie二级推理)-tracker-osd-sink这样的简单管道,至于您要想搞什么tee插件分流,搞什么opencv挂探针取图,基本不可能,只能靠二次开发。如果您的管道设计非常简单,甚至不用二次开发用deepstream-app脚本挂管道就行了。但是如果您的设计较为复杂,此脚本远远无法满足。还是得搞开发环境二次开发。
6.相关资料
上述配置文件中各种眼花缭乱的配置有些很重要有些是次要的,好多都没写,我只写了主要的。但是要查这些组件的配置去哪里查呢?英伟达doc文档中心有deepstream的设置参数手册,里边罗列了非常详细的参数列表和建议参数还有参数含义。在这里将地址挂出来您自行查询。
地址在这里:
https://docs.nvidia.com/metropolis/deepstream/dev-guide/text/DS_ref_app_deepstream.html
感谢您的阅读!
相关文章:

带你玩转Jetson之Deepstream简明教程(四)DeepstreamApp如何使用以及用于工程验证。
1.DeepstreamApp是什么? 如果你安装完毕deepstream整体框架,会在你的系统执行目录内有可执行文件,文件名字是deepstream-app。这是一个可执行脚本文件,通过deepstream框架中的代码在安装的时候编译后install到系统根目录内。 此脚…...

快速搭建个人在线书库,随时随地畅享阅读!
前边我们利用NAS部署了个人的导航页、小说站、云笔记,今天,我们再看看怎么部署一个个人的在线书库。 相信很多朋友都在自己的电脑中收藏了大量的PDF、MOBI等格式的电子书籍,但是一旦换了一台设备,要么是无法翻阅,要么…...

电子纸墨水屏的现实应用场景
电子纸挺好个东西,大家都把注意力集中在商超场景 其实还有更多有趣的场景方案可用,价值也不小,比如: 一、仓库场景 通过亮灯拣选,提高仓库作业效率 二、仓库循环使用标签 做NFC类发卡式应用,替代传统纸…...

常量const、引用、指针的大杂烩
文章目录1 普通引用1.1 对普通值的普通引用1.2 对常量值的普通引用1.3 对普通指针的普通引用1.4 对常量指针的普通引用1.5 对指针常量的普通引用1.6 对指向常量的指针常量的普通引用2 常量引用2.1 对普通值的常量引用2.2 对常量值的常量引用2.3 对普通指针的常量引用2.4 对常量…...

宝塔搭建实战php开源likeadmin通用管理移动端uniapp源码(四)
大家好啊,我是测评君,欢迎来到web测评。 上一期给大家分享了pc端的部署方式,今天来给大家分享uniapp端在本地搭建,与打包发布到宝塔的方法。感兴趣的朋友可以自行下载学习。 技术架构 vscode node16 vue3 uniapp vite types…...
Hive的分区表与分桶表内部表外部表
文章目录1 Hive分区表1.1 Hive分区表的概念?1.1.1 分区表注意事项1.2 分区表物理存储结构1.3 分区表使用场景1.4 静态分区表是什么?1.4.1 静态分区表案例1.4.2 分区表练习一1.4.3 分区操作1.5 动态分区表是什么?1.5.1 动态态分区表案例&#…...

和数集团打造《神念无界:源起山海》,诠释链游领域创新与责任
首先,根据网上资料显示,一部《传奇》,二十年热血依旧。 《传奇》所缔造的成绩,承载的是多少人的青春回忆,《传奇》无疑已经在游戏史上写下了浓墨重彩的一笔。 相比《传奇》及背后的研发运营公司娱美德名声大噪&#x…...

小白入门模拟IC设计,如何快速学习?
众所周知,模拟电路很难学。以最普遍的晶体管来说,我们分析它的时候必须首先分析直流偏置,其次在分析交流输出电压。可以说,确定工作点就是一项相当麻烦的工作(实际中来说),晶体管的参数多、参数…...

51单片机——中断系统之外部中断实验,小白讲解,相互学习
中断介绍 中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的,中断功能的存在,很大程度上提高了单片机处理外部或内部事件的能力。它也是单片机最重要的功能之一,是我们学些单片机必须要掌握的。 为了更容易的理解中断概念&…...

如何设计一个秒杀系统
秒杀系统要如何设计? 前言 高并发下如何设计秒杀系统?这是一个高频面试题。这个问题看似简单,但是里面的水很深,它考查的是高并发场景下,从前端到后端多方面的知识。 秒杀一般出现在商城的促销活动中,指定…...
厄瓜多尔公司注册方案
简介: 经济概况与商机 厄瓜多尔是世界上第74大国家,是南美西部国家,与哥伦比亚,秘鲁和太平洋接壤。厄瓜多尔地处世界中心,地理位置优越,地理位置优越-赤道线零纬度,使其成为通往太平洋的理想枢…...

安全渗透环境准备(工具下载)
数据来源 01 一些VM虚拟机的安装 攻击机kali: kali官网 渗透测试工具Kali Linux安装与使用 kali汉化 虚拟机网络建议设置成NAT模式,桥接有时不稳定。 靶机OWASP_Broken_Web_Apps: 迅雷下载 网盘下载 安装教程 开机之后需要登录&am…...

118.(leaflet篇)leaflet空间判断-点与geojson面图层的空间关系(turf实现)
听老人家说:多看美女会长寿 地图之家总目录(订阅之前建议先查看该博客) 文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。 效果如下所示: 下面献上完整代码,代码重要位置会做相应解释 <!DOCTYPE html> <html>...

目标检测与目标跟踪算法技术汇总
现如今chatgpt的爆火,我也使用了一段时间,问了许多关于人工智能技术的问题,基本是它能够回答了大部分的原理的,至于其人工智能涉及到的算法以及网络,考虑到也没有图,可能在给出这类回答上,是不太…...
Linux 系统启动过程
过去几十年,公用事业行业发生了重大变化。能源需求的转变导致企业利润率的波动,但不是运营成本的波动。 许多公用事业公司通过后勤部门流程自动化来削减成本,比如招采流程自动化。 在招采活动中,人工招采会产生盲点。由于公共事业…...
【每日一题Day118】LC1124表现良好的最长时间段 | 前缀和+单调栈/哈希表
表现良好的最长时间段【LC1124】 给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。 我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。 所谓「表现良好的时间段」,意味在这段时间内&#…...
vue使用nprogress(进度条)
目录 1.安装 2.引入 3.配置 4.使用 5.使用场景 6.改变颜色 1.安装 npm install --save nprogress2.引入 import NProgress from nprogress import nprogress/nprogress.css3.配置 NProgress.configure({easing: ease, // 动画方式,和css动画属性一样&#…...
@NotNull 、@NotBlank、@NotEmpty区别和使用
引言 今天在使用validation校验的时候,发现了使用校验不起作用,一时间有点摸不到头绪,就看了一下同事提交的代码,发现了问题在用NotNull用法,用的有些错误,所以在这里讲一下NotNull、NotBlank、NotEmpty区…...

Nacos——Nacos简介以及Nacos Server安装
资料来源:02-Nacos配置管理-什么是配置中心_哔哩哔哩_bilibili nacos记得下载2.x版本的,负责以后新建配置的时候会出现“发布错误,请检查参数是否正确”错误!!!! 目录 一、Nacos简介 1.1 四…...
Presto 文档和笔记
1. Presto Presto 官网 Presto 文档 2. 配置 3.1 node 配置 cat etc/node.properties # Generated by Apache Ambari. Fri Feb 10 14:52:10 2023node.data-dir/mnt/bmr/presto/data node.environmentproduction node.idbmr-master-4b7cbaa3.2 jvm 配置 cat etc/jvm.confi…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...