Linux 36.3 + JetPack v6.0@jetson-inference之目标检测

news2024/11/22 23:18:25

Linux 36.3 + JetPack v6.0@jetson-inference之目标检测

  • 1. 源由
  • 2. detectnet
    • 2.1 命令选项
    • 2.2 下载模型
    • 2.3 操作示例
      • 2.3.1 单张照片
      • 2.3.2 多张照片
      • 2.3.3 视频
  • 3. 代码
    • 3.1 Python
    • 3.2 C++
  • 4. 参考资料

1. 源由

从应用角度来说,目标检测是计算机视觉里面第二个重要环节。之前的识别示例输出了表示整个输入图像的类别概率。接下来,将专注于目标检测,通过提取边界框来找到帧中各种目标的位置。与图像分类不同,目标检测网络能够在每帧中检测到多个不同的目标。

2. detectnet

detectNet对象接受图像作为输入,并输出检测到的边界框坐标列表以及它们的类别和置信度值。detectNet可以在Python和C++中使用。请参阅下面可供下载的各种预训练检测模型。默认使用的模型是基于MS COCO数据集训练的91类SSD-Mobilenet-v2模型,该模型在Jetson上结合TensorRT实现了实时推理性能。

2.1 命令选项

$ detectnet --help
usage: detectnet [--help] [--network=NETWORK] [--threshold=THRESHOLD] ...
                 input [output]

Locate objects in a video/image stream using an object detection DNN.
See below for additional arguments that may not be shown above.

positional arguments:
    input           resource URI of input stream  (see videoSource below)
    output          resource URI of output stream (see videoOutput below)

detectNet arguments:
  --network=NETWORK     pre-trained model to load, one of the following:
                            * ssd-mobilenet-v1
                            * ssd-mobilenet-v2 (default)
                            * ssd-inception-v2
                            * peoplenet
                            * peoplenet-pruned
                            * dashcamnet
                            * trafficcamnet
                            * facedetect
  --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-cvg=COVERAGE name of the coverage/confidence output layer (default is 'coverage')
  --output-bbox=BOXES   name of the bounding output layer (default is 'bboxes')
  --mean-pixel=PIXEL    mean pixel value to subtract from input (default is 0.0)
  --confidence=CONF     minimum confidence threshold for detection (default is 0.5)
  --clustering=CLUSTER  minimum overlapping area threshold for clustering (default is 0.75)
  --alpha=ALPHA         overlay alpha blending value, range 0-255 (default: 120)
  --overlay=OVERLAY     detection overlay flags (e.g. --overlay=box,labels,conf)
                        valid combinations are:  'box', 'lines', 'labels', 'conf', 'none'
  --profile             enable layer profiling in TensorRT

objectTracker arguments:
  --tracking               flag to enable default tracker (IOU)
  --tracker=TRACKER        enable tracking with 'IOU' or 'KLT'
  --tracker-min-frames=N   the number of re-identified frames for a track to be considered valid (default: 3)
  --tracker-drop-frames=N  number of consecutive lost frames before a track is dropped (default: 15)
  --tracker-overlap=N      how much IOU overlap is required for a bounding box to be matched (default: 0.5)

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. 创建 对象时,初始化会自动下载
  2. 通过手动将模型文件放置到data/networks/目录下

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

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

  --network=NETWORK     pre-trained model to load, one of the following:
                            * ssd-mobilenet-v1
                            * ssd-mobilenet-v2 (default)
                            * ssd-inception-v2
                            * peoplenet
                            * peoplenet-pruned
                            * dashcamnet
                            * trafficcamnet
                            * facedetect
  --model=MODEL         path to custom model to load (caffemodel, uff, or onnx)

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

  • ssd-mobilenet-v1
  • ssd-mobilenet-v2 (default)
  • ssd-inception-v2
  • peoplenet
  • peoplenet-pruned
  • dashcamnet
  • trafficcamnet
  • facedetect
  • 支持定制模型(需要用到通用的模型文件caffemodel, uff, or onnx)

