I want to double image with an linear interpolation scheme so that even indices of the new image is copied from indices/2 of the original and odd indices would linearly interpolate from the even indices. Example:
static Mat prepare_img(bool rows_indexed) {
int rows = 5;
int columns = 5;
Mat img(rows, columns, CV_32F);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (rows_indexed) {
img.at<float>(i, j) = (float)i;
} else {
img.at<float>(i, j) = (float)j;
}
}
}
return img;
}
static void double_linear(Mat& src, Mat& dst) {
dst.create(Size(src.cols*2, src.rows*2), src.type());
for (int i = 0; i < dst.rows; i = i + 2) {
for (int j = 0; j < dst.cols; j = j + 2) {
dst.at<float>(i, j) = src.at<float>(i/2, j/2);
}
}
for (int i = 0; i < dst.rows; i = i + 2) {
for (int j = 0; j < dst.cols; j = j + 2) {
if (i < dst.cols - 2) {
dst.at<float>(i + 1, j) = (dst.at<float>(i, j) + dst.at<float>(i + 2, j)) / 2;
if (j < dst.cols - 2) {
float a = dst.at<float>(i, j);
float b = dst.at<float>(i + 2, j);
float c = dst.at<float>(i, j + 2);
float d = dst.at<float>(i + 2, j + 2);
dst.at<float>(i + 1, j + 1) = (a + b + c + d) / 4;
}
}
if (j < dst.cols - 2) {
dst.at<float>(i, j + 1) = (dst.at<float>(i, j) + dst.at<float>(i, j + 2)) / 2;
}
if (i >= dst.cols - 2) {
dst.at<float>(i + 1, j) = dst.at<float>(i, j);
dst.at<float>(i + 1, j + 1) = dst.at<float>(i, j + 1);
}
if (j >= dst.cols - 2) {
dst.at<float>(i, j + 1) = dst.at<float>(i, j);
dst.at<float>(i + 1, j + 1) = dst.at<float>(i + 1, j);
}
}
}
}
Mat img1 = prepare_img(true);
std::cout << "image = " << std::endl << format(img1, Formatter::FMT_PYTHON) << std::endl << std::endl;
Mat dbl1;
double_linear(img1, dbl1);
std::cout << "double image = " << std::endl << format(dbl1, Formatter::FMT_PYTHON) << std::endl << std::endl;
Mat img2 = prepare_img(false);
std::cout << "image = " << std::endl << format(img2, Formatter::FMT_PYTHON) << std::endl << std::endl;
Mat dbl2;
double_linear(img2, dbl2);
std::cout << "double image = " << std::endl << format(dbl2, Formatter::FMT_PYTHON) << std::endl << std::endl;
Output:
image =
[[0, 0, 0, 0, 0],
[1, 1, 1, 1, 1],
[2, 2, 2, 2, 2],
[3, 3, 3, 3, 3],
[4, 4, 4, 4, 4]]
double image =
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5],
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
[3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5],
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4]]
image =
[[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]]
double image =
[[0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4],
[0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4],
[0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4],
[0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4],
[0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4],
[0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4],
[0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4],
[0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4],
[0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4],
[0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4]]
Let’s put aside that double_linear
is not a template function and it works only for 1 channel - ideally I want to do this as fast as possible using OpenCV infrastructure (e.g. even using private API from within my OpenCV clone. I was looking at and trying resize function (opencv/resize.cpp at 4.x · opencv/opencv · GitHub). It seemed to me that if I used INTER_AREA and changed the coefficients to something like [0.5, 0.5] here:
opencv/resize.cpp at 4.x · opencv/opencv · GitHub
and on line 4030
Is that the way to go? Can you give me advice on how to achieve that as generically and as fast as possible?
Thank you in advance