极慢的双线性插值(与 OpenCV 相比)

Ste*_*ing 6 c++ algorithm opencv image

template<typename T>\ncv::Mat_<T> const bilinear_interpolation(cv::Mat_<T> const &src, cv::Size dsize,\n                                     float dx, float dy)\n{\n    cv::Mat_<T> dst = dsize.area() == 0 ? cv::Mat_<T>(src.rows * dy, src.cols * dx) :\n                                        cv::Mat_<T>(dsize);\n  \n    float const x_ratio = static_cast<float>((src.cols - 1)) / dst.cols;\n    float const y_ratio = static_cast<float>((src.rows - 1)) / dst.rows;\n    for(int row = 0; row != dst.rows; ++row)\n    {\n        int y = static_cast<int>(row * y_ratio);\n        float const y_diff = (row * y_ratio) - y; //distance of the nearest pixel(y axis)\n        float const y_diff_2 = 1 - y_diff;\n        auto *dst_ptr = &dst(row, 0)[0];\n        for(int col = 0; col != dst.cols; ++col)\n        {\n            int x = static_cast<int>(col * x_ratio);\n            float const x_diff = (col * x_ratio) - x; //distance of the nearest pixel(x axis)\n            float const x_diff_2 = 1 - x_diff;\n            float const y2_cross_x2 = y_diff_2 * x_diff_2;\n            float const y2_cross_x = y_diff_2 * x_diff;\n            float const y_cross_x2 = y_diff * x_diff_2;\n            float const y_cross_x = y_diff * x_diff;\n            for(int channel = 0; channel != cv::DataType<T>::channels; ++channel)\n            {\n                *dst_ptr++ = y2_cross_x2 * src(y, x)[channel] +\n                             y2_cross_x * src(y, x + 1)[channel] +\n                             y_cross_x2 * src(y + 1, x)[channel] +\n                             y_cross_x * src(y + 1, x + 1)[channel];\n            }\n        }\n    }\n    \n    return dst;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是双线性插值的实现,我用它来将 512 * 512 图像(“lena.png”)放大到 2048 * 2048。我需要 0.195 秒才能完成这项工作,但是 cv::resize (不是 GPU 版本) )的OpenCV只需要0.026秒。我不知道是什么让我的程序这么慢(OpenCV比我快了近750%),我想查看OpenCV调整大小的源代码,但我找不到它的实现。

\n

你知道为什么 OpenCV 的大小调整这么快或者我的双线性太慢吗?

\n
    {\n        timeEstimate<> time;\n        cv::Mat_<cv::Vec3b> const src = input;\n        bilinear_interpolation(src, cv::Size(), dx, dy);\n        std::cout << "bilinear" << std::endl;\n    }\n\n    {\n        timeEstimate<> time;\n        cv::Mat output = input.clone();\n        cv::resize(input, output, cv::Size(), dx, dy, cv::INTER_LINEAR);\n        std::cout << "bilinear cv" << std::endl;\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

编译器:mingw4.6.2\nos:win7 64位\ncpu:Intel\xc2\xae i3-2330M (2.2G)

\n

And*_*aev 5

有两个主要因素使得 OpenCV 的版本更快:

  1. OpenCV 将调整大小实现为“可分离操作”。即分两步完成:图像水平拉伸,然后垂直拉伸。该技术允许使用较少的算术运算来调整大小。

  2. 手工编码的 SSE 优化。