日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

(转载)Pytorch中的仿射变换(affine_grid)

發布時間:2023/12/31 综合教程 30 生活家
生活随笔 收集整理的這篇文章主要介紹了 (转载)Pytorch中的仿射变换(affine_grid) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載于:Pytorch中的仿射變換(affine_grid)

參考:詳細解讀Spatial Transformer Networks (STN)

假設我們有這么一張圖片:


下面我們將通過分別通過手動編碼和pytorch方式對該圖片進行平移、旋轉、轉置、縮放等操作,這些操作的數學原理在本文中不會詳細講解。

實現載入圖片(注意,下面的代碼都是在 jupyter 中進行):

 1 from torchvision import transforms
 2 from PIL import Image
 3 import matplotlib.pyplot as plt
 4 
 5 %matplotlib inline
 6 
 7 img_path = "圖片文件路徑"
 8 img_torch = transforms.ToTensor()(Image.open(img_path))
 9 
10 plt.imshow(img_torch.numpy().transpose(1,2,0))
11 plt.show()

平移操作

普通方式

例如我們需要向右平移50px,向下平移100px。

 1 import numpy as np
 2 import torch
 3 
 4 theta = np.array([
 5     [1,0,50],
 6     [0,1,100]
 7 ])
 8 # 變換1:可以實現縮放/旋轉,這里為 [[1,0],[0,1]] 保存圖片不變
 9 t1 = theta[:,[0,1]]
10 # 變換2:可以實現平移
11 t2 = theta[:,[2]]
12 
13 _, h, w = img_torch.size()
14 new_img_torch = torch.zeros_like(img_torch, dtype=torch.float)
15 for x in range(w):
16     for y in range(h):
17         pos = np.array([[x], [y]])
18         npos = t1@pos+t2
19         nx, ny = npos[0][0], npos[1][0]
20         if 0<=nx<w and 0<=ny<h:
21             new_img_torch[:,ny,nx] = img_torch[:,y,x]
22 plt.imshow(new_img_torch.numpy().transpose(1,2,0))
23 plt.show()

圖片變為:

圖片平移-1

pytorch 方式

向右移動0.2,向下移動0.4:

 1 from torch.nn import functional as F
 2 
 3 theta = torch.tensor([
 4     [1,0,-0.2],
 5     [0,1,-0.4]
 6 ], dtype=torch.float)
 7 grid = F.affine_grid(theta.unsqueeze(0), img_torch.unsqueeze(0).size())
 8 output = F.grid_sample(img_torch.unsqueeze(0), grid)
 9 new_img_torch = output[0]
10 plt.imshow(new_img_torch.numpy().transpose(1,2,0))
11 plt.show()

得到的圖片為:


圖片平移-2

總結:

要使用 pytorch 的平移操作,只需要兩步:theta 的第三列為平移比例,向右為負,向下為負;

創建 grid:grid = torch.nn.functional.affine_grid(theta, size),其實我們可以通過調節 size 設置所得到的圖像的大小(相當于resize);
grid_sample 進行重采樣:outputs = torch.nn.functional.grid_sample(inputs, grid, mode='bilinear')

theta 的第三列為平移比例,向右為負,向下為負;

