RK3588部署YOLOv8(2):OpenCV和RGA实现模型前处理对比

news2025/3/12 11:25:51

目录

前言

1. 结果对比

1.1 时间对比

1.2 CPU和NPU占用对比

2. RGA实现YOLO前处理

2.1 实现思路

2.2 处理类的声明

2.3 处理类的实现

总结


前言

RK平台上有RGA (Raster Graphic Acceleration Unit) 加速,使用RGA可以减少资源占用、加速图片处理速度。因此,在部署YOLOv8是针对RGA和OpenCV的分别进行了实现,并对性能、速度和资源占用进行对比。


1. 结果对比

1.1 时间对比

总共跑100次计算平均时间。

纯OpenCV实现:

OPencv实现resize+pad
[Convert] Step1: Check input pointer => 0 us
[Convert] Step2: define intermediate Mat => 37 us
[Convert] Step3: cv::resize => 9564 us
[Convert] Step4: create pad_img => 1629 us
[Convert] Step5: compute position => 61 us
[Convert] Step6: copyTo => 340 us
[Convert] Step7: return => 54 us
INFO: image resize time 12.15 ms
INFO: total infer time 22.71 ms: model time is 22.45 ms and postprocess time is 0.26ms
Iteration 100 - time: 35.034000 ms
Total execution time: 3770.930000 ms
Average execution time: 37.709300 ms

纯RGA实现:

RGA实现
[Convert] Step1: Check input pointer => 1 us
[Convert] Step2: Set format/bpp => 92 us
[Convert] Step3: Calculate buffer sizes => 13 us
[Convert] Step4: Define variables => 12 us
[Convert] Step5: Compute border => 13 us
[Convert] Step6: Alloc & memcpy src => 10048 us
[Convert] Step7: Alloc resized buffer => 477 us
[Convert] Step8: Alloc dst buffer => 269 us
[Convert] Step9: importbuffer_fd => 3494 us
[Convert] Step10: wrapbuffer_handle => 80 us
[Convert] Step11: imresize => 2714 us
[Convert] Step12: immakeBorder => 1154 us
[Convert] Step13: copy result => 428 us
[Convert] Step14: cleanup => 2607 us
INFO: image resize time 24.26 ms
INFO: total infer time 22.10 ms: model time is 21.84 ms and postprocess time is 0.26ms
Iteration 100 - time: 46.496000 ms
Total execution time: 4398.143000 ms
Average execution time: 43.981430 ms

总结:

(1)从上可以看到OpenCV最占时间的是resize步骤,需要9~10ms,而RGA只要2~3ms。

(2)但使用RGA,如果图片数据不在DMA缓冲区,则需要进行拷贝,导致耗时太久。

(3)最终,导致RGA实现resize要比OpenCV慢了6~7ms。

1.2 CPU和NPU占用对比

跑单个模型持续推理。

纯OpenCV实现:

CPU占用率:120%~140%

NPU占用率:43%~48%

纯RGA实现:

CPU占用率:50%~60%

NPU占用率:35%~40%

总结:

(1)OPenCV使用CPU多线程计算差值,导致CPU占用率较高

(2)RGA在DMA缓冲区使用硬件计算,减少对CPU依赖。

(3)RGA比OpenCV减少了60%的CPU占用和10%的NPU占用。


2. RGA实现YOLO前处理

参考代码:

[1] https://github.com/airockchip/librga

[2] rga_resize_demo.cpp

[3] rga_padding_demo.cpp

2.1 实现思路

        在DMA缓冲区,每有一个形状,便需要一个CPU指针、句柄和缓冲区,导致分配内存、处理起来极其麻烦,且宽度需要16倍对齐(高度没有要求)、同时还存在着4G范围寻址问题。所以,实际应用要起来还是很麻烦的(尤其是自定义的任意尺寸输入)。

        所以,这里仅使用RGA对合规的图片做resize,再使用OpenCV做pad填充。

        由于工资预算有限,这里仅实现摄像头输入的原图尺寸(宽度满足16倍长,主要以1920×1080为主)的图片的前处理。

补充(实现任意尺寸处理的思路):

