2017-02-19 10 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

Создайте пример [Минимальный, полный и проверенный] (http://stackoverflow.com/help/mcve). Это облегчает нам помощь. –

ответ

2

Кажется, что contours.shape (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

Я редактирую сообщение для этого случая. –