2015-10-05 9 views
5

Ich habe ein Beispielbild wie dieseWie weißen Bereich in einem Bild

enter image description here

Ich bin auf der Suche nach einem Weg zu Schwarz aus dem Rauschen aus dem Bild so extrahieren, dass ich mit einem Bild am Ende das hat nur schwarzen Text auf weißem Hintergrund, damit ich es zu Tesseract schicken kann.

Ich habe Morphing versucht, mit

kernel = np.ones((4,4),np.uint8) 
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) 
cv2.imshow("opening", opening) 

, aber es scheint nicht zu funktionieren.

Ich habe auch versucht

img = cv2.cvtColor(rotated, cv2.COLOR_BGR2GRAY) 
(cnts, _) = cv2.findContours(img, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:1] 
for c in cnts: 
    x,y,w,h = cv2.boundingRect(c) 
    roi=rotated[y:y+h,x:x+w].copy() 
    cv2.imwrite("roi.png", roi) 

Mit dem obigen Code Konturen zu finden, erhalte ich folgende Konturen:

enter image description here

, die zu diesem Bild führt, wenn abgeschnitten:

enter image description here

was immer noch nicht gut genug ist. Ich möchte schwarzen Text auf weißem Hintergrund, damit ich ihn an Tesseract OCR senden kann und gute Erfolgsquote habe.

Gibt es noch etwas, das ich ausprobieren kann?

aktualisieren

Hier ist ein weiteres ähnliches Bild. Dieser ist ein bisschen einfacher, weil es eine glatte Rechteck hat in ihm

enter image description here

+1

an die Wähler, die Frage ist zu breit. Bitte lassen Sie mich wissen, wie Sie es weiter eingrenzen können. Ich glaube nicht, dass die Frage breit ist. – Anthony

+0

Sie müssen eine adaptive Schwellenwertbildung durchführen und Operationen öffnen und schließen. http://docs.opencv.org/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html Sie könnten auch benutzerdefinierte Erosion oder Dilatation tun (die basicall ist, welche öffnen und schließen Operationen tun). –

+0

Ist dies das Eingabebild? Oder ergeben sich aus einer Art Schwellwert? – ZdaR

Antwort

3

Das Folgende funktioniert für Ihr angegebenes Beispiel, obwohl es möglicherweise für eine größere Anzahl von Bildern optimiert werden muss.

import numpy as np 
import cv2 

image_src = cv2.imread("input.png") 
gray = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY) 
ret, gray = cv2.threshold(gray, 250,255,0) 

image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 
largest_area = sorted(contours, key=cv2.contourArea)[-1] 
mask = np.zeros(image_src.shape, np.uint8) 
cv2.drawContours(mask, [largest_area], 0, (255,255,255,255), -1) 
dst = cv2.bitwise_and(image_src, mask) 
mask = 255 - mask 
roi = cv2.add(dst, mask) 

roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) 
ret, gray = cv2.threshold(roi_gray, 250,255,0) 
image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 

max_x = 0 
max_y = 0 
min_x = image_src.shape[1] 
min_y = image_src.shape[0] 

for c in contours: 
    if 150 < cv2.contourArea(c) < 100000: 
     x, y, w, h = cv2.boundingRect(c) 
     min_x = min(x, min_x) 
     min_y = min(y, min_y) 
     max_x = max(x+w, max_x) 
     max_y = max(y+h, max_y) 

roi = roi[min_y:max_y, min_x:max_x] 
cv2.imwrite("roi.png", roi) 

Geben Sie die folgende Art der Ausgangsbilder:

enter image description here

Und ...

enter image description here

Der Code funktioniert, indem zuerst die größte Konturbereich zu lokalisieren. Daraus wird eine Maske erzeugt, die verwendet wird, um zuerst nur den Bereich innerhalb, d. H. Den Text, auszuwählen. Die Umkehrung der Maske wird dann zu dem Bild hinzugefügt, um den Bereich außerhalb der Maske in Weiß umzuwandeln.

Endlich Konturen sind wieder für dieses neue Bild gefunden. Alle Konturbereiche außerhalb eines geeigneten Größenbereichs werden verworfen (dies wird verwendet, um kleine Rauschbereiche zu ignorieren), und für jeden wird ein begrenzendes Rechteck gefunden. Mit jedem dieser Rechtecke wird für alle verbleibenden Konturen ein begrenzender Rect outer berechnet, und unter Verwendung dieser Werte wird ein Ausschnitt erstellt, um das endgültige Bild zu erhalten.

