【问题标题】:Are there any alternatives to using OpenCV's imdecode? It is too slow有没有使用 OpenCV 的 imdecode 的替代方法?太慢了
【发布时间】:2015-05-07 20:48:36
【问题描述】:

我创建了一个 DLL,用户可以在其中从文件名或流中读取图像,如下所示:

std::string filePath = "SomeImage.bmp";

// (1) Reading from a file
Image2D img1;
img1.readImage(filePath);

// (2) Reading from a stream
std::ifstream imgStream (filePath.c_str(), std::ios::binary);
Image2D img2;
img2.readImage(imgStream);

第一个readImage(filePath) 是使用cv::imread(filePath) 实现的,速度相当快(对于600 x 900 的图像,平均需要0.001 秒)。然而,第二个版本readImage(fileStream) 是使用cv::imdecode 实现的,这相当慢(对于相同的图像平均需要2.5 秒)。

是否有任何替代 cv::imdecode 的方法,我可以从内存缓冲区中解码图像而无需花费这么长时间?这是针对经常使用的应用程序的核心组件,所以它必须快速。

我们将不胜感激。提前致谢。

编辑:

我使用计时器测量时间。这对我来说也没有意义。我不明白为什么在时间上有这么大的差距。 Image2D 只是一个以 OpenCV 矩阵为成员的类。 readImage函数的实现简化如下:

int Image2D::readImage(std::ifstream& input)
{       
    input.seekg(0, std::ios::end);
    size_t fileSize = input.tellg();
    input.seekg(0, std::ios::beg);

    if (fileSize == 0) {
        return 1;
    }

    std::vector<unsigned char> data(fileSize);
    input.read(reinterpret_cast<char*>(&data[0]), sizeof(unsigned char) * fileSize);

    if (!input) {
        return 1;
    }

    StopWatch stopWatch;
    mImg = cv::imdecode(cv::Mat(data), CV_LOAD_IMAGE_COLOR);
    std::cout << "Time to decode: " << stopWatch.getElapsedTime() << std::endl;

    return 0;
}


int Image2D::readImage(const std::string& fileName)
{
    StopWatch stopWatch;
    mImg = cv::imread(fileName, CV_LOAD_IMAGE_COLOR);

    std::cout << "Time to read image: " << stopWatch.getElapsedTime() << std::endl;
    return 0;
}

【问题讨论】:

  • 你如何衡量时间?这似乎没有多大意义:imread 在内部使用imdecode,而您只是在读取实际上根本没有解码的位图文件。您还应该显示您的类 Image2D 和方法 readImage 实现的代码(2 个重载选项)。
  • 查看我的编辑@Antonio。
  • 秒表是如何实现的?自从您第一次测量 imread 以来,也许它是某种单例且未重置?
  • 用时钟测量(我知道这是 cpu 时间,而不是 wall 时间),流版本在我的系统上要快一些(但它只是解码)。
  • @Micka 不,这绝对不是单例。只是一个使用 Windows _ftime64_s 的简单轻量级类。我不明白流版本在您的机器上如何更快,但在我的机器上却慢得多。事实上,在我测试过的几台机器上,它的速度更慢。

标签: c++ image opencv memory-management


【解决方案1】:

这就是我测试您的代码的方式,也许您可​​以尝试相同的方法(在一个干净的项目中)来比较结果。

对我来说,时间测量(CPU 时间,它不是墙上时间)表明,仅解码字节流比读取图像要快一点(这是有道理的)-Windows-VC 2010 OpenCV 2.49

#include <fstream>

cv::Mat MreadImage(std::ifstream& input)
{       
    input.seekg(0, std::ios::end);
    size_t fileSize = input.tellg();
    input.seekg(0, std::ios::beg);

    if (fileSize == 0) {
        return cv::Mat();
    }

    std::vector<unsigned char> data(fileSize);
    input.read(reinterpret_cast<char*>(&data[0]), sizeof(unsigned char) * fileSize);

    if (!input) {
        return cv::Mat();
    }

    clock_t startTime = clock();
    cv::Mat mImg = cv::imdecode(cv::Mat(data), CV_LOAD_IMAGE_COLOR);
    clock_t endTime = clock();
    std::cout << "Time to decode image: " << (float)(endTime-startTime)/(float)CLOCKS_PER_SEC << std::endl;

    return mImg;
}


cv::Mat MreadImage(const std::string& fileName)
{
    clock_t startTime = clock();
    cv::Mat mImg = cv::imread(fileName, CV_LOAD_IMAGE_COLOR);
    clock_t endTime = clock();

    std::cout << "Time to read image: " << (float)(endTime-startTime)/(float)CLOCKS_PER_SEC << std::endl;
    return mImg;
}

// test speed of imread vs imdecode
int main()
{

    //std::string path = "../inputData/Lenna.png";
    //std::string path = "../inputData/Aachen_Germany_Imperial-Cathedral-01.jpg";
    std::string path = "../inputData/bmp.bmp";

    cv::Mat i1 = MreadImage(path);


    std::ifstream imgStream (path.c_str(), std::ios::binary);
    cv::Mat i2 = MreadImage(imgStream);

    cv::imshow("input 1", i1);
    cv::imshow("input 2", i2);
    cv::waitKey(0);
    return 0;
}

【讨论】:

  • 所以我在一个干净的项目中测试了上面的代码,时间和你提到的差不多。我真的不明白为什么在我的生产级应用程序中运行imdecode 需要更长的时间。我将不得不更深入地研究这一点。我可能会遗漏一些东西。任何建议都会有所帮助。谢谢。
  • 您是否在生产代码中尝试过替代时间测量方法?
  • 是的,我做到了。我不明白为什么需要这么长时间。我为这个问题创建了一个解决方法,但我仍然对时间差异感到困惑。我不知道为什么当我明确调用cv::imdecode 时需要更长的时间。不过感谢您的帮助。
猜你喜欢
  • 2018-06-08
  • 1970-01-01
  • 2021-03-26
  • 1970-01-01
  • 2017-07-14
  • 1970-01-01
  • 2017-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多