ncnn vulkan 以类的方式推理示例

news2024/9/23 3:31:13

ncnn vulkan 以类的方式推理示例

flyfish

环境
ncnn-android-vulkan.zip 20230517
opencv 4.6.0
开发环境Qt 6.2.4
模型 yolov5_62

在这里插入图片描述
构建套件 Clang arm64-v8a

在这里插入图片描述

ndk 25 和api 28版本如下
在这里插入图片描述
头文件

#ifndef YOLOV5GPU_H
#define YOLOV5GPU_H

#include <string>
#include <vector>
#include <algorithm>
// ncnn
#include "layer.h"
#include "net.h"
#include "benchmark.h"
#include <opencv2/opencv.hpp>

struct Object
{
    cv::Rect_<float> rect;
    int label; // class_index
    float prob;
};

class Yolov5GPU
{
public:
    int RGB_; // input image channel order,0 bgr,1 rgb
    bool use_gpu_;
    int load_model();

    int inference(const cv::Mat &bgr, std::vector<Object> &objects);
    void draw_objects(const cv::Mat &bgr, const std::vector<Object> &objects);
public:
    Yolov5GPU();
    ~Yolov5GPU();

private:
    ncnn::Net yolov5_;
    ncnn::UnlockedPoolAllocator g_blob_pool_allocator;
    ncnn::PoolAllocator g_workspace_pool_allocator;

    inline float
    intersection_area(const Object &a, const Object &b);

    void qsort_descent_inplace(std::vector<Object> &faceobjects, int left, int right);

    void qsort_descent_inplace(std::vector<Object> &faceobjects);

    void nms_sorted_bboxes(const std::vector<Object> &faceobjects, std::vector<int> &picked, float nms_threshold);

    inline float sigmoid(float x);

    void generate_proposals(const ncnn::Mat &anchors, int stride, const ncnn::Mat &in_pad, const ncnn::Mat &feat_blob, float prob_threshold, std::vector<Object> &objects);
};

#endif // YOLOV5GPU_H

实现文件

#include "yolov5gpu.h"
#include <iostream>

Yolov5GPU::Yolov5GPU()
{

    ncnn::create_gpu_instance();

    use_gpu_ = true;
    RGB_ = 0; // 默认opencv加载 使用bgr 顺序

    ncnn::Option opt;
    opt.lightmode = true;
    opt.num_threads = 4;
    opt.blob_allocator = &(g_blob_pool_allocator);
    opt.workspace_allocator = &(g_workspace_pool_allocator);
    opt.use_packing_layout = true;

    if (ncnn::get_gpu_count() != 0)
        opt.use_vulkan_compute = use_gpu_;

    yolov5_.opt = opt;

    std::cout << "get_gpu_count():" << ncnn::get_gpu_count() << std::endl;
}
Yolov5GPU::~Yolov5GPU()
{
    g_blob_pool_allocator.clear();
    g_workspace_pool_allocator.clear();
    yolov5_.clear();

    ncnn::destroy_gpu_instance();
}

