2017-02-19 150 views
2

我有一個NumPy數組contours,我從cv2.findContours得到並使用contours = np.concatenate(contours, axis = 0)變平。它存儲圖像中物體輪廓的座標。但是,我想刪除X或Y低於100的座標,或者大於1000.我首先嚐試使用contours = np.delete(contours, 0)contours = np.delete(contours[0], 0)來刪除任何項目,但我一直收到此錯誤: IndexError: invalid index to scalar variable.從NumPy數組中刪除值對

如何刪除這樣的值對?

print(type(contours)) 
→ <class 'numpy.ndarray'> 
print(contours[0]) 
→ [[2834 4562]] 
print(type(contours[0])) 
→ <class 'numpy.ndarray'> 
print(contours[0][0]) 
→ [2834 4562] 
print(type(contours[0][0])) 
<class 'numpy.ndarray'> 

而且,我不希望任何進一步串聯/壓平的列表中,因爲它正是在我需要它發送到cv2.convexHull(contours)形式。

這裏是我的代碼的最小工作示例:

import cv2   # library for processing images 
import numpy as np # numerical calculcations for Python 

img = cv2.imread("img.png") 
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
_, img_thr = cv2.threshold(img_gray,0,255,cv2.THRESH_OTSU) 
img_rev = cv2.bitwise_not(img_thr) 
img_cnt, contours, hierarchy = cv2.findContours(img_rev, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 
contours = np.concatenate(contours, axis = 0) 

hull = cv2.convexHull(contours) 
rect = cv2.minAreaRect(np.int0(hull)) 
box = cv2.boxPoints(rect) 
box = np.int0(box) 

img_cnt = cv2.drawContours(img, contours, -1, (0,255,0), 3) 
img_cnt = cv2.drawContours(img, [box], -1, (0,0,255), 5) 

cv2.imwrite("img_out.png", img_cnt) 

下面是一個簡單input image,這裏是我的output image。我想忽略文字選擇的偏離「噪音」。假設我不能進一步降噪。

+1

請創建一個[Minimal,Complete,and Verifiable](http://stackoverflow.com/help/mcve)示例。這使我們更容易幫助你。 –

回答

2

似乎輪廓形狀是(N,1,2)。在這種情況下,

contours[((contours>100)&(contours<1000)).all(axis=(1,2))] 

將工作。

舉例:

In [106]: contours=randint(0,1100,(10,1,2)) 
[[[ 803 772]] 
[[ 210 490]] 
[[ 433 76]] 
[[ 347 88]] 
[[ 763 747]] 
[[ 678 200]] 
[[ 816 444]] 
[[ 528 817]] 
[[ 140 440]] 
[[1019 654]]] 

In [108]: valid = ((contours>100)&(contours<1000)).all(axis=(1,2)) 
Out[108]: array([ True, True, False, False, True, True, 
        True, True, True, False], dtype=bool) 

In [111]: contours[valid] 
Out[111]: 
array([[[803, 772]], 
     [[210, 490]], 
     [[763, 747]], 
     [[678, 200]], 
     [[816, 444]], 
     [[528, 817]], 
     [[140, 440]]]) 

如果你想在X和Y不同的片段,那麼你可以使用

(contours>[xmin,ymin])&(contours<[xmax,ymax]) 

代替。

+0

感謝您的解決方案和解釋。像現在的魅力:) – MrVocabulary

+0

我會允許我自己一個簡短的後續問題:如果我想爲每個軸設置不同的閾值,該怎麼辦?據我所知,所有()需要一個迭代。 – MrVocabulary

+1

我編輯這個案例的帖子。 –