aktualisieren - Um den Rest des Bildes zu erhalten, das heißt mit dem obigen Bereich entfernt wird, werden die folgenden könnten verwendet:

image_src = cv2.imread("input.png") 
gray = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY) 
ret, gray = cv2.threshold(gray, 10, 255,0) 
image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 
largest_area = sorted(contours, key=cv2.contourArea)[-1] 
mask = np.zeros(image_src.shape, np.uint8) 
cv2.drawContours(mask, [largest_area], 0, (255,255,255,255), -1) 
image_remainder = cv2.bitwise_and(image_src, 255 - mask) 

cv2.imwrite("remainder.png", image_remainder) 
+0

Wenn möglich, erläutern Sie bitte Ihre Vorgehensweise. Danke für die Antwort! – Anthony

+0

Kein Problem, ich habe die Erklärung aktualisiert. –

+0

danke. hmm Ich bekomme einen Fehler in Zeile 8 'Bild, Konturen, Hierarchie = cv2.findContours (grau, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) ValueError: mehr als 2 Werte zum Entpacken benötigen ' – Anthony

0

Grundidee dieser Antwort ist Grenze um Text zu verwenden.

1) Erodieren horizontal mit einem sehr großen Kern, sagt Größe von 100 Pixeln oder 8-fache Größe einzelner erwarteten Charakter, so ähnlich. Es sollte reihenweise gemacht werden. Die äußerste Ordinate gibt die Y-Position der Grenzen um den Text an.

2) Prozess vertikal gleichen Weg, um X-Position von Grenzen um Text zu erhalten. Verwenden Sie dann diese Orte, um das gewünschte Bild auszuschneiden.

- Ein Vorteil dieser Methode ist, dass Sie jeden Satz/Wort separat getrennt erhalten, die, wie ich annehme, gut für eine OCR ist.

Glücklich Coding :)

Herausgegeben in Mark Setchell

Hier ist eine Demo von 1)

enter image description here

Hier ist eine Demo von 2)

enter image description here

+1

Ich hoffe, dass Sie nichts dagegen haben, eine Animation hinzuzufügen - fühlen Sie sich frei, es zu löschen, wenn Sie tun. –

+0

Hallo @MarkSetchell, wow, das sind wirklich cool :) Danke –

+0

Ich werde diesen Ansatz versuchen, wie es möglicherweise für andere ähnliche Bilder anwendbar sein könnte. Ich werde meine Fortschritte hier aktualisieren. Ich hoffe, dass opencv eine Möglichkeit hat, horizontal und vertikal zu erodieren – Anthony

0

bekomme ich diese: Result

Source Code:

if __name__ == '__main__': 
    SrcImg = cv2.imread('./Yahi9.png', cv2.CV_LOAD_IMAGE_GRAYSCALE) 
    _, BinImg = cv2.threshold(SrcImg, 80, 255, cv2.THRESH_OTSU) 

    Contours, Hierarchy = cv2.findContours(image=copy.deepcopy(SrcImg), 
             mode=cv2.cv.CV_RETR_EXTERNAL, 
             method=cv2.cv.CV_CHAIN_APPROX_NONE) 
    MaxContour, _ = getMaxContour(Contours) 
    Canvas = np.ones(SrcImg.shape, np.uint8) 
    cv2.drawContours(image=Canvas, contours=[MaxContour], contourIdx=0, color=(255), thickness=-1) 
    mask = (Canvas != 255) 
    RoiImg = copy.deepcopy(BinImg) 
    RoiImg[mask] = 255 
    RoiImg = cv2.morphologyEx(src=RoiImg, op=cv2.MORPH_CLOSE, kernel=np.ones((3,3)), iterations=4) 
    cv2.imshow('RoiImg', RoiImg) 
    cv2.waitKey(0) 

Funktion:

def getMaxContour(contours): 
    MaxArea = 0 
    Location = 0 
    for idx in range(0, len(contours)): 
     Area = cv2.contourArea(contours[idx]) 
     if Area > MaxArea: 
      MaxArea = Area 
      Location = idx 
    MaxContour = np.array(contours[Location]) 
    return MaxContour, MaxArea 

Ehh, es ist Python-Code. Es funktioniert nur, wenn die weiße Region die maximale Kontur ist.

+0

Wenn möglich, könnten Sie bitte Ihren Ansatz erklären. Danke für die Antwort! – Anthony

+0

Es tut mir leid, ich war so müde, dass ich einschlief, sobald ich nach Hause kam. –

+0

Martin Evans verwendet den gleichen Weg, um zu extrahieren, es ist ziemlich gut. –

Verwandte Themen