int Yolov5GPU::load_model()
{

    // init params
    int ret = yolov5_.load_param("yolov5s_6.2.param");
    if (ret != 0)
    {
        // error
        std::cout << "load_param error" << std::endl;
        return -1;
    }

    // init bin

    ret = yolov5_.load_model("yolov5s_6.2.bin");
    if (ret != 0)
    {
        // error
        std::cout << "load_model error" << std::endl;
        return -1;
    }
    return 0;
}
int Yolov5GPU::inference(const cv::Mat &bgr, std::vector<Object> &objects)
{

    const int target_size = 640;
    const float prob_threshold = 0.25f;
    const float nms_threshold = 0.45f;

    int img_w = bgr.cols;
    int img_h = bgr.rows;

    // letterbox pad to multiple of 32

    int w = img_w;
    int h = img_h;
    float scale = 1.f;
    if (w > h)
    {
        scale = (float)target_size / w;
        w = target_size;
        h = h * scale;
    }
    else
    {
        scale = (float)target_size / h;
        h = target_size;
        w = w * scale;
    }

    // w h , is original size now.
    // img_w img_h,is target size now.
    ncnn::Mat in;
    if (RGB_ == 0)
    {
        in = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR2RGB, img_w, img_h, w, h);
    }

    else
    {
        in = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_RGB, img_w, img_h, w, h);
    }

    // pad to target_size rectangle
    // yolov5/utils/datasets.py letterbox
    int wpad = (w + 31) / 32 * 32 - w;
    int hpad = (h + 31) / 32 * 32 - h;
    ncnn::Mat in_pad;
    ncnn::copy_make_border(in, in_pad, hpad / 2, hpad - hpad / 2, wpad / 2, wpad - wpad / 2, ncnn::BORDER_CONSTANT, 114.f);

    // yolov5
    // std::vector<Object> objects;
    {

        const float norm_vals[3] = {1 / 255.f, 1 / 255.f, 1 / 255.f};
        in_pad.substract_mean_normalize(0, norm_vals);

        ncnn::Extractor ex = yolov5_.create_extractor();

        ex.set_vulkan_compute(use_gpu_);

        ex.input("images", in_pad);

        std::vector<Object> proposals;

        // anchor setting from yolov5/models/yolov5s.yaml

        // stride 8
        {
            ncnn::Mat out;
            ex.extract("output", out);

            ncnn::Mat anchors(6);
            anchors[0] = 10.f;
            anchors[1] = 13.f;
            anchors[2] = 16.f;
            anchors[3] = 30.f;
            anchors[4] = 33.f;
            anchors[5] = 23.f;

            std::vector<Object> objects8;
            generate_proposals(anchors, 8, in_pad, out, prob_threshold, objects8);

            proposals.insert(proposals.end(), objects8.begin(), objects8.end());
        }

        // stride 16
        {
            ncnn::Mat out;
            ex.extract("353", out);

            ncnn::Mat anchors(6);
            anchors[0] = 30.f;
            anchors[1] = 61.f;
            anchors[2] = 62.f;
            anchors[3] = 45.f;
            anchors[4] = 59.f;
            anchors[5] = 119.f;

            std::vector<Object> objects16;
            generate_proposals(anchors, 16, in_pad, out, prob_threshold, objects16);

            proposals.insert(proposals.end(), objects16.begin(), objects16.end());
        }

        // stride 32
        {
            ncnn::Mat out;
            ex.extract("367", out);

            ncnn::Mat anchors(6);
            anchors[0] = 116.f;
            anchors[1] = 90.f;
            anchors[2] = 156.f;
            anchors[3] = 198.f;
            anchors[4] = 373.f;
            anchors[5] = 326.f;

            std::vector<Object> objects32;
            generate_proposals(anchors, 32, in_pad, out, prob_threshold, objects32);

            proposals.insert(proposals.end(), objects32.begin(), objects32.end());
        }

        // sort all proposals by score from highest to lowest
        qsort_descent_inplace(proposals);

        // apply nms with nms_threshold
        std::vector<int> picked;
        nms_sorted_bboxes(proposals, picked, nms_threshold);

        int count = picked.size();

        objects.resize(count);

        std::cout << "count:" << count << std::endl;
        for (int i = 0; i < count; i++)
        {

            objects[i] = proposals[picked[i]];

            // adjust offset to original unpadded
            float x0 = (objects[i].rect.x - (wpad / 2)) / scale;
            float y0 = (objects[i].rect.y - (hpad / 2)) / scale;
            float x1 = (objects[i].rect.x + objects[i].rect.width - (wpad / 2)) / scale;
            float y1 = (objects[i].rect.y + objects[i].rect.height - (hpad / 2)) / scale;

            // clip
            x0 = std::max(std::min(x0, (float)(img_w - 1)), 0.f);
            y0 = std::max(std::min(y0, (float)(img_h - 1)), 0.f);
            x1 = std::max(std::min(x1, (float)(img_w - 1)), 0.f);
            y1 = std::max(std::min(y1, (float)(img_h - 1)), 0.f);

            objects[i].rect.x = x0;
            objects[i].rect.y = y0;
            objects[i].rect.width = x1 - x0;
            objects[i].rect.height = y1 - y0;
        }
    }
    return 0;
}
void Yolov5GPU::draw_objects(const cv::Mat &bgr, const std::vector<Object> &objects)
{
    for (size_t i = 0; i < objects.size(); i++)
    {
        const Object &obj = objects[i];

        fprintf(stderr, "%d = %.5f at %.2f %.2f %.2f x %.2f\n", obj.label, obj.prob,
                obj.rect.x, obj.rect.y, obj.rect.width, obj.rect.height);

        cv::rectangle(bgr, obj.rect, cv::Scalar(255, 0, 0), 1);
    }
    return;
}

