參考文章
(1條消息) 幾種常用的插值和分段插值方法Matlab算法實現_樹莓、的博客-CSDN博客_分段線性插值matlab
MATLAB 圖像的插值算法2:最近鄰插值_Effend的博客-CSDN博客_matlab最近鄰插值
[數字圖像處理](六)插值運算
前言
本文章介紹的幾種算法都是用變化后的坐標\(((n*R || m*R)R 為變化率(如1.5))\) 來計算映射到原始圖像的位置,有很多博客和wiki都介紹了這些算法的數學原理,這里就不做介紹了就是數學不好。
本文章就matlab代碼,來解釋算法的執行邏輯,以便於更好的理解算法的實際思想。
1____最近鄰插值法
基本思想
下文會用到的標記
-
transim()變換后的圖像
-
grayim()變換之前的圖像
-
n,m——grayim的大小,c,l——transim的大小
-
R變換率——\(n*R = c,m*R = l\)
最近鄰插值法,本質上就是變換后圖像的坐標等比映射到原圖像取值
$ transim(i,j) = grayim( round(i/R),round(j/R) ) $
實現代碼
%% nearest_neighbor
clc;
clear all;
close all;
rgbim = imread('p2.png');
grayim = rgb2gray(rgbim);
[n,m] = size(grayim);
figure;
imshow(grayim);
%% 設置變換率
R = 2.8;
n = round(n*R);% 四舍五入
m = round(m*R);
%% 變換
transim = zeros(n,m,class(grayim));% class的作用的把transim的數據類型變成和grayim一直的數據類型
for i = 1:1:n
for j = 1:1:m
x = round(i/R) ;% 映射到原圖像
y = round(j/R);
if x == 0 % 考慮到邊界問題
x = x + 1;
end
if y == 0
y = y + 1;
end
%------------
transim(i,j) = grayim(x,y);
end
end
%% 輸出圖像
figure;
imshow(transim);
imwrite(transim,'transim.png');
2____雙線性插值法
前言
我在學習了最近鄰插值法之后,想學的是線性插值法,去了解了之后發現,這是一個處理一維圖像的算法。在粗略的了解與思考之后發現其實也是可以做二維圖像的,只不過說處理時只能參考橫向偏移量,或者縱向偏移量,有一定的局限性。
所以在這里我就直接跳過線性插值法,直接來說說雙線性插值法
基本思想
如果知道線性插值法是如何處理的,那么雙線性插值法也就明白了。
同時雙線性插值法也是最近鄰插值法的優化,在最近鄰插值法中,我們直接用等比縮放的映射值來充當變換圖像的灰度值(詳見上),這樣就浪費了很多領域的信息,如果把領域的信息利用起來,是不是就可以在一定程度上提升畫質呢(通過之前學習的各種優化來推到)?
雙線性插值法就是這樣的思路,利用到了映射之后的領域信息,以及映射的比率來確定橫縱上的偏移量,我這有系統的說,肯定很多小伙伴是雲里霧里,但是看了下面的描述,再來看這段文字,必定茅塞頓開。

-
理解偏移量 \(u,v\)
-
橫向:\(u = \frac{i}{R} - floor(\frac{i}{R})\)
-
縱向:\(v = \frac{i}{R}-floor(\frac{j}{R})\)
如何理解這個偏移量呢?
我們假設 $ i = 7,j = 131, R = 0.5 $
那么\(u = 3.5 - 3 = 0.5\) 這個0.5就對應的是上圖的u,從圖像的意義來解釋,這個值反應的是是這個映射坐標本質上是更靠近x還是x+1 (因為很有可能不同的i,在同一R的情況下,能得到相同的映射坐標x)那么在這個時候,有了u以及v這個偏移量,就能更好的反應出圖像的映射關系,進而得到更真實的變化圖像。
同理,你也可以試着來設定一些y值來理解一下在縱向上的偏移量。
-
-
如果得到最終圖像
查看上圖我們發現,我們運用的是3*3領域中的4個邊角,從坐標的描述上我們就可以得到,下面的計算式子(如果看不懂的話,可以結合上面的圖來分析)
\(transim(i,j) = u*v*grayim(x,y) + (1-u)*v*grayim(x+1,y) + u*(1-v)*grayim(x,y+1)+(1-u)*(1-v)*grayim(x+1,y+1);\)
實現代碼
%% 雙線性插值法
clc;
close all;
clear all;
rgbim = imread('p2.png');
grayim = rgb2gray(rgbim);
figure;
imshow(grayim);
R = 0.4; % 變換率
[n,m] = size(grayim);
ans = round(3/2)
n = round(n*R); % 變換后的寬
m = round(m*R); % 變換后的高
%% 變換
transim = zeros(n,m,class(grayim));
for i = 1:1:n
for j = 1:1:m
x = round(i/R); % 映射到原圖像的位置
y = round(j/R); % 映射到原圖像的位置
if x == 0
x = x+1; end
if y == 0
y = y +1; end
%-----------------求得偏移量
u = i/R - floor(i/R); % 水平
v = j/R - floor(j/R); % 垂直
% 對於在邊緣位置的圖像用最近鄰插值法
if i >= n - R || j >= m - R;
transim(i,j) = grayim(x,y);
else transim(i,j) = u*v*grayim(x,y) + (1-u)*v*grayim(x+1,y) + u*(1-v)*grayim(x,y+1)+(1-u)*(1-v)*grayim(x+1,y+1);
end
end
end
%% 輸出結果
figure;
imshow(transim);
imwrite(transim,'BI.png');
