一文讲解图像插值算法原理!附Python实现

2023-05-31 0 389

一文讲解图像插值算法原理!附Python实现

责任编辑约4834字,提议写作12两分钟

责任编辑如是说了前段时间邻对数法、微分形式对数法和四次傅里叶对数法的基本原理,并以影像滑动例,对基本原理展开了C++及Python同时实现。

在影像处置中,射影变换是将两幅影像态射到除此之外两幅影像内的操作形式,能约莫分成阿提斯鲁夫尔谷、滑动、射影(移位、转动)、折射、重态射几部份。

在射影变换时,难以给很多直方图间接表达式,比如,将影像弱化三倍,必定会再加许多难以被间接态射的直方图,对那些直方图,透过对数下定决心它的值。且相同对数形式的结论相同。

在两幅输出影像[u,v]中,位图值仅在有理数边线上有表述。不过,输出影像的座标态射彭衍堂影像后,通常为非有理数的座标。因此输出影像[x,y]的位图值,通常迪拉县有理数座标来下定决心,非有理数座标的画素值,就须要对数演算法来展开处置。常用的对数演算法有前段时间邻对数、微分形式对数和四次傅里叶对数。

责任编辑最终目标

介绍对数演算法与常用射影变换间的亲密关系认知对数演算法的基本原理掌控OpenCV架构下对数演算法API的采用

对数演算法基本原理如是说

比邻对数演算法

1.基本原理概要

将最终目标影像中的点,相关联到原影像后段,找出最交界处的有理数座标点的画素值,做为该点的画素值输出。

一文讲解图像插值算法原理!附Python实现

示意图右图,最终目标影像中的某点二维到原影像中的边线为点P,与P距离前段时间的点为Q11,此时易知,f(P)=f(Q11)。

2.例子说明

如图右图:

一文讲解图像插值算法原理!附Python实现

将两幅3*3影像弱化到4*4,用f(x , y)表示原影像,h(x ,y)表示最终目标影像,我们有如下公式:

一文讲解图像插值算法原理!附Python实现

3.缺点

由最邻近对数法,弱化后的影像有很严重的马赛克,会出现明显的块状效应;缩小后的影像有很严重的失真。

这是一种最基本、最简单的影像滑动形式。变换后的每个直方图的画素值,只由原影像中的一个画素点确定。比如上面,点(0,0.75)的画素只由(0,1)确定,这样的效果显然不好。点(0,0.75)的画素不止和(0,1)有关,和(0,0)也有关,只是(0,1)的影响更大。如果能用附近的几个直方图按权重分配,共同确定最终目标影像某点的画素,效果会更好。下面的微分形式对数就解决了这个问题。

微分形式对数演算法

1.线性对数

在讲微分形式对数之前先介绍一下线性对数。线性对数:采用连接两个已知量的直线来确定在这两个已知量间的一个未知量的值。线性对数形式:

一文讲解图像插值算法原理!附Python实现

如下图右图:

一文讲解图像插值算法原理!附Python实现

线性对数多项式:

一文讲解图像插值算法原理!附Python实现

其实,即使x不在x0到x1间,这个公式也是成立的。在这种情况下,这种方法叫作线性外插。

线性对数的误差:线性对数其实就是拉格朗日对数有2个结点时的情况。对数余项为:

一文讲解图像插值算法原理!附Python实现

从对数余项能看出,随着二阶导数的增大,线性对数的误差增大。即函数的曲率越大,线性对数近似的误差也越大。

举个例子。下图中,左边为原影像,拉伸后,理想的输出影像的画素分布应该为绿色箭头指向的,但是按照线性对数,会得到红色箭头指向的结论。

一文讲解图像插值算法原理!附Python实现

2.微分形式对数

微分形式对数形式:

一文讲解图像插值算法原理!附Python实现

微分形式对数是线性对数在二维时的推广,在两个方向上共做了四次线性对数。表述了一个双曲抛物面与四个已知点拟合。

具体操作形式为在X方向上展开两次线性对数计算,然后在Y方向上展开一次对数计算。如下图右图:

一文讲解图像插值算法原理!附Python实现