inline float Yolov5GPU::intersection_area(const Object &a, const Object &b)
{
    cv::Rect_<float> inter = a.rect & b.rect;
    return inter.area();
}

void Yolov5GPU::qsort_descent_inplace(std::vector<Object> &faceobjects, int left, int right)
{
    int i = left;
    int j = right;
    float p = faceobjects[(left + right) / 2].prob;

    while (i <= j)
    {
        while (faceobjects[i].prob > p)
            i++;

        while (faceobjects[j].prob < p)
            j--;

        if (i <= j)
        {
            // swap
            std::swap(faceobjects[i], faceobjects[j]);

            i++;
            j--;
        }
    }

#pragma omp parallel sections
    {
#pragma omp section
        {
            if (left < j)
                qsort_descent_inplace(faceobjects, left, j);
        }
#pragma omp section
        {
            if (i < right)
                qsort_descent_inplace(faceobjects, i, right);
        }
    }
}

void Yolov5GPU::qsort_descent_inplace(std::vector<Object> &faceobjects)
{
    if (faceobjects.empty())
        return;

    qsort_descent_inplace(faceobjects, 0, faceobjects.size() - 1);
}

void Yolov5GPU::nms_sorted_bboxes(const std::vector<Object> &faceobjects, std::vector<int> &picked, float nms_threshold)
{

    picked.clear();

    const int n = faceobjects.size();

    std::vector<float> areas(n);
    for (int i = 0; i < n; i++)
    {
        areas[i] = faceobjects[i].rect.area();
    }

    for (int i = 0; i < n; i++)
    {
        const Object &a = faceobjects[i];

        int keep = 1;
        for (int j = 0; j < (int)picked.size(); j++)
        {
            const Object &b = faceobjects[picked[j]];

            //            if (!agnostic && a.label != b.label)
            //                continue;

            // intersection over union
            float inter_area = intersection_area(a, b);
            float union_area = areas[i] + areas[picked[j]] - inter_area;
            // float IoU = inter_area / union_area
            if (inter_area / union_area > nms_threshold)
                keep = 0;
        }

        if (keep)
            picked.push_back(i);
    }
}

inline float Yolov5GPU::sigmoid(float x)
{
    return static_cast<float>(1.f / (1.f + exp(-x)));
}

