如何在OpenCV 3.4.7中计算CV_32FC1 cv::GpuMat图像的(范围)直方图



我想使用 OpenCV 3.4.7 计算类型 CV_32FC1 的 cv::GpuMat 图像的(范围(直方图。速度优化是我的主要关注点。

我阅读了命名空间 cv::cuda 中直方图函数的文档 (https://docs.opencv.org/3.4.7/d8/d0e/group__cudaimgproc__hist.html(,发现,鉴于 cv::GpuMat 图像是 CV_8U、CV_16U 或 CV_16S 类型的整数值,cv::cuda::histRange 将是首选函数。对于类型为 CV_32FC1 的浮点值 cv::GpuMat 图像,类似的方法是什么?

我能想到的唯一方法是将数据下载到 CPU 内存,执行 CPU 变体 cv::histRange(支持 CV_32F 类型的 cv::Mat(,然后上传回 GPU 内存或在 GPU 内存上进行量化(缩放(和类型转换。

有没有办法规避开销?

感谢@timo的评论,感谢@Gehová的回答。

按照@timo的建议阅读源代码后,我发现CV_32F是受支持的,尽管文档中没有说明。

假设您有一些类型CV_32FC1cv::cuda::GpuMat image_gpu,例如由

cv::cuda::GpuMat image_gpu(cv::Size(image_height, image_width), CV_32FC1);

然后,您可以直接计算范围直方图。我举了一个示例,该示例检测设备上(非恒定值(image_gpu的最小值和最大值,并将这两个值下载到主机,在主机上创建最小值和最大值之间的均匀分布的分箱向量,将该分箱向量上传到设备,然后使用 cv:计算设备上的范围直方图:cuda::histRange((.

// set number of bins
int num_bins = 100;
// detect min and max of image_gpu
double min_val, max_val;
cv::cuda::minMax(image_gpu, &min_val, &max_val);
// create binning vector at host
float bin_width = static_cast<float>(max_val - min_val) / num_bins;
cv::Mat_<float> bin_edges(1, num_bins + 1);
for (int bin_index = 0; bin_index < num_bins + 1; bin_index++)
{
bin_edges.at<float>(0, bin_index) = static_cast<float>(min_val) + bin_index * bin_width;
}
// make the histogram calculation inclusive regarding the range [min_val, max_val]
bin_edges.at<float>(0, num_bins) += 1E-08F;
// upload binning vector from host to device
cv::cuda::GpuMat bin_edges_gpu;
bin_edges_gpu.create(1, num_bins + 1, CV_32FC1);
bin_edges_gpu.upload(bin_edges, cuda_stream);
cuda_stream.waitForCompletion();
cv::cuda::GpuMat absolute_histogram_gpu;
absolute_histogram_gpu.create(1, num_bins, CV_32SC1);
// calculate the absolute histogram of image_gpu at the device using OpenCV's cuda implementation
cv::cuda::histRange(image_gpu, absolute_histogram_gpu, bin_edges_gpu, cuda_stream);
cuda_stream.waitForCompletion();
// download the absolute histogram of image_gpu from device to host
cv::Mat_<int32_t> absolute_histogram(1, num_bins);
absolute_histogram_gpu.download(absolute_histogram, cuda_stream);
cuda_stream.waitForCompletion();

为函数nppiHistogramRange_32f_C1R创建一个包装器。您可以阅读您已经提到的 opencv 函数的代码。

最新更新