首先,f(x,y)为二元函数,假设我们知道f(x0,y0),f(x1,y1),f(x0,y1),f(x1,y0)四个点的值。这四个点确定一个矩形,我们希望透过对数得到矩形内任意点的函数值。

先在x方向上展开两次线性对数,得到:

一文讲解图像插值算法原理!附Python实现

再在y方向上展开一次线性对数,得到:

一文讲解图像插值算法原理!附Python实现

综合起来,就是微分形式对数的结论:

一文讲解图像插值算法原理!附Python实现

如果选择一个座标系统,使f(x)已知的四个点的座标分别为(0,0),(0,1),(1,0),(1,1),那么确定一个单位正方形,四个点分别为正方形的四个顶点:

首先对上端的两个顶点展开线性对数得:
一文讲解图像插值算法原理!附Python实现
再对底端的两个顶点展开线性对数得:
一文讲解图像插值算法原理!附Python实现
最后,做垂直方向的线性对数,以确定:
一文讲解图像插值算法原理!附Python实现
整理得对数公式的化简形式:
一文讲解图像插值算法原理!附Python实现

3.原影像和最终目标影像的几何中心对称

在计算最终目标影像中,相关联原影像的虚拟座标点时,通常的变换是:

一文讲解图像插值算法原理!附Python实现

这种变换下,原影像的很多点没有参与计算。举个例子,把9∗9的原影像缩小成3∗3,原影像的原点(0,0)和最终目标影像的原点(0,0)都为左上角,最终目标影像右上角的座标为(0,2),相关联原影像的座标为(0∗(9/3),2∗(9/3))=(0,6)。最终目标影像右边已经没有点了,(0,6)右边的直方图也就用不到了。

原影像和最终目标影像的画素间的相关联亲密关系如下:

一文讲解图像插值算法原理!附Python实现

从图片能看出,只有圈出来的红色部份参与运算了。最终目标影像的每个直方图的位图值相对原影像偏左上方,右下角的元素实际上没有参与运算。

为了让原影像和最终目标影像的中心对齐,我们规定除此之外一种变换形式:

一文讲解图像插值算法原理!附Python实现

就是在原来的变换后面加了调节因子:

0.5(src_width/dst_width−1)

一文讲解图像插值算法原理!附Python实现

这种变换下,最终目标图像的中心点(1,1),相关联了原影像的中心点(4,4),两个影像的几何中心重合,能充分利用原影像的点,并且最终目标影像的每个直方图间都是等间隔的,也都和两边有一定的边距。实际上,在openCv中也是这种变换形式。

一文讲解图像插值算法原理!附Python实现

4.cv.resize()的计算过程

对缩小影像,最终目标影像中每个点都能找出原影像中包围它的四个临近点,每个点都展开微分形式对数即可。

对弱化影像,边界附近的点经过座标变换可能超出了原影像的范围。举个例子,把3∗3的原影像弱化成4∗4。

中间的点:微分形式对数

中间的点都能在原影像中找出包围它的四个临近点,做微分形式对数即可。

边界上的点(除了顶点):线性对数

比如,最终目标影像中的点(1,3),相关联原影像的点为(0.625,2.125),原影像的纵座标最大为2,找不到包围(0.625,2.125)四个点,因此用它最邻近的两个点(0,2)和(1,2)做线性对数(外插),得到最终目标影像中(1,3)的画素值。

四个顶点:最邻近对数

比如,最终目标影像右上角的顶点(0,3),对原影像的点为(0,2.125),间接用原影像右上角的顶点(0,2)做为它的值即可。

计算过程:

用h(x,y)表示最终目标影像,f(x,y)表示原图像

中间的点:微分形式对数
一文讲解图像插值算法原理!附Python实现
边界上的点(除了顶点):线性对数
一文讲解图像插值算法原理!附Python实现
四个顶点:最邻近对数
一文讲解图像插值算法原理!附Python实现
一文讲解图像插值算法原理!附Python实现

能用代码举例子测试:

import cv2import numpy as npsrc = np.array([[56,23,15],[65,32,78],[12,45,62]],dtype=np.uint8)print(src)dst = cv2.resize(src,dsize=(4,4),interpolation=cv2.INTER_LINEAR)print(dst)

四次傅里叶对数演算法

