2016-07-29 10 views
3

Ich versuche, ein Zeichenerkennungsprogramm mit Python zu erstellen. Ich bin dabei, die Konturen zu sortieren. Ich verwende this page als Referenz.Wie kann ich Konturen von links nach rechts und von oben nach unten sortieren?

ich es geschafft, die Konturen mit dem folgenden Stück Code zu finden:

mo_image = di_image.copy() 
contour0 = cv2.findContours(mo_image.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 
contours = [cv2.approxPolyDP(cnt,3,True) for cnt in contour0[0]] 

Und die Hüllrechtecke hinzugefügt und segmentiert das Bild in diesem Teil des Code verwendet:

maxArea = 0 
rect=[] 
for ctr in contours: 
    maxArea = max(maxArea,cv2.contourArea(ctr)) 

if img == "Food.jpg": 
    areaRatio = 0.05 
elif img == "Plate.jpg": 
    areaRatio = 0.5 

for ctr in contours:  
    if cv2.contourArea(ctr) > maxArea * areaRatio: 
     rect.append(cv2.boundingRect(cv2.approxPolyDP(ctr,1,True))) 

symbols=[] 
for i in rect: 
    x = i[0] 
    y = i[1] 
    w = i[2] 
    h = i[3] 
    p1 = (x,y) 
    p2 = (x+w,y+h) 
    cv2.rectangle(mo_image,p1,p2,255,2) 
    image = cv2.resize(mo_image[y:y+h,x:x+w],(32,32)) 
    symbols.append(image.reshape(1024,).astype("uint8")) 

testset_data = np.array(symbols) 

cv2.imshow("segmented",mo_image) 
plt.subplot(2,3,6) 
plt.title("Segmented") 
plt.imshow(mo_image,'gray') 
plt.xticks([]),plt.yticks([]); 

jedoch die resultierende Segmente erscheinen in zufälliger Reihenfolge. Hier ist das Originalbild gefolgt von dem verarbeiteten Bild mit erkannten Segmenten.

segments

Das Programm schreitet dann jedes Segment separat ausgibt, jedoch ist es in der Reihenfolge: 4 1 9 8 7 5 3 2 0 6 und nicht 0 1 2 3 4 5 6 7 8 9. Das einfache Hinzufügen einer Sortieroperation in "rect" behebt dies, aber die gleiche Lösung funktioniert nicht für ein Dokument mit mehreren Zeilen.

Also meine Frage ist: Wie sortiere ich die Konturen von links nach rechts und von oben nach unten?

+0

Könnten Sie ein Beispiel für den Inhalt von 'rect' hinzufügen? –

+0

rect enthält (x, y, w, h) für jede erkannte Kontur [(287, 117, 13, 46), (102, 117, 34, 47), (513, 116, 36, 49), (454 , 116, 32, 49), (395, 116, 28, 48), (334, 116, 31, 49), (168, 116, 26, 49), (43, 116, 30, 48), (224, 115, 33, 50), (211, 33, 34, 47), ( 45, 33, 13, 46), (514, 32, 32, 49), (455, 32, 31, 49), (396, 32, 29, 48), (275, 32, 28, 48), (156, 3 2, 26, 49), (91, 32, 30, 48), (333, 31, 33, 50)] Dies ist für das obige Beispiel. (0-9) – Nissan

Antwort

1

Ich glaube nicht, dass Sie die Konturen direkt in der richtigen Reihenfolge zu erzeugen in der Lage sein werden, aber eine einfache Art wie folgt tun, was Sie brauchen:

import numpy as np 

c = np.load(r"rect.npy") 
contours = list(c) 

# Example - contours = [(287, 117, 13, 46), (102, 117, 34, 47), (513, 116, 36, 49), (454, 116, 32, 49), (395, 116, 28, 48), (334, 116, 31, 49), (168, 116, 26, 49), (43, 116, 30, 48), (224, 115, 33, 50), (211, 33, 34, 47), (45, 33, 13, 46), (514, 32, 32, 49), (455, 32, 31, 49), (396, 32, 29, 48), (275, 32, 28, 48), (156, 32, 26, 49), (91, 32, 30, 48), (333, 31, 33, 50)] 

max_width = np.sum(c[::, (0, 2)], axis=1).max() 
max_height = np.max(c[::, 3]) 
nearest = max_height * 1.4 

contours.sort(key=lambda r: (int(nearest * round(float(r[1])/nearest)) * max_width + r[0])) 

for x, y, w, h in contours: 
    print "{:4} {:4} {:4} {:4}".format(x, y, w, h) 

Die folgende Ausgabe würde angezeigt werden :

36 45 33 40 
    76 44 29 43 
109 43 29 45 
145 44 32 43 
184 44 21 43 
215 44 21 41 
241 43 34 45 
284 46 31 39 
324 46 7 39 
337 46 14 41 
360 46 26 39 
393 46 20 41 
421 45 45 41 
475 45 32 41 
514 43 38 45 
    39 122 26 41 
    70 121 40 48 
115 123 27 40 
148 121 25 45 
176 122 28 41 
212 124 30 41 
247 124 91 40 
342 124 28 39 
375 124 27 39 
405 122 27 43 
    37 210 25 33 
    69 199 28 44 
102 210 21 33 
129 199 28 44 
163 210 26 33 
195 197 16 44 
214 210 27 44 
247 199 25 42 
281 212 7 29 
292 212 11 42 
310 199 23 43 
340 199 7 42 
355 211 43 30 
406 213 24 28 
437 209 31 35 
473 210 28 43 
506 210 28 43 
541 210 17 31 
    37 288 21 33 
    62 282 15 39 
    86 290 24 28 
116 290 72 30 
192 290 23 30 
218 290 26 41 
249 288 20 33 

es durch Gruppieren Ähnliche y Werten arbeitet, und dann durch die Breite multipliziert wird, das Ergebnis ist ein Schlüssel, die Zeile für Zeile erhöht. Die maximale Höhe eines einzelnen Rechtecks ​​wird berechnet, um einen geeigneten Gruppierungswert für nearest zu bestimmen. Der Wert 1.4 ist ein Zeilenabstandswert. Dies könnte auch automatisch berechnet werden. Also für beide Ihrer Beispiele nearest ist etwa 70.

Die Berechnungen könnten auch direkt in numpy erfolgen.

+0

Das funktionierte für die obigen Ziffern, jedoch scheinen sie beim Sortieren von Textkonturen nicht zu funktionieren. Hier sind die Konturen für den Beispieltext gefunden: https://i.imgur.com/b3fnDFP.jpg Die Konturen (nach dem Sortieren) sind nicht in der Reihenfolge des Textes, sondern in der Reihenfolge "Dkhdf? Oyou ... . " Wie auch immer, ich kann das reparieren? – Nissan

+0

Nicht in der Nähe eines Computers für eine Weile, wird so bald wie möglich aktualisiert. –

+0

Können Sie mir die aktualisierte Rekteliste geben? Es sollte nur eine Frage sein, den "nächsten" Wert einzustellen, der ungefähr die erwartete Höhe eines Wortes sein sollte. d. h. Versuch 20. –

Verwandte Themen