C++ 处理图像时出现CUDA错误

C++ 处理图像时出现CUDA错误,c++,image,opencv,cuda,C++,Image,Opencv,Cuda,我试图得到黑白图像作为输出,彩色图像作为输入。我使用OpenCV获取图像并写入输出,CUDA在内核中使图像黑白。我尝试了相同的代码,但是没有OpenCV,它运行得很好。但现在的输出与我真正期望得到的略有不同 我认为CUDA代码需要一些修改才能使用OpenCV。我对它做了一些研究,但没能找到方法。也许有人可以给我一个建议或者修改我的代码,好吗?我真的被这个问题弄糊涂了 __global__ void addMatrix(uchar4 *DataIn, unsigned char *DataO

我试图得到黑白图像作为输出,彩色图像作为输入。我使用OpenCV获取图像并写入输出,CUDA在内核中使图像黑白。我尝试了相同的代码,但是没有OpenCV,它运行得很好。但现在的输出与我真正期望得到的略有不同

我认为CUDA代码需要一些修改才能使用OpenCV。我对它做了一些研究,但没能找到方法。也许有人可以给我一个建议或者修改我的代码,好吗?我真的被这个问题弄糊涂了

   __global__ void addMatrix(uchar4 *DataIn, unsigned char *DataOut)
    {
        int idx = blockIdx.x * blockDim.x + threadIdx.x;
        DataOut[idx] = (DataIn[idx].x + DataIn[idx].y + DataIn[idx].z)/3;
    }

int main() 
{
        cudaDeviceProp deviceProp;
        cudaGetDeviceProperties(&deviceProp, 0);

        char* c = "";
        printf("Input source of image\n Example of right directory file: E:\henrik-evensen-castle-valley-v03.jpg\n Your turn:\n");
        char *tbLEN;
        tbLEN = new char [1024];

        cin.getline(tbLEN,1024);

        cout<< endl << "Your image: " << tbLEN << endl;

        //Data for input image
        IplImage* image;
        image = cvLoadImage(tbLEN, 1);
        int height = image->height;
        int width = image->width;
        int step = image->widthStep;
        int SizeIn = (step*height);
        printf("\nProcessing image\n");
        //Data for output image
        IplImage *image2 = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
        int step2 = image2->widthStep;
        int SizeOut = step2 * height;

        //GPU
        uchar4* DatIn = (uchar4*)image->imageData;
        unsigned char* DatOut = (unsigned char*)image2->imageData;
        uchar4 *datIndev;
        unsigned char *datOutdev;

        printf("Allocating memory on Device\n");
        /* Allocate memory on Device */
        cudaMalloc(&datIndev, SizeIn * sizeof(unsigned char));
        cudaMalloc(&datOutdev, SizeOut * sizeof(unsigned char));

        printf("Copy data on Device\n");
        /* Copy data on Device */
        cudaMemcpy(datIndev, DatIn, SizeIn * sizeof(unsigned char), cudaMemcpyHostToDevice);
        cudaMemcpy(datOutdev, DatOut, SizeOut * sizeof(unsigned char), cudaMemcpyHostToDevice);

        int NumThreadsX = deviceProp.maxThreadsPerBlock;
        int NumBlocksX = (width * height)/NumThreadsX;

        dim3 blocks(NumBlocksX, 1, 1);
        dim3 threads(NumThreadsX, 1, 1);
        addMatrix <<< blocks, threads >>> (datIndev, datOutdev);


        cudaMemcpy(DatOut, datOutdev, SizeOut * sizeof(unsigned char), cudaMemcpyDeviceToHost);
        cvNamedWindow("Imagecolor");
        cvShowImage("Imagecolor", image);

        cvNamedWindow("Gray");
        cvShowImage("Gray", image2);
        const char* filename1 = "CcPwSwMW4AELPUc.jpg";
        printf("Saving an output image\n");
        cvSaveImage( filename1, image2 );
        cudaFree(datOutdev);
        cudaFree(datIndev);
        cvWaitKey(0);
        return 0;
}
\uuuuu全局\uuuuu无效添加矩阵(uchar4*DataIn,unsigned char*DataOut)
{
int idx=blockIdx.x*blockDim.x+threadIdx.x;
DataOut[idx]=(DataIn[idx].x+DataIn[idx].y+DataIn[idx].z)/3;
}
int main()
{
cudaDeviceProp deviceProp;
CudaGetDeviceProperty(&deviceProp,0);
char*c=“”;
printf(“图像的输入源\n右目录文件的示例:E:\henrik-evensen-castle-valley-v03.jpg\n轮到您了:\n”);
char*tbLEN;
tbLEN=新字符[1024];
cin.getline(tbLEN,1024);
coutwidthStep;
int SizeOut=step2*高度;
//GPU
uchar4*DatIn=(uchar4*)图像->图像数据;
无符号字符*数据输出=(无符号字符*)图像2->图像数据;
uchar4*datIndev;
无符号字符*datOutdev;
printf(“在设备上分配内存\n”);
/*在设备上分配内存*/
cudamaloc(&datIndev,SizeIn*sizeof(无符号字符));
cudamaloc(&datOutdev,SizeOut*sizeof(无符号字符));
printf(“在设备上复制数据”);
/*在设备上复制数据*/
cudaMemcpy(datIndev,DatIn,SizeIn*sizeof(无符号字符),cudaMemcpyHostToDevice);
cudaMemcpy(datOutdev、DatOut、SizeOut*sizeof(无符号字符)、cudamemcpyhostodevice);
int NumThreadsX=deviceProp.maxThreadsPerBlock;
int NumBlocksX=(宽度*高度)/NumThreadsX;
dim3块(NumBlocksX,1,1);
dim3螺纹(NumThreadsX,1,1);
addMatrix>(datIndev,datOutdev);
cudaMemcpy(datut、datutdev、SizeOut*sizeof(无符号字符)、cudaMemcpyDeviceToHost);
cvNamedWindow(“图像颜色”);
cvShowImage(“Imagecolor”,图像);
CvNamedwindoww(“灰色”);
cvShowImage(“灰色”,图像2);
const char*filename1=“CcPwSwMW4AELPUc.jpg”;
printf(“保存输出图像\n”);
cvSaveImage(filename1,image2);
cudaFree(datOutdev);
库达弗里(达廷德夫);
cvWaitKey(0);
返回0;
}


这里有几个问题:

  • 您关于四通道数据的假设是不正确的。您的代码将从文件中将三通道BGR映像加载到内存中。因此,您需要将引用从
    uchar4
    更改为
    uchar
    ,然后让每个线程从内核中的源映像加载三个字节

  • 内核本身包含一个潜在的算术错误。三个无符号字符像素值之和可能使无符号字符中间结果溢出,并产生不正确的平均值。计算时应使用较大的类型

  • 综上所述,您的内核应该如下所示:

    __global__ void addMatrix(unsigned char *DataIn, unsigned char *DataOut)
    {
        int idx = blockIdx.x * blockDim.x + threadIdx.x;
        int b = DataIn[3*idx];
        int g = DataIn[3*idx+1];
        int r = DataIn[3*idx+2];
    
        DataOut[idx] = (unsigned char)((b + r + g)/3);
    }
    

    然后您可能会发现您的图像看起来是正确的。

    您可能希望验证图像的实际步长是否为每像素4个通道。乍一看,我会说图像是每像素3字节,因此uchar4不是合适的类型。我很确定OpenCV只是丢弃了alpha通道,所以您的源图像
    cvLoadImage
    中有BGR而不是BGRA数据,带有标志1的将是BGR,所以您有3个通道。。。如果你想使用alpha,它应该是-1(并且图像必须有alpha)。另外,我只是想知道,如果您使用的是的
    c
    函数,为什么会有
    c++
    标记opencv@Generwp没问题,一切都取决于你到底想做什么。OpenCV网页中有一些教程。这可能有助于学习一些初学者的东西。关于alpha部分,它在OpenCV中没有很好地实现,或者我听说。。。。可以在函数的中找到标志选项。另外,OpenCV的一些功能已经在CUDA中:)@Generwp最后一件事,可以在中找到教程和图像处理教程,非常感谢!我现在明白我做错了什么,非常感谢。