(1) 设传入的宽和高为:[H,W],目标宽高(模型输入大小)为:[H_T, W_T],INT_UP表示向上取整函数。
(2) 原16倍宽度 W_16 为: INT_UP(W / 16) * 16,则现将原图先填充(仅右边填充)到尺寸[H, W_16]。
(3) 计算放缩比 R = min(H / H_T, W_16 / W_t)。
(4) 继续计算得到目标放缩尺寸宽度的16倍 W_T_16 为:INT_UP(W_T_16 / 16) * 16。
(5) 然后更新放缩比 R = min(H / H_T, W_T_16 / R / W_T),此过程可能需要迭代。
(6) 得到放缩比 R 后,计算原图真正要填充到的尺寸为:[H_T / R, W_T_16 / R]。
(7) 然后对原图仅做右边和下面的填充,这样就把原图对齐到16倍长(放缩前后均是)。

2.2 处理类的声明

#include <iostream>
#include <memory>
#include <numeric>
#include <vector>
#include <algorithm>
#include "opencv2/opencv.hpp"
#include "common.h"
// 增加RGA库实现pad resize
#include <rga/RgaApi.h>
#include <rga/im2d.hpp>
#include <rga/rga.h>
#include <rga/RgaUtils.h>
#include <dma/dma_alloc.h>
// 打印时间
#include <sys/time.h>
#include <stdint.h>
#include <stdio.h>

// RGA 版本的 Pad Resize 处理类
class ImagePreProcessRGA {
    public:
        // 构造函数:输入图像为 width x height,目标尺寸为正方形 target_size x target_size
        ImagePreProcessRGA(int width, int height, int target_size);
        // 构造函数:输入图像为 width x height,目标尺寸为 target_width x target_height
        ImagePreProcessRGA(int width, int height, int target_width, int target_height);
        // 对输入图像数据进行pad resize处理,返回处理后的图像数据(unique_ptr管理)
        std::unique_ptr<uint8_t[]> Convert(const det_model_input& input);
        // 获取letterbox信息
        const letterbox_t &get_letter_box() { return letterbox_; }
    
    private:
        double scale_;  // 缩放比例
        int input_width_, input_height_;            // 输入图像尺寸
        int real_input_width_, real_input_height_;  // 输入的实际尺寸
        int target_width_, target_height_;          // 目标图像尺寸
        int new_width_, new_height_;                // 缩放后图像的尺寸(填输入的尺寸缩放后,经过填充才能变成目标尺寸)
        int padding_x_, padding_y_;                 // pad的总尺寸(左右、上下)
        letterbox_t letterbox_;     // letterbox信息记录缩放比例及左右/上下填充(一般为居中填充)
};

2.3 处理类的实现

        实现RGB的3通道或者4通道的图片。

// 构造函数1:只传一个target_size,默认目标是正方形
ImagePreProcessRGA::ImagePreProcessRGA(int width, int height, int target_size)
    : input_width_(width), input_height_(height), target_width_(target_size), target_height_(target_size){
    // ------------------【Step1:根据最大边计算放缩比例】---------------------
    // 如果原图是 (width x height),目标是 (target_size x target_size),则 scale = target_size / max(width, height)
    scale_ = static_cast<double>(target_size) / std::max(input_width_, input_height_);

    // ------------------【Step2:计算缩放后尺寸】----------------------------
    new_width_  = static_cast<int>(input_width_  * scale_);
    new_height_ = static_cast<int>(input_height_ * scale_);

    // ------------------【Step3:计算在目标图像中的剩余填充】------------------
    padding_x_ = target_size - new_width_;
    padding_y_ = target_size - new_height_;

    // ------------------【Step4:更新 letterbox】--------------------------
    letterbox_.scale = scale_;
    letterbox_.x_pad = padding_x_ / 2;
    letterbox_.y_pad = padding_y_ / 2;

    // ------------------【可选:打印结果】-----------------------------------
    // printf(">>> After => new_width_=%d, new_height_=%d, scale=%.3f\n", new_width_, new_height_, scale_);
    // printf(">>> padding_x_=%d, padding_y_=%d\n", padding_x_, padding_y_);
}