作为示例,就下载一个SSD-Mobilenet-v2(default)模型

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

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

2.3 操作示例

$ cd build/aarch64/bin/

2.3.1 单张照片

# C++
$ ./detectnet --network=ssd-mobilenet-v2 images/peds_0.jpg images/test/output_detectnet_cpp.jpg
# Python
$ ./detectnet.py --network=ssd-mobilenet-v2 images/peds_0.jpg images/test/output_detectnet_python.jpg

本次CPP和Python执行概率结果一致,不像imagenet有差异。

在这里插入图片描述

2.3.2 多张照片

# C++
$ ./detectnet "images/peds_*.jpg" images/test/peds_output_detectnet_cpp_%i.jpg
# Python
$ ./detectnet.py "images/peds_*.jpg" images/test/peds_output_detectnet_python_%i.jpg

注:多张图片这里就不再放出了,感兴趣的朋友下载代码,本地运行一下即可。

2.3.3 视频

# Download test video
wget https://nvidia.box.com/shared/static/veuuimq6pwvd62p9fresqhrrmfqz0e2f.mp4 -O pedestrians.mp4
# C++
$ ./detectnet ../../../pedestrians.mp4 images/test/pedestrians_ssd_detectnet_cpp.mp4
# Python
$ ./detectnet.py ../../../pedestrians.mp4 images/test/pedestrians_ssd_detectnet_python.mp4

pedestrians

3. 代码

3.1 Python

Import statements
├── import sys
├── import argparse
├── from jetson_inference import detectNet
└── from jetson_utils import videoSource, videoOutput, Log

Command-line argument parsing
├── Create ArgumentParser
│   ├── description: "Locate objects in a live camera stream using an object detection DNN."
│   ├── formatter_class: argparse.RawTextHelpFormatter
│   └── epilog: detectNet.Usage() + videoSource.Usage() + videoOutput.Usage() + Log.Usage()
├── Add arguments
│   ├── input: "URI of the input stream"
│   ├── output: "URI of the output stream"
│   ├── --network: "pre-trained model to load (default: 'ssd-mobilenet-v2')"
│   ├── --overlay: "detection overlay flags (default: 'box,labels,conf')"
│   └── --threshold: "minimum detection threshold to use (default: 0.5)"
└── Parse arguments
    ├── args = parser.parse_known_args()[0]
    └── Exception handling
        ├── print("")
        └── parser.print_help()
        └── sys.exit(0)

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

Load object detection network
└── net = detectNet(args.network, sys.argv, args.threshold)

# Note: Hard-code paths to load a model (commented out)
   ├── net = detectNet(model="model/ssd-mobilenet.onnx", labels="model/labels.txt", 
   ├──                 input_blob="input_0", output_cvg="scores", output_bbox="boxes", 
   └──                 threshold=args.threshold)

Process frames until EOS or user exits
└── while True:
    ├── Capture next image
    │   └── img = input.Capture()
    │       └── if img is None: # timeout
    │           └── continue
    ├── Detect objects in the image
    │   └── detections = net.Detect(img, overlay=args.overlay)
    ├── Print the detections
    │   ├── print("detected {:d} objects in image".format(len(detections)))
    │   └── for detection in detections:
    │       └── print(detection)
    ├── Render the image
    │   └── output.Render(img)
    ├── Update the title bar
    │   └── output.SetStatus("{:s} | Network {:.0f} FPS".format(args.network, net.GetNetworkFPS()))
    ├── Print 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"
