OpenCV+CUDA学习2---图像灰度化

对于图像灰度化,使用了opencv-cuda实现与完全基于cuda实现,本程序中参考了网上多个教程,主要记录和学习的过程。

目录

1、opencv+cuda实现图像灰度化

2、CUDA实现图像灰度化

3、图像展示

3.1 opencv+cuda

3.2 cuda


1、opencv+cuda实现图像灰度化

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 



int main() {

    cv::Mat img1 = cv::imread("H:\\opencv_project\\opencv_cuda学习\\image\\hist_02.jpg");
    cv::Mat img3;
    cv::cuda::GpuMat cuda_img1, cuda_img2, cuda_img3;
    cuda_img1.upload(img1);


    cv::cuda::cvtColor(cuda_img1,cuda_img3,cv::COLOR_BGR2GRAY);

    cuda_img3.download(img3);

    cv::namedWindow("cuda_gpu", cv::WINDOW_NORMAL);
    cv::imshow("cuda_gpu", img3);
    cv::waitKey(0);
    ====================================================

    return 0;

}

opencv中实现图像灰度化跟之前写法几乎一样,不同的就是数据从cpu拷贝到gup上这个操作,剩下的都差不读。

2、CUDA实现图像灰度化

cuda里面实现图像灰度化需要介绍很多东西了,比如__global__函数

grid、block、thread、。。。

针对程序里面出现的一些名词,给与我自己的理解。

1、uchar3对应的CV_8UC3即三通道图像

2、unsigned char ---CV_8UC1(目前我知道)

3、核 kernel

CUDA执行流程中最重要的一个过程是调用CUDA的核函数来执行并行计算,kernel是CUDA中一个重要的概念。在CUDA程序构架中,主机端代码部分在CPU上执行,是普通的C代码;当遇到数据并行处理的部分,CUDA 就会将程序编译成GPU能执行的程序,并传送到GPU,这个程序在CUDA里称做核(kernel)。设备端代码部分在GPU上执行,此代码部分在kernel上编写(.cu文件)。kernel用__global__符号声明,在调用时需要用<<>>来指定kernel要执行及结构。

4、CUDA是通过函数类型限定词区别在host和device上的函数,主要的三个函数类型限定词如下:

    global:在device上执行,从host中调用(一些特定的GPU也可以从device上调用),返回类型必须是void,不支持可变参数参数,不能成为类成员函数。注意用__global__定义的kernel是异步的,这意味着host不会等待kernel执行完就执行下一步。

    device:在device上执行,单仅可以从device中调用,不可以和__global__同时用。

    host:在host上执行,仅可以从host上调用,一般省略不写,不可以和__global__同时用,但可和__device__同时使用,此时函数会在device和host都编译。

网格 grid

kernel在device上执行时,实际上是启动很多线程,一个kernel所启动的所有线程称为一个网格(grid),同一个网格上的线程共享相同的全局内存空间。grid是线程结构的第一层次。

线程块 block

网格又可以分为很多线程块(block),一个block里面包含很多线程。各block是并行执行的,block间无法通信,也没有执行顺序。block的数量限制为不超过65535(硬件限制)。第二层次。

grid和block都是定义为dim3类型的变量,dim3可以看成是包含三个无符号整数(x,y,z)成员的结构体变量,在定义时,缺省值初始化为1。grid和block可以灵活地定义为1-dim,2-dim以及3-dim结构。

5、 dim3 grid2((imgWidth + block2.x - 1) / block2.x, (imgHeight + block2.y - 1) / block2.y);这其中为什么需要减1,这是因为最大快能有1024个线程,对于N个线程来说,每个块有512的线程,则需要N/512个块,但是如果N不是512的整数倍,那么N除以512会得到一个错误的块数量,比实际需要的少一块,所以减去1再除以num,实际上就是一个除法向上取整的操作

#include "cuda_check.h"
#include 
#include 
#include 
#include 
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include 
#include 

//=================CUDA实现图像灰度化====================
__global__ void BGR2GRAYincuda(uchar3* const d_in, unsigned char* const d_out,
    uint imgheight, uint imgwidth)
{
    const unsigned int idx = blockIdx.x * blockDim.x + threadIdx.x;
    const unsigned int idy = blockIdx.y * blockDim.y + threadIdx.y;

    if (idx < imgwidth && idy < imgheight)
    {
        uchar3 rgb = d_in[idy * imgwidth + idx];
        d_out[idy * imgwidth + idx] = 0.299f * rgb.x + 0.587f * rgb.y + 0.114f * rgb.z;
    }
}




int main()
{
    cv::Mat img1 = cv::imread("H:\\opencv_project\\opencv_cuda学习\\image\\hist_02.jpg");

    int imgHeight = img1.rows;
    int imgWidth = img1.cols;

    int length = imgWidth * imgHeight;

    //============CUDA实现后的传回的图像=======
    cv::Mat grayImg(imgHeight, imgWidth, CV_8UC1, cv::Scalar(255)); 

    //==============创建GPU内存============
    uchar3* d_in1;
    unsigned char* d_out;
    CUDA_CHECK(cudaMalloc((void**)&d_in1, imgHeight * imgWidth * sizeof(char3)));
    CUDA_CHECK(cudaMalloc((void**)&d_out, imgHeight * imgWidth * sizeof(unsigned char)));

    //===========将图像从CPU传入GPU========
    CUDA_CHECK(cudaMemcpy(d_in1, img1.data, imgHeight * imgWidth * sizeof(char3), cudaMemcpyHostToDevice));
   
    //===========3维网格和3维线程块===========
    dim3 grid(1 + (length / (32 * 32 + 1)), 1, 1);      // grid
    dim3 block(32, 32, 1);

    //=========使用2维网格和2维的线程块========
    dim3 block2(16, 16);
    dim3 grid2((imgWidth + block2.x - 1) / block2.x, (imgHeight + block2.y - 1) / block2.y);
    

    //调用核函数
    BGR2GRAYincuda << > > (d_in1, d_out, imgHeight, imgWidth);

    CUDA_CHECK(cudaMemcpy(grayImg.data, d_out, imgHeight * imgWidth * sizeof(unsigned char), cudaMemcpyDeviceToHost));


    //释放GPU内存
    cudaFree(d_in1);
    cudaFree(d_out);
    cv::namedWindow("mm",cv::WINDOW_NORMAL);
    cv::imshow("mm", grayImg);
    cv::waitKey(0);
    return 0;
}

3、图像展示

3.1 opencv+cuda

OpenCV+CUDA学习2---图像灰度化_第1张图片

 

3.2 cuda

OpenCV+CUDA学习2---图像灰度化_第2张图片

 

你可能感兴趣的:(OpenCV+CUDA+GPU,opencv,计算机视觉,人工智能,cuda)