画像処理におけるいくつかの一般的な補間方法: 最近傍補間、バイリニア補間、およびバイキュービック補間 (Pytorch テスト コードを使用)

ゼロ、序文

変形可能な畳み込みを学習する場合、学習した変位 Δp nが小数になる可能性があるため、著者は双一次補間アルゴリズムを使用して畳み込み演算の最終サンプリング位置を決定します。補間アルゴリズムを通じて、既存の既知のデータに基づいて未知の位置のデータを推定でき、この方法を使用して画像の拡大縮小、回転、幾何学的補正などのタスクを実行できますここでは、この記事を使用して、最近傍補間、バイリニア補間、およびバイキュービック補間アルゴリズムを含む 3 つの一般的な補間方法を学び、要約します。その中で、バイリニア補間方法は、Pytorch や Tensorflow などでより頻繁に使用される方法です。フレームワーク内の方法は、双線形補間方法です。
デジタル画像処理では、画像が次の図で表されることがわかっています。各ピクセルの位置は整数です。補間の前に、最初に次の式を使用して、マップバックされた
ここに画像の説明を挿入します
ターゲット画像内のピクセルの位置が計算されます。元の画像へ: What、dst および src は、それぞれターゲット イメージと元の画像を表すためにここで使用されます。(x, y) はピクセル座標位置です。この式は特に重要です。
ここに画像の説明を挿入します

1. 最近傍補間

1.関連紹介

最近傍補間 (ゼロ次補間とも呼ばれます) は、計算量が少ない最も単純な補間方法です。未知の位置の場合、最も近いピクセルの値が直接その位置に割り当てられます。この方法では通常、 補間 が発生します。グレー値画像内のピクセル数が不連続になるため、画像の端に明らかなギザギザが生じるため、この方法が実際に使用されることはほとんどありません。
Src と Dst は、それぞれ元の画像とターゲット画像を表すためにここで使用されます。それらのサイズはそれぞれ (Src_H, Src_W) と (Dst_H, Dst_W) です。目的は、元の画像を使用して、ピクセル値を埋めることです。対象画像を確認してください
各要素について、充填値の計算は 2 つのステップに分かれています:
1) 上記の式を通じて Src の座標 (src_x、src_y) に対応する Dst の座標 (dst_x、dst_y) を計算します; 2)
必要な ( src_x, src_y) フロア操作の座標 (丸めが使用されていると言っている人が多いですが、結果から明らかにフロアであることがわかります)。つまり、最も近い隣接点 (フロア) を取得するために切り捨てられます ( dst_x, dst_y) in the original image (src_x),floor(src_y))
;
ここに画像の説明を挿入します
たとえば、元の画像 Src とターゲット画像 Dst のサイズがそれぞれ (2,2) と (4,4) であると仮定すると、目的は、元の画像を使用してターゲット画像のピクセルをマッピングすることです 値を入力し、Pytorch を使用して、上に示すように結果を取得します。例としてターゲット画像のデータ 7、7、2、2 の最初の行を取り上げます。 , f(x,y) と g(x,y) を使用してターゲット イメージと元のイメージをそれぞれ表します。中央ピクセルのグレースケール値については、「最近傍」補間法の実装プロセスを示します。最近
ここに画像の説明を挿入します
補間法は使いにくいので、心配する必要はありません。読み続けてください。

2. コードの実装

import torch
import torch.nn as nn
from torchvision import transforms


img=torch.randint(10,size=(1,2,2),dtype=torch.float32)
print(img)
print('---'*5)
nearest_neighbor_interpolation=transforms.Resize(size=(4,4),
                                       interpolation=transforms.InterpolationMode.NEAREST)
resize_img=nearest_neighbor_interpolation(img)
print(resize_img)

2. 双一次補間

1.線形補間

