当前位置: 首页 > article >正文

树莓派5实战:用NCNN跑通YOLOv5目标检测(附完整代码)

树莓派5实战用NCNN跑通YOLOv5目标检测附完整代码最近在捣鼓树莓派5想在上面跑点“硬核”的视觉应用比如实时目标检测。市面上方案不少但要么太重动辄几百兆的框架塞不进小小的SD卡要么太慢一帧图等上好几秒黄花菜都凉了。折腾了一圈最后把目光锁定在了NCNN和YOLOv5这对组合上。NCNN的轻量和高效配上YOLOv5在精度与速度间的平衡感觉是为树莓派这类嵌入式设备量身定做的。不过从模型准备到最终在派上流畅运行中间有不少坑要踩尤其是性能调优部分直接决定了你的应用是“玩具”还是“工具”。这篇文章我就把自己从零搭建、优化到最终部署的完整过程包括那些容易出错的细节和提升性能的“骚操作”毫无保留地分享出来。无论你是想做个智能门铃、小车避障还是搞点边缘AI的创意项目这套流程应该都能给你省下不少时间。1. 环境准备与基础搭建在树莓派5上玩转深度学习第一步不是急着写代码而是把地基打牢。树莓派5虽然性能相比前代有显著提升配备了更强大的ARM Cortex-A76 CPU但其计算资源和内存尤其是4GB或8GB版本相比桌面级设备依然有限。因此一个干净、高效且针对硬件优化的系统环境至关重要。我强烈推荐使用Raspberry Pi OS (64-bit) Lite版本作为起点。这个版本没有图形桌面资源占用极低能把每一分算力都留给我们的推理任务。通过SSH连接操作即可对于服务器或嵌入式应用来说这才是“专业”的做法。当然如果你需要桌面环境进行图像预览或调试也可以选择带桌面的版本只是要接受性能上的一点妥协。系统烧录并启动后第一件事就是更新软件源并安装核心的编译工具和依赖库。下面这个命令组合是我每次搭建环境必跑的它能确保后续编译NCNN或OpenCV时不会因为缺少某个库而报错。sudo apt update sudo apt upgrade -y sudo apt install -y build-essential cmake git wget unzip sudo apt install -y libopencv-dev libjpeg-dev libpng-dev libtiff-dev sudo apt install -y libvulkan-dev vulkan-tools # 为可选的Vulkan加速做准备注意libopencv-dev安装的是系统仓库中预编译的OpenCV。对于追求极致性能的玩家可以后续从源码编译开启更多优化选项如NEON、VFPv3的OpenCV但这会耗费大量时间。对于初次部署使用预编译版本更快捷。接下来我们需要一个合适的C编译环境。树莓派5的ARM Cortex-A76架构支持ARMv8-A指令集GCC编译器版本最好在8以上。检查一下你的GCC版本gcc --version如果版本较低可以考虑更新到较新的版本。不过Raspberry Pi OS的最新版本通常已经提供了足够新的工具链。环境准备的最后一步是为我们的项目创建一个独立的工作空间。这有助于保持文件结构清晰也方便管理多个项目。mkdir -p ~/projects/raspberrypi_yolov5 cd ~/projects/raspberrypi_yolov5至此一个为深度学习推理优化的基础Linux环境就准备好了。我们避开了图形界面的资源消耗安装了所有必要的开发工具为下一步编译高性能的NCNN推理引擎扫清了障碍。2. 编译与部署NCNN推理引擎NCNN是腾讯优图实验室开源的宝藏框架它的设计哲学深深契合嵌入式场景极致轻量、无第三方依赖、CPU推理高效。在树莓派上使用它通常有两种方式直接安装预编译的包或者从源码编译。为了获得最佳的硬件适配性和开启所有可能的优化比如针对ARM架构的NEON SIMD指令加速我强烈推荐从源码编译。首先获取NCNN的源代码。建议使用git克隆最新的稳定版本或某个特定发布版以确保功能的完整性和稳定性。cd ~/projects/raspberrypi_yolov5 git clone https://github.com/Tencent/ncnn.git cd ncnnNCNN的编译配置非常灵活。树莓派5是ARM64aarch64架构我们可以使用其自带的交叉编译工具链文件也可以直接在派上进行原生编译。原生编译更简单直接也是我最常用的方式。mkdir -p build cd build cmake -DCMAKE_BUILD_TYPERelease -DNCNN_VULKANON -DNCNN_SYSTEM_GLSLANGOFF -DNCNN_BUILD_EXAMPLESON ..这里有几个关键的CMake选项-DCMAKE_BUILD_TYPERelease: 启用编译器优化这是提升性能的关键务必使用。-DNCNN_VULKANON: 开启Vulkan API支持。树莓派5的GPUVideoCore VII驱动正在逐步完善对Vulkan的支持。虽然目前可能还不是最稳定的选择但先编译进去为未来的GPU加速留个后门。-DNCNN_BUILD_EXAMPLESON: 编译官方示例程序。这些示例是极好的学习资料能帮你快速理解API用法。配置完成后就可以开始编译了。使用make -j$(nproc)命令让编译过程充分利用树莓派5的所有CPU核心这能大幅缩短等待时间。make -j$(nproc) sudo make install编译安装完成后NCNN的库文件和头文件会被安装到/usr/local/目录下。你可以通过以下命令验证是否安装成功ls /usr/local/lib/libncnn* ls /usr/local/include/ncnn/如果看到libncnn.a静态库或libncnn.so动态库以及一系列头文件恭喜你推理引擎就位了。为了后续编写代码方便我们最好让系统知道如何找到NCNN的库。如果遇到链接错误可以尝试将库路径加入环境变量export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATH更一劳永逸的方法是创建一个.conf文件让系统在启动时自动加载echo /usr/local/lib | sudo tee /etc/ld.so.conf.d/ncnn.conf sudo ldconfig至此一个为树莓派5量身定制、开启了所有可能加速选项的NCNN推理引擎已经部署完毕。它就像一台高性能的发动机只等我们放入合适的燃料——也就是经过转换的YOLOv5模型。3. YOLOv5模型转换与优化技巧有了NCNN引擎下一步就是准备“燃料”——将训练好的YOLOv5模型转换成NCNN能识别的格式。这个过程就像把汽油精炼成发动机能直接燃烧的形式转换的质量直接决定最终推理的效率和精度。通常我们从PyTorch生态获取YOLOv5模型。你可以使用官方预训练的模型如yolov5s.pt,yolov5m.pt也可以使用自己数据集训练得到的.pt权重文件。模型转换的通用路径是PyTorch (.pt) - ONNX (.onnx) - NCNN (.param .bin)。我建议在一台性能更强的x86机器比如你的开发电脑上完成转换工作因为模型导出和优化可能需要一些计算资源。首先确保你有一个Python环境并安装了必要的包# 在你的开发机上操作 pip install torch torchvision onnx onnx-simplifier pip install ncnn # 用于后续的pnnx工具可选更推荐 # 克隆YOLOv5官方仓库用于导出脚本 git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt步骤一导出为ONNX格式使用YOLOv5官方提供的export.py脚本可以很方便地完成导出。关键参数是--include onnx和--dynamic。--dynamic允许输入尺寸动态变化这在嵌入式设备上调整输入大小时非常有用。python export.py --weights yolov5s.pt --include onnx --dynamic执行后你会得到yolov5s.onnx文件。但直接导出的ONNX模型可能包含一些冗余算子不利于在NCNN上高效推理。步骤二简化与优化ONNX模型这里推荐使用onnx-simplifier工具它能自动优化计算图结构合并冗余算子显著减小模型体积并提升推理速度。python -m onnxsim yolov5s.onnx yolov5s-sim.onnx现在我们得到了一个优化后的yolov5s-sim.onnx文件。对比一下原始文件和简化后文件的大小通常会有可观的缩减。步骤三转换为NCNN格式这是最关键的一步。我们需要使用NCNN提供的转换工具onnx2ncnn。这个工具通常在编译NCNN时生成位于ncnn-root/build/tools/onnx/目录下。将其拷贝到方便使用的地方。# 假设在开发机上也有编译好的ncnn /path/to/ncnn/build/tools/onnx/onnx2ncnn yolov5s-sim.onnx yolov5s.param yolov5s.bin转换成功后你会得到两个文件yolov5s.param: 文本文件描述模型的计算图结构。yolov5s.bin: 二进制文件包含模型的所有权重参数。模型优化进阶技巧直接转换的模型可能还不是最优。为了在树莓派5上获得最佳性能我们还可以进行以下优化FP16量化NCNN支持将模型权重从FP32转换为FP16存储。这几乎不会损失精度但能减少近一半的模型体积并利用ARM处理器的半精度计算单元提升速度。可以使用NCNN提供的ncnnoptimize工具/path/to/ncnn/build/tools/ncnnoptimize yolov5s.param yolov5s.bin yolov5s-opt.param yolov5s-opt.bin 65536参数65536代表使用FP16存储。优化后的yolov5s-opt.param和yolov5s-opt.bin就是最终部署的模型。自定义输入输出名转换后的.param文件中输入和输出层的名称可能是通用的input和output。为了代码清晰你可以用文本编辑器打开.param文件将第一行的输入层名如Input_0改为data将输出层名改为output或你喜欢的名字并在代码中保持一致。选择合适的基础模型YOLOv5有s/m/l/x等多个版本体积和精度递增。对于树莓派5yolov5s或yolov5nnano通常是速度和精度兼顾的最佳起点。下表对比了不同模型在典型输入尺寸下的参数量和相对速度模型版本参数量 (百万)相对推理速度 (树莓派5预估)适用场景YOLOv5n~1.9最快对速度要求极高精度要求稍低YOLOv5s~7.2快通用推荐平衡之选YOLOv5m~21.2中等需要更高检测精度可接受稍慢速度YOLOv5l~46.5慢精度要求高实时性要求不高将优化好的yolov5s-opt.param和yolov5s-opt.bin通过SCP或SD卡拷贝到树莓派5的项目目录中模型的准备工作就全部完成了。4. 编写与调试C推理代码模型和引擎都已就绪现在让我们用C代码将它们串联起来实现完整的检测流程。在嵌入式开发中C能提供最好的性能控制。我们的代码主要分为几个部分加载模型、预处理图像、执行推理、解析输出结果、后处理非极大值抑制NMS以及绘制检测框。首先在项目目录下创建我们的主程序文件main.cpp并开始编写代码。第一部分头文件与全局定义引入必要的头文件并定义一些常量如输入图像尺寸、置信度阈值和NMS阈值。这些参数直接影响检测效果。#include ncnn/net.h #include opencv2/opencv.hpp #include iostream #include vector #include algorithm // 定义YOLOv5的输入尺寸这里使用640x640 const int target_width 640; const int target_height 640; // 置信度阈值低于此值的检测框将被过滤 const float confidence_threshold 0.25f; // 非极大值抑制阈值用于消除重叠框 const float nms_threshold 0.45f; // 假设使用COCO数据集的80个类别 const char* class_names[] { person, bicycle, car, motorcycle, airplane, bus, train, truck, boat, traffic light, fire hydrant, stop sign, parking meter, bench, bird, cat, dog, horse, sheep, cow, elephant, bear, zebra, giraffe, backpack, umbrella, handbag, tie, suitcase, frisbee, skis, snowboard, sports ball, kite, baseball bat, baseball glove, skateboard, surfboard, tennis racket, bottle, wine glass, cup, fork, knife, spoon, bowl, banana, apple, sandwich, orange, broccoli, carrot, hot dog, pizza, donut, cake, chair, couch, potted plant, bed, dining table, toilet, tv, laptop, mouse, remote, keyboard, cell phone, microwave, oven, toaster, sink, refrigerator, book, clock, vase, scissors, teddy bear, hair drier, toothbrush };第二部分定义检测结果结构体和后处理函数我们需要一个结构体来存储每个检测框的信息并实现NMS算法来过滤冗余框。struct Object { cv::Rect_float rect; // 检测框 int label; // 类别ID float prob; // 置信度 }; // 非极大值抑制实现 static void nms_sorted_bboxes(const std::vectorObject objects, std::vectorint picked, float nms_threshold) { picked.clear(); const int n objects.size(); std::vectorfloat areas(n); for (int i 0; i n; i) { areas[i] objects[i].rect.area(); } for (int i 0; i n; i) { const Object a objects[i]; bool keep true; for (int j : picked) { const Object b objects[j]; // 计算IoU float inter_area (a.rect b.rect).area(); float union_area areas[i] areas[j] - inter_area; float iou inter_area / union_area; if (iou nms_threshold) { keep false; break; } } if (keep) { picked.push_back(i); } } }第三部分主函数——加载模型与推理这是代码的核心我们按步骤加载模型、处理图像、运行网络并解析输出。int main(int argc, char** argv) { if (argc ! 3) { std::cerr Usage: argv[0] model.param model.bin std::endl; return -1; } const char* param_path argv[1]; const char* bin_path argv[2]; const char* image_path test.jpg; // 测试图片 // 1. 加载模型 ncnn::Net net; if (net.load_param(param_path) ! 0 || net.load_model(bin_path) ! 0) { std::cerr Failed to load ncnn model! std::endl; return -1; } std::cout Model loaded successfully. std::endl; // 2. 读取并预处理图像 cv::Mat img_bgr cv::imread(image_path); if (img_bgr.empty()) { std::cerr Failed to read image: image_path std::endl; return -1; } int img_w img_bgr.cols; int img_h img_bgr.rows; // 将图像缩放到网络输入尺寸并保持长宽比进行填充letterbox cv::Mat resized; float scale std::min(target_width / (float)img_w, target_height / (float)img_h); int new_w (int)(img_w * scale); int new_h (int)(img_h * scale); cv::resize(img_bgr, resized, cv::Size(new_w, new_h)); int dw target_width - new_w; int dh target_height - new_h; dw / 2; dh / 2; cv::Mat padded; cv::copyMakeBorder(resized, padded, dh, dh, dw, dw, cv::BORDER_CONSTANT, cv::Scalar(114, 114, 114)); // 3. 转换为ncnn::Mat并进行归一化 (除以255) ncnn::Mat in ncnn::Mat::from_pixels(padded.data, ncnn::Mat::PIXEL_BGR, target_width, target_height); in.substract_mean_normalize(0, 1.f/255.f); // 通常YOLOv5只需要除以255 // 4. 创建提取器并执行推理 ncnn::Extractor ex net.create_extractor(); // 设置线程数树莓派5有4个高性能核心可以尝试设置为4 ex.set_num_threads(4); ex.input(data, in); // 注意这里的data需要与.param文件中的输入层名一致 ncnn::Mat out; ex.extract(output, out); // 注意这里的output需要与.param文件中的输出层名一致 // 5. 解析输出 std::vectorObject proposals; // YOLOv5的输出格式为 [num_boxes, 85]其中85 cx, cy, w, h, conf 80个类别的概率 for (int i 0; i out.h; i) { const float* ptr out.row(i); float obj_conf ptr[4]; if (obj_conf confidence_threshold) continue; // 找到最大类别概率 int class_id -1; float cls_conf -1.0f; for (int c 0; c 80; c) { float score ptr[5 c]; if (score cls_conf) { cls_conf score; class_id c; } } float final_score obj_conf * cls_conf; if (final_score confidence_threshold) continue; // 解析框坐标 (cx, cy, w, h) 并转换到原始图像尺寸 float cx ptr[0]; float cy ptr[1]; float w ptr[2]; float h ptr[3]; float x1 (cx - w * 0.5f - dw) / scale; float y1 (cy - h * 0.5f - dh) / scale; float x2 (cx w * 0.5f - dw) / scale; float y2 (cy h * 0.5f - dh) / scale; // 确保坐标在图像范围内 x1 std::max(std::min(x1, (float)(img_w - 1)), 0.f); y1 std::max(std::min(y1, (float)(img_h - 1)), 0.f); x2 std::max(std::min(x2, (float)(img_w - 1)), 0.f); y2 std::max(std::min(y2, (float)(img_h - 1)), 0.f); Object obj; obj.rect cv::Rect_float(x1, y1, x2 - x1, y2 - y1); obj.label class_id; obj.prob final_score; proposals.push_back(obj); } // 6. 应用非极大值抑制 std::vectorint picked; nms_sorted_bboxes(proposals, picked, nms_threshold); // 7. 绘制检测框并输出结果 cv::Mat result_img img_bgr.clone(); for (int idx : picked) { const Object obj proposals[idx]; cv::rectangle(result_img, obj.rect, cv::Scalar(0, 255, 0), 2); char text[256]; sprintf(text, %s %.2f, class_names[obj.label], obj.prob); int baseLine 0; cv::Size label_size cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, baseLine); cv::putText(result_img, text, cv::Point(obj.rect.x, obj.rect.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 1); std::cout Detected: class_names[obj.label] at [ obj.rect.x , obj.rect.y , obj.rect.width , obj.rect.height ] with confidence obj.prob std::endl; } cv::imwrite(result.jpg, result_img); std::cout Detection finished. Result saved to result.jpg std::endl; return 0; }第四部分编译与运行编写一个简单的CMakeLists.txt来管理编译cmake_minimum_required(VERSION 3.10) project(YOLOv5_NCNN_Demo) set(CMAKE_CXX_STANDARD 11) find_package(OpenCV REQUIRED) # 假设ncnn安装在默认路径如果没有可以手动指定 find_package(ncnn REQUIRED) add_executable(yolov5_demo main.cpp) target_link_libraries(yolov5_demo ${OpenCV_LIBS} ncnn)然后进行编译mkdir build cd build cmake .. make -j$(nproc)编译成功后将测试图片test.jpg、模型文件yolov5s-opt.param和yolov5s-opt.bin放在与可执行文件相同的目录运行./yolov5_demo yolov5s-opt.param yolov5s-opt.bin如果一切顺利你将看到控制台输出检测到的物体信息并在当前目录生成一张带有检测框的result.jpg图片。至此一个完整的YOLOv5目标检测程序就在树莓派5上跑起来了。5. 性能调优与实战踩坑指南代码能跑通只是第一步让它在树莓派5上跑得又快又稳才是实战的精华所在。性能调优是一个系统工程涉及模型、代码、系统多个层面。下面是我在多次实践中总结出的有效策略和常见问题的解决方法。1. 输入分辨率与模型剪裁这是提升速度最直接有效的方法。YOLOv5默认输入是640x640但对于一些近距离、大目标的场景比如人脸识别门禁降低到320x320甚至224x224速度能有数倍提升而精度下降在可接受范围内。你需要在模型转换前在导出ONNX时指定--imgsz 320参数。同时代码中的target_width和target_height也要相应修改。2. 多线程推理设置NCNN的Extractor支持设置线程数。树莓派5有4个高性能核心理论上设置为4可以获得最佳性能。但实际测试中由于内存带宽和调度开销有时设置为2或3可能效率更高。这是一个需要根据实际场景微调的参数。ex.set_num_threads(4); // 尝试2, 3, 43. 内存与缓存优化深度学习推理是内存密集型任务。确保树莓派5有足够的可用内存并尽量关闭不必要的后台进程。你可以使用htop命令监控内存和CPU使用情况。此外将模型文件和程序放在高速SD卡甚至USB 3.0的固态硬盘上也能减少加载时间。4. 利用ARM NEON指令集NCNN在编译时默认已开启对NEON的支持这是ARM架构的SIMD指令集能大幅加速浮点计算。确保你的CMake编译选项中没有意外关闭它。你可以通过查看NCNN的编译输出确认是否包含了-mfpuneon等优化标志。5. 性能基准测试与监控要优化先测量。编写一个简单的循环对同一张图片进行多次推理计算平均耗时和帧率(FPS)。#include chrono // ... 在推理循环前后 auto start std::chrono::high_resolution_clock::now(); // 推理代码 auto end std::chrono::high_resolution_clock::now(); std::chrono::durationdouble elapsed end - start; std::cout Inference time: elapsed.count() * 1000 ms std::endl;常见踩坑点与解决方案坑点一模型转换后输出维度不对或结果异常。排查首先检查ONNX模型是否简化成功。然后用Netron工具一个神经网络可视化工具分别打开原始的ONNX模型和转换后的NCNN.param文件对比输入输出层的名称和维度是否一致。确保代码中ex.input()和ex.extract()使用的层名与.param文件完全一致。坑点二推理速度远低于预期。排查检查是否在Release模式下编译的程序cmake -DCMAKE_BUILD_TYPERelease。使用perf或sudo cpufreq-set -g performance命令将CPU频率 governor 设置为性能模式避免动态调频。通过ex.set_num_threads()调整线程数找到最佳点。考虑使用更小的模型如YOLOv5n或更低的输入分辨率。坑点三检测框位置错乱或大小异常。排查这几乎总是预处理或后处理的坐标转换逻辑错误。仔细核对代码中从网络输出坐标(cx, cy, w, h)到原始图像坐标(x1, y1, x2, y2)的转换过程特别是letterbox填充dw,dh和缩放比例scale的计算是否正确。建议用一张简单的、目标居中的图片进行调试并打印出每一步的中间坐标值。坑点四内存不足导致程序崩溃。排查树莓派5的4GB内存看似不少但系统、桌面环境如果有和其他应用会占用一部分。运行推理程序时如果出现std::bad_alloc或段错误可能是内存不足。尝试关闭所有不必要的图形界面和应用。使用sudo dphys-swapfile swapoff sudo dphys-swapfile swapon适当增加交换空间swap但这会影响速度。从根本上还是优化模型大小和输入分辨率。实战建议表格优化方向具体措施预期效果潜在代价模型层面使用YOLOv5n/v5s模型进行FP16量化显著提升速度减少内存占用精度轻微下降输入层面降低输入图像分辨率如640-320大幅提升推理速度对小目标检测能力下降代码层面设置合适线程数优化预处理/后处理逻辑中等程度提升效率增加代码复杂度系统层面CPU调频模式设为performance关闭无关进程稳定且小幅提升增加功耗与发热最后性能调优没有银弹它是一个权衡的艺术。你需要根据具体应用场景是要求实时性30FPS还是可以接受1FPS来调整这些旋钮。我的经验是在树莓派5上使用量化后的YOLOv5s模型输入320x320配合4线程处理单张图片的时间可以稳定在100-200毫秒以内这对于很多边缘计算项目来说已经是一个相当可用的性能了。多试几次找到最适合你那个项目的甜蜜点这个过程本身也充满了乐趣。

