Linux 36.3 + JetPack v6.0@jetson-inference之图像分类

Linux 36.3 + JetPack v6.0@jetson-inference之图像分类

  • 1. 源由
  • 2. imagenet
    • 2.1 命令选项
    • 2.2 下载模型
    • 2.3 操作示例
      • 2.3.1 单张照片
      • 2.3.2 视频
  • 3. 代码
    • 3.1 Python
    • 3.2 C++
  • 4. 参考资料
  • 5. 补充
    • 5.1 第一次运行模型本地适应初始化
    • 5.2 samba软连接

1. 源由

从应用角度来说,图像分类是计算机视觉里面最基本的一个操作。

2. imagenet

imageNet对象接受输入图像并输出每个类别的概率。GoogleNet和ResNet-18模型在构建过程中自动下载,这些模型已在包含1000个物体的ImageNet ILSVRC数据集上进行了训练。

2.1 命令选项

$ imagenet --help
usage: imagenet [--help] [--network=NETWORK] ...
                input_URI [output_URI]

Classify a video/image stream using an image recognition DNN.
See below for additional arguments that may not be shown above.

optional arguments:
  --help            show this help message and exit
  --network=NETWORK pre-trained model to load (see below for options)
  --topK=N         show the topK number of class predictions (default: 1)
positional arguments:
    input_URI       resource URI of input stream  (see videoSource below)
    output_URI      resource URI of output stream (see videoOutput below)

imageNet arguments:
  --network=NETWORK    pre-trained model to load, one of the following:
                           * alexnet
                           * googlenet (default)
                           * googlenet-12
                           * resnet-18
                           * resnet-50
                           * resnet-101
                           * resnet-152
                           * vgg-16
                           * vgg-19
                           * inception-v4
  --model=MODEL        path to custom model to load (caffemodel, uff, or onnx)
  --prototxt=PROTOTXT  path to custom prototxt to load (for .caffemodel only)
  --labels=LABELS      path to text file containing the labels for each class
  --input-blob=INPUT   name of the input layer (default is 'data')
  --output-blob=OUTPUT name of the output layer (default is 'prob')
  --threshold=CONF     minimum confidence threshold for classification (default is 0.01)
  --smoothing=WEIGHT   weight between [0,1] or number of frames (disabled by default)
  --profile            enable layer profiling in TensorRT