共一次補間について説明する前に、まず線形補間について理解しましょう。線形補間は 1 次元データの内挿に適用され、内挿計算は補間される点の左右にある既知の 2 つの隣接点に基づいて実行されます補間プロセスは、2 つの点を知り、直線を表す 2 点法を使用して、既知の x で y を見つけるか、既知の y で x を見つけるプロセスです。詳細については、次の式の導出と図を参照してください。この図の目的は補間点
ここに画像の説明を挿入します
(x, y) を見つけることであり、この点の左右の 2 つの点 (x0, y0) と (x1, y1) がわかっています。この直線を表すために使用されます: 式 (1) は、y が既知の場合に x を見つけるために使用されます; 式
ここに画像の説明を挿入します
(2) は、x が既知の場合に y を見つけるために使用されます。

2. 双一次補間

バイリニア補間法は画像を平滑化する効果があり、実際には2次元データのx方向とy方向の両方に1次元線形補間を施し、合計3回の1次元線形補間を行いますこの方法がより一般的に使用されます.未知の位置に隣接する 4 つのピクセル
を使用してそのピクセル値を計算します. 具体的な割り当てプロセスは次の式で計算されます (ここでの f(Q xy ) は1 次元のy xとして理解できます)補間式):ターゲット画像内の未知の点 (dst_x, dst_y) が、P(x,y)=P(src_x,src_y) として元の画像内の点に対応すると仮定し、Q11、Q12、Q21、Q22 とします。は、元の画像内の P の 4 つの隣接する点です。点 P の補間プロセスは、次の 2 つのステップに分かれています: 1) に沿って; 2) R1 と R2 を使用して、Y 方向に沿って 1 次元線形補間を実行します (合計 1 回) 最終的な 2 次元線形補間結果 P を取得するには、双線形補間における 4 つの隣接点の選択をよりよく理解するために、次の図に示すように、画像処理における4 つの対角近傍。 . 点 P には、その対角方向に隣接する点が 4 つあります。充填ステップの分析: 1) 記事の冒頭の式を使用して、Dst の座標 (dst_x, dst_y) が Src の座標 P (src_x, src_y) にどの程度対応するかを計算します; 2) 得られた点 P を計算します対応する元の画像内の (src_x, src_y) コーナーの 4 つの角の座標関係を使用して、その隣接点を取得します: Q11、Q12、Q21、Q22; 3) 取得した隣接点を使用して、次の操作を実行します。 X および Y 方向に沿った次元線形補間により、双線形補間プロセスを完了します。
ここに画像の説明を挿入します
ここに画像の説明を挿入します



ここに画像の説明を挿入します

ここに画像の説明を挿入します




たとえば、元の画像 Src とターゲット画像 Dst のサイズがそれぞれ (4,4) と (8,8) であると仮定すると、目的は元の画像を使用してターゲット画像のピクセル値を埋めることです。を使用し、Pytorch を使用して以下に示す結果を取得します。ターゲット画像座標 (5,5) の点を例として、f(x,y)、g(x,y) を使用してグレースケール値を表します。元の画像とターゲット画像のそれぞれのピクセルの「二重線」に興味があります 補間法の実装プロセスが示されています: この時点で埋められる値の計算プロセスは次のとおりです
ここに画像の説明を挿入します
:
ここに画像の説明を挿入します
手動で計算された値と Pytorch の内部実装の間にはわずかな偏差がありますが、アルゴリズムは Pytorch によって内部的に最適化されているはずです。
ここに画像の説明を挿入します

3. コードの実装

import torch
import torch.nn as nn
from torchvision import transforms


img=torch.randint(10,size=(1,4,4),dtype=torch.float32)
print(img)
print('---'*5)
bilinear_interpolation=transforms.Resize(size=(8,8),
                                       interpolation=transforms.InterpolationMode.BILINEAR)
resize_img=bilinear_interpolation(img)
print(resize_img)

3. バイキュービック補間

1.関連紹介