相关文章:

树莓派5实战:用NCNN跑通YOLOv5目标检测(附完整代码)

树莓派5实战:用NCNN跑通YOLOv5目标检测(附完整代码) 最近在捣鼓树莓派5,想在上面跑点“硬核”的视觉应用,比如实时目标检测。市面上方案不少,但要么太重,动辄几百兆的框架塞不进小小的SD卡&…...

Web原生数据库工具选型指南:SQLynx vs Navicat在云环境下的真实表现

Web原生数据库工具选型指南:SQLynx vs Navicat在云环境下的真实表现 最近和几个技术团队负责人聊天,话题总绕不开一个痛点:数据库管理工具在云时代好像有点“水土不服”。过去,我们习惯在本地装个客户端,连上数据库就开…...

GTE模型在在线教育中的应用:学习资源智能推荐

GTE模型在在线教育中的应用:学习资源智能推荐 1. 引言 在线教育平台面临着一个共同的难题:如何从海量的学习资源中,为每个学生找到最适合的内容?传统的关键词匹配方式往往力不从心,学生搜索"机器学习入门"…...

Intel(R) Wireless-AC 9560网络适配器故障排查指南(从设备管理器到网络重置)

1. 当你的Wi-Fi突然“消失”:从设备管理器开始诊断 不知道你有没有遇到过这种情况:正用着笔记本电脑,突然发现右下角的Wi-Fi图标不见了,或者它变成了一个地球仪,提示你“未连接”。你点开网络列表,空空如也…...