void Yolov5GPU::generate_proposals(const ncnn::Mat &anchors, int stride, const ncnn::Mat &in_pad, const ncnn::Mat &feat_blob, float prob_threshold, std::vector<Object> &objects)
{
    const int num_grid = feat_blob.h;

    int num_grid_x;
    int num_grid_y;
    if (in_pad.w > in_pad.h)
    {
        num_grid_x = in_pad.w / stride;
        num_grid_y = num_grid / num_grid_x;
    }
    else
    {
        num_grid_y = in_pad.h / stride;
        num_grid_x = num_grid / num_grid_y;
    }

    const int num_class = feat_blob.w - 5;

    const int num_anchors = anchors.w / 2;

    for (int q = 0; q < num_anchors; q++)
    {
        const float anchor_w = anchors[q * 2];
        const float anchor_h = anchors[q * 2 + 1];

        const ncnn::Mat feat = feat_blob.channel(q);

        for (int i = 0; i < num_grid_y; i++)
        {
            for (int j = 0; j < num_grid_x; j++)
            {
                const float *featptr = feat.row(i * num_grid_x + j);
                float box_confidence = sigmoid(featptr[4]);
                if (box_confidence >= prob_threshold)
                {
                    // find class index with max class score
                    int class_index = 0;
                    float class_score = -FLT_MAX;
                    for (int k = 0; k < num_class; k++)
                    {
                        float score = featptr[5 + k];
                        if (score > class_score)
                        {
                            class_index = k;
                            class_score = score;
                        }
                    }
                    float confidence = box_confidence * sigmoid(class_score);
                    if (confidence >= prob_threshold)
                    {
                        //                        if(class_index>=3 && class_index<=14){
                        //                            int new_label_index=class_index;
                        // yolov5/models/yolo.py Detect forward
                        // y = x[i].sigmoid()
                        // y[..., 0:2] = (y[..., 0:2] * 2. - 0.5 + self.grid[i].to(x[i].device)) * self.stride[i]  # xy
                        // y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i]  # wh

                        float dx = sigmoid(featptr[0]);
                        float dy = sigmoid(featptr[1]);
                        float dw = sigmoid(featptr[2]);
                        float dh = sigmoid(featptr[3]);

                        float pb_cx = (dx * 2.f - 0.5f + j) * stride;
                        float pb_cy = (dy * 2.f - 0.5f + i) * stride;

                        float pb_w = pow(dw * 2.f, 2) * anchor_w;
                        float pb_h = pow(dh * 2.f, 2) * anchor_h;

                        float x0 = pb_cx - pb_w * 0.5f;
                        float y0 = pb_cy - pb_h * 0.5f;
                        float x1 = pb_cx + pb_w * 0.5f;
                        float y1 = pb_cy + pb_h * 0.5f;

                        Object obj;
                        obj.rect.x = x0;
                        obj.rect.y = y0;
                        obj.rect.width = x1 - x0;
                        obj.rect.height = y1 - y0;

                        obj.label = class_index;
                        //                            if(new_label_index>8 && new_label_index<12){
                        //                                obj.label=9;
                        //                            }
                        //                            else if(new_label_index>=12){
                        //                                obj.label=(new_label_index-2);
                        //                            }
                        // obj.label = new_label_index;
                        obj.prob = confidence;
                        objects.push_back(obj);
                        //                        }
                    }
                }
            }
        }
    }
}

调用 方式

#include <iostream>

#include "yolov5gpu.h"

int main()
{
    std::cout << "begin" << std::endl;
    Yolov5GPU model;

    model.load_model();
    std::cout << "load_model succeed" << std::endl;
    std::vector<Object> objects;
    cv::Mat bgr = cv::imread("./test.jpg", cv::IMREAD_COLOR);
    if (!bgr.empty())
    {
        std::cout << " cv::imread succeed" << std::endl;
    }
    else
    {
        std::cout << " cv::imread failed" << std::endl;
    }

    for (int i = 0; i < 5; i++) //tests
    {
        double start_time = ncnn::get_current_time();

        model.inference(bgr, objects);
        std::cout << "inference succeed" << std::endl;
        double elasped = ncnn::get_current_time() - start_time;

        std::cout << "result:" << elasped << std::endl;
    }
    model.draw_objects(bgr, objects);
    cv::imwrite("./result.jpg", bgr);
  

    std::cout << "end" << std::endl;

    return 0;
}

编译配置 CMakeLists.txt

cmake_minimum_required(VERSION 3.5) 

