2017-01-06 50 views
1

我想通過OpenCV重新映射函數(在python 2.7中)翹曲640x360圖像。執行的步驟如下使用OpenCV重新映射函數作物圖像

  1. 生成曲線和它的x和y座標存儲在兩個不同的陣列,並且curve_x curve_y.I正在附加所生成的曲線作爲圖像(使用pyplot):Curve

  2. 通過OpenCV的imread函數
  3. 加載圖像

    original = cv2.imread('C:\\Users\\User\\Desktop\\alaskan-landscaps3.jpg') 
    
  4. 執行嵌套的for循環,使得每個像素按比例向上移動到曲線在該高度point.For我度的計算的每個像素通過將曲線的y座標和「天花板」(360)之間的距離除以圖像的高度來確定翹曲因素。然後,該因子與像素的y座標和「天花板」之間的距離相乘,以便找到像素必須與「天花板」相距的新距離(因爲我們有向上移動,所以它會更短)。最後,我從「天花板」中減去這個新距離以獲得像素的新y座標。我想到了這個公式,以確保在重映射函數中使用的map_y數組中的所有條目都在原始圖像的區域內。

    for i in range(0, y_size): 
        for j in range(0,x_size): 
         map_y[i][j]= y_size-((y_size - i) * ((y_size - curve_y[j])/y_size)) 
         map_x[i][j]=j` 
    
  5. 然後使用重映射功能

    warped=cv2.remap(original,map_x,map_y,cv2.INTER_LINEAR) 
    

由此產生的圖像似乎是沿着曲線的路徑有點扭曲,但它被裁剪 - 我附上原始和產生的圖像

Images

我知道我一定是錯過了一些東西,但我無法弄清楚我的代碼中出現了哪些錯誤 - 我不明白爲什麼因爲map_y中的所有y座標都在0-360之間,因此在重映射後圖像的前三分之一已經消失

任何指針或幫助將不勝感激。由於

[編輯:]我已經編輯我的功能如下:

#array to store previous y-coordinate, used as a counter during mapping process 
floor_y=np.zeros((x_size),np.float32) 
#for each row and column of picture 
for i in range(0, y_size): 
    for j in range(0,x_size): 
     #calculate distance between top of the curve at given x coordinate and top 
     height_above_curve = (y_size-1) - curve_y_points[j] 
     #calculated a mapping factor, using total height of picture and distance above curve 
     mapping_factor = (y_size-1)/height_above_curve 
     # if there was no curve at given x-coordinate then do not change the pixel coordinate 
     if(curve_y_points[j]==0): 
      map_y[i][j]=j 
     #if this is the first time the column is traversed, save the curve y-coordinate 
     elif (floor_y[j]==0): 
      #the pixel is translated upwards according to the height of the curve at that point 
      floor_y[j]=i+curve_y_points[j] 
      map_y[i][j]=i+curve_y_points[j] # new coordinate saved 
     # use a modulo operation to only translate each nth pixel where n is the mapping factor. 
     # the idea is that in order to fit all pixels from the original picture into a new smaller space 
     #(because the curve squashes the picture upwards) a number of pixels must be removed 
     elif ((math.floor(i % mapping_factor))==0): 
      #increment the "floor" counter so that the next group of pixels from the original image 
      #are mapped 1 pixel higher up than the previous group in the new picture 
      floor_y[j]=floor_y[j]+1 
      map_y[i][j]=floor_y[j] 
     else: 
      #for pixels that must be skipped map them all to the last pixel actually translated to the new image 
      map_y[i][j]=floor_y[j] 
     #all x-coordinates remain unchanges as we only translate pixels upwards 
     map_x[i][j] = j 
#printout function to test mappings at x=383 
for j in range(0, 360): 
    print('At x=383,y='+str(j)+'for curve_y_points[383]='+str(curve_y_points[383])+' and floor_y[383]='+str(floor_y[383])+' mapping is:'+str(map_y[j][383])) 

的底線是,現在的圖像較高的部分不應該從最低的一部分,以便覆蓋像素收到的映射不應該發生。然而,我仍然在圖片中看到了一個極其誇張的向上翹曲效果,這是我無法解釋的。 (見下圖)。彎曲部分的頂部在原始圖片中y = 140左右,但現在非常接近頂部,即約300.還有一個問題,爲什麼我沒有獲得空白區域在曲線下方的像素底部。

The top of the curved part is at around y=140 in the original picture yet now is very close to the top i.e y around 300

我在想,也許還有一些與行和列的map_y排列的順序怎麼回事?

+0

{}按鈕沒有格式化我發佈的代碼示例,我不知道爲什麼。我試圖格式化代碼,以便它清晰可讀 - 如果您在我管理它之前閱讀這篇文章,我會道歉。 – Socrats

+0

縮進4個空格不起作用,但反推似乎已經奏效。 – Socrats

+0

從編輯器的幫助:「如果你想在列表中有一個預先格式化的塊,用八個空格縮進」。更多詳細信息請參見[高級幫助](http://stackoverflow.com/editing-help#advanced-lists)。 –

回答

0

我不認爲圖像被裁剪。相反,這些值在頂部中間像素中「擁擠」,以便它們被覆蓋。考慮下面的例子,在棋盤上使用一個簡單的函數。

import numpy as np 
import cv2 
import pickle 

y_size=200 
x_size=200 

x=np.linspace(0,x_size,x_size+1) 
y=(-(x-x_size/2)*(x-x_size/2))/x_size+x_size 
plt.plot(x,y) 

功能如下: The curve

然後讓我們產生的圖像與規律。

test=np.zeros((x_size,y_size),dtype=np.float32) 

for i in range(0, y_size): 
    for j in range(0,x_size): 
     if i%2 and j%2: 
      test[i][j]=255 
cv2.imwrite('checker.png',test) 

regular pattern

現在讓我們套用您的移動功能,以這種模式:

map_y=np.zeros((x_size,y_size),dtype=np.float32) 
map_x=np.zeros((x_size,y_size),dtype=np.float32) 

for i in range(0, y_size): 
    for j in range(0,x_size): 
     map_y[i][j]= y_size-((y_size - i) * ((y_size - y[j])/y_size)) 
     map_x[i][j]=j 

warped=cv2.remap(test,map_x,map_y,cv2.INTER_LINEAR) 

cv2.imwrite('warped.png',warped) 

enter image description here

如果您發現,由於移,多個值對應於頂部 - 中部地區,這使得它看起來像被裁剪。但是,如果您檢查圖像的左上角和右下角,請注意值較稀疏,因此「裁剪」效果不會發生太多。我希望這個簡單的例子有助於更好地理解正在發生的事情。

+0

它確實有幫助,謝謝。所以我猜測我需要更復雜的功能來扭曲圖像的那一部分。基本上,我所追求的效果是,由於向上移動,圖像的頂部會出現「壓扁」。有沒有可以產生類似效果的Python/OpenCV實現? – Socrats

+0

嗨,我修改了我的映射函數,考慮到你所描述的內容,但我仍然得到一個奇怪的效果,我無法解釋[用新代碼更新的問題] – Socrats