本文目錄一覽:
如何通過python實現三次樣條插值
spline函數可以實現三次樣條插值 x = 0:10; y = sin(x); xx = 0:.25:10; yy = spline(x,y,xx); plot(x,y,’o’,xx,yy) 另外fnplt csapi這兩個函數也是三次樣條插值函數,具體你可以help一下!
雙線性插值法原理 python實現
碼字不易,如果此文對你有所幫助,請幫忙點贊,感謝!
一. 雙線性插值法原理:
① 何為線性插值?
插值就是在兩個數之間插入一個數,線性插值原理圖如下:
② 各種插值法:
插值法的第一步都是相同的,計算目標圖(dstImage)的坐標點對應原圖(srcImage)中哪個坐標點來填充,計算公式為:
srcX = dstX * (srcWidth/dstWidth)
srcY = dstY * (srcHeight/dstHeight)
(dstX,dstY)表示目標圖像的某個坐標點,(srcX,srcY)表示與之對應的原圖像的坐標點。srcWidth/dstWidth 和 srcHeight/dstHeight 分別表示寬和高的放縮比。
那麼問題來了,通過這個公式算出來的 srcX, scrY 有可能是小數,但是原圖像坐標點是不存在小數的,都是整數,得想辦法把它轉換成整數才行。
不同插值法的區別就體現在 srcX, scrY 是小數時,怎麼將其變成整數去取原圖像中的像素值。
最近鄰插值(Nearest-neighborInterpolation):看名字就很直白,四捨五入選取最接近的整數。這樣的做法會導致像素變化不連續,在目標圖像中產生鋸齒邊緣。
雙線性插值(Bilinear Interpolation):雙線性就是利用與坐標軸平行的兩條直線去把小數坐標分解到相鄰的四個整數坐標點。權重與距離成反比。
雙三次插值(Bicubic Interpolation):與雙線性插值類似,只不過用了相鄰的16個點。但是需要注意的是,前面兩種方法能保證兩個方向的坐標權重和為1,但是雙三次插值不能保證這點,所以可能出現像素值越界的情況,需要截斷。
③ 雙線性插值演算法原理
假如我們想得到未知函數 f 在點 P = (x, y) 的值,假設我們已知函數 f 在 Q11 = (x1, y1)、Q12 = (x1, y2), Q21 = (x2, y1) 以及 Q22 = (x2, y2) 四個點的值。最常見的情況,f就是一個像素點的像素值。首先在 x 方向進行線性插值,然後再在 y 方向上進行線性插值,最終得到雙線性插值的結果。
④ 舉例說明
二. python實現灰度圖像雙線性插值演算法:
灰度圖像雙線性插值放大縮小
import numpy as np
import math
import cv2
def double_linear(input_signal, zoom_multiples):
”’
雙線性插值
:param input_signal: 輸入圖像
:param zoom_multiples: 放大倍數
:return: 雙線性插值後的圖像
”’
input_signal_cp = np.copy(input_signal) # 輸入圖像的副本
input_row, input_col = input_signal_cp.shape # 輸入圖像的尺寸(行、列)
# 輸出圖像的尺寸
output_row = int(input_row * zoom_multiples)
output_col = int(input_col * zoom_multiples)
output_signal = np.zeros((output_row, output_col)) # 輸出圖片
for i in range(output_row):
for j in range(output_col):
# 輸出圖片中坐標 (i,j)對應至輸入圖片中的最近的四個點點(x1,y1)(x2, y2),(x3, y3),(x4,y4)的均值
temp_x = i / output_row * input_row
temp_y = j / output_col * input_col
x1 = int(temp_x)
y1 = int(temp_y)
x2 = x1
y2 = y1 + 1
x3 = x1 + 1
y3 = y1
x4 = x1 + 1
y4 = y1 + 1
u = temp_x – x1
v = temp_y – y1
# 防止越界
if x4 = input_row:
x4 = input_row – 1
x2 = x4
x1 = x4 – 1
x3 = x4 – 1
if y4 = input_col:
y4 = input_col – 1
y3 = y4
y1 = y4 – 1
y2 = y4 – 1
# 插值
output_signal[i, j] = (1-u)*(1-v)*int(input_signal_cp[x1, y1]) + (1-u)*v*int(input_signal_cp[x2, y2]) + u*(1-v)*int(input_signal_cp[x3, y3]) + u*v*int(input_signal_cp[x4, y4])
return output_signal
# Read image
img = cv2.imread(“../paojie_g.jpg”,0).astype(np.float)
out = double_linear(img,2).astype(np.uint8)
# Save result
cv2.imshow(“result”, out)
cv2.imwrite(“out.jpg”, out)
cv2.waitKey(0)
cv2.destroyAllWindows()
三. 灰度圖像雙線性插值實驗結果:
四. 彩色圖像雙線性插值python實現
def BiLinear_interpolation(img,dstH,dstW):
scrH,scrW,_=img.shape
img=np.pad(img,((0,1),(0,1),(0,0)),’constant’)
retimg=np.zeros((dstH,dstW,3),dtype=np.uint8)
for i in range(dstH-1):
for j in range(dstW-1):
scrx=(i+1)*(scrH/dstH)
scry=(j+1)*(scrW/dstW)
x=math.floor(scrx)
y=math.floor(scry)
u=scrx-x
v=scry-y
retimg[i,j]=(1-u)*(1-v)*img[x,y]+u*(1-v)*img[x+1,y]+(1-u)*v*img[x,y+1]+u*v*img[x+1,y+1]
return retimg
im_path=’../paojie.jpg’
image=np.array(Image.open(im_path))
image2=BiLinear_interpolation(image,image.shape[0]*2,image.shape[1]*2)
image2=Image.fromarray(image2.astype(‘uint8’)).convert(‘RGB’)
image2.save(‘3.png’)
五. 彩色圖像雙線性插值實驗結果:
六. 最近鄰插值演算法和雙三次插值演算法可參考:
① 最近鄰插值演算法:
② 雙三次插值演算法:
七. 參考內容:
圖像雙三次插值演算法原理及python實現
一. 圖像雙三次插值演算法原理:
假設源圖像 A 大小為 m*n ,縮放後的目標圖像 B 的大小為 M*N 。那麼根據比例我們可以得到 B(X,Y) 在 A 上的對應坐標為 A(x,y) = A( X*(m/M), Y*(n/N) ) 。在雙線性插值法中,我們選取 A(x,y) 的最近四個點。而在雙立方插值法中,我們選取的是最近的16個像素點作為計算目標圖像 B(X,Y) 處像素值的參數。如圖所示:
如圖所示 P 點就是目標圖像 B 在 (X,Y) 處對應於源圖像中的位置,P 的坐標位置會出現小數部分,所以我們假設 P 的坐標為 P(x+u,y+v),其中 x,y 分別表示整數部分,u,v 分別表示小數部分。那麼我們就可以得到如圖所示的最近 16 個像素的位置,在這裡用 a(i,j)(i,j=0,1,2,3) 來表示。
雙立方插值的目的就是通過找到一種關係,或者說係數,可以把這 16 個像素對於 P 處像素值的影響因子找出來,從而根據這個影響因子來獲得目標圖像對應點的像素值,達到圖像縮放的目的。
BiCubic基函數形式如下:
二. python實現雙三次插值演算法
from PIL import Image
import numpy as np
import math
# 產生16個像素點不同的權重
def BiBubic(x):
x=abs(x)
if x=1:
return 1-2*(x**2)+(x**3)
elif x2:
return 4-8*x+5*(x**2)-(x**3)
else:
return 0
# 雙三次插值演算法
# dstH為目標圖像的高,dstW為目標圖像的寬
def BiCubic_interpolation(img,dstH,dstW):
scrH,scrW,_=img.shape
#img=np.pad(img,((1,3),(1,3),(0,0)),’constant’)
retimg=np.zeros((dstH,dstW,3),dtype=np.uint8)
for i in range(dstH):
for j in range(dstW):
scrx=i*(scrH/dstH)
scry=j*(scrW/dstW)
x=math.floor(scrx)
y=math.floor(scry)
u=scrx-x
v=scry-y
tmp=0
for ii in range(-1,2):
for jj in range(-1,2):
if x+ii0 or y+jj0 or x+ii=scrH or y+jj=scrW:
continue
tmp+=img[x+ii,y+jj]*BiBubic(ii-u)*BiBubic(jj-v)
retimg[i,j]=np.clip(tmp,0,255)
return retimg
im_path=’../paojie.jpg’
image=np.array(Image.open(im_path))
image2=BiCubic_interpolation(image,image.shape[0]*2,image.shape[1]*2)
image2=Image.fromarray(image2.astype(‘uint8’)).convert(‘RGB’)
image2.save(‘BiCubic_interpolation.jpg’)
三. 實驗結果:
四. 參考內容:
求c語言寫的雙三次插值函數
void SPL(int n, double *x, double *y, int ni, double *xi, double *yi); 是你所要。
已知 n 個點 x,y; x 必須已按順序排好。要插值 ni 點,橫坐標 xi[], 輸出 yi[]。
程序里用double 型,保證計算精度。
SPL調用現成的程序。
現成的程序很多。端點處理方法不同,結果會有不同。想同matlab比較,你需 嘗試 調用 spline()函數 時,令 end1 為 1, 設 slope1 的值,令 end2 為 1 設 slope2 的值。
#include stdio.h
#include math.h
int spline (int n, int end1, int end2,
double slope1, double slope2,
double x[], double y[],
double b[], double c[], double d[],
int *iflag)
{
int nm1, ib, i, ascend;
double t;
nm1 = n – 1;
*iflag = 0;
if (n 2)
{ /* no possible interpolation */
*iflag = 1;
goto LeaveSpline;
}
ascend = 1;
for (i = 1; i n; ++i) if (x[i] = x[i-1]) ascend = 0;
if (!ascend)
{
*iflag = 2;
goto LeaveSpline;
}
if (n = 3)
{
d[0] = x[1] – x[0];
c[1] = (y[1] – y[0]) / d[0];
for (i = 1; i nm1; ++i)
{
d[i] = x[i+1] – x[i];
b[i] = 2.0 * (d[i-1] + d[i]);
c[i+1] = (y[i+1] – y[i]) / d[i];
c[i] = c[i+1] – c[i];
}
/* —- Default End conditions */
b[0] = -d[0];
b[nm1] = -d[n-2];
c[0] = 0.0;
c[nm1] = 0.0;
if (n != 3)
{
c[0] = c[2] / (x[3] – x[1]) – c[1] / (x[2] – x[0]);
c[nm1] = c[n-2] / (x[nm1] – x[n-3]) – c[n-3] / (x[n-2] – x[n-4]);
c[0] = c[0] * d[0] * d[0] / (x[3] – x[0]);
c[nm1] = -c[nm1] * d[n-2] * d[n-2] / (x[nm1] – x[n-4]);
}
/* Alternative end conditions — known slopes */
if (end1 == 1)
{
b[0] = 2.0 * (x[1] – x[0]);
c[0] = (y[1] – y[0]) / (x[1] – x[0]) – slope1;
}
if (end2 == 1)
{
b[nm1] = 2.0 * (x[nm1] – x[n-2]);
c[nm1] = slope2 – (y[nm1] – y[n-2]) / (x[nm1] – x[n-2]);
}
/* Forward elimination */
for (i = 1; i n; ++i)
{
t = d[i-1] / b[i-1];
b[i] = b[i] – t * d[i-1];
c[i] = c[i] – t * c[i-1];
}
/* Back substitution */
c[nm1] = c[nm1] / b[nm1];
for (ib = 0; ib nm1; ++ib)
{
i = n – ib – 2;
c[i] = (c[i] – d[i] * c[i+1]) / b[i];
}
b[nm1] = (y[nm1] – y[n-2]) / d[n-2] + d[n-2] * (c[n-2] + 2.0 * c[nm1]);
for (i = 0; i nm1; ++i)
{
b[i] = (y[i+1] – y[i]) / d[i] – d[i] * (c[i+1] + 2.0 * c[i]);
d[i] = (c[i+1] – c[i]) / d[i];
c[i] = 3.0 * c[i];
}
c[nm1] = 3.0 * c[nm1];
d[nm1] = d[n-2];
}
else
{
b[0] = (y[1] – y[0]) / (x[1] – x[0]);
c[0] = 0.0;
d[0] = 0.0;
b[1] = b[0];
c[1] = 0.0;
d[1] = 0.0;
}
LeaveSpline:
return 0;
}
double seval (int n, double u,
double x[], double y[],
double b[], double c[], double d[],
int *last)
{
int i, j, k;
double w;
i = *last;
if (i = n-1) i = 0;
if (i 0) i = 0;
if ((x[i] u) || (x[i+1] u))
{
i = 0;
j = n;
do
{
k = (i + j) / 2;
if (u x[k]) j = k;
if (u = x[k]) i = k;
}
while (j i+1);
}
*last = i;
w = u – x[i];
w = y[i] + w * (b[i] + w * (c[i] + w * d[i]));
return (w);
}
void SPL(int n, double *x, double *y, int ni, double *xi, double *yi)
{
double *b, *c, *d;
int iflag,last,i;
b = (double *) malloc(sizeof(double) * n);
c = (double *)malloc(sizeof(double) * n);
d = (double *)malloc(sizeof(double) * n);
if (!d) { printf(“no enough memory for b,c,d\n”);}
else {
spline (n,0,0,0,0,x,y,b,c,d,iflag);
if (iflag==0) printf(“I got coef b,c,d now\n”); else printf(“x not in order or other error\n”);
for (i=0;ini;i++) yi[i] = seval(ni,xi[i],x,y,b,c,d,last);
free(b);free(c);free(d);
};
}
main(){
double x[6]={0.,1.,2.,3.,4.,5};
double y[6]={0.,0.5,2.0,1.6,0.5,0.0};
double u[8]={0.5,1,1.5,2,2.5,3,3.5,4};
double s[8];
int i;
SPL(6, x,y, 8, u, s);
for (i=0;i8;i++) printf(“%lf %lf \n”,u[i],s[i]);
return 0;
}
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/240001.html