给定n+1个点,a=x_0<x_1<…<x_n=b,以及他们的函数值f(x_i),i=0,1,2,…n上,确定一个四次多项式:

一文讲解图像插值算法原理!附Python实现

每个四次多项式中有四个未知参数,有n个区间,n个多项式,共4n个未知参数。我们知道“n个未知数须要n个已知条件确定唯一解”,因此要确定这4n个未知参数,共须要4n个已知条件。

每个四次多项式满足如下条件:

一文讲解图像插值算法原理!附Python实现

以上共4n−2个条件,还差2个条件,由如下三种边界条件确定:

一文讲解图像插值算法原理!附Python实现

4n个条件有了,就能确定每个区间上的四次多项式。

对每个区间内的点,就能用Si(x)得到对数结论。四次傅里叶对数具有良好的收敛性,稳定性和光滑性,优点明显,是非常重要的对数工具。

这里主要介绍四次傅里叶对数的作用,具体的推导过程比较繁琐,想介绍的能查阅资料。

两种态射方法

向前态射和向后态射都是将一个影像经过射影变换得到另一个影像的过程,它们的目的都是得到最终目标影像的画素,只是形式相同。

向前态射

影像变换的本质是将直方图的座标透过某一种函数亲密关系,态射到除此之外的边线。

向前态射的过程能分解为两步:座标变换+分配画素值

向前态射的座标变换:由原影像座标推算该画素在最终目标影像的边线。

比如,我们知道原影像的某个直方图的座标(x,y),变换后在新影像的座标为(x′,y′),变换后的座标通常为非有理数的,而非有理数的座标是没意义的,因此将这个点的画素按权重分配给周围四个直方图。对变换后座标仍为有理数的点,间接把其画素值分配给最终目标影像中相关联的点即可。将原影像的所有直方图都展开这种座标变换和分配画素值,就得到了新影像。

因此,新影像的每个直方图的画素值,都是由它周围的非有理数座标的点的画素分配给它并叠加得到的(或者间接等于某个有理数座标点的画素值)。由于这个分配、叠加的特性,向前态射法有时也叫画素移交态射。

对向前态射,虽然原影像中的每个点分配系数之和为1。但最终目标影像上每个点的画素值是多个分配值叠加而成的,因此不能保证所有分配到其上的权重之和为1。因此必须记录下所有分配到其上的权重并累加起来,最后利用累加权重展开归一化,才能得到正确的对数结论。因此,确定目标影像某一点的画素值,须要遍历原影像的所有画素值,展开座标变换和分配画素值。这是向前态射法的缺点。

向后态射

向后态射的过程能分解为两步:座标变换+对数。

向后态射的座标变换:由输出影像座标反过来推算该像素在原影像的边线

前面说的几种对数形式,就是向后态射的例子。是由最终目标影像的座标算出在原影像的座标,再确定它的画素值由原影像的哪几个点按权重分配得到。然后展开对数操作形式,得到该点的画素值。某一点的画素值展开一次操作形式就能得到,不须要遍历全部直方图。向后态射法也叫画素填充演算法。向后态射法解决了漏点的问题,出现了马赛克。

动手同时实现

c++同时实现

1. 函数原型

voidcv::resize(InputArray src, OutputArray dst, Size dsize,double fx=0, double fy=0, int interpolation=INTER_LINEAR )
一文讲解图像插值算法原理!附Python实现

2. 对数形式

一文讲解图像插值算法原理!附Python实现

注:最终目标影像大小可以透过“参数dsize”和“参数fx和fy”两种形式确定。两种参数不能同时为0。

透过参数dsize确定

dsize的第一个参数为列数,第二个参数为行数,都为有理数。若指定了dsize的值,无论是否指定了fx和fy的值,都由参数dsize来下定决心最终目标影像的大小。

透过参数fx和fy确定

如果dsize的值None,最终目标影像的大小透过fx和fy确定。fx为列数滑动的倍数,fy为行数滑动的倍数。

3.代码同时实现