├── "detectNet.h"
├── "objectTracker.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: detectnet [--help] [--network=NETWORK] [--threshold=THRESHOLD] ...\n");
    ├── printf("                 input [output]\n\n");
    ├── printf("Locate objects in a video/image stream using an object detection DNN.\n");
    ├── printf("See below for additional arguments that may not be shown above.\n\n");
    ├── printf("positional arguments:\n");
    ├── printf("    input           resource URI of input stream  (see videoSource below)\n");
    ├── printf("    output          resource URI of output stream (see videoOutput below)\n\n");
    ├── printf("%s", detectNet::Usage());
    ├── printf("%s", objectTracker::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("detectnet:  failed to create input stream\n");
│       └── return 1;
├── Create output stream
│   ├── videoOutput* output = videoOutput::Create(cmdLine, ARG_POSITION(1));
│   └── if (!output)
│       ├── LogError("detectnet:  failed to create output stream\n");
│       └── return 1;
├── Create detection network
│   ├── detectNet* net = detectNet::Create(cmdLine);
│   └── if (!net)
│       ├── LogError("detectnet:  failed to load detectNet model\n");
│       └── return 1;
│   └── const uint32_t overlayFlags = detectNet::OverlayFlagsFromStr(cmdLine.GetString("overlay", "box,labels,conf"));
├── Processing loop
│   └── while (!signal_recieved)
│       ├── Capture next image
│       │   ├── uchar3* image = NULL;
│       │   ├── int status = 0;
│       │   ├── if (!input->Capture(&image, &status))
│       │   │   └── if (status == videoSource::TIMEOUT)
│       │   │       └── continue;
│       │   │   └── break; // EOS
│       ├── Detect objects in the frame
│       │   ├── detectNet::Detection* detections = NULL;
│       │   ├── const int numDetections = net->Detect(image, input->GetWidth(), input->GetHeight(), &detections, overlayFlags);
│       │   └── if (numDetections > 0)
│       │       └── LogVerbose("%i objects detected\n", numDetections);
│       │       └── for (int n=0; n < numDetections; n++)
│       │           ├── LogVerbose("\ndetected obj %i  class #%u (%s)  confidence=%f\n", n, detections[n].ClassID, net->GetClassDesc(detections[n].ClassID), detections[n].Confidence);
│       │           ├── LogVerbose("bounding box %i  (%.2f, %.2f)  (%.2f, %.2f)  w=%.2f  h=%.2f\n", n, detections[n].Left, detections[n].Top, detections[n].Right, detections[n].Bottom, detections[n].Width(), detections[n].Height());
│       │           └── if (detections[n].TrackID >= 0)
│       │               └── LogVerbose("tracking  ID %i  status=%i  frames=%i  lost=%i\n", detections[n].TrackID, detections[n].TrackStatus, detections[n].TrackFrames, detections[n].TrackLost);
│       ├── Render outputs
│       │   ├── 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, precisionTypeToStr(net->GetPrecision()), net->GetNetworkFPS());
│       │   │   ├── output->SetStatus(str);
│       │   │   └── if (!output->IsStreaming())
│       │   │       └── break;
│       └── Print out timing info
│           └── net->PrintProfilerTimes();
├── Destroy resources
│   ├── LogVerbose("detectnet:  shutting down...\n");
│   ├── SAFE_DELETE(input);
│   ├── SAFE_DELETE(output);
│   ├── SAFE_DELETE(net);
└── LogVerbose("detectnet:  shutdown complete.\n");
    └── return 0;

4. 参考资料

【1】jetson-inference - Locating Objects with DetectNet

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【python/pytorch】已解决ModuleNotFoundError: No module named ‘torch‘

【PyTorch】成功解决ModuleNotFoundError: No module named torch 一、引言 在深度学习领域&#xff0c;PyTorch作为一款强大的开源机器学习库&#xff0c;受到了众多研究者和开发者的青睐。然而&#xff0c;在安装和使用PyTorch的过程中&#xff0c;有时会遇到一些问题和挑战…

安全测试 之 安全漏洞: ClickHiJacking

