我想找到GPUMat的平均像素值和标准偏差,然后在GPU上进行缩小,而不必下载图像并在CPU上计算平均值(因为这会使我的应用程序大大减慢速度) 。问题是,我要处理的GpuMat图像是32位浮点数-但是opencv documentation指出
目前支持CV_8UC1矩阵
我可以轻松地编译以下代码:
#include <opencv2/core/core.hpp>
#include <opencv2/core/cuda.hpp>
#include <opencv2/cudaarithm.hpp>
int main(int argc, char** argv)
{
cv::cuda::GpuMat img = cv::cuda::GpuMat(cv::Mat::zeros(cv::Size(kIWEWidth,kIWEHeight), CV_32FC1));
cv::Scalar mean, std;
cv::cuda::meanStdDev(img, mean, std);
}
但是,当我尝试实际执行此操作时,
error: (-215:Assertion failed) src.type() == CV_8UC1 in function 'meanStdDev'
所以,我想知道是否有人知道是否有可能在meanStdDev方法上使用32位浮点数支持来编译OpenCV,或者是否有推荐的替代方法。我意识到,例如,我应该能够使用cuda::sum
,cuda::subtract
和cuda::sqrSum
来找到平均值。但这需要一堆内核启动,在我的特殊情况下,每一微秒都很重要。
无论如何,在此先感谢您的帮助!
答案 0 :(得分:0)
我发现cv :: cuda版本仅支持CV_8U1真的很奇怪,因为它实际上调用了npp函数nppiMean_StdDev_8u_C1R,并且存在更多图像类型的版本。
void meanStdDev_32FC1M(cv::cuda::GpuMat src, cv::cuda::GpuMat mask, double *mean, double *stddev)
{
CV_Assert(src.type() == CV_32FC1);
double *mean_dev, *stddev_dev;
cudaMalloc((void**)&mean_dev, sizeof(double));
cudaMalloc((void**)&stddev_dev, sizeof(double));
NppiSize sz;
sz.width = src.cols;
sz.height = src.rows;
int bufSize;
nppiMeanStdDevGetBufferHostSize_32f_C1R(sz, &bufSize);//nppSafeCall
cv::cuda::BufferPool pool(cv::cuda::Stream::Null());
cv::cuda::GpuMat buf = pool.getBuffer(1, bufSize, CV_8UC1);
nppiMean_StdDev_32f_C1MR(src.ptr<Npp32f>(), static_cast<int>(src.step), mask.ptr<Npp8u>(), static_cast<int>(mask.step), sz, buf.ptr<Npp8u>(), mean_dev, stddev_dev);
cudaMemcpy(mean, mean_dev, sizeof(double), cudaMemcpyDeviceToHost);
cudaMemcpy(stddev, stddev_dev, sizeof(double), cudaMemcpyDeviceToHost);
cudaFree(mean_dev);
cudaFree(stddev_dev);
}