5分钟快速上手腾讯混元翻译模型HY-MT1.5-1.8B,开箱即用

5分钟快速上手腾讯混元翻译模型HY-MT1.5-1.8B,开箱即用 你是不是也遇到过这样的场景?想给海外客户发一封邮件,对着翻译软件纠结半天,总觉得词不达意;或者想快速翻译一份技术文档,却发现免费的在线工具要么…...

从医疗设备到工业控制:Multisim电路设计的5个实战技巧(以呼叫系统为例)

从医疗设备到工业控制:Multisim电路设计的5个实战技巧(以呼叫系统为例) 很多硬件工程师在从教学案例转向实际工业项目时,总会遇到一个尴尬的境地:仿真跑得风生水起,一到实际打板就问题频出。这中间的鸿沟&a…...

通达OA header伪造漏洞实战:从原理到未授权访问

1. 通达OA身份认证绕过漏洞初探 第一次听说通达OA这个漏洞时,我正在给客户做安全审计。当时发现一个奇怪的现象:明明没有登录,却能直接访问后台管理页面。后来深入研究才发现,原来是header伪造导致的身份认证绕过问题。这个漏洞影…...

国产MCU USB多协议转换器设计与实现

1. 项目概述USB多协议转换器是一种面向嵌入式系统调试、传感器数据汇聚与工业现场通信协同的硬件桥接设备。其核心目标是将单一USB主机接口统一映射为多路异构物理层通信通道,实现上位机对底层多样化外设的集中管控与数据调度。本设计基于国产高性能Cortex-M4F内核M…...