#include <opencv2/opencv.hpp>#include <iostream>using namespace cv;using namespace std;int main(int argc,char* argv[]){ Mat img = imread(“”C:/Users/94890/Desktop/picture/luelue.jpg“”); if(img.empty()) { cout <<“难以读取影像” << endl; return 0; } int height = img.rows;//原影像行数 int width = img.cols;//原影像列数 // 缩小影像,比例为(0.2, 0.2),行列数必须为有理数 Size dsize = Size(round(0.2 * width), round(0.2* height)); Mat shrink; //采用微分形式插值 resize(img, shrink, dsize,0, 0, INTER_LINEAR); // 在缩小影像的基础上,弱化影像,比例为(1.5, 1.5) float fx = 1.5; float fy =1.5; Mat enlarge1, enlarge2; resize(shrink, enlarge1, Size(), fx, fy, INTER_NEAREST); resize(shrink, enlarge2, Size(), fx, fy, INTER_LINEAR); // 显示 imshow(“src”, img); imshow(“shrink”, shrink); imshow(“INTER_NEAREST”, enlarge1); imshow(“INTER_LINEAR”, enlarge2); //保存影像 imwrite(“C:/Users/94890/Desktop/picture/shrink2.jpg”,shrink); imwrite(“C:/Users/94890/Desktop/picture/INTER_NEAREST2.jpg”, enlarge1); imwrite(“C:/Users/94890/Desktop/picture/INTER_LINEAR2.jpg”, enlarge2); waitKey(0); return 0;}

原影像

一文讲解图像插值算法原理!附Python实现

0.2倍缩小,微分形式对数

一文讲解图像插值算法原理!附Python实现

缩小后的影像1.5倍弱化,前段时间邻对数

一文讲解图像插值算法原理!附Python实现

缩小后的影像1.5倍弱化,微分形式对数

一文讲解图像插值算法原理!附Python实现

python同时实现

1. 函数原型

#dst为输出影像,类型与原影像相同dst = cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
一文讲解图像插值算法原理!附Python实现

2. 对数形式

通常,缩小影像采用区域对数(cv.INTER_AREA),弱化影像采用四次傅里叶对数(cv.INTER_CUBIC)和微分形式对数(cv.INTER_LINEAR)。四次傅里叶对数形式速度较慢,微分形式对数形式较快且效果也不错。

一文讲解图像插值算法原理!附Python实现

3. 代码同时实现

import cv2if __name__ == “__main__”: img = cv2.imread(C:/Users/94890/Desktop/smile.jpg, cv2.IMREAD_UNCHANGED) print(Original shape :, img.shape)#img.shape属性种第一个值相关联行数,第二个值相关联列数 width = int(img.shape[1] * 0.3)#列数必须是有理数 height = int(img.shape[0] * 0.3)#行数必须是有理数 dsize = (width, height)#dsize属性值第一个数相关联列数,第二个数相关联行数 # resize image resized = cv2.resize(img, dsize, interpolation=cv2.INTER_LINEAR)#微分形式对数形式print(Resized shape : , resized.shape) fx = 1.5#列数变为原来的1.5倍 fy = 1.5#行数变为原来的1.5倍 resized1 = cv2.resize(resized, dsize=None, fx=fx, fy=fy, interpolation=cv2.INTER_NEAREST)#最邻近对数 resized2 = cv2.resize(resized, dsize=None, fx=fx, fy=fy, interpolation=cv2.INTER_LINEAR)#微分形式对数print(Resized1 shape : , resized1.shape) #显示影像 cv2.imshow(“Resized image”, resized) cv2.imshow(“INTER_NEAREST image”, resized1) cv2.imshow(“INTER_LINEAR image”, resized2) #保存影像 cv2.imwrite(“C:/Users/94890/Desktop/Resized_image.jpg”, resized) cv2.imwrite(“C:/Users/94890/Desktop/INTER_NEAREST_image.jpg”, resized1) cv2.imwrite(“C:/Users/94890/Desktop/INTER_LINEAR_image.jpg”, resized2) cv2.waitKey(0) cv2.destroyAllWindows()

原影像

一文讲解图像插值算法原理!附Python实现

0.3倍缩小,微分形式对数

一文讲解图像插值算法原理!附Python实现

缩小后的影像1.5倍弱化,前段时间邻对数

一文讲解图像插值算法原理!附Python实现

缩小后的影像1.5倍弱化,微分形式对数

一文讲解图像插值算法原理!附Python实现

—完—

数据派THU

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务