C++ 极慢的双线性插值(与opencv相比) 模板 cv::Mat_uu常量双线性插值(cv::Mat_uu常量和src,cv::Size dsize, 浮点数dx,浮点数dy) { cv::Mat_uDST=dsize.area()==0?cv::Mat_dst(src.rows*dy,src.cols*dx): cv::Mat_uz(dsize); float const x_ratio=static_cast((src.cols-1))/dst.cols; float const y_ratio=static_cast((src.rows-1))/dst.rows; for(int行=0;行!=dst.rows;++row) { int y=静态铸型(行×y比); float const y_diff=(行*y_比率)-y;//最近像素的距离(y轴) 浮动常数y_diff_2=1-y_diff; 自动*dst_ptr=&dst(行,0)[0]; for(int col=0;col!=dst.cols;++col) { int x=静态投影(col*x\u比率); float const x_diff=(列*x_比率)-x;//最近像素的距离(x轴) 浮点常量x_diff_2=1-x_diff; 浮动常数y2_交叉_x2=y_差异_2*x_差异_2; 浮点数y2_交叉x=y_差异2*x差异; 浮动常数y_交叉x 2=y_差异*x_差异2; 浮动常数y_交叉x=y_差值*x_差值; 对于(int channel=0;channel!=cv::DataType::channels;++channel) { *dst_ptr++=y2_交叉_x2*src(y,x)[通道]+ y2_交叉_x*src(y,x+1)[通道]+ y_交叉x 2*src(y+1,x)[通道]+ y_交叉x*src(y+1,x+1)[通道]; } } } 返回dst;

C++ 极慢的双线性插值(与opencv相比) 模板 cv::Mat_uu常量双线性插值(cv::Mat_uu常量和src,cv::Size dsize, 浮点数dx,浮点数dy) { cv::Mat_uDST=dsize.area()==0?cv::Mat_dst(src.rows*dy,src.cols*dx): cv::Mat_uz(dsize); float const x_ratio=static_cast((src.cols-1))/dst.cols; float const y_ratio=static_cast((src.rows-1))/dst.rows; for(int行=0;行!=dst.rows;++row) { int y=静态铸型(行×y比); float const y_diff=(行*y_比率)-y;//最近像素的距离(y轴) 浮动常数y_diff_2=1-y_diff; 自动*dst_ptr=&dst(行,0)[0]; for(int col=0;col!=dst.cols;++col) { int x=静态投影(col*x\u比率); float const x_diff=(列*x_比率)-x;//最近像素的距离(x轴) 浮点常量x_diff_2=1-x_diff; 浮动常数y2_交叉_x2=y_差异_2*x_差异_2; 浮点数y2_交叉x=y_差异2*x差异; 浮动常数y_交叉x 2=y_差异*x_差异2; 浮动常数y_交叉x=y_差值*x_差值; 对于(int channel=0;channel!=cv::DataType::channels;++channel) { *dst_ptr++=y2_交叉_x2*src(y,x)[通道]+ y2_交叉_x*src(y,x+1)[通道]+ y_交叉x 2*src(y+1,x)[通道]+ y_交叉x*src(y+1,x+1)[通道]; } } } 返回dst;,c++,image,algorithm,opencv,C++,Image,Algorithm,Opencv,} 这是一个双线性插值的实现,我用它来放大512*512的图像(“lena.png”) 到2048*2048,完成这项工作需要0.195秒,但opencv的cv::resize(不是gpu版本)只需要0.026秒。我不知道是什么让我的双线性变得如此缓慢(opencv比我快了将近750%),我想看看opencv的源代码,但我找不到它的实现 你知道为什么openCV的大小调整会这么快,或者我的双线性太慢吗 template<typename T> cv::Mat_<T> co

}

这是一个双线性插值的实现,我用它来放大512*512的图像(“lena.png”) 到2048*2048,完成这项工作需要0.195秒,但opencv的cv::resize(不是gpu版本)只需要0.026秒。我不知道是什么让我的双线性变得如此缓慢(opencv比我快了将近750%),我想看看opencv的源代码,但我找不到它的实现

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

template<typename T>
cv::Mat_<T> const bilinear_interpolation(cv::Mat_<T> const &src, cv::Size dsize,
                                     float dx, float dy)
{
  cv::Mat_<T> dst = dsize.area() == 0 ? cv::Mat_<T>(src.rows * dy, src.cols * dx) :
                                      cv::Mat_<T>(dsize);

  float const x_ratio = static_cast<float>((src.cols - 1)) / dst.cols;
  float const y_ratio = static_cast<float>((src.rows - 1)) / dst.rows;
  for(int row = 0; row != dst.rows; ++row)
  {
    int y = static_cast<int>(row * y_ratio);
    float const y_diff = (row * y_ratio) - y; //distance of the nearest pixel(y axis)
    float const y_diff_2 = 1 - y_diff;
    auto *dst_ptr = &dst(row, 0)[0];
    for(int col = 0; col != dst.cols; ++col)
    {
        int x = static_cast<int>(col * x_ratio);
        float const x_diff = (col * x_ratio) - x; //distance of the nearet pixel(x axis)
        float const x_diff_2 = 1 - x_diff;
        float const y2_cross_x2 = y_diff_2 * x_diff_2;
        float const y2_cross_x = y_diff_2 * x_diff;
        float const y_cross_x2 = y_diff * x_diff_2;
        float const y_cross_x = y_diff * x_diff;
        for(int channel = 0; channel != cv::DataType<T>::channels; ++channel)
        {
            *dst_ptr++ = y2_cross_x2 * src(y, x)[channel] +
                         y2_cross_x * src(y, x + 1)[channel] +
                         y_cross_x2 * src(y + 1, x)[channel] +
                         y_cross_x * src(y + 1, x + 1)[channel];

        }
    }
}

return dst;
{
时间估计时间;
cv::Mat_uuconstsrc=输入;
双线性插值(src,cv::Size(),dx,dy);

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

  • OpenCV将调整大小作为一个“可分离的操作”来实现。也就是说,它分两步完成:先水平拉伸图像,然后垂直拉伸。这种技术允许使用较少的算术运算来调整大小

  • 手工编码的SSE优化


  • 可能有点晚了,但也要检查一下您是否在调试模式下运行应用程序。OpenCV是一个库,可能会通过编译器优化进行编译以供发布。

    可能是
    cv::resize
    利用了处理器指令集扩展,例如SSE,允许它运行多个倍数例如,并行编译。要自己完成此操作,您需要智能编译器优化或手动编写x86程序集。编辑:。(但是,
    -O3
    可能会导致异常奇怪的错误,因此一般不建议使用它。)谢谢,我最近会看一看opencl,希望gpgpu开发的代码能更具可移植性。你可以考虑在特定情况下的具体实现,比如说每个通道8位深度的典型RGB整数图像,从而加快速度。然后可以用更少的乘法和更多的比特数执行此插值ise操作。虽然我的注释中没有适合这里的实现,但您可以找到一个我没有检查正确性的实现。我研究了hqx中的类似代码,我需要转换cv::Vec3b(或4b)使用int,然后将int转换回cv::Vec3b以保存或显示图像,这不是一个非常通用的解决方案,但值得一试。我检查了第一个解决方案,但不知道如何将操作分为两步。它可以用于一些矩阵乘法和dct,但我不知道如何将其应用于双线性。
        {
            timeEstimate<> time;
            cv::Mat_<cv::Vec3b> const src = input;
            bilinear_interpolation(src, cv::Size(), dx, dy);
            std::cout << "bilinear" << std::endl;
        }
    
        {
            timeEstimate<> time;
            cv::Mat output = input.clone();
            cv::resize(input, output, cv::Size(), dx, dy, cv::INTER_LINEAR);
            std::cout << "bilinear cv" << std::endl;
        }