STM32 TM1637数码管驱动:IIC时序解析与Proteus仿真验证

1. 从零开始:为什么选择STM32和TM1637这对“黄金搭档”? 大家好,我是老李,一个在嵌入式领域摸爬滚打了十多年的“老码农”。今天想和大家聊聊一个非常经典且实用的组合:用STM32的GPIO口去驱动TM1637数码管模块。很多刚…...

Ubuntu 22.04 LTS 服务器 SSH 密钥配置与自动化部署实践

1. 从零开始:为什么SSH密钥是服务器管理的基石 如果你刚接触服务器运维,或者还在用密码登录你的Ubuntu 22.04服务器,那今天这篇分享可能会彻底改变你的工作流。我管理过上百台服务器,从早期的密码登录到后来的密钥认证&#xff0c…...

STM32G070多传感器融合终端设计:温湿度/空气质量/称重/RTC一体化嵌入式系统

1. 项目概述本项目是一款集成环境参数监测、实时时钟显示与便携式电子称重功能的嵌入式终端设备,面向嵌入式学习、环境监测原型开发及小型IoT节点应用场景。系统以STM32G070CBT6为主控核心,运行FreeRTOS实时操作系统,通过多任务协同调度实现温…...

探秘RestTemplateBuilder:为何连接超时设置频频‘失效’及最佳实践

