CUDA项目技术报告 RGB2Grey 山东科技大学并行程序设计

本文主要是介绍CUDA项目技术报告 RGB2Grey 山东科技大学并行程序设计,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Technical Record&Report for CUDA_RGB2Grey Project

Copyright© workgroup41 All Rights Reserved.
Authored by ZLT - Science and Technology of Intelligence

交流使用,禁止转载

文章目录

      • Technical Record&Report for CUDA_RGB2Grey Project
        • 〇. 硬件平台搭建
        • 一. 开发环境搭建
          • 前置芝士
          • 实践过程
        • 二、交叉编译
          • 前置芝士:
        • 三、代码实现
        • 四、运行效果
      • 参考资料

〇. 硬件平台搭建

测试平台使用Nvidia Jetson nano B02 4GB版本开发板,选择原因如下:

  1. 带有GPU,满足project条件;
  2. 功耗低,最大功耗模式TDP仅有10w,散热需求低,不必担心噪音问题;
  3. 便携,方便跑路

缺点也有不少,比如:

  1. 性能差,但是毕竟边缘计算设备,而且只卖100$,还要啥自行车;
  2. 原生只支持TF卡作为存储器,IO性能低(但是可以魔改,挂载nvme SSD);
  3. 这只arm处理器挑食

就是按照Nvidia官方教程进行系统烧录,按步骤走完,鉴于手头没有多余的卡,用了一张32GB的普通闪迪作为代替,整个过程由于是成熟产品因此非常顺利,直接进大眼睛背景的Ubuntu桌面。

一. 开发环境搭建
前置芝士
  • OpenCV
  • NVCC
  • CMake
实践过程

首先,此项目的核心需求:cuda和opencv
首先由于开发板自带nvcc开发环境,故不需要单独安装,直接使用指令查看:

nvcc -V

即可看到当前可用版本。

在此项目中opencv的作用仅限于打开及存储图片,因此选择直接安装最熟悉的opencv3.4.3
安装过程:

  1. 解压

     unzip opencv-3.4.3.zipunzip opencv_contrib-3.4.3.zip
    
  2. 生成makefile,新建build文件夹准备编译:

     cd opencv-3.4.3mkdir buildcd build
    
  3. 执行cmake:

    cmake -DCMAKE_INSTALL_PREFIX=/usr/local \-DCMAKE_BUILD_TYPE=Release \-DOPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-3.4.3/modules \-DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-10.2 \-DCUDA_ARCH_BIN=5.3 \-DCUDA_ARCH_PTX="" \-DBUILD_PNG=OFF \-DBUILD_TIFF=OFF \-DBUILD_TBB=OFF \-DBUILD_JPEG=OFF \-DBUILD_JASPER=OFF \-DBUILD_ZLIB=OFF \-DBUILD_EXAMPLES=ON \-DBUILD_opencv_java=OFF \-DBUILD_opencv_python2=OFF \-DBUILD_opencv_python3=ON \-DENABLE_PRECOMPILED_HEADERS=OFF \-DWITH_OPENCL=OFF \-DWITH_OPENMP=OFF \-DWITH_FFMPEG=ON \-DWITH_GSTREAMER=OFF \-DWITH_GSTREAMER_0_10=OFF \-DWITH_CUDA=ON \-DWITH_GTK=ON \-DWITH_VTK=OFF \-DWITH_TBB=ON \-DWITH_1394=OFF \-DWITH_OPENEXR=OFF \-DINSTALL_C_EXAMPLES=ON \-DINSTALL_TESTS=OFF \..
  4. 编译

     make -j4
    

使用全部4个核心进行编译,但即使如此还是很慢
特别的,在这台开发板上,编译会出很多问题:

  • fatal error: boostdesc_bgm.i: No such file or directory
    这是由于其中几个库被墙无法成功下载,解决方法是在网上找到资源手动添加到相应目录下;
  • fatal error: opencv2/xfeatures2d/cuda.hpp: No such file or directory
    这类错误在进度70%后就会频繁出现,特别是到了97%甚至99%的时候(没事儿,心态很棒,手动微笑)
    解决办法也很暴力,错误原因是出错的代码中找不到文件,只需要把include里的相对路径改成绝对路径就行了,至于具体要改哪个代码,改成什么路径,抛出的错误中会告诉我们。
  • 这一步是安装过程中最难的,需要解决上述问题的无数次重复出现,但还好最后成功了
  1. 安装

     sudo make install
    
  2. 这时就可以高兴的查看安装情况了!

    opencv版本查看:

     pkg-config --modversion opencv
    