project(yolov5_gpu_test LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(ncnn_DIR ${CMAKE_SOURCE_DIR}/ncnn_gpu/lib/cmake/ncnn)
find_package(ncnn REQUIRED)


include_directories(
    ${CMAKE_SOURCE_DIR}/ncnn_gpu/include
    ${CMAKE_SOURCE_DIR}/ncnn_gpu/include/ncnn
)


set(OpenCV_DIR opencv-mobile-4.6.0-android/sdk/native/jni)


find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

message(STATUS "version: ${OpenCV_VERSION}")
message(STATUS "libraries: ${OpenCV_LIBS}")
message(STATUS "include path: ${OpenCV_INCLUDE_DIRS}")



add_executable(yolov5_gpu_test yolov5gpu.h yolov5gpu.cpp main.cpp)

target_link_libraries(yolov5_gpu_test z dl m log android

      ncnn ${OpenCV_LIBS}

)

完整的代码地址

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

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

相关文章

C#调用Matlab--解决外部引用包问题(全网唯一)

1、好久没写文章了&#xff0c;今天给大家带来的是C#调用matlab程序的解决方案。 2、应用场景&#xff1a;C#调用matlab网上已经有很多文章了&#xff0c;但本文主要解决的是无法调用时的问题。 如当Matlab调用外部包&#xff08;CVX、IPOPT、gurobi、yalmip等优化求解器&…

STM32--DHT11温湿度传感器

本文介绍基于STM32F103实现的DHT11温湿度传感器数据采集及显示&#xff0c;完整代码见文末链接 一、DHT11传感器简介 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术&#xff0c;确保产品具有极高的可…

LabVIEW轿厢电梯控制系统

LabVIEW轿厢电梯控制系统 随着国民经济的快速发展&#xff0c;私家车不再是奢侈的商品&#xff0c;逐渐属于大众。大城市中越来越多的汽车对交通和环境造成了灾难性的影响&#xff0c;尤其是市中心遭受了损失。市中心拥堵和停车困难是两大交通问题。增加停车位以留出更多车辆是…

一个vue3注册表单,自定义element-ui的label样式

<template><div class"form"><div class"backLogin"><div class"text">已有账号&#xff1f;</div><el-button click"toLogin" typeprimary>立即登录</el-button></div><div clas…

elment-ui的Cascader 级联选择器,点击lable 也能选中前面的复选框

直接mounted里加就OK啦 mounted() {// Cascader 级联选择器: 点击文本就让它自动点击前面的input就可以触发选择。setInterval(function() {document.querySelectorAll(.el-cascader-node__label).forEach(el > {el.onclick function() {if (this.previousElementSibl…

解码奇思妙想:揭秘力扣解压缩编码列表的独特解题之道

本篇博客会讲解力扣“1313. 解压缩编码列表”的解题思路&#xff0c;这是题目链接。 题目要返回一个数组&#xff0c;这个数组是多大呢&#xff1f;由于下标是偶数的元素决定了每个数据要写入几次&#xff0c;所以要对这些项求和&#xff0c;就知道答案数组要开多大了。 接着&…

从零开始理解Linux中断架构(13)--Linux中断域

由于计算机系统日益复杂,外设中断数量不断增加,系统可能同时需要多个中断控制器进行级联,中断源需要统一管理,面对这样的状况,Linux对各种中断控制器进行抽象,对如何进行硬件中断号到IRQ number映射关系上进行进一步抽象出通用与设备无关的架构,通用中断处理代码中就有了…

SpringBoot整合FastDFS笔记

SpringBoot整合FastDFS笔记 FastDFS是国人余庆开发的一个的分布式存储系统&#xff0c;github地址是https://github.com/happyfish100/fastdfsFastDFS的特性:1、分组存储&#xff0c;灵活简洁、对等结构&#xff0c;不存在单点2、 文件ID由FastDFS生成&#xff0c;作为文件访问…

CSDN 周赛 60 期

CSDN 周赛 60 期 60期体验判断题单选题填空题编程题1、题目名称:贝博士的论文审阅统计2、题目名称:括号匹配小结60期体验 本次体验极差,编程题第一题完全看不懂。 然后就是,成绩极差,选择、判断、填空题一共40分,仅仅拿到了十分。 嗯。。。。请允许我先唱两句“都选C”…

[SWPUCTF 2021 新生赛] jicao

需要将json的值进行get传参&#xff0c;以及将id的值进行post传参 因此可以构造payload get传参&#xff1a;?json{"x":"wllm"} post传参&#xff1a;idwllmNB

Z世代消费者崛起,品牌如何靠吉祥物IP增强商业变现能力?

Z世代人群逐渐成为消费者最大主力军&#xff0c;对品牌而言&#xff0c;抓住Z世代消费者的心&#xff0c;就等于抓住机遇。Z世代的年轻人更趋向于为“兴趣”买单&#xff0c;将商品的使用价值与情感价值逐渐分离&#xff0c;拥抱更多的文化&#xff0c;崇尚个性潮流、喜欢新鲜事…

Linux——进程间通信——命名管道

目录 一.命名管道 1.1定义与区别 1.2命名管道的原理 1.3命名管道的创建 1.4命名管道的实现 Comm.hpp 头文件&#xff1a; Sever.cc代码(该进程是读取数据的)&#xff1a; Client.cc(该进程是写数据的)&#xff1a; 1.4.2案例测试&#xff1a; 重新执行Sever: 1.4.3案例…

如何学习PHP常用函数和内置库? - 易智编译EaseEditing

要学习PHP的常用函数和内置库&#xff0c;可以按照以下步骤进行&#xff1a; 学习PHP基础知识&#xff1a; 首先&#xff0c;掌握PHP的基础语法和核心概念。了解变量、数据类型、操作符、控制流程、函数等基本概念和语法规则。 查阅官方文档&#xff1a; PHP官方文档是学习P…

el-date-picker类型是datetimerange然后时间选择器的时分错位和el-time-picker 组件时分秒样式错位

第一种&#xff1a; 现象&#xff1a; 原因&#xff1a; 当分辨率过小且使用了px转换成vw的插件的话&#xff0c;存在vw的精确度不一致导致出现错位&#xff0c;【不知道不用vw转换插件会不会这样&#xff0c;但是解决方法应该是通用的】 解决方法&#xff1a; 在全局引入一…

高通 P-sensor 阈值调整

阈值效果debug 距离传感器调试基本没有太多工作量&#xff0c;主要根据整机来调整阈值&#xff0c;选择最合适的 P-Sensor 感应效果。高通平台sensor代码主要在modem侧&#xff0c;阈值设置是在AP侧&#xff0c;对应配置文件一般是&#xff1a; vendor/qcom/proprietary/senso…

【博客679】LVS NAT模式与FULLNAT模式原理与配置差别

LVS NAT模式与FULLNAT模式原理与配置差别 注意&#xff1a; LVS NAT模式是LVS原生的一种工作方式&#xff0c;而FULLNAT是在NAT模式下通过配置SNAT来 实现FULLNAT的&#xff0c;而且配合SNAT这部分是靠我们自己来实现的 1、LVS NAT模式原理与特点 NAT模式的数据包请求流程&…

基于matlab使用校准相机拍摄的两张图像中恢复相机运动并重建场景的3D结构(附源码)

一、前言 运动结构 &#xff08;SfM&#xff09; 是从一组 3-D 图像估计场景的 2-D 结构的过程。此示例演示如何从两个图像估计校准相机的姿势&#xff0c;将场景的三维结构重建为未知比例因子&#xff0c;然后通过检测已知大小的对象来恢复实际比例因子。 此示例演示如何从使…

如何开一家真人手办店?

从目前的情况来看&#xff0c;在3D建模这一个行业里&#xff0c;真人手办算是一个不错的风口&#xff0c;之前在圈子里刮起了一阵浪潮。手办大家都接触过&#xff0c;真人手办简单来说就是把以前手办的角色变成了真人&#xff0c;作为礼物和纪念品再合适不过。 许多人对这个新生…

【软件安装】Linux系统中安装Nginx服务器(Ubuntu系统)

这篇文章&#xff0c;主要介绍Linux系统中安装Nginx服务器&#xff08;Ubuntu系统&#xff09;。 目录 一、Linux安装Nginx 1.1、下载nginx安装包 &#xff08;1&#xff09;第一种方式 &#xff08;2&#xff09;第二种方式 1.2、上传nginx压缩包到Linux服务器 1.3、解压…

新项目搞完啦!!!

大家好&#xff0c;我是鱼皮。 经过了 7 场直播&#xff0c;总时长近 20 小时&#xff0c;我在 自己的编程导航 的第 5 个 全程直播开发 的项目 —— 智能 BI 项目&#xff0c;完结啦&#xff01; 我在这里对该项目做一个简单的总结&#xff0c;希望让更多需要它的同学看到&am…