Hier ist eine Idee. Wir unterteilen dieses Problem in mehrere Schritte:
Bestimmen Sie die durchschnittliche rechteckige Konturfläche. Wir schwellen dann Konturen und filtern anhand des begrenzenden Rechteckbereichs der Kontur. Der Grund, warum wir dies tun, ist die Beobachtung, dass jedes typische Zeichen nur so groß ist, während großes Rauschen einen größeren rechteckigen Bereich überspannt. Wir bestimmen dann die durchschnittliche Fläche.
Entfernen Sie große Ausreißerkonturen. Wir durchlaufen die Konturen erneut und entfernen die großen Konturen, wenn sie 5x
größer als die durchschnittliche Konturfläche sind, indem wir die Kontur ausfüllen. Anstatt einen festen Schwellenwertbereich zu verwenden, verwenden wir diesen dynamischen Schwellenwert für mehr Robustheit.
Erweitern Sie mit einem vertikalen Kernel, um Zeichen zu verbinden . Die Idee ist, die Beobachtung zu nutzen, dass Zeichen in Spalten ausgerichtet sind. Durch die Erweiterung mit einem vertikalen Kernel verbinden wir den Text miteinander, sodass in dieser kombinierten Kontur kein Rauschen enthalten ist.
Entfernen Sie kleine Geräusche . Nachdem der zu behaltende Text verbunden ist, finden wir Konturen und entfernen alle Konturen, die kleiner als 4x
die durchschnittliche Konturfläche sind.
Bitweise - und um das Bild zu rekonstruieren . Da wir nur gewünschte Konturen haben, um auf unserer Maske zu bleiben, arbeiten wir bitweise - und um den Text zu erhalten und unser Ergebnis zu erhalten.
Hier ist eine Visualisierung des Prozesses:
Wir Otsus Schwelle , um ein Binärbild zu erhalten, finden dann Konturen , um die durchschnittliche rechteckige Konturfläche zu bestimmen. Von hier aus entfernen wir die großen grün hervorgehobenen Ausreißerkonturen durch Füllen von Konturen
Als nächstes konstruieren wir einen vertikalen Kernel und erweitern ihn , um die Charaktere zu verbinden. Dieser Schritt verbindet den gesamten gewünschten Text, um das Rauschen beizubehalten, und isoliert es in einzelne Blobs.
Jetzt finden wir Konturen und filtern mithilfe des Konturbereichs , um das kleine Rauschen zu entfernen
Hier sind alle entfernten Rauschpartikel grün hervorgehoben
Ergebnis
Code
import cv2
# Load image, grayscale, and Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Determine average contour area
average_area = []
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
area = w * h
average_area.append(area)
average = sum(average_area) / len(average_area)
# Remove large lines if contour area is 5x bigger then average contour area
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
area = w * h
if area > average * 5:
cv2.drawContours(thresh, [c], -1, (0,0,0), -1)
# Dilate with vertical kernel to connect characters
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,5))
dilate = cv2.dilate(thresh, kernel, iterations=3)
# Remove small noise if contour area is smaller than 4x average
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area < average * 4:
cv2.drawContours(dilate, [c], -1, (0,0,0), -1)
# Bitwise mask with input image
result = cv2.bitwise_and(image, image, mask=dilate)
result[dilate==0] = (255,255,255)
cv2.imshow('result', result)
cv2.imshow('dilate', dilate)
cv2.imshow('thresh', thresh)
cv2.waitKey()
Hinweis: Die herkömmliche Bildverarbeitung beschränkt sich auf Schwellenwerte, morphologische Operationen und Konturfilterung (Konturnäherung, Fläche, Seitenverhältnis oder Blob-Erkennung). Da die Eingabebilder je nach Größe des Zeichentextes variieren können, ist es ziemlich schwierig, eine singuläre Lösung zu finden. Vielleicht möchten Sie Ihren eigenen Klassifikator mit maschinellem / tiefem Lernen für eine dynamische Lösung trainieren.