// 构造函数2:传入独立的target_width和target_height,可能目标不是正方形
ImagePreProcessRGA::ImagePreProcessRGA(int width, int height, int target_width, int target_height)
    : input_width_(width), input_height_(height), target_width_(target_width), target_height_(target_height){
    // ------------------【Step1:分别计算宽高缩放比例】-----------------------
    double width_scale  = static_cast<double>(target_width_)  / input_width_;
    double height_scale = static_cast<double>(target_height_) / input_height_;

    // 取较小的缩放比例
    scale_ = std::min(width_scale, height_scale);

    // ------------------【Step2:计算缩放后尺寸】----------------------------
    new_width_  = static_cast<int>(input_width_  * scale_);
    new_height_ = static_cast<int>(input_height_ * scale_);

    // ------------------【Step3:计算填充大小】------------------------------
    padding_x_ = target_width_  - new_width_;
    padding_y_ = target_height_ - new_height_;

    // ------------------【Step4:更新 letterbox】---------------------------
    letterbox_.scale = scale_;
    letterbox_.x_pad = padding_x_ / 2;
    letterbox_.y_pad = padding_y_ / 2;

    // ------------------【可选:打印结果】-----------------------------------
    // printf(">>> After => new_width_=%d, new_height_=%d, scale=%.3f\n", new_width_, new_height_, scale_);
    // printf(">>> padding_x_=%d, padding_y_=%d\n", padding_x_, padding_y_);
}

// 核心函数:基于RGA对输入图像进行pad resize,并返回处理后的图像数据
std::unique_ptr<uint8_t[]> ImagePreProcessRGA::Convert(const det_model_input& input){
    // -------------------【Step0:在函数开头声明所有变量】-------------------
    // 中间处理函数返回值
    int ret = 0;

    // DMA fd
    int src_dma_fd     = -1;
    int resized_dma_fd = -1;

    // CPU指针
    uint8_t *src_buf     = nullptr;
    uint8_t *resized_buf = nullptr;

    // RGA handle
    rga_buffer_handle_t src_handle     = 0;
    rga_buffer_handle_t resized_handle = 0;

    // RGA buffer
    rga_buffer_t rga_src;
    rga_buffer_t rga_resized;
    memset(&rga_src, 0, sizeof(rga_src));
    memset(&rga_resized, 0, sizeof(rga_resized));

    // 最终的返回结果
    std::unique_ptr<uint8_t[]> final_data;

    // 其他局部变量
    int bpp_src    = 0;
    int bpp_dst    = 3;  // 目标一定3通道
    int src_format = 0;
    int dst_format = RK_FORMAT_RGB_888;

    // 源图大小和resize后大小
    int src_size     = 0;  
    int resized_size = 0;  

    // 用于 pad 的边界
    int left=0, right=0, top=0, bottom=0;

    // 常用114作为灰度
    cv::Scalar pad_color(114,114,114);

    // -------------------【Step1:基础检查】------------------------------------
    if (!input.data || input.width <= 0 || input.height <= 0 || (input.channel != 3 && input.channel != 4)){
        fprintf(stderr, "ERROR: invalid input data or channel.\n");
        return nullptr;
    }

    // 根据通道数决定 bpp & format
    bpp_src    = (input.channel == 4) ? 4 : 3;
    src_format = (input.channel == 4) ? RK_FORMAT_RGBA_8888 : RK_FORMAT_RGB_888;

    // 源图大小
    src_size   = input.width  * input.height  * bpp_src;
    
    // resize后大小
    int out_size_w = new_width_;   // 由构造函数算好
    int out_size_h = new_height_;  // 由构造函数算好
    resized_size = out_size_w * out_size_h * bpp_dst;
    std::unique_ptr<uint8_t[]> resized_cpu(new uint8_t[resized_size]);

    // 用于后面 OpenCV pad
    left   = padding_x_ / 2;
    right  = padding_x_ - left;
    top    = padding_y_ / 2;
    bottom = padding_y_ - top;

    // -------------------【Step2:分配 src_buf, resized_buf】-------------------
    ret = dma_buf_alloc(DMA_HEAP_DMA32_PATH, src_size, &src_dma_fd, (void**)&src_buf);
    if (ret < 0 || !src_buf) {
        fprintf(stderr, "ERROR: alloc src_buf failed.\n");
        return nullptr;
    }

    ret = dma_buf_alloc(DMA_HEAP_DMA32_PATH, resized_size, &resized_dma_fd, (void**)&resized_buf);
    if (ret < 0 || !resized_buf) {
        fprintf(stderr, "ERROR: alloc resized_buf failed.\n");
        goto cleanup;
    }

    // 不考虑16对齐等,只做最原始的 YOLO思路。只需将 input.data 拷贝到 src_buf
    memcpy(src_buf, input.data, src_size);

    // -------------------【Step3:import & wrap】-------------------------------
    src_handle     = importbuffer_fd(src_dma_fd,     src_size);
    resized_handle = importbuffer_fd(resized_dma_fd, resized_size);

    if (!src_handle || !resized_handle) {
        fprintf(stderr, "ERROR: importbuffer_fd failed.\n");
        ret = -1;
        goto cleanup;
    }

    rga_src     = wrapbuffer_handle(src_handle,     input.width,  input.height,  src_format);
    rga_resized = wrapbuffer_handle(resized_handle, out_size_w,   out_size_h,    dst_format);

    // -------------------【Step4:RGA仅做 resize or color convert+resize】-------------------
    if (input.channel == 4) {
        // RGBA => color convert => resized
        IM_STATUS st_cvt = imcvtcolor(rga_src, rga_resized, RK_FORMAT_RGBA_8888, RK_FORMAT_RGB_888);
        if (st_cvt != IM_STATUS_SUCCESS) {
            fprintf(stderr, "ERROR: imcvtcolor failed: %s.\n", imStrError(st_cvt));
            ret = -1;
            goto cleanup;
        }
    }
    else {
        // channel=3 => 直接 resize
        IM_STATUS st_resize = imresize(rga_src, rga_resized, 0, 0, INTER_LINEAR);
        if (st_resize != IM_STATUS_SUCCESS) {
            fprintf(stderr, "ERROR: imresize failed: %s.\n", imStrError(st_resize));
            ret = -1;
            goto cleanup;
        }
    }

    // -------------------【Step5:将 resized_buf 拷回 CPU】-------------------
    // 拿到 resize 后的 RGB 图像数据
    memcpy(resized_cpu.get(), resized_buf, resized_size);

    // -------------------【Step6:用OpenCV进行 pad】-------------------
    {
        // 1) 构造一个 cv::Mat 指向 resized_cpu
        cv::Mat resized_mat(new_height_, new_width_, CV_8UC3, resized_cpu.get());

        // 2) 构造一个 pad_mat (target_height_ x target_width_),初始颜色(114,114,114)
        cv::Mat pad_mat(target_height_, target_width_, CV_8UC3, pad_color);

        // 3) 计算在 pad_mat 中的放置位置
        // left=padding_x_/2, top=padding_y_/2
        cv::Rect roi(left, top, resized_mat.cols, resized_mat.rows);

        // 4) 拷贝 resized_mat 到 pad_mat 对应区域
        resized_mat.copyTo(pad_mat(roi));

        // 5) 将 pad_mat 拷到 final_data
        int final_size = target_width_ * target_height_ * 3; // 3通道
        final_data.reset(new uint8_t[final_size]);
        memcpy(final_data.get(), pad_mat.data, final_size);
    }

    cleanup:
        // -------------------【Step7:释放资源】-------------------
        if (src_handle)     releasebuffer_handle(src_handle);
        if (resized_handle) releasebuffer_handle(resized_handle);
        if (src_buf)     dma_buf_free(src_size,   &src_dma_fd,     src_buf);
        if (resized_buf) dma_buf_free(resized_size,&resized_dma_fd, resized_buf);

        // 若 ret!=0, 返回 nullptr
        if (ret != 0) {
            return nullptr;
        }

        // 否则返回 final_data,即 "pad后" 的图像
        return final_data;
}

