2017-11-13 4 views
1

Ich habe ein Bild der Nummer wie unten gezeigt.
Image
Ich segmentierte die Nummer oben in ihre Ziffern mit Methoden der adaptiven Schwellenwertbildung und Erkennung von Konturen und eine Beschränkung der Höhe und des Gewichts für Begrenzungsrechteck größer als 15, um die folgenden segmentierten Ziffern zu erhalten.
enter image description hereenter image description hereenter image description hereenter image description hereenter image description here
Zeichensegmentierung und Erkennung für ungleichmäßig beabstandete Ziffern

Statt über Ausgabe, würde ich oben so die Zahl im Bild zu segmentieren gerne als jede Ziffer einzeln zu bekommen. Dieses Ergebnis kann nach der Größenanpassung an (28, 28) CNN von MNIST zur besseren Vorhersage bestimmter Ziffern zugeführt werden.

Eine Methode wie erwähnt here schlägt vor, ein grünes Fenster von fester Größe zu schieben und die Ziffern durch Training eines neuronalen Netzes zu erkennen. Also, wie wird diese NN trainiert, um die Ziffern zu klassifizieren? Diese Methode vermeidet den OpenCV-Ansatz, um jede einzelne Ziffer zu trennen, aber nur ein Schiebefenster über das ganze Bild ist nicht ein bisschen teuer. Wie man mit positiven und negativen Beispielen während des Trainings umgehen kann (sollte ich einen separaten Datensatz erstellen ... positive Beispiele können aus kleinen Ziffern bestehen, aber was ist mit negativen Beispielen?)?

Segmentation:

img = cv2.imread('Image') 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

blur = cv2.GaussianBlur(gray,(3,3), 0) 
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_MEAN_C,\ 
      cv2.THRESH_BINARY_INV, 7,10) 
thresh = clear_border(thresh) 

# find contours in the thresholded image, then initialize the 
# list of group locations 
clone = np.dstack([gray.copy()] * 3) 
groupCnts = cv2.findContours(thresh.copy(), cv2.RETR_TREE, 
    cv2.CHAIN_APPROX_SIMPLE) 
groupCnts = groupCnts[0] if imutils.is_cv2() else groupCnts[1] 
groupLocs = [] 

clone = np.dstack([gray.copy()] * 3) 
# loop over the group contours 
for (i, c) in enumerate(groupCnts): 
    # compute the bounding box of the contour 
    (x, y, w, h) = cv2.boundingRect(c) 
    # only accept the contour region as a grouping of characters if 
    # the ROI is sufficiently large 
    if w >= 15 and h >= 15: 
     print (i, (x, y, w, h)) 
     cv2.rectangle(clone, (x,y), (x+w, y+h), (255,0,0), 1) 
     groupLocs.append((x, y, w, h)) 

gleitendes Fenster:

clf = joblib.load("digits_cls.pkl") #mnist trained classifier 
img = cv2.imread('Image', 0) 
winW, winH = (22, 40) 
cv2.imshow("Window0", img) 
cv2.waitKey(1) 

blur = cv2.GaussianBlur(img, (5,5),0) 
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\ 
      cv2.THRESH_BINARY,11,2) 
thresh = clear_border(thresh) 

for (x, y, window) in sliding_window(img, stepSize=10, windowSize=(winW, winH)): 
    if (window.shape[0] != winH or window.shape[1] != winW): 
     continue 
    clone = img.copy() 
    roi = thresh[y:y+winH, x:x+winW] 
    roi = cv2.resize(roi, (28, 28), interpolation=cv2.INTER_AREA) 
    roi = cv2.dilate(roi, (3, 3)) 
    cv2.imshow("Window1", roi) 
    cv2.waitKey(1) 
    roi_hog_fd = hog(roi, orientations=9, pixels_per_cell=(14, 14), cells_per_block=(1, 1), visualise=False) 
    nbr = clf.predict(np.array([roi_hog_fd], 'float64')) 
    print (nbr) 

    # since we do not have a classifier, we'll just draw the window 
    clone = img.copy() 
    cv2.rectangle(clone, (x, y), (x + winW, y + winH), (0, 255, 0), 2) 
    cv2.imshow("Window2", clone) 
    cv2.waitKey(1) 
    time.sleep(0.95) 

Schräge Output (sogar für leeres Fenster vorhersagt IT): 522637753787357777722

Trenn Stellen verbunden:

h,w = img.shape[:2] 
count = 0 
iw = 15 
dw = w 
sw, sh = int(0), int(0) 
while (dw > 0): 
    new_img = img[:, sw:(count+1)*iw] 
    dw = dw - iw 
    sw = sw + iw 
    if (dw-iw < 0): 
     iw = w 
    new = os.path.join('amount/', 'amount_'+ str(count)+'.png') 
    cv2.imwrite(new, new_img) 

Ausgang:
enter image description here ->enter image description hereenter image description hereenter image description here
enter image description here ->enter image description hereenter image description here

Mit einer Art und Weise, diese verbundene Ziffern seprate gefunden und Fütterung trainierte Klassifizierer mnist, ausgegeben noch ungenau.

Schritte, die ich verwendete:
(i) Erstes Bild extrahieren
(ii) Segmentieren Sie das erste Bild in ein separates Bild, zum Beispiel das zweite Bild.
(iii) Prüfen Sie, ob die Bildbreite einen bestimmten Schwellenwert überschreitet, falls ja, segmentiert sie weiter getrennte Ziffern (im Fall von verbundenen Ziffern wie oben)
(iv) Führen Sie alle separaten Ziffern nach Schritt 3 ein, um mnist classifier zu erhalten die Vorhersage der Ziffer basierend auf dem umgeformten Bild.
Lengthy right?
Is there any other efficient way to convert first image to digits directly (yes I used pytesseract too!!)?

+0

Können Sie Code-Segmentierung hinzufügen? – Link

+0

Wäre es nicht einfacher, das CNN zu trainieren, 00 und 000 (und andere verknüpfte Ziffernkombinationen) zu erkennen und zu generieren? – barny

+0

@ barny, statt mehrstelligen Datensatz zu erstellen, wird Training auf SVHN-Datensatz und Tests auf oben mehrstellige geben gutes Ergebnis? – SupposeXYZ

Antwort

1

ein neues neuronales Netz Ausbildung wird eine elegante Lösung, wenn Sie die Zeit und Ressourcen haben, dies zu tun.

Um jede der Ziffern einzeln zu trennen, können Sie versuchen, die Intensität des Bildes umzukehren, so dass die Handschrift weiß und der Hintergrund schwarz ist. Projizieren Sie die Werte dann horizontal (summieren Sie alle Pixelwerte horizontal) und suchen Sie nach den Peaks.Jeder Spitzenstandort sollte einen neuen Zeichenstandort angeben.

Die zusätzliche Glättungsfunktion im projizierten Diagramm sollte die Zeichenpositionen verfeinern.

+0

Was ist mit Ziffern, die zwei Spitzen haben, je nachdem, wo Sie sie abfangen, wie 0,4,6,8 und 9? – grovina

+0

Sie können versuchen, das Signal mit einem Gauss-Filter zu glätten, die Größe der durchschnittlichen Zeichenbreite und der Peak sollte in der Mitte jedes Zeichens erscheinen. – yapws87

+0

Sie können sogar einen Vorverarbeitungsschritt hinzufügen, indem Sie alle Zeichen morphologisch erweitern, also den Blob zusammen, um Ihrem späteren Projektionsergebnis zu helfen – yapws87