我們通過設置 size 可以將圖像resize:

 1 from torch.nn import functional as F
 2 
 3 theta = torch.tensor([
 4     [1,0,-0.2],
 5     [0,1,-0.4]
 6 ], dtype=torch.float)
 7 # 修改size
 8 N, C, W, H = img_torch.unsqueeze(0).size()
 9 size = torch.Size((N, C, W//2, H//3))
10 grid = F.affine_grid(theta.unsqueeze(0), size)
11 output = F.grid_sample(img_torch.unsqueeze(0), grid)
12 new_img_torch = output[0]
13 plt.imshow(new_img_torch.numpy().transpose(1,2,0))
14 plt.show()


修改size的效果

縮放操作

普通方式

放大1倍:

 1 import numpy as np
 2 import torch
 3 
 4 theta = np.array([
 5     [2,0,0],
 6     [0,2,0]
 7 ])
 8 t1 = theta[:,[0,1]]
 9 t2 = theta[:,[2]]
10 
11 _, h, w = img_torch.size()
12 new_img_torch = torch.zeros_like(img_torch, dtype=torch.float)
13 for x in range(w):
14     for y in range(h):
15         pos = np.array([[x], [y]])
16         npos = t1@pos+t2
17         nx, ny = npos[0][0], npos[1][0]
18         if 0<=nx<w and 0<=ny<h:
19             new_img_torch[:,ny,nx] = img_torch[:,y,x]
20 plt.imshow(new_img_torch.numpy().transpose(1,2,0))
21 plt.show()

結果為:

放大操作-1

由于沒有使用插值算法,所以中間有很多部分是黑色的。

pytorch 方式

 1 from torch.nn import functional as F
 2 
 3 theta = torch.tensor([
 4     [0.5, 0  , 0],
 5     [0  , 0.5, 0]
 6 ], dtype=torch.float)
 7 grid = F.affine_grid(theta.unsqueeze(0), img_torch.unsqueeze(0).size())
 8 output = F.grid_sample(img_torch.unsqueeze(0), grid)
 9 new_img_torch = output[0]
10 plt.imshow(new_img_torch.numpy().transpose(1,2,0))
11 plt.show()

結果為:

放大操作-2

結論:可以看到,affine_grid的放大操作是以圖片中心為原點的。

旋轉操作

普通操作

將圖片旋轉30度:

import numpy as np
import torch
import math

angle = 30*math.pi/180
theta = np.array([
    [math.cos(angle),math.sin(-angle),0],
    [math.sin(angle),math.cos(angle) ,0]
])
t1 = theta[:,[0,1]]
t2 = theta[:,[2]]

_, h, w = img_torch.size()
new_img_torch = torch.zeros_like(img_torch, dtype=torch.float)
for x in range(w):
    for y in range(h):
        pos = np.array([[x], [y]])
        npos = t1@pos+t2
        nx, ny = int(npos[0][0]), int(npos[1][0])
        if 0<=nx<w and 0<=ny<h:
            new_img_torch[:,ny,nx] = img_torch[:,y,x]
plt.imshow(new_img_torch.numpy().transpose(1,2,0))
plt.show()

結果為:

旋轉操作-1

pytorch 操作

from torch.nn import functional as F
import math

angle = -30*math.pi/180
theta = torch.tensor([
    [math.cos(angle),math.sin(-angle),0],
    [math.sin(angle),math.cos(angle) ,0]
], dtype=torch.float)
grid = F.affine_grid(theta.unsqueeze(0), img_torch.unsqueeze(0).size())
output = F.grid_sample(img_torch.unsqueeze(0), grid)
new_img_torch = output[0]
plt.imshow(new_img_torch.numpy().transpose(1,2,0))
plt.show()

結果為:

旋轉操作-2

pytorch 以圖片中心為原點進行旋轉,并且在旋轉過程中會發生圖片縮放,如果選擇角度變為 90°,圖片為:

旋轉 90° 結果

轉置操作

普通操作

 1 import numpy as np
 2 import torch
 3 
 4 theta = np.array([
 5     [0,1,0],
 6     [1,0,0]
 7 ])
 8 t1 = theta[:,[0,1]]
 9 t2 = theta[:,[2]]
10 
11 _, h, w = img_torch.size()
12 new_img_torch = torch.zeros_like(img_torch, dtype=torch.float)
13 for x in range(w):
14     for y in range(h):
15         pos = np.array([[x], [y]])
16         npos = t1@pos+t2
17         nx, ny = npos[0][0], npos[1][0]
18         if 0<=nx<w and 0<=ny<h:
19             new_img_torch[:,ny,nx] = img_torch[:,y,x]
20 plt.imshow(new_img_torch.numpy().transpose(1,2,0))
21 plt.show()

結果為:


圖片轉置-1

pytorch 操作

我們可以通過size大小,保存圖片不被壓縮:

 1 from torch.nn import functional as F
 2 
 3 theta = torch.tensor([
 4     [0, 1, 0],
 5     [1, 0, 0]
 6 ], dtype=torch.float)
 7 N, C, H, W = img_torch.unsqueeze(0).size()
 8 grid = F.affine_grid(theta.unsqueeze(0), torch.Size((N, C, W, H)))
 9 output = F.grid_sample(img_torch.unsqueeze(0), grid)
10 new_img_torch = output[0]
11 plt.imshow(new_img_torch.numpy().transpose(1,2,0))
12 plt.show()

結果為:

圖片轉置-2

總結

以上是生活随笔為你收集整理的(转载)Pytorch中的仿射变换(affine_grid)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。