总结

这样实现资源占用还是约等于纯RGA实现,在推理单张图的时候,速度还可能更快一些:

RGA-resize+OpenCV-pad:
>>> After => new_width_=640, new_height_=360, scale=0.333
>>> padding_x_=0, padding_y_=24
[Convert] Step1: check => 9 us
   Original Input => width=1920, height=1080, channel=3
   Resize => new_width_=640, new_height_=360
   Pad => target_width_=640, target_height_=384
[Convert] Step2: alloc => 187 us
[Convert] StepFILL => copy input => 6220800 bytes
[Convert] StepFILL => 1709 us
rga_api version 1.10.1_[0]
[Convert] Step3: wrap => src=(1920x1080), resized=(640x360)
[Convert] Step3 => 892 us
[Convert] Step4: imresize => done
[Convert] Step4 => 2294 us
[Convert] Step5: copy resized => 691200 bytes
[Convert] Step5 => 543 us
[Convert] Step6: OpenCV pad => final_size=737280
[Convert] Step6 => 1314 us
[Convert] Step7: cleanup => 648 us
INFO: image resize time 7.64 ms
INFO: total infer time 28.11 ms: model time is 27.93 ms and postprocess time is 0.18ms
Iteration 1 - time: 35.846000 ms
Total execution time: 35.846000 ms
Average execution time: 35.846000 ms

