OpenCV+CUDA 遍历cv::Mat笔记

之前因项目需要,除了用到OpenCV,还要将代码移植到GPU里,今天整理总结一下,防止自己忘记。主要参考以下几篇文章,个人觉得都很有用,尤其是对于小白。
【学习OpenCV】Mat::data指针
OpenCV-Efficient pixel access using cv::Mat::ptr pointer
https://www.cnblogs.com/hustwx/p/8425640.html
cuda练习(一):使用cuda将rbg图像转为灰度图像
CUDA精进之路(三):图像处理——图像灰度化、灰度直方图统计
OpenCV学习(4) Mat的基本操作(1)
【OpenCV & CUDA】OpenCV和Cuda结合编程

总结为以下几条:
1.最重要的概念cv::Mat::data指针
对于最常见的BGR三通道图片来说,cv::Mat::data指针默认是uchar* 类型,用的时候可以用强制类型转换成需要的类型,比如uchar3*。

2.假设cv::Mat image 是一个cv::Vec3b类型的图片,创建一个uchar* 类型的指针 uchar* imagePtr,那么分给imagePtr的空间应该等于image所占用的空间

uchar* imagePtr = (uchar*)malloc(sizeof(uchar) * height * width * 3);//imagePtr是一个超长数组
imagePtr[(i * width + j) * 3 + 0] = image.at<cv::Vec3b>(i,j)[0];
imagePtr[(i * width + j) * 3 + 1] = image.at<cv::Vec3b>(i,j)[1];
imagePtr[(i * width + j) * 3 + 2] = image.at<cv::Vec3b>(i,j)[2];

或者使用cv::Mat::ptr指针取值赋给imagePtr数组

for(int i = 0; i < height; i++)
{
    uchar3* ptr = image.ptr<cv::Vec3b>(i);//创建指针是要注意指针类型要与图片类型对应
    for(int j = 0; j < width; j++)
    {
	imagePtr[(i * width + j) * 3 + 0] = ptr[j].x;
	imagePtr[(i * width + j) * 3 + 1] = ptr[j].y;
	imagePtr[(i * width + j) * 3 + 2] = ptr[j].z;
    }
}

3.创建一个新的cv::Mat image_,与image同样的尺寸和类型,image_.data = imagePtr;
Mat image_(image_size,TYPE,imagePtr);最好是先创建好图片,最后cudaMemcpy的时候直接传入image_.data中。

__global__ void swap_rb_kernel(const uchar3* src,uchar3* dst,int width,int height)
{
    int x = threadIdx.x + blockIdx.x * blockDim.x;
    int y = threadIdx.y + blockIdx.y * blockDim.y;
    
    if(x < width && y < height)
    {
        uchar3 v = src[y * width + x];
        dst[y * width + x].x = v.z;
        dst[y * width + x].y = v.y;
        dst[y * width + x].z = v.x;
    }
}

void swap_rb_caller(const uchar3* src,uchar3* dst,int width,int height)
{
    dim3 block(32,8);
    dim3 grid((width + block.x - 1)/block.x,(height + block.y - 1)/block.y);
    
    swap_rb_kernel<<<grid,block,0>>>(src,dst,width,height);
    cudaThreadSynchronize();
}

int main()
{
    Mat image = imread("lena.jpg");
    imshow("src",image);
    
    size_t memSize = image.cols*image.rows*sizeof(uchar3);
    uchar3* d_src = NULL;
    uchar3* d_dst = NULL;
    cudaMalloc((void**)&d_src,memSize);
    cudaMalloc((void**)&d_dst,memSize);
    cudaMemcpy(d_src,image.data,memSize,cudaMemcpyHostToDevice);
    
    swap_rb_caller(d_src,d_dst,image.cols,image.rows);
    
    cudaMemcpy(image.data,d_dst,memSize,cudaMemcpyDeviceToHost);
    imshow("gpu",image);
    waitKey(0);
    
    cudaFree(d_src);
    cudaFree(d_dst);
    return 0;
}

4.通过对以下几行代码进行测试:

uchar3 u3_arr[10]; uchar3* p2_arr = u3_arr; //p2_arr 转换成 uchar* 之后好使
uchar u_arr[30]; uchar* p_arr = u_arr; //p_arr 转换成 uchar3* 之后不好使,没有规律
cv::Mat image1(10, 10, CV_8UC3, cv::Scalar(100, 255, 0)); //image1.data 转换成 uchar3* 之后好使
cv::Mat image2(10, 10, CV_8UC1, cv::Scalar(66)); //image2.data 转换成 uchar3* 之后不好使

进行uchar3* 和uchar* 反复进行强制类型转换测试,
猜测:如果image是CV_8UC3类型的,那么将指针image.data强制类型转换成uchar3* 之后,(uchar3*)image.data是可以正常使用(包括解引和传递进d_src)的。
相邻地址差12,目前不知道为什么(sizeof(uchar3) = 3)。
如果image是CV_8UC1类型的,那么将指针image.data强制类型转换成uchar3* 之后,(uchar3*)image.data是不可以正常使用的。

其实,如果直接用image.data传给d_in,然后输出d_out也可以是uchar3* 类型

//此时d_in是uchar* 类型
d_out[i * width + j].x = d_in[(i * width + j) * 3 + 0];
d_out[i * width + j].y = d_in[(i * width + j) * 3 + 1];
d_out[i * width + j].z = d_in[(i * width + j) * 3 + 2];
//此时d_in是uchar3*类型
d_out[i * width + j].x = d_in[i * width + j].x;
d_out[i * width + j].y = d_in[i * width + j].y;
d_out[i * width + j].z = d_in[i * width + j].z;
//传给uchar3*类型的h_out
cudaMemcpy(h_out, d_out, sizeof(uchar3) * width * height, cudaMemcpyDeviceToHost);
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Jetson是一款由NVIDIA开发的嵌入式计算平台,它具有高性能的GPU和专门用于AI和机器学习的硬件加速功能。而OpenCV(Open Source Computer Vision Library)是一个广泛使用的计算机视觉库,它提供了丰富的图像和视频处理功能。 当在Jetson上使用OpenCV时,有时会遇到"import cv2 Modulenotfounderror: no module named 'cv2'"的错误。这个错误通常表示系统没有找到cv2模块,导致无法引入OpenCV库。 解决此问题的方法如下: 1. 检查OpenCV是否正确安装:首先,确保已在Jetson上正确安装了OpenCV库。可以通过在终端中运行"sudo apt-get install python3-opencv"命令来安装。 2. 检查Python环境:确保在使用OpenCV的Python脚本中使用的是正确的Python解释器。有时候系统中同时存在多个Python版本,需要确保使用的是与OpenCV库相兼容的Python版本。 3. 检查库路径:打开Python交互式终端,并输入以下命令: ``` import sys print(sys.path) ``` 确保OpenCV库所在的路径在sys.path中被正确添加。 4. 检查库名称:有时候,在不同的平台上,OpenCV库的名称可能略有不同,可能是"cv2"或其他名称。请检查您的代码中是否使用了正确的库名称。 5. 重新安装OpenCV:如果以上方法都没有解决问题,可以尝试重新安装OpenCV库。可以通过重新运行安装命令,或者手动下载OpenCV源代码进行编译安装。 总之,"import cv2 Modulenotfounderror: no module named 'cv2'"错误表示系统无法找到cv2模块,导致无法引入OpenCV库。通过上述方法检查安装、Python环境、库路径等问题,可以解决此错误并成功引入cv2模块。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值