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)
The results of Bicubic interpolation are far better as compared to NN or bilinear algorithms.
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.
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.
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.
There are two main things making OpenCV's version faster:
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.
Hand-coded SSE optimization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With