OpenCV:
INFO: image resize time 9.49 ms
INFO: total infer time 23.12 ms: model time is 23.09 ms and postprocess time is 0.03ms
Iteration 1 - time: 32.688000 ms

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

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

相关文章

打造智能钉钉机器人:借助智谱GLM-4-Flash实现高效智能回复(文末附源码)

文章目录 前言一、准备工作&#xff08;一&#xff09;钉钉机器人&#xff08;二&#xff09;智谱 GLM-4-Flash&#xff08;三&#xff09;内网穿透工具 cpolar&#xff08;四&#xff09;需要准备的工具和环境 二、钉钉机器人的创建与配置步骤1&#xff1a;创建钉钉机器人步骤…

使用Mermaid语法绘制的C语言程序从Linux移植到Windows的流程图

以下是使用Mermaid语法绘制的C语言程序从Linux移植到Windows的流程图&#xff1a; graph TDA[开始移植] --> B[代码兼容性检查]B --> C[检查系统调用差异\nfork/exec -> CreateProcess]B --> D[检查文件路径格式\n/ vs \\]B --> E[检查依赖库兼容性\nPOSIX vs …

入门到入土,Java学习 day16(算法1)

利用循环遍历来判断是否相等 二分查找/折半查找 前提条件&#xff1a;数组中的数据有序 每次排除一般的查找范围 用min,max,mid来处理&#xff0c;最大加最小除2&#xff0c;比较&#xff0c;然后得到在中间左边还是右边然后更新最大最小 public class Two {// 二分查找方法…

Vulnhub 靶机 VulnOSv2 write up opendocman cms 32075 sql注入 账号密码 ssh连接 37292.c 脏牛提权

Vulnhub 靶机 VulnOSv2 write up opendocman cms 32075 sql注入 账号密码 ssh连接 37292.c 脏牛提权 一、信息收集 1、首先拿到靶场先扫一下ip arp-scan -l 3、 2、指纹扫描 nmap -sS -sV 192.168.66.178nmap -p- -sV -A 192.168.66.253 PORT STATE SERVICE VERSION 22…

Unity辅助工具_头部与svn