1. 从一次深夜告警说起:你的超时设置真的生效了吗? 我记得很清楚,那是一个周五的晚上,正准备下班,突然手机开始疯狂震动。监控系统显示,我们一个核心服务的接口响应时间飙到了60秒以上,大量请求…...

构建城市可信数据空间:从标准到实践的全方位指南

1. 城市数据困局:我们为什么需要一个“可信”的空间? 想象一下,你所在的城市,交通部门掌握着实时车流数据,环保部门监测着空气质量,卫健委管理着医疗资源分布,而商业平台则记录着市民的消费习惯…...

基于AIR001的FRS数字对讲机设计与实现

1. 项目概述本项目是一款基于AIR001主控芯片与SR_FRS_2WUS无线对讲模块构建的便携式数字对讲终端,定位于轻量级、低功耗、高可用性的短距语音通信场景。系统在城市复杂电磁环境下实测通信距离超过1公里,语音清晰可辨,具备完整的频道管理、亚音…...

从CVSS2.0评分到漏洞证书:详解CNVD漏洞评级背后的逻辑

从CVSS2.0评分到漏洞证书:详解CNVD漏洞评级背后的逻辑 在数字化安全领域,漏洞评级体系如同医疗行业的急诊分诊系统,决定了有限资源应当优先分配给哪些威胁。CNVD作为国家级漏洞库,其评级机制直接影响着数千万互联网资产的防御优先…...

