https://en.wikipedia.org/wiki/Interpolation
https://en.wikipedia.org/wiki/Image_scaling
https://en.wikipedia.org/wiki/Comparison_gallery_of_image_scaling_algorithms
https://en.wikipedia.org/wiki/Whittaker%E2%80%93Shannon_interpolation_formula
https://en.wikipedia.org/wiki/Pixel-art_scaling_algorithms
Common scaling interpolation methods: nearest neighbor interpolation, bilinear interpolation, cubic convolution
Traditional scaling interpolation is a square matrix, so the mosaic is square
Unlike traditional interpolation, covering the area of the right circular squares interpolation to optimize the weight, as shown below:
Provided square side length 2, R is the radius of the circle 1. The calculation of the area:
The quarter circle cut: S (A) + S ( B) + (R / 3) ^ 2 = (π * R ^ 2) / 4
green region area: S (green) = (R / 3) * sqrt ((R ^ 2- ( R / 3) ^ 2))
arcuate area of the green region where: S (arc) = (2 * (arcsin ( 1/3)) / (2 * π)) * R & lt ^ 2 * [pi]
B area white region area: S (white) = (R * 2/3 ) * (R-sqrt ((R ^ 2- (R / 3) ^ 2))) - ((S ( arc) -S (green))
S (B) = (2 * R & lt /. 3) ^ 2-S (white)
S (A) = (2 [pi] ^ R & lt *) /. 4-S (B) - (R & lt / 3) ^ 2
R set to 1, then:
SA = 0.24240268452708302834111528260373
SB = 0.43188436775925417016343445210503
SC = 0.44444444444444444444444444444444
SC / SB = 1.0290820358939030947876874261659
SC / SA = 1.8334963794296915471537108683276
SB / SA = 1.781681455392466335545886919352
Matrix operators said that about 178 SB accounts, while SA accounted for 100 parts, basically assuming lossless information is not lost in the case of a point source in nature are extended model scaled:
| 100 178 100 |
| 178 178 0 |
| 100 178 100 |
Reduced image: Known A / B, when the interpolation pixel C is filled region, should consider four symmetrically B pixel region weight value S (PC) = ((B1 + B2 + B3 + B4) * 178 + (A1 + A2 + A3 + A4) * 100) / (4 * (100 + 178)) = ((5 + 6 + 7 + 7) * 178 + (5 + 6 + 7 + 8) * 100) / (4 * (100+ 178))
5 5 6
6 PC 7
7 7 8
It is known that C1 = 10, C2 = 8, the interpolation pixel fill A / B region, as follows:: the value of the enlarged image can be confirmed red question mark area should be filled, in particular the right of the intermediate region in bold red question mark value S (PC) = ((. 5 +. 6 +. 7 +. 8) * 100 + (S (PC1) + S (PC2) + S (PC3) + S (PC4)) * 178) / (. 4 * (100 +
178)): ? ? ? ? ?
? 5 P2 6?
? P1 PC P3 ?
? 7 P4 8?
? ? ? ? ?
As can be seen, S (PC) to be dependent on the calculated vertical and horizontal four areas P1 / P2 / P3 / P4 pixel value. The rest is to consider how the recursive calculation of the zoomed image from edge to the center area S (PC), a high-quality enlarged image finally obtained whole.
Intuitively understand that it is the entire image in order to obtain a smooth, no mosaic, it becomes necessary to calculate the boundary of the intermediate from FIG full spread like water - not only consider the simple previously known bi-linear interpolation neighborhood.
// resize.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "pch.h"
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/hal/interface.h"
#include <iostream>
using namespace cv;
using namespace std;
template <typename T>
string basic2str(const T &int_temp)
{
string string_temp;
stringstream stream;
stream << int_temp;
string_temp = stream.str(); //此处也可以用 stream>>string_temp
return string_temp;
}
int resizeCompare(Mat& image, double div, String fileName)
{
Mat imageNew(image.rows / div, image.cols / div, CV_8UC1, Scalar(1));
Mat imageResize(image.rows / div, image.cols / div, CV_8UC1, Scalar(1));
Mat imageResizeLine(image.rows / div, image.cols / div, CV_8UC1, Scalar(1));
Mat imageResizeLanczos4(image.rows / div, image.cols / div, CV_8UC1, Scalar(1));
resize(image, imageResizeLine, Size(image.cols / div, image.rows / div));
resize(image, imageResizeLanczos4, Size(image.cols / div, image.rows / div), 0, 0, INTER_LANCZOS4);
cv::imwrite(fileName.substr(0, fileName.length() - 4) + "Line.png", imageResizeLine);
cv::imwrite(fileName.substr(0, fileName.length() - 4) + "Lanczos4.png", imageResizeLanczos4);
// 调整分区的权重
double rightRatioValueArray[] = { 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0 };
for (int k = 0; k < 11; k++)
{
for (int i = 0; i < imageNew.rows; i++)
{
for (int j = 0; j < imageNew.cols; j++)
{
int center_x = i * div + div / 2;
int center_y = j * div + div / 2;
if (center_x > 0 && center_y > 0 && center_x < image.rows - 1 && center_y < image.cols - 1)
{
int a[10] = { 0 };
a[1] = image.at<uchar>(center_x - 1, center_y - 1);
a[2] = image.at<uchar>(center_x - 1, center_y);
a[3] = image.at<uchar>(center_x - 1, center_y + 1);
a[4] = image.at<uchar>(center_x, center_y - 1);
a[5] = image.at<uchar>(center_x, center_y);
a[6] = image.at<uchar>(center_x, center_y + 1);
a[7] = image.at<uchar>(center_x + 1, center_y - 1);
a[8] = image.at<uchar>(center_x + 1, center_y);
a[9] = image.at<uchar>(center_x + 1, center_y + 1);
// 强行保留边缘部分
int b1 = 4, b2 = 4;
for (int p = 1; p < 10; p++)
{
if (abs(a[5] - a[p]) > 10)
{
a[p] = 0;
if(0 == p%2)
{
b2--;
}
else { b1--; }
}
}
// 使用圆形插值,保证平滑特性
int a0 = ((a[1] + a[3] + a[7] + a[9]) * 100.0 / rightRatioValueArray[k] + (a[2] + a[4] + a[6] + a[8]) * 178.0 / rightRatioValueArray[k] + a[5] * 183) * 1.0
/ ((b1 * 100 + b2 * 178)/ rightRatioValueArray[k] + 183) + 0.5;
imageNew.at<uchar>(i, j) = a0;
}
else
{
imageNew.at<uchar>(i, j) = image.at<uchar>(i * div + div / 2, j * div + div / 2);
}
}
}
string strRightRatio = basic2str(k);
string strDiv = basic2str(div);
cv::imwrite(fileName.substr(0, fileName.length() - 4) + "Circle" + "-" + strDiv + "-" +strRightRatio + ".png", imageNew);
}
return 0;
}
int main()
{
bool useCanny = false;
bool useRefine = false;
bool overlay = false;
String filename[2] = {
"D:\\opencv\\resize\\Debug\\Text.png" ,
"D:\\opencv\\resize\\Debug\\Lena.png" };
for (int k = 0; k < 2; k++)
{
for (int i = 0; i < 2; i++)
{
Mat image = imread(filename[i], IMREAD_GRAYSCALE);
if (k % 2 == 0)
{
resizeCompare(image, 2, filename[i]);
}
else
{
resizeCompare(image, 0.5, filename[i]);
}
}
}
waitKey();
return 0;
}