使用gpu编程时,计算两张图的不同的代码如下,debug了两天了,因为是初学者,怎么也想不出是哪里的问题,导致图像一部分会缺失,不管裁剪多小的图,都会存在y方向的部分缺失,想知道这是什么问题?(ps 假设 cal difference没有错误)
__global__ void Cal_difference_Kernel(const uchar* R_max_tolerance, const uchar* R_min_tolerance, const uchar* I_max_tolerance, const uchar* I_min_tolerance, const uchar* src_image, const uchar* ref_model, uchar *dst, int rows, int cols) {
int x = (threadIdx.x + blockIdx.x * blockDim.x);
int y = (threadIdx.y + blockIdx.y * blockDim.y);
if (x >= cols || y >= rows) {
return;
}
dst[y * cols + x] = cal_difference((int)R_max_tolerance[y*cols+x],(int)R_min_tolerance[y*cols+x],(int)I_max_tolerance[y*cols+x],(int)I_min_tolerance[y*cols+x],(int)src_image[y*cols+x], (int)ref_model[y*cols+x]); //设置dst为0或1 ,初始为0
}
extern "C"
void Cal_difference_gpu(const Mat& ref,const Mat& src,const Mat& result) {
auto t1 = std::chrono::system_clock::now();
cv::cuda::GpuMat ref_model(ref);
cv::cuda::GpuMat src_image(src);
cv::cuda::GpuMat R_max_tolerance(ref.size(), CV_8UC1);
cv::cuda::GpuMat R_min_tolerance(ref.size(), CV_8UC1);
cv::cuda::GpuMat I_max_tolerance(ref.size(), CV_8UC1);
cv::cuda::GpuMat I_min_tolerance(ref.size(), CV_8UC1);
// ...这里省略了一些tolerance计算
cv::cuda::GpuMat Difference(ref.size(), CV_8UC1,Scalar(0));
dim3 block(32, 32);
dim3 grid((ref.rows -1 ) / 32 + 1 , (ref.cols - 1) / 32 +1 ); // 向上取整
Cal_difference_Kernel<<<grid, block>>>(R_max_tolerance.ptr<uchar>(),R_min_tolerance.data,I_max_tolerance.ptr<uchar>(),I_min_tolerance.ptr<uchar>(),src_image.ptr<uchar>(), ref_model.ptr<uchar>(), Difference.ptr<uchar>(), ref.rows, ref.cols);
cudaDeviceSynchronize();
Difference.download(result);
//cudaFree((void*)differ_data);
}
缺失效果如下 : (截了部分图)
引用 皆我百晓生 小程序回复内容作答:
根据提供的代码和缺失效果,问题可能出在以下几个方面:
正确的代码应该是:
dim3 grid((ref.cols - 1) / 32 + 1 , (ref.rows - 1) / 32 +1 );
在修改核函数的内部if语句之前,可以添加以下代码来检查并调整x和y的取值范围:
x = max(min(x, cols - 1), 0);
y = max(min(y, rows - 1), 0);
并且在核函数中使用修正后的x和y的值:
dst[y * cols + x] = cal_difference(...);
这些修正可以帮助确保在计算图像差异时,不会访问超出图像范围的内存空间,从而解决图像部分缺失的问题。
如果问题仍然存在,请提供更多关于图像和计算差异函数(cal_difference
)的详细信息,以便我能够提供更具体的帮助。
你的代码中有一些可能导致图像缺失的问题,你可以尝试以下的排查方案:
cv::cuda::GpuMat
来分配内存。你需要确保这些GpuMat
对象的大小与你的输入图像的大小相同。uchar
,你需要确保你的输入图像的数据类型确实是uchar
。如果输入图像的数据类型与你的核函数期望的类型不同,可能会导致图像的一部分被忽略。Cal_difference_Kernel
,你需要确保所有的参数都传递正确。特别是图像的宽度和高度,你需要确保它们的值是正确的。【以下回答由 GPT 生成】
问题1: 您是使用哪种GPU编程框架(例如CUDA、OpenCL)进行开发的?
回答1: 我正在使用CUDA进行GPU编程。
问题2: 请提供用于调用Cal_difference_gpu
函数的代码片段,以及传递给该函数的参数。
回答2: 这里稍微修改一下您的代码片段,添加了调用Cal_difference_gpu
函数的代码和传递的参数。
#include <iostream>
#include <opencv2/opencv.hpp>
// 函数声明
extern "C" void Cal_difference_gpu(const uchar* R_max_tolerance, const uchar* R_min_tolerance, const uchar* I_max_tolerance, const uchar* I_min_tolerance, const uchar* src_image, const uchar* ref_model, uchar* dst, int rows, int cols);
int main() {
// 读取图像和模型
cv::Mat src_image = cv::imread("src_image.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat ref_model = cv::imread("ref_model.jpg", cv::IMREAD_GRAYSCALE);
// 把图像和模型转换为uchar数组
uchar* src_data = src_image.data;
uchar* ref_data = ref_model.data;
// 定义输出数组
uchar* dst_data = new uchar[src_image.rows * src_image.cols * sizeof(uchar)];
// 调用GPU计算函数
Cal_difference_gpu(nullptr, nullptr, nullptr, nullptr, src_data, ref_data, dst_data, src_image.rows, src_image.cols);
// 打印计算结果
for (int i = 0; i < src_image.rows * src_image.cols; i++) {
std::cout << "dst[" << i << "] = " << (int)dst_data[i] << std::endl;
}
// 释放内存
delete[] dst_data;
return 0;
}
请将src_image.jpg
和ref_model.jpg
替换为您实际使用的图像文件路径。
问题3: 您期望得到什么样的输出?您可以提供一些示例输入和期望的输出吗?
回答3: 由于您的代码没有提供关于cal_difference
函数的实现细节,无法确定具体的期望输出。但可以根据dst
数组的输出来判断是否存在图像部分缺失的问题。如果图像部分缺失,则应该检查您的cal_difference
函数的实现。
问题4: 除了图像部分缺失的问题,您还遇到了其他任何问题吗?
回答4: 目前只能根据提供的代码判断存在图像部分缺失的问题。如果还有其他问题,请提供更多的相关信息,以便进一步帮助解决。
问题可能出在以下几个方面:
线程块大小(blockDim.x)和网格大小(grid)的设置。你可以尝试调整这两个参数的值,以找到最佳的性能和图像质量平衡点。例如,你可以尝试将blockDim.x和grid分别设置为32和(ref.rows - 1) / 32 + 1。
cal_difference函数的实现。确保这个函数能够正确处理输入数据,并返回期望的结果。你可以在GPU上调试这个函数,以确保其正确性。
内存传输问题。在调用Cal_difference_Kernel时,确保R_max_tolerance、R_min_tolerance、I_max_tolerance、I_min_tolerance、src_image和ref_model的数据已经正确传输到GPU内存中。你可以使用cudaMemcpy()函数进行数据传输。
结果存储空间的大小。确保Difference的容量足够存储计算出的差异值。如果结果图像的尺寸非常大,你可能需要增加Difference的容量。
检查是否有其他错误或警告。在编译和运行代码时,仔细检查编译器和运行时的错误和警告信息,以找到潜在的问题。
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
根据您提供的代码和缺失效果的示例图像,我注意到您在调用 CUDA 内核函数 Cal_difference_Kernel
时,可能存在一个错误的索引计算。在计算 x
和 y
索引时,您使用了 threadIdx.x
和 threadIdx.y
以及 blockIdx.x
和 blockIdx.y
,但是在索引计算中,您将 x
与 cols
进行比较,将 y
与 rows
进行比较。
然而,根据您提供的代码和示例图像,您的 grid
大小是 (ref.rows - 1) / 32 + 1, (ref.cols - 1) / 32 + 1
,即网格的行数是 ref.rows
,网格的列数是 ref.cols
。因此,在内核函数中,您应该将 x
与 cols
进行比较,将 y
与 rows
进行比较。
请尝试将以下行代码:
if (x >= cols || y >= rows) {
return;
}
更改为:
if (x >= cols || y >= rows) {
dst[y * cols + x] = 0; // 或者设置其他默认值
return;
}
这样可以确保超出图像范围的线程将设置对应位置的像素值为0或其他默认值,避免出现缺失的问题。
请注意,还有其他可能导致缺失问题的因素,例如内核函数中的计算逻辑或图像的数据传输。如果上述修改仍未解决问题,请提供更多关于 cal_difference
函数的信息以及完整的代码和示例图像,以便能够更深入地帮助您解决问题。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
结合GPT给出回答如下请题主参考
首先,可能是您的图像像素坐标计算有误导致图像部分缺失。
其次,您使用的GPU编程框架是否支持您所使用的操作?例如,如果您的代码使用了CUDA,您需要检查您的显卡是否支持CUDA。
另外,您使用的图像文件的格式是否正确?有些图像格式可能不被某些编程框架支持,导致图像部分缺失。
最后,您可以尝试使用图像处理库(如OpenCV)提供的函数来实现图像比较,这些函数经过了充分的测试和验证,可以避免由于编程错误导致的图像部分缺失问题。
确保 Cal_difference_Kernel 函数的线程块和网格设置正确。你已经计算了 grid 和 block 的值,但是如果 ref.rows 或 ref.cols 不是 32 的倍数,就可能会导致问题。你可以尝试使用较小的块尺寸来进行测试,以查看是否有改善。你的计算似乎依赖于 R_max_tolerance、R_min_tolerance、I_max_tolerance、I_min_tolerance、src_image 和 ref_model 这些图像,如果其中任何一个有越界访问,就会导致问题。