Image scaling: circular interpolation points Diffusion Model

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

 

Guess you like

Origin blog.csdn.net/lonelyrains/article/details/82714508