簡介
本文主要介紹柱面投影變換,將這種變換用於圖像處理,可以產生圖像扭曲的效果,如下圖所示,產生了將平面圖像投影到了柱面上的視覺效果。博客最後給出了柱面投影的python實現,供讀者參考。
數學原理
如下圖所示,矩形GHEF爲待處理的原圖,投影到柱面上之後則變成了曲面JDILCK。我們假設相機模型爲針孔模型,且所處位置爲N點,下面分析原圖GHEF與投影曲面JDILCK各像素之間的對應關係。
俯視圖如下圖所示,我們以原圖像的中心(W/2, H/2)爲原點,假設相機的焦距爲f(f的值我們可以隨意選擇,不需要相機的真實焦距)。
下面我們進行幾何分析,點 –W/2 映射到 –W‘/2 ,點W/2 映射到W’/2 ,因此直線【–W/2,W/2】爲原圖X方向,曲線【–W‘/2 ,O ,W’/2】爲投影曲面的X方向。
假設原平面上有一點x, 映射到曲面上爲x‘(在投影曲面X方向上的座標爲x‘, 即弧長爲x’),設角xNO爲θ,θ = arctan
(x/f),弧長x’ = f×θ。因此X方向上柱面投影的映射關係爲 x‘ = f × arctan(x/f)。
接下來看側視圖,以確定Y方向上原圖與投影圖像素的對應關係。側視圖中的紅色虛線與俯視圖中的紅色虛線相對
應。由俯視圖可得線段xN = f / cos(θ),由側視圖中的相似三角形關係可得y‘ / f = y /(f/cos(θ))。
綜上所述,可得原圖與投影曲面各像素的對應關係如下
from skimage.io import imread, imshow ,imsave
from skimage.transform import resize
import math
import numpy as np
img = imread('img.jpg')
img = (resize(img , [1000,800])*255).astype(np.uint8)
###圓柱投影
def cylindrical_projection(img , f) :
rows = img.shape[0]
cols = img.shape[1]
#f = cols / (2 * math.tan(np.pi / 8))
blank = np.zeros_like(img)
center_x = int(cols / 2)
center_y = int(rows / 2)
for y in range(rows):
for x in range(cols):
theta = math.atan((x- center_x )/ f)
point_x = int(f * math.tan( (x-center_x) / f) + center_x)
point_y = int( (y-center_y) / math.cos(theta) + center_y)
if point_x >= cols or point_x < 0 or point_y >= rows or point_y < 0:
pass
else:
blank[y , x, :] = img[point_y , point_x ,:]
return blank
waved_img = cylindrical_projection(img,500)
imshow(waved_img)
補充:
2、此外,我們可以將相機的位置N點進行移動,產生不同的柱面變換。在程序實現時,我們直接更改center_x與
center_y的值即可。例如,center_x = int(cols/3), center_y = int(rows/2), 產生的效果圖如下所示。