OpenCV cuda :: meanStdDev支持CV_32FC1

时间:2019-03-20 08:13:39

标签: opencv opencv3.0

我想找到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::sumcuda::subtractcuda::sqrSum来找到平均值。但这需要一堆内核启动,在我的特殊情况下,每一微秒都很重要。

无论如何,在此先感谢您的帮助!

1 个答案:

答案 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);
}