2017-02-19 6 views
2

Ich habe ein NumPy-Array contours, das ich von cv2.findContours erhalten und mit contours = np.concatenate(contours, axis = 0) abgeflacht habe. Es speichert Koordinaten von Konturen von Objekten aus einem Bild. Allerdings möchte ich Koordinaten löschen, deren entweder X oder Y niedriger ist als, sagen wir, 100 oder größer als 1000. Ich versuchte zunächst contours = np.delete(contours, 0) und contours = np.delete(contours[0], 0) mit nur ein Element zu löschen, aber ich hielt diesen Fehler: IndexError: invalid index to scalar variable.Entfernen Sie Wertepaare aus dem NumPy-Array

Wie lösche ich solche Wertepaare?

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'> 

Außerdem mag ich die Liste nicht weiter verketten/abflachen, weil es genau das ist in der Form ich es brauche, um cv2.convexHull(contours) zu senden.

Hier ist eine minimale Arbeitsprobe meines Codes:

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) 

Hier ein Beispiel input image, hier ist mein output image. Ich möchte das "Rauschen" für die Textauswahl ignorieren. Angenommen, ich kann keine weitere Rauschreduzierung verwenden.

+1

Bitte erstellen Sie ein Beispiel [Minimal, vollständig und verifizierbar] (http://stackoverflow.com/help/mcve). Das erleichtert es uns, Ihnen zu helfen. –

Antwort

2

Es scheint, dass contours.shape ist (N, 1,2). In diesem Fall

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

wird funktionieren.

mit gutem Beispiel:

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]]]) 

Wenn Sie verschiedene Clips auf X und Y möchten, dann können Sie

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

stattdessen verwenden.

+0

Danke für die Lösung und die Erklärung. Funktioniert wie Charme jetzt :) – MrVocabulary

+0

Ich erlaube mir eine kurze Folgefrage: Was wäre, wenn ich für jede Achse unterschiedliche Schwellen setzen möchte? Soweit ich weiß, erfordert all() ein iterables. – MrVocabulary

+1

Ich bearbeite den Beitrag für diesen Fall. –