videoSource arguments:
    input                resource URI of the input stream, for example:
                             * /dev/video0               (V4L2 camera #0)
                             * csi://0                   (MIPI CSI camera #0)
                             * rtp://@:1234              (RTP stream)
                             * rtsp://user:pass@ip:1234  (RTSP stream)
                             * webrtc://@:1234/my_stream (WebRTC stream)
                             * file://my_image.jpg       (image file)
                             * file://my_video.mp4       (video file)
                             * file://my_directory/      (directory of images)
  --input-width=WIDTH    explicitly request a width of the stream (optional)
  --input-height=HEIGHT  explicitly request a height of the stream (optional)
  --input-rate=RATE      explicitly request a framerate of the stream (optional)
  --input-save=FILE      path to video file for saving the input stream to disk
  --input-codec=CODEC    RTP requires the codec to be set, one of these:
                             * h264, h265
                             * vp8, vp9
                             * mpeg2, mpeg4
                             * mjpeg
  --input-decoder=TYPE   the decoder engine to use, one of these:
                             * cpu
                             * omx  (aarch64/JetPack4 only)
                             * v4l2 (aarch64/JetPack5 only)
  --input-flip=FLIP      flip method to apply to input:
                             * none (default)
                             * counterclockwise
                             * rotate-180
                             * clockwise
                             * horizontal
                             * vertical
                             * upper-right-diagonal
                             * upper-left-diagonal
  --input-loop=LOOP      for file-based inputs, the number of loops to run:
                             * -1 = loop forever
                             *  0 = don't loop (default)
                             * >0 = set number of loops

videoOutput arguments:
    output               resource URI of the output stream, for example:
                             * file://my_image.jpg       (image file)
                             * file://my_video.mp4       (video file)
                             * file://my_directory/      (directory of images)
                             * rtp://<remote-ip>:1234    (RTP stream)
                             * rtsp://@:8554/my_stream   (RTSP stream)
                             * webrtc://@:1234/my_stream (WebRTC stream)
                             * display://0               (OpenGL window)
  --output-codec=CODEC   desired codec for compressed output streams:
                            * h264 (default), h265
                            * vp8, vp9
                            * mpeg2, mpeg4
                            * mjpeg
  --output-encoder=TYPE  the encoder engine to use, one of these:
                            * cpu
                            * omx  (aarch64/JetPack4 only)
                            * v4l2 (aarch64/JetPack5 only)
  --output-save=FILE     path to a video file for saving the compressed stream
                         to disk, in addition to the primary output above
  --bitrate=BITRATE      desired target VBR bitrate for compressed streams,
                         in bits per second. The default is 4000000 (4 Mbps)
  --headless             don't create a default OpenGL GUI window

logging arguments:
  --log-file=FILE        output destination file (default is stdout)
  --log-level=LEVEL      message output threshold, one of the following:
                             * silent
                             * error
                             * warning
                             * success
                             * info
                             * verbose (default)
                             * debug
  --verbose              enable verbose logging (same as --log-level=verbose)
  --debug                enable debug logging   (same as --log-level=debug)

注:关于照片、视频等基本操作,详见: 《Linux 36.3 + JetPack v6.0@jetson-inference之视频操作》

2.2 下载模型

两种方式:

  1. 创建imageNet对象时,初始化会自动下载
  2. 通过手动将模型文件放置到data/networks/目录下

国内,由于“墙”的存在,对于我们这种处于起飞阶段的菜鸟来说就是“障碍”。有条件的朋友可以参考《apt-get通过代理更新系统》进行设置网络。

不过,NVIDIA还是很热心的帮助我们做了“Work around”,所有的模型都已经预先存放在中国大陆能访问的位置:Github - model-mirror-190618

  --network=NETWORK    pre-trained model to load, one of the following:
                           * alexnet
                           * googlenet (default)
                           * googlenet-12
                           * resnet-18
                           * resnet-50
                           * resnet-101
                           * resnet-152
                           * vgg-16
                           * vgg-19
                           * inception-v4
  --model=MODEL        path to custom model to load (caffemodel, uff, or onnx)

根据以上Model方面信息,该命令支持:

  • alexnet
  • googlenet (default)
  • googlenet-12
  • resnet-18
  • resnet-50
  • resnet-101
  • resnet-152
  • vgg-16
  • vgg-19
  • inception-v4
  • 支持定制模型(需要用到通用的模型文件caffemodel, uff, or onnx)

作为示例,就下载一个googlenet (default)模型

$ mkdir model-mirror-190618
$ cd model-mirror-190618
$ wget https://github.com/dusty-nv/jetson-inference/releases/download/model-mirror-190618/GoogleNet.tar.gz
$ mkdir -p ../data/networks/Googlenet
$ tar -zxvf GoogleNet.tar.gz -C ../data/networks/Googlenet
$ cd ..

注:这个模型文件下载要注意,将解压缩文件放置到Googlenet目录下。

2.3 操作示例

它加载图像(或多张图像),使用TensorRT和imageNet类进行推理,然后叠加分类结果并保存输出图像。该项目附带了供您使用的示例图像,这些图像位于images/目录下。

  • What’s wrong with imagenet, continous printf?
$ cd build/aarch64/bin/

2.3.1 单张照片

# C++
$ ./imagenet images/orange_0.jpg images/test/output_imagenet_cpp.jpg

在这里插入图片描述

# Python
$ ./imagenet.py images/strawberry_0.jpg images/test/output_imagenet_python.jpg

在这里插入图片描述

2.3.2 视频

# Download test video (thanks to jell.yfish.us)
$ wget https://nvidia.box.com/shared/static/tlswont1jnyu3ix2tbf7utaekpzcx4rc.mkv -O jellyfish.mkv
# C++
$ ./imagenet --network=resnet-18 ../../../jellyfish.mkv images/test/output_imagenet_jellyfish_cpp.mkv
# Python
$ ./imagenet.py --network=resnet-18 ../../../jellyfish.mkv images/test/output_imagenet_jellyfish_python.mkv

这里视频就放一份了,理论上将既然有概率性的问题求解方式,不同时间运算的结果可能会有差异。但是基于这个模型,计算机没有记忆,所以理论上是同一个概率。

那么问题来了,照片的CPP和Python两次运算概率确是是不一样的。这是什么原因呢?

output_imagenet_jellyfish_cpp

3. 代码

3.1 Python

Import statements
├── sys
├── argparse
├── jetson_inference
│   └── imageNet
└── jetson_utils
    ├── videoSource
    ├── videoOutput
    ├── cudaFont
    └── Log

Command line parsing
├── Create ArgumentParser
│   ├── description
│   ├── formatter_class
│   └── epilog
├── Add arguments
│   ├── input
│   ├── output
│   ├── --network
│   └── --topK
└── Parse arguments
    ├── try
    │   └── args = parser.parse_known_args()[0]
    └── except
        ├── print("")
        ├── parser.print_help()
        └── sys.exit(0)

Load the recognition network
└── net = imageNet(args.network, sys.argv)

Optional hard-coded model loading (commented out)
└── net = imageNet(model="model/resnet18.onnx", labels="model/labels.txt", 
                   input_blob="input_0", output_blob="output_0")

Create video sources & outputs
├── input = videoSource(args.input, argv=sys.argv)
├── output = videoOutput(args.output, argv=sys.argv)
└── font = cudaFont()

Process frames until EOS or user exits
└── while True
    ├── Capture the next image
    │   ├── img = input.Capture()
    │   └── if img is None
    │       └── continue
    ├── Classify the image and get the topK predictions
    │   └── predictions = net.Classify(img, topK=args.topK)
    ├── Draw predicted class labels
    │   └── for n, (classID, confidence) in enumerate(predictions)
    │       ├── classLabel = net.GetClassLabel(classID)
    │       ├── confidence *= 100.0
    │       ├── print(f"imagenet:  {confidence:05.2f}% class #{classID} ({classLabel})")
    │       └── font.OverlayText(img, text=f"{confidence:05.2f}% {classLabel}", 
    │                            x=5, y=5 + n * (font.GetSize() + 5),
    │                            color=font.White, background=font.Gray40)
    ├── Render the image
    │   └── output.Render(img)
    ├── Update the title bar
    │   └── output.SetStatus("{:s} | Network {:.0f} FPS".format(net.GetNetworkName(), net.GetNetworkFPS()))
    ├── Print out performance info
    │   └── net.PrintProfilerTimes()
    └── Exit on input/output EOS
        └── if not input.IsStreaming() or not output.IsStreaming()
            └── break

3.2 C++

#include statements
├── "videoSource.h"
├── "videoOutput.h"
├── "cudaFont.h"
├── "imageNet.h"
└── <signal.h>

Global variables
└── bool signal_recieved = false;

Function definitions
├── void sig_handler(int signo)
│   └── if (signo == SIGINT)
│       ├── LogVerbose("received SIGINT\n");
│       └── signal_recieved = true;
└── int usage()
    ├── printf("usage: imagenet [--help] [--network=NETWORK] ...\n");
    ├── printf("                input_URI [output_URI]\n\n");
    ├── printf("Classify a video/image stream using an image recognition DNN.\n");
    ├── printf("See below for additional arguments that may not be shown above.\n\n");
    ├── printf("optional arguments:\n");
    ├── printf("  --help            show this help message and exit\n");
    ├── printf("  --network=NETWORK pre-trained model to load (see below for options)\n");
    ├── printf("  --topK=N          show the topK number of class predictions (default: 1)\n");
    ├── printf("positional arguments:\n");
    ├── printf("    input_URI       resource URI of input stream  (see videoSource below)\n");
    ├── printf("    output_URI      resource URI of output stream (see videoOutput below)\n\n");
    ├── printf("%s", imageNet::Usage());
    ├── printf("%s", videoSource::Usage());
    ├── printf("%s", videoOutput::Usage());
    └── printf("%s", Log::Usage());

main function
├── Parse command line
│   ├── commandLine cmdLine(argc, argv);
│   └── if (cmdLine.GetFlag("help"))
│       └── return usage();
├── Attach signal handler
│   └── if (signal(SIGINT, sig_handler) == SIG_ERR)
│       └── LogError("can't catch SIGINT\n");
├── Create input stream
│   ├── videoSource* input = videoSource::Create(cmdLine, ARG_POSITION(0));
│   └── if (!input)
│       ├── LogError("imagenet:  failed to create input stream\n");
│       └── return 1;
├── Create output stream
│   ├── videoOutput* output = videoOutput::Create(cmdLine, ARG_POSITION(1));
│   └── if (!output)
│       ├── LogError("imagenet:  failed to create output stream\n");
│       └── return 1;
├── Create font for image overlay
│   ├── cudaFont* font = cudaFont::Create();
│   └── if (!font)
│       ├── LogError("imagenet:  failed to load font for overlay\n");
│       └── return 1;
├── Create recognition network
│   ├── imageNet* net = imageNet::Create(cmdLine);
│   └── if (!net)
│       ├── LogError("imagenet:  failed to initialize imageNet\n");
│       └── return 1;
│   ├── const int topK = cmdLine.GetInt("topK", 1);  // default top result
├── Processing loop
│   └── while (!signal_recieved)
│       ├── uchar3* image = NULL;
│       ├── int status = 0;
│       ├── if (!input->Capture(&image, &status))
│       │   └── if (status == videoSource::TIMEOUT)
│       │       └── continue;
│       │   └── break; // EOS
│       ├── imageNet::Classifications classifications; // classID, confidence
│       ├── if (net->Classify(image, input->GetWidth(), input->GetHeight(), classifications, topK) < 0)
│       │   └── continue;
│       ├── for (uint32_t n=0; n < classifications.size(); n++)
│       │   ├── const uint32_t classID = classifications[n].first;
│       │   ├── const char* classLabel = net->GetClassLabel(classID);
│       │   ├── const float confidence = classifications[n].second * 100.0f;
│       │   ├── LogVerbose("imagenet:  %2.5f%% class #%i (%s)\n", confidence, classID, classLabel);
│       │   ├── char str[256];
│       │   ├── sprintf(str, "%05.2f%% %s", confidence, classLabel);
│       │   └── font->OverlayText(image, input->GetWidth(), input->GetHeight(),
│       │       str, 5, 5 + n * (font->GetSize() + 5), 
│       │       make_float4(255,255,255,255), make_float4(0,0,0,100));
│       ├── if (output != NULL)
│       │   ├── output->Render(image, input->GetWidth(), input->GetHeight());
│       │   ├── char str[256];
│       │   ├── sprintf(str, "TensorRT %i.%i.%i | %s | Network %.0f FPS", NV_TENSORRT_MAJOR, NV_TENSORRT_MINOR, NV_TENSORRT_PATCH, net->GetNetworkName(), net->GetNetworkFPS());
│       │   └── output->SetStatus(str);
│       │   └── if (!output->IsStreaming())
│       │       └── break;
│       └── net->PrintProfilerTimes();
├── Destroy resources
│   ├── LogVerbose("imagenet:  shutting down...\n");
│   ├── SAFE_DELETE(input);
│   ├── SAFE_DELETE(output);
│   ├── SAFE_DELETE(net);
└── LogVerbose("imagenet:  shutdown complete.\n");
    return 0;

4. 参考资料

【1】jetson-inference - Classifying Images with ImageNet

5. 补充

5.1 第一次运行模型本地适应初始化

第一次运行神经网络,虽然模型是预训练的,但是本地部署还是有个初始化过程,好像是建立一些cache的过程,具体有待进一步研究。

注:有知道为什么是这样,也请评论区告诉我,谢谢!

  • imagenet can’t work as readme says, see attached log #1858
  • could not find engine cache … MonoDepth-FCN-Mobilenet/monodepth_fcn_mobilenet.onnx.1.1.8602.GPU.FP16.engine ? #1855
  • What’s wrong with imagenet/detectnet, continous printf?

5.2 samba软连接

注:share请替换为samba共享目录,比如:home

  • ubuntu22.04 配置
[global]
allow insecure wide links = yes

[share]
follow symlinks = yes
wide links = yes
  • 之前的版本
[global]
unix extensions = no

[share]
follow symlinks = yes
wide links = yes

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/688918.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用 Apache Commons Exec 自动化脚本执行实现 MySQL 数据库备份

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

windows任意窗口置顶/前台显示/不被最小化或遮挡

问题&#xff1a;在办公时&#xff0c;当同时需要打开好几个重要的窗口&#xff0c;比如需要对若干个文件夹里的文件进行操作&#xff0c;几个窗口都需要一直在桌面前台显示&#xff0c;但这样的话容易在打开其他页面或是切其他窗口的时候被遮挡&#xff0c;因此考虑如何让几个…

Java学习笔记(六):Array List、学生管理系统、学生管理系统升级版

目录 一、ArrayList 1.1集合和数组的优势对比&#xff1a; 1.2 ArrayList类概述 1.3 ArrayList类常用方法 1.3.1 构造方法 1.3.2 成员方法 1.4 ArrayList存储字符串并遍历 1.5 ArrayList存储学生对象并遍历 1.6 查找用户的索引 1.7 添加手机对象并返回要求的数据 二…

想要提升地推效果吗?试试Xinstall数据查看功能,让您事半功倍!

在如今竞争激烈的移动互联网时代&#xff0c;地推作为一种直接有效的推广方式&#xff0c;受到了越来越多企业和品牌的青睐。然而&#xff0c;地推过程中产生的数据如何高效地收集、整理和分析&#xff0c;成为了摆在推广者面前的一大难题。Xinstall作为一款专业的App推广工具&…

开发人员必备的常用工具合集-lombok

Project Lombok 是一个 java 库&#xff0c;它会自动插入您的编辑器和构建工具&#xff0c;为您的 Java 增添趣味。 再也不用编写另一个 getter 或 equals 方法了&#xff0c;只需一个注释&#xff0c;您的类就拥有了一个功能齐全的构建器&#xff0c;自动化了您的日志记录变量…

CSS基础知识汇总

目录 CSS 基础知识1. CSS 的基本结构2. 选择器3. 常用 CSS 属性4. CSS 单位5. CSS 盒模型 总结 学习 CSS&#xff08;Cascading Style Sheets&#xff09;是前端开发的重要部分&#xff0c;它用于控制网页的样式和布局。以下是学习 CSS 过程中需要掌握的基本概念、符号和对应的…

Alsa UCM

Alsa Use Case Manager&#xff08;用例管理器&#xff09;描述如何为某些用例&#xff08;如 “播放音频”、“通话”&#xff09;设置 mixer 混频器。它还描述如何修改 mixer 混频器状态以将音频路由到某些输出和输入&#xff0c;以及如何控制这些设备。 这基本上涵盖了 Pul…

【AI基础】第三步:纯天然保姆喂饭级-安装并运行chatglm2-6b

chatglm2构建时使用了RUST&#xff0c;所以在安装chatglm2之前&#xff0c;先安装RUST。 此系列文章列表&#xff1a; 【AI基础】第一步&#xff1a;安装python开发环境-windows篇_下载安装ai环境python-CSDN博客 【AI基础】第一步&#xff1a;安装python开发环境-conda篇_mini…

uniapp余额银行卡支付密码界面实现(直接复制)

示例&#xff1a; 插件地址&#xff1a;自定义数字/身份证/密码输入框&#xff0c;键盘密码框可分离使 - DCloud 插件市场 1.下载插件并导入HBuilderX&#xff0c;找到文件夹&#xff0c;copy number-keyboard.vue一份为number-keyboard2.vue&#xff08;number-keyboard.vue是…

木质家具板材甲醛释放量检测 木制家具含水率检测

木质家具板材甲醛释放量检测 木制家具含水率检测 甲醛是一种无色,有强烈刺激型气味的气体。对人体健康有负面影响,长期接触低剂量的甲醛会引起慢性呼吸道疾病、女性月经紊乱、妊娠综合征,引起新生儿体质降低、染色体异常、甚至鼻咽癌,甲醛的危害还表现在它能凝固蛋白质,可使人…

MySQ中CONCAT函数使用

在MySQL数据库管理系统中&#xff0c;处理和连接字符串是一项常见的操作。本文将介绍几个常用的字符串连接函数&#xff0c;包括CONCAT(), CONCAT_WS(), GROUP_CONCAT()以及其他相关函数&#xff0c;这些功能可以极大地简化数据库查询中的字符串操作。 1. CONCAT() 函数 CONC…

【Git】如何不管本地文件,强制git pull

要在 Git 中强制执行 git pull 操作&#xff0c;忽略本地文件的更改&#xff0c;可以按照以下步骤操作&#xff1a; 保存当前工作状态&#xff1a;如果你有未提交的更改&#xff0c;可以使用 git stash 将这些更改存储起来。 git stash强制拉取最新代码&#xff1a;使用 git re…

企业公户验证API在Java、Python、PHP中的使用教程

在金融和商业领域&#xff0c;企业公户验证API是一种用于验证企业对公账户的真实性和合法性的技术解决方案。这种API通常由金融机构或第三方服务提供商提供&#xff0c;旨在帮助企业加快账户认证流程&#xff0c;提高效率&#xff0c;降低审核成本&#xff0c;并确保符合法规要…

别人状告你怎么办?你知道还可反告吗?

别人状告你怎么办&#xff1f;你知道还可反告吗&#xff1f; --李秘书讲写作&#xff1a;关于反诉状的写作技巧与策略 反诉状是民事诉讼中的一种重要法律文书&#xff0c;它允许被告在原告提起诉讼后&#xff0c;对原告提起反诉&#xff0c;以抵消原告的诉讼请求。李秘书这节…

Android中打印某应用的堆栈信息

先更具报名获取pid adb shell "ps|grep 包名" zygote的堆栈dump 实际上这个可以同时dump java线程及native线程的堆栈&#xff0c;对于java线程&#xff0c;java堆栈和native堆栈都可以得到。 kill -3 <pid> debuggerd的堆栈dump debuggerd是android的一个…

python中关于函数的两种链式调用

函数之间的嵌套调用之函数的返回值就是另一个函数的参数 用一个函数的返回值作为另一个函数的参数。 如上图所示&#xff0c;将is0dd&#xff08;10&#xff09;的结果交给print函数来执行。 如上图所示&#xff0c;也是一个链式调用的案例&#xff0c;先将add&#xff08;x&a…

QT之可拖动布局研究

1. 背景 最开始只用到了最基本的水平布局 、垂直布局。它的好处就是窗口整体缩放后&#xff0c;控件也自动等比例缩放。 但是比如水平布局之中的控件宽度比例、垂直布局之中的控件高度比例都是固定的。 平时也不怎么开发界面&#xff0c;最近有个需求&#xff0c;想界面上的…

使用 ISIC 快速申请 JetBrain 学生免费产品

此篇文章适合急需通过学生优惠使用 JetBrain 产品并且愿意花费 50 &#xff08;申请国际电子学生证 ISIC 需要 50&#xff09;的学生。需要等待时间1-3天&#xff0c;主要是等待 ISIC 的时间&#xff0c;只要 ISIC 发放 ISIC name 和 ISIC ID&#xff0c;将其填写到 JetBrain 的…

代码随想录算法训练营第31天(py)| 贪心 | 455.分发饼干、376. 摆动序列、53. 最大子序和

455.分发饼干 力扣链接 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j&#…

Java 初识

Java 的发展历程 Sun 公司。 Oracle 公司。 普通版本&#xff0c;也叫过渡版本。 正式版本&#xff0c;也叫长期支持版本&#xff08;LTS&#xff09;。 Java SE&#xff0c;Java EE&#xff0c;Java ME Java 技术体系分为三个平台&#xff1a;Java SE&#xff0c;Java EE&a…