我正在使用flow = cv2.calcOpticalFlowFarneback()來計算視頻中的光流,它給了我一個形狀為 (height, width, 2) 的 numpy 陣列,其中包含每個像素的Fx和Fy值(flow[: ,:,0] = Fx和流[:,:,1] = Fy )。
為了計算散度,我使用 np.gradient 像這樣:
def divergence_npgrad(flow):
Fx, Fy = flow[:, :, 0], flow[:, :, 1]
F = [Fx, Fy]
d = len(F)
return np.ufunc.reduce(np.add, [np.gradient(F[i], axis=i) for i in range(d)])
接下來,我要計算卷曲。我知道sympy.physics.vector中有一個 curl 函式,但我真的不明白它是如何作業的,或者它如何應用于我的flow。所以我想我也可以為此使用 np.gradient 。在 2D 中,我需要為每個像素計算dFy/dx - dFx/dy,所以我會是這樣的:
def curl_npgrad(flow):
Fx, Fy = flow[:, :, 0], flow[:, :, 1]
dFx_dy = np.gradient(Fx, axis=1)
dFy_dx = np.gradient(Fy, axis=0)
curl = np.ufunc.reduce(np.subtract, [dFy_dx, dFx_dy])
return curl
這是正確的方法還是我錯過了什么?
現在,如果我有curl,我想用matplotlib制作兩個圖。我的觀點是我想用不同的顏色圖顯示來自流的向量。一個圖將使用向量的幅度值作為顏色圖,歸一化為 (0-magnitude_max)。另一個圖將使用curl值作為顏色圖,如果curl為負,則箭頭為藍色,如果curl在該位置為正,則箭頭為紅色。
這是我正在嘗試使用的:
def flow_plot(flow, frame):
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w = flow.shape[:2]
dpi = 72
xinch = w / dpi
yinch = h / dpi
step = 24
y, x = np.mgrid[step / ((h % step) // 2):h:step, step / ((w % step) // 2):w:step].reshape(2, -1).astype(int)
fx, fy = flow[y, x].T
mag = np.sqrt(np.power(fx, 2) np.power(fy, 2))
fx = fx / mag
fy = fy / mag
curl = curl_npgrad(flow)
curl_map = curl[y, x]
quiver_params = dict(cmap='Oranges', # for magnitude
#cmap='seismic', # for curl
norm=colors.Normalize(vmin=0.0, vmax=1.0), # for magnitude
#norm = colors.CenteredNorm(), # for curl
units='xy',
scale=0.03,
headwidth=3,
headlength=5,
minshaft=1.5,
pivot='middle')
fig = plt.figure(figsize=(xinch, yinch), dpi=dpi)
plt.imshow(frame)
plt.quiver(x, y, fx, fy, mag, **quiver_params)
plt.gca().invert_yaxis()
plt.gca().set_aspect('equal', 'datalim')
plt.axis('off')
fig.tight_layout(pad=0)
fig.canvas.draw()
img = np.frombuffer(fig.canvas.tostring_rgb(), dtype='uint8')
img = img.reshape(fig.canvas.get_width_height()[::-1] (3,))
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
img = cv2.flip(img, 0)
plt.close(fig)
return img
我正在將繪圖轉換為 cv2 影像,以便可以將其用于 opencv 視頻撰寫器。
我注意到,如果我沒有在繪圖后面顯示原始幀,我必須反轉 y 軸并在plt.quiver()中使用-fy,如果我想顯示后面的幀,我必須反轉 y 軸也可以使用fy,但之后我必須翻轉整個影像。這有什么意義?我無法得到它。
至于卷曲,對我來說有點亂。幾乎沒有任何顏色,隨機的紅色和藍色斑點,而不是流體明顯旋轉的紅色/藍色箭頭。就像這樣:

對于這個函式,各處的散度都應該很高。應用你的函式,它告訴我散度為 0。
生成此陣列的代碼:
import numpy as np
import matplotlib.pyplot as plt
x,y = np.meshgrid(np.linspace(-2,2,10),np.linspace(-2,2,10))
u = x
v = y
field2 = np.stack((u, v), axis=-1)
plt.quiver(x, y, field2[:, :, 0], field2[:, :, 1])
我還嘗試了一個測驗 curl 的函式:
F_x = cos(x y)
F_y = sin(x - y)
這產生了這個情節:

生成此陣列的代碼:
import numpy as np
import matplotlib.pyplot as plt
x,y = np.meshgrid(np.linspace(0,2,10),np.linspace(0,2,10))
u = np.cos(x y)
v = np.sin(x - y)
field = np.stack((u, v), axis=-1)
plt.quiver(x, y, field[:, :, 0], field[:, :, 1])
感謝
結果:到處都是正的、恒定的值。
這是第二個函式的 curl 計算結果。

結果:以函式的漩渦部分為中心的正值。(這里的軸發生了變化 - 0,0 在左上角。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/464616.html
標籤:Python 麻木的 opencv matplotlib