⚖️Lychee-Rerank多场景落地:制造业BOM文档检索、电力规程匹配、航空手册查检

Lychee-Rerank多场景落地:制造业BOM文档检索、电力规程匹配、航空手册查检 1. 引言:当精准匹配成为刚需 想象一下,你是一位制造业的工程师,面对一份包含上千个零部件的BOM(物料清单)文档,需要…...

从内网到外网:手把手教你用FFmpeg+RTSP实现远程视频监控(2023最新版)

2023年跨网络视频监控实战:基于FFmpeg与RTSP的高效部署指南 在智能安防需求激增的当下,远程视频监控已成为中小企业、家庭农场乃至个人工作室的刚需配置。传统方案常受限于网络边界,而现代技术栈让内网摄像头穿透NAT成为可能——无需昂贵硬件…...

Linux服务器外网访问失败的5个常见坑点(附详细排查命令)

Linux服务器外网访问失败的5个系统性排查指南 刚部署完项目却发现外网无法访问?这可能是每个Linux运维新手都会遇到的"成人礼"。不同于零散的问题解决,本文将用系统化的排查思路,带你从底层网络原理到实操命令,彻底掌握…...

Dify 2026 API网关安全攻防推演(2024Q4最新CISA红队渗透报告深度解码)

第一章:Dify 2026 API网关安全态势全景概览Dify 2026 版本将API网关安全能力提升至企业级零信任架构标准,全面覆盖认证、授权、流量审计、策略执行与威胁响应五大核心维度。其安全态势不再依赖单点防护组件,而是通过统一策略引擎驱动动态策略…...

