好的。在我看來,你的期望是正確的,例如np.interp
給出了0.1
和0.9
的值。
我們繪製金字塔(插值到49:51方形像素範圍):
import numpy as np
import cv2
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
prvs = np.zeros((100,80), dtype=np.float32)
prvs[50:51, 50:51] = 1
lin = np.linspace(49,51,200)
grid_x,grid_y = np.meshgrid(lin,lin)
grid_x = grid_x.astype(np.float32)
grid_y = grid_y.astype(np.float32)
prvs_zoommapped = cv2.remap(prvs, grid_x, grid_y, interpolation=cv2.INTER_LINEAR)
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
ax.plot_surface(grid_x,grid_y,prvs_zoommapped,cmap='viridis')
plt.show()
注意到什麼了嗎?用200x200的繪圖網格,在金字塔上有非常明顯的步驟。讓我們來看看我們結果的橫截面:
fig,ax = plt.subplots()
ax.plot(prvs_zoommapped[100,:],'x-')
ax.grid('on')
plt.show()
正如你所看到的,結果是分段常數函數,即有輸出巨大的離散誤差。準確地說,我們在結果中看到0.03125 == 1/32
的步驟。
我懷疑cv2.remap
不是用於子像素操作,而是用於從一個網格到另一個網格的大規模映射。另一種選擇是內部精度已經犧牲了性能。無論哪種方式,你都不會發瘋:你應該看到0.1
和0.9
是精確(雙)線性插值的結果。
如果由於其他任務而不承諾openCV,則可以用scipy.interpolate
的各個位即its parts made for 2d interpolation來執行該映射,即2d內插。對於常規網格上的線性插值的特殊情況,scipy.interpolate.RegularGridInterpolator
或類似的東西可能是合適的。
甚至更好(但我沒有用過這個子模塊還):scipy.ndimage.map_coordinates
好像你正在尋找什麼:
from scipy import ndimage
ndimage.map_coordinates(prvs, [[50.1, 49.1], [50, 50]], order=1)
# output: array([ 0.89999998, 0.1 ], dtype=float32)
應用到金字塔例如:
import numpy as np
import cv2
from scipy import ndimage
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
prvs = np.zeros((100,80), dtype=np.float32)
prvs[50:51, 50:51] = 1
lin = np.linspace(49,51,200)
grid_x,grid_y = np.meshgrid(lin,lin)
prvs_zoommapped = ndimage.map_coordinates(prvs, [grid_x, grid_y], order=1)
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
ax.plot_surface(grid_x,grid_y,prvs_zoommapped,cmap='viridis')
plt.show()
好多了。
謝謝。 ndimage.map_coordinates按預期工作。 插值錯誤似乎與您已經說過的一些性能優化有關。另見http://answers.opencv.org/question/123197/how-to-increase-warpperspective-or-warpaffine-precision/ –
@JulianS。我很高興它,並感謝鏈接,似乎是正確的。 –
只是更多的後續工作:我重新編譯OpenCV並將imgproc.hpp中的INTER_BITS從5更改爲10(如上面給出的鏈接所示)。現在錯誤降到0.00391。該錯誤似乎是1/2^N,N是一個整數。但是,在INTER_BITS = 5的情況下爲1/2^4,在INTER_BITS = 10的情況下爲1/2^8。所以它不只是1/2 ^(INTER_BITS - 1)。但爲了防止有人想提高OpenCV的精度,並且不能更改爲另一個庫,我認爲這可能會有所幫助。 –