バイキュービック補間 (バイキュービック補間とも呼ばれる) は、バイリニア補間方法よりも滑らかなエッジ補間結果を生成できます。より優れた正確な補間結果を生成できますが、速度は遅くなります
補間処理では、図の点 (x, y) = (i + u, j + v) の値は、長方形グリッド内の点に隣接する 16 個の点の加重平均によって取得されます。点に対する 16 点の順序は {(i-1,j-1),(i-1,j),(i-1,j+1),(i-1,j+2) , …,(i,j),… ,(i+2,j-1),(i+2,j),(i+2,j+1),(i+2,j+2)}, で今回は、X 方向と Y 方向にそれぞれ従う必要があります。対応する結果は、多項式補間 3 次関数を使用して計算されます
補間式は次のとおりです。a ij
ここに画像の説明を挿入します
を使用して各隣接点を表し、f ij を使用して元の画像内の点 a ijのピクセル値を表し、w iと w jはそれぞれ、対応する方向の点の重みを表します。たとえば、00 は、長方形グリッドの左上隅の最初の点を表します。以下同様です。最初のステップは、バイキュービック関数を通じてすべての重みを計算し、必要な補間計算を実行することです。構築された双三次関数は次のとおりです。a=-0.5 の場合、関数の形状は次のとおりです。

ここに画像の説明を挿入します

ここに画像の説明を挿入します
基本的な知識は理解できました。次に、補間処理の具体的な手順を見てみましょう。Dst と Src をそれぞれターゲット画像と元の画像を表すために使用します。点 A のピクセル値を知る必要があります。 Dst の (dst_x, dst_y) は次のようになります。A (dst_x,dst_y) は、P(src_x,src_y)=P(x,y) として元の画像内の点に対応します。 1) 記事の冒頭の式を使用します
ここに画像の説明を挿入します

。 src_x, src_y から dst_x, dst_y までを計算します。このとき、一般的に src_x, src_y は 10 進数であり、src_x=i+u、src_y=j+v、(i, j) とその周囲の 16 個の隣接する src_x=i+u、src_y=j+v として記録できます。点は長方形のグリッドを形成します; 2) バイキュービック関数は 1 次元関数であるため、
X および Y 方向に沿って各点に対応する重みを個別に計算する必要があります。各点の重みは w ij (w_x, w_y).計算プロセスは次のとおりです。

  • 点と点 P の XY 方向の距離 l ij (l_x,l_y) を明らかにします。たとえば、 00 (i-1,j-1) と P(i+u,j+v)の距離) は l 00 (i+u-i+1,j+v-j+1)=l 00 (u+1,v+1)、a 33 (i+2,j+2) および P(i+ u,j +v) は l 33 (i+2-iu,j+2-jv)=l 33 (2-u,2-v) です。
  • したがって、各隣接点に対応する重みは w(w_x,w_y)=w(W(l_x),W(l_y)) になります。ここで、W はバイキュービック関数を指します。

3) 各点に対応する重みを求めた後、補間式により補間結果 B(dst_x,dst_y) を求めることができ、00 点から合計 16 点の距離 l(l_x,l_y) を簡単に計算
できます
。たとえば、 a 00と Pの間の距離は次のようになります。 l 00 (l_0,l_0)=l 00 (u+1,v+1)、 a 33と Pの間の距離はのようになります。 : l 33 (l_3,l_3) =l 33 (2-u,2-v)、これで誰もがバイキュービック補間のプロセスを理解できるはずです。-------------------------------------------------- -------------------------------------------------- -----------------------実際、行列表現は次のように補間計算にも使用できます。
ここに画像の説明を挿入します



ここに画像の説明を挿入します

このうち、f(i+u,j+v) は計算対象の値、A と C はそれぞれ重みを表し、第 1 の方法では w_x、w_y、B は第 1 の方法では隣接する 16 点からなる行列です。重みを計算する関数は S(x) を使用して近似します。

2. 例を挙げる

入力はSrc:5×5、出力はDst:10×10、Dstの中点(5,5)の値を求めてみましょう:
ここに画像の説明を挿入します
上記の行列演算方法の計算処理を手動で実装します(計算結果は常に計算されます) Pytorch の組み込み関数を使用すると、結果に一定の偏差があり、非常に困惑しています)。

import numpy as np
import math

src_w=src_h=5
dst_w=dst_h=10

dst_x=dst_y=5
src_x=dst_x*(src_h/dst_h)
src_y=dst_y*(src_w/dst_w)

i=math.floor(src_x)
j=math.floor(src_y)