原子操作 CAS 与锁实现

原子操作 CAS 与锁实现 文章目录原子操作 CAS 与锁实现1. CPU 缓存架构与缓存一致性1.1 为什么需要 CPU 缓存?1.2 写回策略与缓存不一致问题1.3 缓存一致性协议:MESI 与总线嗅探2. 原子操作:不可分割的执行单元2.1 什么是原子操作&#xff1f…...

商旅MICE平台怎么选?2026高性价比平台推荐|含核心功能测评

2026年中国十大商旅MICE平台综合推荐与深度解析 随着企业数字化转型的加速和全球业务拓展的需求增长,商旅MICE(会议、奖励旅游、会议展览)管理已成为企业战略的重要组成部分。到2026年,中国商旅管理市场预计将突破5000亿规模&…...

本地部署千问大模型

下载千问大模型大家可以从魔搭社区平台,下载各种版本的各种大模型,尽量能在自己的电脑上运行,所以这边下载1.5B的版本下载后的文件夹里的东西不要动即可环境准备在开始之前,先统一环境。本文基于transformersPyTorch,支…...

C# 基于OpenCv的视觉工作流-章34-投影向量

C# 基于OpenCv的视觉工作流-章34-投影向量 本章目标: 一、投影向量;一、 投影向量 投影向量分为行投影、列投影,原理是将各行/行像素值进行汇总统计。 本例中对汇总统计进行求取平均值,截取高出平均值的部分进行数量统计。 OpenCv…...

