Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extremely slow bilinear interpolation (compared to 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 nearest 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;
}

This is an implementation of bilinear interpolation, I use it to enlarge a 512 * 512 image ("lena.png") to 2048 * 2048. It takes me 0.195 secs to finish the job, but cv::resize (not the GPU version) of OpenCV only takes 0.026 secs. I don't know what makes my program so slow (OpenCV is faster than me by almost 750%), I would like to see the source code of the resize of OpenCV but I can't find the implementation of it.

Do you have any idea why the resize of OpenCV could be so fast or my bilinear is too slow?

    {
        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;
    }

compiler : mingw4.6.2 os : win7 64bits cpu : Intel® i3-2330M (2.2G)

like image 974
StereoMatching Avatar asked Dec 15 '12 00:12

StereoMatching


People also ask

Which interpolation method is best OpenCV?

The results of Bicubic interpolation are far better as compared to NN or bilinear algorithms.

Which interpolation is best for image resizing?

If you are enlarging the image, you should prefer to use INTER_LINEAR or INTER_CUBIC interpolation. If you are shrinking the image, you should prefer to use INTER_AREA interpolation. Cubic interpolation is computationally more complex, and hence slower than linear interpolation.

What does interpolation do in OpenCV?

Interpolation in OpenCV Interpolation is the way the extra pixels in the new image is calculated. If the original image is smaller, then a larger rescaled image has extra pixels which is not exactly the same as a nearby pixels. The value of the extra pixel depends on the technique used.

What is CV Inter_area?

INTER_AREA. Python: cv.INTER_AREA. resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire'-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.


1 Answers

There are two main things making OpenCV's version faster:

  1. OpenCV implements resize as a "separable operation". I.e. it is done in two steps: image is stretched horizontally and then vertically. This technique allows to make resize using less arithmetic operations.

  2. Hand-coded SSE optimization.

like image 115
Andrey Kamaev Avatar answered Oct 20 '22 01:10

Andrey Kamaev