Unity调用者按钮增加PlaySideButton using QQu; using UnityEditor; using UnityEngine; [InitializeOnLoad] public class PlaySideButton {static PlaySideButton(){UnityEditorToolbar.RightToolbarGUI.Add(OnRightToolbarGUI);UnityEditorToolbar.LeftToolbarGUI.Add(OnLe…

DeepLabv3+改进8:在主干网络中添加SIM注意力机制|助力涨点

🔥【DeepLabv3+改进专栏!探索语义分割新高度】 🌟 你是否在为图像分割的精度与效率发愁? 📢 本专栏重磅推出: ✅ 独家改进策略:融合注意力机制、轻量化设计与多尺度优化 ✅ 即插即用模块:ASPP+升级、解码器 PS:订阅专栏提供完整代码 论文简介 在本文中,我们提出了…

电路原理(电容 集成电路NE555)

电容 1.特性&#xff1a;充放电&#xff0c;隔直流&#xff0c;通交流 2.电容是通过聚集正负电荷来存储电能的 3.电容充放电过程可等效为导通回路 4.多电容并联可以把容量叠加&#xff0c;但是多电容串联就不会&#xff0c;只会叠加电容的耐压值。 6.电容充放电时相当于通路&a…

函数式编程的核心

函数式编程 函数式编程&#xff08;funcitonal programming&#xff09;其实是个很古老的概念。 高阶函数和内存分析 函数式一阶公民 函数式编程最鲜明的特点就是&#xff1a;函数式一等公民&#xff0c;指的是函数与其他数据类型一样&#xff0c;处于平等地位&#xff0c;可…

【易康eCognition实验教程】006:在影像上添加文本

在某些情况下&#xff0c;希望能在影像上面显示文本文字&#xff0c;例如&#xff0c;一个地图的名称或者是多时相影像分析的年或月的显示。此外&#xff0c;文本如果作为一个规则集导出的部分则可以被纳入数字影像中。如下图所示&#xff1a; 若要添加文本&#xff0c;在影像视…

C++【类和对象】(超详细!!!)

C【类和对象】 1.运算符重载2.赋值运算符重载3.日期类的实现 1.运算符重载 (1).C规定类类型运算符使用时&#xff0c;必须转换成调用运算符重载。 (2).运算符重载是具有特殊名字的函数&#xff0c;名字等于operator加需要使用的运算符&#xff0c;具有返回类型和参数列表及函数…

如何简单预估大模型运行所需的显存

模型消耗的显存主要来源于模型参数&#xff0c;前向/反向&#xff0c;梯度以及优化器…… 1、为什么显存很重要 显存就是显卡的“仓库”和“高速公路”。 容量越大&#xff0c;能存储的图形数据就越多&#xff0c;就能支持更高分辨率、更高纹理质量的游戏或图形程序。 速度越…

python基础知识补充

一.区分列表、元组、集合、字典&#xff1a; 二.输出&#xff1a; <1>格式化输出字符串&#xff1a; 格式符号转换%s字符串%d有符号的十进制整数%f浮点数%c字符%u无符号十进制整数%o八进制整数%x十六进制整数&#xff08;小写ox&#xff09;%X十六进制整数(大写OX)%e科…

STM32-I2C通信外设

目录 一&#xff1a;I2C外设简介 二&#xff1a;I2C外设数据收发 三&#xff1a;I2C的复用端口 四&#xff1a;主机发送和接收 五&#xff1a;硬件I2C读写MPU6050 相关函数&#xff1a; 1.I2C_ GenerateSTART 2.I2C_ GenerateSTOP 3.I2C_ AcknowledgeConfig 4.I2C…

【脚本】Linux一键扩大虚拟内存的大小

Linux增加虚拟内存其实很简单 就那几个命令&#xff0c;free、mkswap、swapon 但是方便起见我写成了脚本 使用方法 进入你的目录&#xff0c; nano ./install_swap.sh 下面的脚本全文复制&#xff0c;粘贴进去之后&#xff0c;按ctrlx后按y保存 然后运行以下命令 sudo bash …

信号隔离器 0-20mA/0-10V模拟信号隔离模块变送器 一进二出高精度

信号隔离器 0-20mA/0-10V模拟信号隔离模块变送器 一进二出高精度https://item.taobao.com/item.htm?ftt&id766022047828 型号 一进二出 0-20mA 转0-20mA/0-10V MS-C12 一进二出 0-10V 转 0-20mA/0-10V MS-V12 信号隔离器 单组输出 MS-C1/V1 双组输出 MS-C12/V12 用于…

Nat. Methods | scPerturb——单细胞扰动数据的标准化资源与统计分析方法

《Nature Methods》提出scPerturb资源平台&#xff0c;整合44个单细胞扰动数据集&#xff08;涵盖转录组、表观组、蛋白组读值&#xff09;&#xff0c;并通过能量统计量&#xff08;E-statistics&#xff09;量化扰动效应&#xff0c;旨在解决单细胞扰动数据的互操作性差、缺乏…

【易康eCognition实验教程】005:影像波段组合显示与单波段显示

文章目录 一、加载多波段影像二、单波段显示三、彩色显示一、加载多波段影像 二、单波段显示 如果导入的影像数据具有三个或者更多的波段,影像场景将自动以RGB(红绿蓝)模式默认显示,如上图所示。在视图设置(View Settings)窗口中使用单波段灰度显示(Single LayuerGrays…

使用Process Explorer、Dependency Walker和PE信息查看工具快速排查dll动态库因库与库版本不一致导致的加载失败问题

目录 1、问题说明 2、使用Process Explorer查看目标dll动态库有没有动态加载起来 3、使用Dependency Walker查看xxpadll.dll库的库依赖关系&#xff0c;找到xxpadll.dll加载失败的原因 4、使用PE信息查看工具查看目标dll库的时间戳 5、关于xxsipstack2.dll中调用xxdatanet…

Git的命令学习——适用小白版

浅要了解一下Git是什么&#xff1a; Git是目前世界上最先进的的分布式控制系统。Git 和其他版本控制系统的主要差别在于&#xff0c;Git 只关心文件数据的整体是否发生变化&#xff0c;而大多数其他系统则只关心文件内容的具体差异。Git 并不保存这些前后变化的差异数据。实际上…

如何安全处置旧设备?

每年&#xff0c;数百万台旧设备因老化、故障或被新产品取代而被丢弃&#xff0c;这些设备上存储的数据可能带来安全风险。 如果设备没有被正确删除数据&#xff0c;这些数据往往仍可被恢复。因此&#xff0c;安全处置旧设备至关重要。 旧设备可能包含的敏感数据 旧设备中可能…