Using Vulkan -- Queues

应用程序通过 VkQueue 提交工作,通常以 VkCommandBuffer 对象或稀疏绑定的形式提交。 提交到同一个 VkQueue 的命令缓冲区按提交顺序开始执行,但开始后允许独立推进并乱序完成。 提交到不同队列的命令缓冲区彼此之间是无序的,除非使用 VkSe…...

无人机高空工程车辆识别 高清工程车辆识别 高清车辆识别 高清铲车压路机识别 无人机矿场行人识别 深度学习yolo第10558期

工程车辆识别计算机视觉数据集数据集概览 本数据集基于高空视角遥感影像构建,聚焦工程场景目标识别,为目标检测模型提供标准化标注样本,支撑工地监测与工程管理场景应用。项目内容类别数量4类类别名称汽车、人员、工程车1、工程车2图像数量50…...

MySQL的安装和卸载组件

目录安装组件:卸载MySQL的组件手动删除目录检查服务📝前言: 我们前面学习了如何安装MySQL,但如果有一些组件需要再安装或者是卸载,可以通过下面的方法执行这个是:MySQL安装和组件安装🔗 通过搜索…...

告别手动截图!Python+SCPI让示波器自动采集数据

在日常测试工作里,频繁手动操作示波器调节参数、截图、记录数据,不仅效率低下,还容易出现操作失误和数据遗漏。借助Python/Labview/C#SCPI指令实现远程自动化控制,就能让罗德示波器自动完成电压波形采集、界面截图与原始数据保存&…...

【力扣-42. 接雨水】Python笔记

题目回顾题目编号:42 题目名称:接雨水 题目难度:困难 输入示例:height [0,1,0,2,1,0,1,3,2,1] 输出示例:6给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接…...

鸿蒙中 应用的权限:申请授权(三)

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新 鸿蒙应用开发中,当应用需要访问用户的隐私信息或使用系统能力时(如获取位置、使用相机、访问日历等),必须向用户申请授…...

私有知识库问答合规失效真相:当Dify RAG遇上《金融消费者权益保护实施办法》,这2类元数据缺失=自动违规

第一章:私有知识库问答合规失效真相:当Dify RAG遇上《金融消费者权益保护实施办法》,这2类元数据缺失自动违规在金融行业部署基于 Dify 的 RAG(检索增强生成)系统时,仅保障答案准确性和响应速度远不足以满足…...