1. ClickHiJacking 定义 点击劫持&#xff08;Click Jacking&#xff09;是一种视觉上的欺骗手段&#xff0c;攻击者通过使用一个透明的iframe&#xff0c;覆盖在一个网页上&#xff0c;然后诱使用户在该页面上进行操作&#xff0c;通过调整iframe页面的位置&#xff0c;可以使…

通用高电子迁移率晶体管(HEMT)的差分微变解算方案及分析型模型

来源&#xff1a;A Difference-Microvariation Solution and Analytical Model for Generic HEMTs&#xff08;TED 22年&#xff09; 摘要 这篇论文提出了一种AlGaN/GaN和AlGaAs/GaAs基高电子迁移率晶体管(HEMT)的分析型直流模型。该模型考虑了高栅偏压下势垒层中积累的电荷。…

Nat Commun|直捣黄龙!空间单细胞组学发现外周血靶细胞亚群的组织落脚点

溃疡性结肠炎&#xff08;Ulcerative colitis&#xff0c;UC&#xff09;是一种慢性炎症性肠道疾病&#xff0c;其特征是免疫介导的黏膜炎症和上皮损伤。目前UC的治疗策略已经从单纯的症状缓解转变为更精准的靶向治疗。Vedolizumab&#xff08;VDZ&#xff09;作为一种抗整合素…

短剧系统源码:打造多平台互动娱乐体验

随着科技的不断进步&#xff0c;多平台互动娱乐体验逐渐成为人们日常生活的一部分。短剧系统源码便是在这样的背景下应运而生&#xff0c;它为开发者提供了一套完整的解决方案&#xff0c;以实现PC端、移动端APP、H5网页以及小程序平台的无缝对接和内容共享。本文将详细介绍短剧…

在iPhone上恢复已删除的Safari历史记录的最佳方法

您是否正在寻找恢复 iPhone 上已删除的 Safari 历史记录的最佳方法&#xff1f;好吧&#xff0c;这篇文章提供了 4 种在有/无备份的情况下恢复 iPhone 上已删除的 Safari 历史记录的最佳方法。现在按照分步指南进行操作。 iPhone 上的 Safari 历史记录会被永久删除吗&#xff1…

开关管的导通损耗和开关损耗及MOS管驱动

导通损耗和开关损耗 开关管的损耗带来的问题 ★使得开关管发热&#xff0c;为了降低温度&#xff0c;需要增大散热面积&#xff0c;从而增大了体积和成本。 ★降低了开关电源的效率。 开关管的损耗分为导通损耗和开关损耗 ★导通损耗&#xff1a;在开关管导通时候&#xf…

重庆耶非凡科技揭秘:海外拼多多选品师岗位真相解析

在当今数字化、全球化的浪潮中&#xff0c;跨境电商行业蓬勃发展&#xff0c;越来越多的企业开始寻求拓展海外市场的新机遇。其中&#xff0c;重庆耶非凡科技有限公司作为一家在软件开发和技术服务领域具有深厚实力的企业&#xff0c;其海外拼多多选品师这一职位引发了广泛关注…

计算机网络学习记录 应用层 Day6

你好,我是Qiuner. 为记录自己编程学习过程和帮助别人少走弯路而写博客 这是我的 github https://github.com/Qiuner ⭐️ ​ gitee https://gitee.com/Qiuner &#x1f339; 如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 &#x1f604; (^ ~ ^) 想看更多 那就点个关注吧 我…

如何将AndroidStudio和IDEA的包名改为分层级目录

新版UIAndroidStudio 1、点击项目目录右上角如图所示的三个点点。 2、然后依次取消Hide empty middle package &#xff0c;Flatten package的勾选 3、注意&#xff1a;一定要先取消hide的勾选&#xff0c;不然目录不会完全分级&#xff08;做错了可以反过来重新设置&#x…

[leetcode hot 150]第七十题,爬楼梯(动态规划)

