图像缩放:点扩散模型的圆形插值

匿名 (未验证) 提交于 2019-12-02 23:43:01





常见的缩放插值方法有:最邻近插值、双线性内插值、三次卷积法

传统缩放插值是方形矩阵的,所以马赛克都是方形的



绿色区域面积:S(绿)=(R/3)*sqrt((R^2-(R/3)^2))

B所在区域白色区域面积:S(白) = (R*2/3)*(R-sqrt((R^2-(R/3)^2)))-((S(弧)-S(绿))
S(B)=(R*2/3)^2-S(白)
S(A)=(π*R^2)/4-S(B)-(R/3)^2

设R为1,则:
SA = 0.24240268452708302834111528260373
SB = 0.43188436775925417016343445210503
SC = 0.44444444444444444444444444444444

SC/SB = 1.0290820358939030947876874261659
SC/SA = 1.8334963794296915471537108683276
SB/SA = 1.781681455392466335545886919352


|100 178 100|

|100 178 100|



6 PC 7



P2
P1 PC P3
P4
? ? ? ? ?
可以看出,S(PC)依赖于上下左右四个待计算的区域P1/P2/P3/P4像素值。剩下的就是要考虑怎么从缩放图像的边缘向中心区域递推计算S(PC),最终得到高质量的整幅放大图像。
直观上理解,它是为了得到图像整体平滑,没有马赛克,所以才需要从边界向中间像水一样漫延的全图计算――不是以前的只考虑已知邻域的简单双向线性插值。

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

文章来源: https://blog.csdn.net/lonelyrains/article/details/82714508
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!