二、交叉编译
前置芝士:
  • 静态库
  • //动态库
  • CMake

经过研(mo)究(yu)发现,实现交叉编译的方法很多,但总体思想是将.cu文件编译出的东西,作为最终编译出的可执行程序的链接依赖。
我们使用gcc/g++编译c/c++部分代码,nvcc编译cuda代码部分
将cuda部分写成接口:
void API(){…}
在c/c++代码中通过添加接口声明:
extend “C” void API(){…}
在了解了静态库和动态库后,发现可以使用cmake来将这些命令制作成CMakeList来方便的编译;将cuda部分作为一个项目并制作为库,由主项目调用。
这里选择了将cuda项目生成静态库,写在cuda的CMakeLists.txt中。
CMakeLists中的编译选项使用了文末链接中的写法,具体原理参考CMake手册
目录树:

RGB2Grey|____ main.cpp|____ CMakeLists.txt|____ cuda|____ foo.cuh|____ foo.cu|____ CMakeLists.txt
三、代码实现
  • main.cpp:

图像相关:读取彩色图片为三通道8bit位图(8UC3),保存该三阶张量使用cv::Mat,由于uchar类型就是8位无符号数据类型,因此这张图片在内存中是这样 ( w i d t h ∗ h e i g h t ) ∗ 3 ∗ u n s i g n e d c h a r (width * height) *3* unsigned char (widthheight)3unsignedchar,在cuda的库中有uchar3类型,可以表示每一个像素(整张图也就是 ( w i d t h ∗ h e i g h t ) ∗ u c h a r 3 (width * height)*uchar3 (widthheight)uchar3)但在当前main之下没有调用cuda库,因此避免出现,只需要将Mat.data作为实参丢进useCUDA函数即可;

注:8bit色深,直观来说是我们在PS里选取颜色时,那个三元组,例如 ( 255 , 255 , 255 ) (255,255,255) (255,255,255)表示白色,对于其中任意一元,它的取值范围是0~255共 256 = 2 8 256 = 2^8 256=28个数值,也就是从黑到白分了256个档(叫做灰度),此时,需要8个bit用来存储这一个灰度值;**回到三元组来,**三个通道(RGB)每一个都是8bit,那么总共就是3*8bit,也就是uchar3类型(见下方代码)。用微积分的极限思想来理解一下,如果我们只有1bit也就是2个数值来表示,那么只能从黑到白划分0和1两个灰度,就是只有黑和白(叫做二值图);若是2bit,那就是4个灰度,黑白之间多了深浅两个灰色,以此类推。因此,bit数越大,黑白过渡越细腻,对应的图片显示效果越棒,同时数据量也越大,这就是为什么显示器10bit的比8bit贵得多,相机能达到12bit,电影机14bit甚至更高(它贵得有理)

