Ich mache oft Fotos von Dokumenten mit meinem Smartphone und benutze sie. Es ist einfach, aber weniger klar als das vom Scanner erfasste. Um das Lesen von Bildern mit mattem Kontrast zu erleichtern, z. B. mit einem Smartphone, sollten Sie die Helligkeit des Hintergrunds erhöhen, während die Zeichen schwarz bleiben. Zur Vereinfachung des Aufhellens des Hintergrunds wurde es notwendig, zwischen dem Zeichenteil des Bildes und dem einfachen weißen Hintergrundteil zu unterscheiden, aber es funktioniert gut, wenn die Statistik der Pixel für jeden lokalen Teil des Bildes anhand der Größe der Standardabweichung der Pixelwerte erstellt und beurteilt wird. Es war.
Lassen Sie uns als Beispiel das folgende Bild verarbeiten. Sie sollten in der Lage sein, jedes Bild zu vergrößern, indem Sie darauf klicken. Naoki Hatano, "Tara Majima Visionary Line" S.36
Beim Schärfen eines Bildes wird häufig ein Abflachungsprozess des Histogramms durchgeführt. Wenn die Helligkeit der Pixel des Bildes in einem engen Bereich liegt, wenn Sie sie auf den gesamten Bereich des Bildformats oder 0 bis 255 für Graustufenbilder erweitern, vergrößert sich der Unterschied zwischen den Pixeln und das Bild wird klarer. OpenCV hat eine eigene Funktion, die unter dem folgenden Link ausführlich erläutert wird. [Hysterogramm in OpenCV> Histogramm Teil 2: Abflachen des Histogramms](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_histograms/py_histogram_equalization/py_histogram_e .html) Auf diese Weise wird das Originalbild grau skaliert und das Histogramm im folgenden Bild abgeflacht. Wird mit dem Programm angezeigt.
bookimg = cv2.imread('tarama36p.jpg')
img_gray = cv2.cvtColor(bookimg, cv2.COLOR_BGR2GRAY)
equ = cv2.equalizeHist(img_gray)
cv2.imwrite('tarama36pcv2.jpg', equ )
Das Ergebnis ist nicht besonders klar. Ich wusste es nicht vom Originalbild, aber es scheint, dass die rechte Seite heller ist als die linke. Die Reflexion des oberen Metallstücks wird betont. Tatsächlich ist das Histogramm dieses Bildes wie folgt und die rote Linie zeigt die Maximal- und Minimalwerte der Helligkeit der Pixel, aber da die Maximal- und Minimalwerte bereits auf den vollen Bildbereich erweitert wurden, wird ein einfaches Histogramm abgeflacht Die Wirkung von ist gering. OpenCV hat auch eine Funktion namens anwendbare Histogrammabflachung, die das Bild in kleine Blöcke unterteilt und das Histogramm für jeden Block abflacht. Das Verarbeitungsergebnis ist das folgende Bild.
bookimg = cv2.imread('tarama36p.jpg')
img_gray = cv2.cvtColor(bookimg, cv2.COLOR_BGR2GRAY)
equ = cv2.equalizeHist(img_gray)
cv2.imwrite('tarama36pcv2.jpg', equ )
Es ist einfacher zu sehen als cv2.equalizeHist (), aber nicht so viel wie ein Scanner.
Der allgemeine Kontrastverbesserungsprozess versucht, einen gewissen Unterschied im Pixelwert des weißen Teils zu hinterlassen. Im Fall eines Textbildes sind keine detaillierten Informationen auf einem weißen Hintergrund erforderlich, sodass alle Pixel über einem bestimmten Schwellenwert vollständig weiß sein können und alle Pixelwerte möglicherweise auf 255 umgeschrieben werden. Da die schwarze Seite Informationen zur Zeichenform enthält, wird der ursprüngliche Pixelwert mit einem Wert kleiner als 1 multipliziert, und der Wert wird zur schwarzen Seite verschoben, die ursprüngliche Tendenz bleibt jedoch erhalten. Es wird angenommen, dass der Schwellenwert 140 aus dem Wert pro Medianwert des Histogramms beträgt. Das Programm und die Verarbeitungsergebnisse sind wie folgt.
for y in range(img_gray.shape[0]):
for x in range(img_gray.shape[1]):
if img_gray[y][x] > 140:
img_gray[y][x] = 255
else:
img_gray[y][x] = img_gray[y][x] * 0.5
cv2.imwrite('tarama36p140.jpg', img_gray )
Auf der rechten Seite war der Hintergrund weiß und die Zeichen waren wie beabsichtigt klar. Die zusätzliche Reflexion der Metallteile ist ebenfalls verschwunden. Da jedoch die untere linke Ecke insgesamt dunkel war, wurde der Hintergrundteil als schwarz erkannt und hervorgehoben. Wenn Sie jedoch den Schwellenwert unten links einstellen, wird der Charakterteil diesmal auf der rechten Seite weiß geflogen. Das heißt, der geeignete Schwellenwert hängt von der Position des Bildes ab.
Ähnlich wie bei der anwendbaren Histogrammabflachung wird das Originalbild vertikal und horizontal in Blöcke mit 64 Punkten unterteilt, und für jeden werden geeignete Schwellenwerte erhalten und verarbeitet. Es ist wichtig, wie der Schwellenwert bestimmt wird, aber hier wird der Wert des Schwellenwerts so eingestellt, dass die untere Hälfte des Medianwerts jedes Blockpixels, dh 1/4 des gesamten Blockpixels, als schwarz angesehen wird. Eine Funktion, die einen Schwellenwert mit dem Blockbild img als Argument zurückgibt, wird in Python wie folgt geschrieben. Es ist eine grobe Idee, aber es scheint einen vernünftigen Wert zu liefern. Schwarzweißtext funktioniert jedoch nicht.
import numpy as np
def getBWThrsh(img):
med = np.median(img)
fild = img[img < med]
return np.median(fild)
Das verarbeitete Ergebnis ist das folgende Bild. Zusätzlich wird der Histogramm-Mittelungsprozess auch für jeden Block durchgeführt, und anstatt einfach die weißen Bereiche durch 255 zu ersetzen, ersetzen Sie das ursprüngliche Pixel durch einen Koeffizienten, so dass der Großteil des Hintergrunds 256 überschreitet. Es gibt. Die meisten von ihnen sind weiß, aber die dunkleren Teile bleiben übrig. Der Hintergrund der Zeichen ist schön weiß, aber die Zeichen auf der Rückseite sind im weißen Hintergrund, wo keine Zeichen vorhanden sind, schwach transparent. Das folgende Bild ist vergrößert. In dem Teil, in dem die Rückseite transparent ist, gibt es nur einen sehr geringen Unterschied in den Schattierungen. Durch Ausführen des Histogramm-Mittelungsprozesses sind die Rückbuchstaben jedoch hervorragend entstanden.
Da die Rückseite transparent ist, möchte ich den Histogramm-Mittelungsprozess auf dem weißen Hintergrund vermeiden. Wie kann ich zwischen dem Textteil und dem weißen Hintergrundteil unterscheiden? Bisher haben wir für jeden Block eine statistische Verarbeitung mit numpy durchgeführt, um den Medianwert der Pixel zu ermitteln. Ich kam jedoch auf die Idee, dass die Standardabweichung der Pixelwerte zur Unterscheidung zwischen Zeichen und weißem Hintergrund verwendet werden kann. Der weiße Hintergrund weist weniger Abweichungen bei den Pixelwerten auf und die Standardabweichung ist gering, und der Zeichenteil hat einen größeren Wert. Wie auch immer, ich fand die Standardabweichung der Pixel jedes Blocks, erstellte ein Histogramm, um festzustellen, welche Art von Wert groß ist, und untersuchte die Tendenz. Auf dem kleinen Wert auf der linken Seite befindet sich eine Spitze, aber dies ist wahrscheinlich ein Block auf weißem Hintergrund. Ein weißer Hintergrund kann bestimmt werden, indem ein Schwellenwert der Standardabweichung auf einen Wert eingestellt wird, der diesen Peak enthält. Wenn Sie den Schwellenwert zu klein machen, bleibt Staub auf einem weißen Hintergrund zurück, und wenn Sie ihn groß machen, wird er, selbst wenn einige kleine Zeichen im weißen Hintergrund enthalten sind, als weißer Hintergrund betrachtet und abgebrochen, sodass es tatsächlich schwierig ist, einen geeigneten Schwellenwert festzulegen. Wie auch immer, das Bild unten zeigt den Prozess der Unterscheidung zwischen Zeichen und weißem Hintergrund und macht den weißen Hintergrund vollständig weiß. Es gab viel Müll an anderen Stellen als dem umgebenden Text, aber ich denke, der Textteil wurde ordentlich verarbeitet. Da es jetzt möglich ist, blockweise zwischen weißen und nicht weißen Hintergründen zu unterscheiden, sind die weißen Hintergrundblöcke, wenn sie durchgehend sind, die umgebenden Ränder, wenn sich lose Zeichen in den Rändern befinden, sind sie nicht bleibbar usw. Ich bin der Meinung, dass es auf verschiedene Urteile angewendet werden kann.
Die obigen Quellen sind wie folgt. Wenn Sie den zu konvertierenden Dateinamen in das Argument sharpenImg () in der unteren Zeile schreiben, wird eine Datei mit weißem Hintergrund erstellt. Im Moment dauert die Konvertierung einige zehn Sekunden, aber ich denke, es wird eine praktische Verarbeitungsgeschwindigkeit sein, wenn es mit C oder ähnlichem neu geschrieben wird.
import cv2
from matplotlib import pyplot as plt
import numpy as np
def getStdThrsh(img, Blocksize):
stds = []
for y in range( 0, img.shape[0], Blocksize ):
for x in range( 0, img.shape[0], Blocksize ):
pimg = img[y:y+Blocksize, x:x+Blocksize]
std = np.std( pimg )
minv = np.min( pimg )
maxv = np.max( pimg )
stds.append(std)
hist = np.histogram( stds, bins=64 )
peaki = np.argmax(hist[0])
#plt.hist( stds, bins=64 )
#plt.show()
slim = 6.0
for n in range(peaki,len(hist[0])-1):
if hist[0][n] < hist[0][n+1]:
slim = hist[1][n+1]
break
if slim > 6.0:
slim = 6.0
return slim
def getBWThrsh(img):
med = np.median(img)
fild = img[img < med]
return np.median(fild)
def getWbias( img, bwthr ):
wimg = img[ img > bwthr ]
hist = np.histogram( wimg, bins=16 )
agm = np.argmax(hist[0])
return hist[1][agm]
def getOutputName( title, slim ):
return title + "_s{:04.2f}.jpg ".format( slim )
def sharpenImg(imgfile):
Testimagefile = imgfile
TestimageTitle = Testimagefile.split('.')[0]
Blocksize = 64
Bbias = 0.2
bookimg = cv2.imread( Testimagefile )
img_gray = cv2.cvtColor(bookimg, cv2.COLOR_BGR2GRAY)
outimage = img_gray.copy()
slim = getStdThrsh(img_gray, Blocksize)
for y in range( 0, img_gray.shape[0], Blocksize ):
s = ""
for x in range( 0, img_gray.shape[1], Blocksize ):
pimg = img_gray[y:y+Blocksize, x:x+Blocksize]
std = np.std( pimg )
minv = np.min( pimg )
maxv = np.max( pimg )
pimg -= minv
cimg = pimg.copy()
if maxv != minv:
for sy in range (cimg.shape[0]):
for sx in range( cimg.shape[1] ):
cimg[sy][sx] = (cimg[sy][sx]*255.0)/(maxv - minv)
bwthrsh = getBWThrsh( pimg )
wb = getWbias( cimg, bwthrsh )
if wb == 0:
wbias = 1.5
else:
wbias = 256 / wb
if std < slim:
s = s + "B"
for sy in range (pimg.shape[0]):
for sx in range( pimg.shape[1] ):
outimage[y+sy][x+sx] = 255
else:
s = s + "_"
for sy in range (cimg.shape[0]):
for sx in range( cimg.shape[1] ):
if cimg[sy][sx] > bwthrsh:
v = cimg[sy][sx]
v = v * wbias
if v > 255:
v = 255
outimage[y+sy][x+sx] = v
else:
outimage[y+sy][x+sx] = cimg[sy][sx] * Bbias
print( "{:4d} {:s}".format( y, s ) )
cv2.imwrite(getOutputName(TestimageTitle, slim), outimage )
if __name__ =='__main__':
sharpenImg('tarama36p.jpg')
https://github.com/pie-xx/TextImageViewer
Recommended Posts