Add threshold function to work around Tesseract's poor thresholding of bright backgrounds

This commit is contained in:
James R. Barlow
2018-11-10 15:34:37 -08:00
parent 0f5c484b62
commit 701ef1df3f
5 changed files with 50 additions and 35 deletions
+4
View File
@@ -253,6 +253,10 @@ preprocessing.add_argument(
help="Mask out any barcodes that appear in the PDF so they are not "
"considered during OCR. Barcodes can introduce false characters into "
"OCR.")
preprocessing.add_argument(
'--threshold', action='store_true',
help="Threshold image to 1bpp before sending it to Tesseract for OCR. Can "
"improve OCR quality compared to Tesseract's thresholder.")
ocrsettings = parser.add_argument_group(
"OCR options",
+12 -9
View File
@@ -631,17 +631,20 @@ def select_ocr_image(
log.debug('blanking %r', pixcoords)
draw.rectangle(pixcoords, fill=white)
#draw.rectangle(pixcoords, outline=pink)
if options.mask_barcodes:
pix = leptonica.Pix.open(image)
barcodes = pix.locate_barcodes()
for barcode in barcodes:
decoded, rect = barcode
log.info('masking barcode %s %r', decoded, rect)
draw.rectangle(rect, fill=white)
del draw
if options.mask_barcodes or options.threshold:
pix = leptonica.Pix.frompil(im)
if options.threshold:
pix = pix.masked_threshold_on_background_norm()
if options.mask_barcodes:
barcodes = pix.locate_barcodes()
for barcode in barcodes:
decoded, rect = barcode
log.info('masking barcode %s %r', decoded, rect)
draw.rectangle(rect, fill=white)
im = pix.topil()
# Pillow requires integer DPI
dpi = round(xres), round(yres)
im.save(output_file, dpi=dpi)
+28 -21
View File
@@ -20,15 +20,16 @@
#
# Python FFI wrapper for Leptonica library
import argparse
import sys
import os
import logging
import warnings
from tempfile import TemporaryFile
from collections.abc import Sequence
from ctypes.util import find_library
from functools import lru_cache
from collections.abc import Sequence
from io import BytesIO
from tempfile import TemporaryFile
import argparse
import logging
import os
import sys
import warnings
from .lib._leptonica import ffi
from .helpers import fspath
@@ -300,8 +301,19 @@ class Pix(LeptonicaObject):
os.fsencode(filename),
self._cdata, jpeg_quality, jpeg_progressive)
@classmethod
def frompil(self, pillow_image):
"""Create a copy of a PIL.Image from this Pix"""
bio = BytesIO()
pillow_image.save(bio, format='png', compress_level=1)
py_buffer = bio.getbuffer()
c_buffer = ffi.from_buffer(py_buffer)
with _LeptonicaErrorTrap():
pix = Pix(lept.pixReadMem(c_buffer, len(c_buffer)))
return pix
def topil(self):
"Returns a PIL.Image version of this Pix"
"""Returns a PIL.Image version of this Pix"""
from PIL import Image
# Leptonica manages data in words, so it implicitly does an endian
@@ -416,8 +428,7 @@ class Pix(LeptonicaObject):
with _LeptonicaErrorTrap():
sx, sy = tile_size
smoothx, smoothy = kernel_size
if mask is None:
mask = ffi.NULL
mask = ffi.NULL
if isinstance(mask, Pix):
mask = mask._cdata
@@ -429,9 +440,7 @@ class Pix(LeptonicaObject):
smoothx, smoothy,
scorefract,
ffi.NULL
)
if thresh_pix == ffi.NULL:
return None
)
return Pix(thresh_pix)
def masked_threshold_on_background_norm(
@@ -440,23 +449,21 @@ class Pix(LeptonicaObject):
with _LeptonicaErrorTrap():
sx, sy = tile_size
smoothx, smoothy = kernel_size
if mask is None:
mask = ffi.NULL
mask = ffi.NULL
if isinstance(mask, Pix):
mask = mask._cdata
new_pix = lept.pixMaskedThreshOnBackgroundNorm(
self._cdata,
pix = Pix(lept.pixConvertTo8(self._cdata, 0))
thresh_pix = lept.pixMaskedThreshOnBackgroundNorm(
pix._cdata,
mask,
sx, sy,
thresh, mincount,
smoothx, smoothy,
scorefract,
ffi.NULL
)
if new_pix == ffi.NULL:
return None
return Pix(new_pix)
)
return Pix(thresh_pix)
def crop_to_foreground(
self, threshold=128, mindist=70, erasedist=30, pagenum=0,
File diff suppressed because one or more lines are too long
+1
View File
@@ -206,6 +206,7 @@ enum {
ffibuilder.cdef("""
PIX * pixRead ( const char *filename );
PIX * pixReadMem ( const l_uint8 *data, size_t size );
PIX * pixScale ( PIX *pixs, l_float32 scalex, l_float32 scaley );
l_int32 pixFindSkew ( PIX *pixs, l_float32 *pangle, l_float32 *pconf );
l_int32 pixWriteImpliedFormat ( const char *filename, PIX *pix, l_int32 quality, l_int32 progressive );