我有兩個numpy數組是OpenCV凸包,我想檢查相交而不創建循環或創建圖像並對它們執行numpy.bitwise_and
,兩者在Python中都很慢。陣列看起來像這樣:
[[[x1 y1]]
[[x2 y2]]
[[x3 y3]]
...
[[xn yn]]]
考慮[[X1 Y1]]爲一個單獨的元件,我想在兩個numpy的ndarrays之間執行交叉點。我怎樣才能做到這一點?我發現了幾個類似性質的問題,但我無法從那裏找出解決方案。
在此先感謝!
我有兩個numpy數組是OpenCV凸包,我想檢查相交而不創建循環或創建圖像並對它們執行numpy.bitwise_and
,兩者在Python中都很慢。陣列看起來像這樣:
[[[x1 y1]]
[[x2 y2]]
[[x3 y3]]
...
[[xn yn]]]
考慮[[X1 Y1]]爲一個單獨的元件,我想在兩個numpy的ndarrays之間執行交叉點。我怎樣才能做到這一點?我發現了幾個類似性質的問題,但我無法從那裏找出解決方案。
在此先感謝!
所以這是我做了什麼,以完成這項工作:
import Polygon, numpy
# Here I extracted and combined some contours and created a convex hull from it.
# Now I wanna check whether a contour acquired differently intersects with this hull or not.
for contour in contours: # The result of cv2.findContours is a list of contours
contour1 = contour.flatten()
contour1 = numpy.reshape(contour1, (int(contour1.shape[0]/2),-1))
poly1 = Polygon.Polygon(contour1)
hull = hull.flatten() # This is the hull is previously constructued
hull = numpy.reshape(hull, (int(hull.shape[0]/2),-1))
poly2 = Polygon.Polygon(hull)
if (poly1 & poly2).area()<= some_max_val:
some_operations
我不得不使用for循環,這完全看起來有點乏味,雖然它給了我預期的結果。任何更好的方法將不勝感激!
可以使用http://pypi.python.org/pypi/Polygon/2.0.4,這裏有一個例子:
>>> import Polygon
>>> a = Polygon.Polygon([(0,0),(1,0),(0,1)])
>>> b = Polygon.Polygon([(0.3,0.3), (0.3, 0.6), (0.6, 0.3)])
>>> a & b
Polygon:
<0:Contour: [0:0.60, 0.30] [1:0.30, 0.30] [2:0.30, 0.60]>
要轉換cv2.findContours到多邊形點格式的結果,您可以:
points1 = contours[0].reshape(-1,2)
這將形狀從轉換(N,1)到(N,2)
以下是完整示例:
import Polygon
import cv2
import numpy as np
from scipy.misc import bytescale
y, x = np.ogrid[-2:2:100j, -2:2:100j]
f1 = bytescale(np.exp(-x**2 - y**2), low=0, high=255)
f2 = bytescale(np.exp(-(x+1)**2 - y**2), low=0, high=255)
c1, hierarchy = cv2.findContours((f1>120).astype(np.uint8),
cv2.cv.CV_RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
c2, hierarchy = cv2.findContours((f2>120).astype(np.uint8),
cv2.cv.CV_RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
points1 = c1[0].reshape(-1,2) # convert shape (n, 1, 2) to (n, 2)
points2 = c2[0].reshape(-1,2)
import pylab as pl
poly1 = pl.Polygon(points1, color="blue", alpha=0.5)
poly2 = pl.Polygon(points2, color="red", alpha=0.5)
pl.figure(figsize=(8,3))
ax = pl.subplot(121)
ax.add_artist(poly1)
ax.add_artist(poly2)
pl.xlim(0, 100)
pl.ylim(0, 100)
a = Polygon.Polygon(points1)
b = Polygon.Polygon(points2)
intersect = a&b # calculate the intersect polygon
poly3 = pl.Polygon(intersect[0], color="green") # intersect[0] are the points of the polygon
ax = pl.subplot(122)
ax.add_artist(poly3)
pl.xlim(0, 100)
pl.ylim(0, 100)
pl.show()
輸出:
可以使用陣列的視圖作爲一個單一的尺寸與intersect1d函數是這樣的:
def multidim_intersect(arr1, arr2):
arr1_view = arr1.view([('',arr1.dtype)]*arr1.shape[1])
arr2_view = arr2.view([('',arr2.dtype)]*arr2.shape[1])
intersected = numpy.intersect1d(arr1_view, arr2_view)
return intersected.view(arr1.dtype).reshape(-1, arr1.shape[1])
這在每個陣列的視圖,改變每行到一個值的元組。然後執行交集,並將結果更改回原始格式。下面是使用它的一個例子:
test_arr1 = numpy.array([[0, 2],
[1, 3],
[4, 5],
[0, 2]])
test_arr2 = numpy.array([[1, 2],
[0, 2],
[3, 1],
[1, 3]])
print multidim_intersect(test_arr1, test_arr2)
此打印:
[[0 2]
[1 3]]
非常感謝您的迴應!如果外圍的所有點都在numpy數組中,這將是完美的。但是,在凸包中,我認爲只有幾點作爲指導。但是在這種情況下,交叉點就是兩個區域的共同價值,這在numpy數組本身內可能並不常見。我剛剛閱讀我的帖子,並意識到我沒有提到這一點。我爲此感到抱歉。 – 2012-02-14 08:26:29
當我將視圖應用於自己的numpy時,它看起來像這樣: [[[(x1,)(y1,)]] [[(x2,)(y2,)]] ... [[(xn, )(YN)]]] 而我們真正需要的是這樣的: [(X1,Y1),(X2,Y2),(X3,Y3),...,(XN,YN)] 任何想法? – 2012-02-14 10:59:44
由於某種原因您是否只有一個額外的軸?你可以用''test_arr1.reshape(len(test_arr1),2)''來重新初始化它嗎?這將避免副本。 – jterrace 2012-02-14 14:13:19
通過jiterrace的回答
我碰到這個帖子附帶Udacity deep learning class(工作試圖找到訓練和測試數據之間的重疊),同時啓發。
我對「視圖」不熟悉,發現語法有點難以理解,當我嘗試與在「表」中思考的朋友進行交流時可能也是如此。 我的方法基本上是將形狀(N,X,Y)的狀態平坦化/重塑爲形狀(N,X * Y,1)。
print(train_dataset.shape)
print(test_dataset.shape)
#(200000L, 28L, 28L)
#(10000L, 28L, 28L)
1)。INNER JOIN(容易理解,緩慢)
%%timeit -n 1 -r 1
def multidim_intersect_df(arr1, arr2):
p1 = pd.DataFrame([r.flatten() for r in arr1]).drop_duplicates()
p2 = pd.DataFrame([r.flatten() for r in arr2]).drop_duplicates()
res = p1.merge(p2)
return res
inters_df = multidim_intersect_df(train_dataset, test_dataset)
print(inters_df.shape)
#(1153, 784)
#1 loop, best of 1: 2min 56s per loop
2)。 SET INTERSECTION(快速)
%%timeit -n 1 -r 1
def multidim_intersect(arr1, arr2):
arr1_new = arr1.reshape((-1, arr1.shape[1]*arr1.shape[2])) # -1 means row counts are inferred from other dimensions
arr2_new = arr2.reshape((-1, arr2.shape[1]*arr2.shape[2]))
intersected = set(map(tuple, arr1_new)).intersection(set(map(tuple, arr2_new))) # list is not hashable, go tuple
return list(intersected) # in shape of (N, 28*28)
inters = multidim_intersect(train_dataset, test_dataset)
print(len(inters))
# 1153
#1 loop, best of 1: 34.6 s per loop
這種方法真的很快嗎?我需要在捕獲時檢查每個幀的相交情況,並且系統資源不是很高。 – 2012-02-14 08:32:35
當我嘗試從opencv輪廓或凸包創建多邊形時,這是我得到的錯誤: 'cPolygon.Error:操作的多邊形或輪廓無效' 您指定的格式不是我擁有的格式(顯示在我原來的帖子中)。我認爲可能需要進行一些修改,但無法想象如何完成。 – 2012-02-14 10:37:58
請發佈一些示例數據。 – HYRY 2012-02-14 11:30:08