//uchar3定义方式
struct uchar3{unsigned char x, y, z;//unsigned char为8bit无符号数据类型
}
 | 方法 |     功能|| :-- | --------|| cv::imwrite()   |   保存图片序列,第一个参数是string类型作为保存路径,第二个是内存数据(Mat类型)|| cv::Mat    |   读入图片保存类型,在这里我们可以用uchar*传参|处理图像序列部分代码:string first_file = "/home/zlt/cvcvcv/cross_compiler_rgb2grey/img/%6d.jpg";VideoCapture sequence(first_file);Mat srcImage;int frameID = 0;while(2){sequence >> srcImage;frameID++;if(srcImage.empty()) break;const uint imgheight = srcImage.rows;const uint imgwidth = srcImage.cols;Mat grayImage(imgheight, imgwidth, CV_8UC1, Scalar(0));grayImage.data = useCUDA(srcImage.data, imgheight, imgwidth);//the type of 'srcImage.data' is 'unsigned char'String SaveName = "/home/zlt/cvcvcv/cross_compiler_rgb2grey/out/" + to_string(frameID) + ".jpg";imwrite(SaveName, grayImage);}cout << "End of Sequence" << endl;
  • foo.cu中的useCUDA()函数:
    用uchar*指针,没有出错(
    后面两个是图片高度和宽度

      unsigned char* useCUDA(uchar* inn, unsigned int imgheight, unsigned int imgwidth)
    

开d_in和d_out指向显存空间,d_return指向内存空间作为返回的灰度图像(in是三阶张量,用uchar3;out是一阶张量,用uchar)

    uchar* d_out;//gpumemoryuchar* d_return;//memoryuchar3* d_in;

使用相应类型开存储空间

    cudaMalloc((void**)&d_in, imgheight * imgwidth * sizeof(uchar3));cudaMalloc((void**)&d_out, imgheight * imgwidth * sizeof(unsigned char));d_return = new uchar[imgheight * imgwidth];

开显存、拷显存、核函数、拷回内存,和前面的作业同理;
注意:彩色图像是三通道

  • foo.cuh:
    声明前面加上 extern "C"
  • 核函数:
    就是个矩阵数乘而已,比作业里的矩阵相乘还简单
四、运行效果

我们顺手使用MOT-20数据集作为测试图像,图像大小1920*1080,选取了其中的150帧进行输入,如期得到了结果。
使用nvprof进行分析:
在这里插入图片描述

输出图像序列:
在这里插入图片描述

参考资料

[1] Jetson Nano 从头配置OpenCV+CUDA+QT完整流程
[2] nvcc gcc g++混合编译器编程
[3] CUDA编译(二)—用CMake混合编译C++与cuda

这篇关于CUDA项目技术报告 RGB2Grey 山东科技大学并行程序设计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/437291

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

一文教你如何将maven项目转成web项目

《一文教你如何将maven项目转成web项目》在软件开发过程中,有时我们需要将一个普通的Maven项目转换为Web项目,以便能够部署到Web容器中运行,本文将详细介绍如何通过简单的步骤完成这一转换过程... 目录准备工作步骤一:修改​​pom.XML​​1.1 添加​​packaging​​标签1.2 添加

tomcat多实例部署的项目实践

《tomcat多实例部署的项目实践》Tomcat多实例是指在一台设备上运行多个Tomcat服务,这些Tomcat相互独立,本文主要介绍了tomcat多实例部署的项目实践,具有一定的参考价值,感兴趣的可... 目录1.创建项目目录,测试文China编程件2js.创建实例的安装目录3.准备实例的配置文件4.编辑实例的

springboot集成Deepseek4j的项目实践

《springboot集成Deepseek4j的项目实践》本文主要介绍了springboot集成Deepseek4j的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录Deepseek4j快速开始Maven 依js赖基础配置基础使用示例1. 流式返回示例2. 进阶

SpringBoot项目启动报错"找不到或无法加载主类"的解决方法

《SpringBoot项目启动报错找不到或无法加载主类的解决方法》在使用IntelliJIDEA开发基于SpringBoot框架的Java程序时,可能会出现找不到或无法加载主类com.example.... 目录一、问题描述二、排查过程三、解决方案一、问题描述在使用 IntelliJ IDEA 开发基于

SpringBoot项目使用MDC给日志增加唯一标识的实现步骤

《SpringBoot项目使用MDC给日志增加唯一标识的实现步骤》本文介绍了如何在SpringBoot项目中使用MDC(MappedDiagnosticContext)为日志增加唯一标识,以便于日... 目录【Java】SpringBoot项目使用MDC给日志增加唯一标识,方便日志追踪1.日志效果2.实现步

Ubuntu中Nginx虚拟主机设置的项目实践

《Ubuntu中Nginx虚拟主机设置的项目实践》通过配置虚拟主机,可以在同一台服务器上运行多个独立的网站,本文主要介绍了Ubuntu中Nginx虚拟主机设置的项目实践,具有一定的参考价值,感兴趣的可... 目录简介安装 Nginx创建虚拟主机1. 创建网站目录2. 创建默认索引文件3. 配置 Nginx4

SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法

《SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法》本文主要介绍了SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法,具有一定的参考价值,感兴趣的可以了解一下... 目录方法1:更改IDE配置方法2:在Eclipse中清理项目方法3:使用Maven命令行在开发Sprin