题目&#xff1a; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 爬到第 n 阶楼梯的方法数量等于爬到第 n-1 阶和第 n-2 阶的方法数量之和,即: f(n) f(n-1) f(n-2) 边界条件 还需要考虑边界…

ChatGPT Prompt技术全攻略-入门篇:AI提示工程基础

系列篇章&#x1f4a5; No.文章1ChatGPT Prompt技术全攻略-入门篇&#xff1a;AI提示工程基础2ChatGPT Prompt技术全攻略-进阶篇&#xff1a;深入Prompt工程技术3ChatGPT Prompt技术全攻略-高级篇&#xff1a;掌握高级Prompt工程技术4ChatGPT Prompt技术全攻略-应用篇&#xf…

独著出书的出版流程是怎样的?

独著出书的出版流程一般包括以下几个步骤&#xff1a; 1. 准备书稿&#xff1a;确保书稿内容完整、准确&#xff0c;并符合出版社的要求。 2. 选择出版社&#xff1a;根据书稿的主题和内容&#xff0c;选择合适的出版社。可以考虑出版社的专业性、声誉和出版范围等因素。 3.…

KT142C语音芯片下载语音过连接电脑PC的usb虚拟成U盘拷贝

一、简介 KT142C-sop16语音芯片&#xff0c;下载语音是连接电脑PC的usb虚拟成U盘直接拷贝 下载方式描述 内置的是320K的空间&#xff0c;但是实际的大小&#xff0c;在电脑里面显示&#xff0c;应该是315Kbyte。 打开我的电脑&#xff0c;芯片连接PC之后&#xff0c;自动多出…

常规操作-ArcGIS常用标注技巧

常规操作-ArcGIS常用标注技巧 1、简单的"&“符号&#xff1a;多字段表达只需要用”&"符号&#xff0c;多个字段之间需要空格&#xff0c;空格符号需要加双引号。 表达式为&#xff1a; [字段] & " " & [字段] 2、“VBnewline"应用…

Navi日语社App一款支持日文OCR文字识别提取的应用,功能丰富,支持日语翻译、语音翻译、日文文字转语音等等功能!

如果你正在寻找一款简单好用、功能丰富的日文OCR识别软件&#xff0c;那么推荐你试试《Navi日语社》App&#xff0c;在安卓和苹果手机上&#xff0c;很多应用都支持免费的日语翻译功能&#xff0c;但是支持日文OCR文字识别的软件并不多&#xff0c;针对这一痛点&#xff0c;准橙…

【SpringBoot + Vue 尚庭公寓实战】项目介绍(一)

【尚庭公寓SpringBoot Vue 项目实战】项目介绍&#xff08;一&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】项目介绍&#xff08;一&#xff09;1、项目业务概述2、移动端介绍3、 后台管理系统4、 核心业务流程5、项目技术概述5、数据库设计 1、项目业务概述 …

车联网安全入门——ICSim模拟器使用

文章目录 车联网安全入门——ISCim模拟器使用介绍主要特点&#xff1a;使用场景&#xff1a; 安装使用捕获can流量candumpcansnifferwiresharkSavvyCAN主要特点&#xff1a;使用场景&#xff1a; 重放can报文cansendSavvyCAN 总结 车联网安全入门——ISCim模拟器使用 &#x1f…

2024年科学教育与现代管理国际会议(ICSEMM 2024)

2024 International Conference on Science Education and Modern Management 【1】大会信息 大会地点&#xff1a;中国成都 投稿邮箱&#xff1a;icsemmsub-paper.com 【2】会议简介 2024年科学教育与现代管理国际会议是一次重要的学术交流活动&#xff0c;旨在汇聚全球…

【docker】 /bin/sh: ./mvnw: No such file or directory解决方案.dockerignore被忽略

报错如下&#xff1a;解决方案很简单&#xff0c;但是容易让大家忽视的问题。 > CACHED [stage-1 2/4] WORKDIR /work/ …