u=src_x-i
v=src_y-j
# print(i,j,u,v)
# l_x=np.array([[1.5,0.5,0.5,1.5]])
# l_y=np.array([[1.5,0.5,0.5,1.5]])
base=[1,0,-1,-2]


def l_(r):
    a=np.zeros((1,4))
    for j in range(4):
        a[0,j]=r+base[j]
    return a


l_x,l_y=l_(u),l_(v)
# print(l_x)
# print(l_y)

# # print(l_x.shape)
#
#
def S_x(l_):
    s=np.zeros(shape=(1,4))
    for j in range(4):
        x_abs=math.fabs(l_[0,j])
        if x_abs <= 1:
            s[0,j] = 1-2* math.pow(x_abs, 2)+math.pow(x_abs, 3)
        elif x_abs < 2 and x_abs > 1:
            s[0,j] = 4-8*x_abs+5*math.pow(x_abs, 2) - math.pow(x_abs, 3)
    return s


A,C=S_x(l_x),S_x(l_y)

B=np.array([
         [9., 0., 7., 3.],
         [7., 0., 1., 8.],
         [1., 8., 1., 3.],
         [5., 5., 1., 1.]])
b=np.matmul(np.matmul(A,B),np.transpose(C))
print(b)

3. コードの実装

import torch
import torch.nn as nn
from torchvision import transforms


img=torch.randint(10,size=(1,4,4),dtype=torch.float32)
print(img)
print('---'*5)
bicubic_interpolation=transforms.Resize(size=(8,8),
                                       interpolation=transforms.InterpolationMode.BICUBIC)
resize_img=bicubic_interpolation(img)
print(resize_img)

4. Pytorchの実装

Pytorch の異なる補間メソッドは、transforms.Resize メソッドの interpolation パラメータによって指定されることに注意してください。上記の 3 つのメソッドは、次の 3 つのモードを順番に使用するだけで済みます。

補間法 指定方法
最近傍補間 変換.InterpolationMode.NEAREST
双一次補間 変換.InterpolationMode.BILINEAR
バイキュービック補間 変換.InterpolationMode.BICUBIC

ここでは、ジェイ・チョウの写真を使用して、3 つの方法に対応する補間結果を示します。
元の画像は次のとおりです。
ここに画像の説明を挿入します

import torch
from torchvision import transforms
from PIL import Image
from torchvision.utils import  save_image


img=Image.open('./Jay.png',mode='r')
img_to_tensor=transforms.ToTensor()(img)
# print(img_to_tensor.shape)

nearest_neighbor_interpolation=transforms.Resize(size=(1024,1024),
                                       interpolation=transforms.InterpolationMode.NEAREST)
nearest_resize_img=nearest_neighbor_interpolation(img_to_tensor)

bilinear_interpolation=transforms.Resize(size=(1024,10248),
                                       interpolation=transforms.InterpolationMode.BILINEAR)
bilinear_resize_img=bilinear_interpolation(img_to_tensor)
#
bicubic_interpolation=transforms.Resize(size=(1024,1024),
                                       interpolation=transforms.InterpolationMode.BICUBIC)
bicubic_resize_img=bicubic_interpolation(img_to_tensor)

save_image(nearest_resize_img,'./nearest.png')
save_image(bilinear_resize_img,'./bilinear.png')
save_image(bicubic_resize_img,'./bicubic.png')

補間結果:
1) 最近傍補間
ここに画像の説明を挿入します

2) 双一次補間
ここに画像の説明を挿入します

3) バイキュービック補間
ここに画像の説明を挿入します

参考:

1) https://blog.csdn.net/JNingWei/article/details/78822026
2) https://blog.csdn.net/qq_30815237/article/details/90605132
3) https://blog.csdn.net/ weixin_43135178/article/details/117262348
4) 「百度百科」は
7 月にはこのイベントに注目していませんでしたが、今日たまたま見つけました。参加しましょう。
皆様からのアドバイスを歓迎し、一緒に学べる内容となっております。

おすすめ

転載: blog.csdn.net/qq_43665602/article/details/126853751