Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opencv 如何在CUDA内核中正确操作CV_16SC3 Mat_Opencv_Cuda - Fatal编程技术网

Opencv 如何在CUDA内核中正确操作CV_16SC3 Mat

Opencv 如何在CUDA内核中正确操作CV_16SC3 Mat,opencv,cuda,Opencv,Cuda,我在使用OpenCV时正在编写CUDA程序。我有一个给定大小(例如1000x800)的空垫子,我使用dataytpe CV_16SC3显式地将其转换为GPUMat。需要在CUDA内核中以这种格式操作图像。然而,试图操纵垫子似乎无法正常工作 我按如下方式调用我的CUDA内核: my_kernel <<< gridDim, blockDim >>>( (unsigned short*)img.data, img.cols, img.rows, img.st

我在使用OpenCV时正在编写CUDA程序。我有一个给定大小(例如1000x800)的空垫子,我使用dataytpe CV_16SC3显式地将其转换为GPUMat。需要在CUDA内核中以这种格式操作图像。然而,试图操纵垫子似乎无法正常工作

我按如下方式调用我的CUDA内核:

    my_kernel <<< gridDim, blockDim >>>( (unsigned short*)img.data, img.cols, img.rows, img.step);
我期待这个小内核样本将所有像素写入白色。然而,在从GPU下载Mat并使用imshow将其可视化后,并非所有像素都是白色的,并且出现了一些奇怪的黑线,这让我相信,不知何故,我正在写入无效的内存地址

我的猜测如下。OpenCV文档声明cv::mat::data返回一个uchar指针。但是,我的Mat有一个数据类型“16U”(据我所知是短的无符号)。这就是为什么在内核启动中我将指针投射到(unsignedshort*)。但这显然是错误的


我应该如何正确地读取和写入内核中的短Mat数据?

首先,输入图像类型应该是
short
,而不是
unsigned short
,因为Mat的类型是
16SC3
(而不是
16UC3

现在,由于图像步长以字节为单位,且数据类型为
short
,因此计算像素索引(或地址)时应考虑这些像素的字节宽度差异。有两种方法可以解决此问题

方法1:
我已经使用方法2很长时间了。这是一种快捷的方法,但后来当我看到某些图像处理库的源代码时,我意识到方法1实际上更便于移植,因为类型的大小可以在不同的平台上变化。

首先,输入图像类型应为
short
而不是
unsigned short
,因为Mat的类型是
16SC3
(而不是
16UC3

现在,由于图像步长以字节为单位,且数据类型为
short
,因此计算像素索引(或地址)时应考虑这些像素的字节宽度差异。有两种方法可以解决此问题

方法1:
我已经使用方法2很长时间了。这是一种快捷方法,但后来当我看到某些图像处理库的源代码时,我意识到方法1实际上更便于移植,因为类型的大小可以在不同的平台上变化。

非常感谢您的帮助!方法2对我有效。我会记住你提到的可移植性问题。非常感谢你的帮助!方法2对我有效。我会记住你提到的可移植性问题。
__global__ void my_kernel( unsigned short* img, int width, int height, int img_step)
{
    int x, y, pixel;
    y = blockIdx.y * blockDim.y + threadIdx.y;
    x = blockIdx.x * blockDim.x + threadIdx.x;
    
    if (y >= height)
        return;
    
    if (x >= width)
        return;

    pixel = (y * (img_step)) + (3 * x);
    
    img[pixel] = 255; //I know 255 is basically an uchar, this is just part of my test
    img[pixel+1] = 255
    img[pixel+2] = 255;

}
__global__ void my_kernel( short* img, int width, int height, int img_step)
{
    int x, y, pixel;
    y = blockIdx.y * blockDim.y + threadIdx.y;
    x = blockIdx.x * blockDim.x + threadIdx.x;
    
    if (y >= height)
        return;
    
    if (x >= width)
        return;

    //Reinterpret the input pointer as char* to allow jump in bytes instead of short
    char* imgBytes = reinterpret_cast<char*>(img);
    
    //Calculate row start address using the newly created pointer
    char* rowStartBytes = imgBytes + (y * img_step); // Jump in byte
    
    //Reinterpret the row start address back to required data type.
    short* rowStartShort = reinterpret_cast<short*>(rowStartBytes);
    
    short* pixelAddress = rowStartShort + ( 3 * x ); // Jump in short
    
    //Modify the image values
    pixelAddress[0] = 255; 
    pixelAddress[1] = 255;
    pixelAddress[2] = 255;

}
my_kernel<<<grid,block>>>( img, width, height, img_step/sizeof(short));