rfct: introduce EynollahDirs to reduce self.dir_* proliferation

refactoring-2024-08-merged
kba 4 months ago
parent 762a7a058e
commit 532ee6fe41

@ -2,6 +2,7 @@ import sys
import click import click
from ocrd_utils import getLogger, initLogging, setOverrideLogLevel from ocrd_utils import getLogger, initLogging, setOverrideLogLevel
from qurator.eynollah.eynollah import Eynollah from qurator.eynollah.eynollah import Eynollah
from qurator.eynollah.utils.dirs import EynollahDirs
@click.command() @click.command()
@ -176,9 +177,8 @@ def main(
print('Error: You used -tll to enable light textline detection but -light is not enabled') print('Error: You used -tll to enable light textline detection but -light is not enabled')
sys.exit(1) sys.exit(1)
eynollah = Eynollah( eynollah = Eynollah(
model, EynollahDirs(
getLogger('Eynollah'), dir_models=model,
image_filename=image,
dir_out=out, dir_out=out,
dir_in=dir_in, dir_in=dir_in,
dir_of_cropped_images=save_images, dir_of_cropped_images=save_images,
@ -186,6 +186,9 @@ def main(
dir_of_deskewed=save_deskewed, dir_of_deskewed=save_deskewed,
dir_of_all=save_all, dir_of_all=save_all,
dir_save_page=save_page, dir_save_page=save_page,
),
getLogger('Eynollah'),
image_filename=image,
enable_plotting=enable_plotting, enable_plotting=enable_plotting,
allow_enhancement=allow_enhancement, allow_enhancement=allow_enhancement,
curved_line=curved_line, curved_line=curved_line,

@ -7,6 +7,7 @@ document layout analysis (segmentation) with output in PAGE-XML
""" """
from logging import Logger from logging import Logger
from dataclasses import dataclass
import math import math
from os import listdir from os import listdir
from os.path import join from os.path import join
@ -21,6 +22,8 @@ import numpy as np
from scipy.signal import find_peaks from scipy.signal import find_peaks
from scipy.ndimage import gaussian_filter1d from scipy.ndimage import gaussian_filter1d
from .utils.dirs import EynollahDirs
from .utils.tf import ( from .utils.tf import (
PatchEncoder, PatchEncoder,
Patches, Patches,
@ -85,17 +88,10 @@ class Eynollah():
def __init__( def __init__(
self, self,
dir_models : str, dirs : EynollahDirs,
logger : Logger, logger : Logger,
image_filename : Optional[str] = None,
image_pil : Optional[Image] = None, image_pil : Optional[Image] = None,
dir_out : Optional[str] = None, image_filename : Optional[str] = None,
dir_in : Optional[str] = None,
dir_of_cropped_images : Optional[str] = None,
dir_of_layout : Optional[str] = None,
dir_of_deskewed : Optional[str] = None,
dir_of_all : Optional[str] = None,
dir_save_page : Optional[str] = None,
enable_plotting : bool = False, enable_plotting : bool = False,
allow_enhancement : bool = False, allow_enhancement : bool = False,
curved_line : bool = False, curved_line : bool = False,
@ -111,7 +107,9 @@ class Eynollah():
override_dpi : Optional[int] = None, override_dpi : Optional[int] = None,
pcgts : Optional[OcrdPage] = None, pcgts : Optional[OcrdPage] = None,
): ):
if not dir_in: self.dirs = dirs
self.logger = logger
if not dirs.dir_in:
if image_pil: if image_pil:
self._imgs = self._cache_images(image_pil=image_pil) self._imgs = self._cache_images(image_pil=image_pil)
else: else:
@ -119,14 +117,6 @@ class Eynollah():
if override_dpi: if override_dpi:
self.dpi = override_dpi self.dpi = override_dpi
self.image_filename = image_filename self.image_filename = image_filename
self.dir_out = dir_out
self.dir_in = dir_in
self.dir_of_all = dir_of_all
self.dir_save_page = dir_save_page
self.dir_of_deskewed = dir_of_deskewed
self.dir_of_deskewed = dir_of_deskewed
self.dir_of_cropped_images=dir_of_cropped_images
self.dir_of_layout=dir_of_layout
self.enable_plotting = enable_plotting self.enable_plotting = enable_plotting
self.allow_enhancement = allow_enhancement self.allow_enhancement = allow_enhancement
self.curved_line = curved_line self.curved_line = curved_line
@ -140,43 +130,37 @@ class Eynollah():
self.light_version = light_version self.light_version = light_version
self.ignore_page_extraction = ignore_page_extraction self.ignore_page_extraction = ignore_page_extraction
self.pcgts = pcgts self.pcgts = pcgts
if not dir_in: # self.batch_mode = bool(self.dirs.dir_in)
self.plotter = None if not enable_plotting else EynollahPlotter( if not dirs.dir_in:
dir_out=self.dir_out, assert self.image_filename
dir_of_all=dir_of_all, self.plotter = None if not self.enable_plotting else EynollahPlotter(self.dirs, image_filename_stem=Path(Path(image_filename).name).stem)
dir_save_page=dir_save_page,
dir_of_deskewed=dir_of_deskewed,
dir_of_cropped_images=dir_of_cropped_images,
dir_of_layout=dir_of_layout,
image_filename_stem=Path(Path(image_filename).name).stem)
self.writer = EynollahXmlWriter( self.writer = EynollahXmlWriter(
dir_out=self.dir_out, dir_out=self.dirs.dir_out,
image_filename=self.image_filename, image_filename=self.image_filename,
curved_line=self.curved_line, curved_line=self.curved_line,
textline_light = self.textline_light, textline_light = self.textline_light,
pcgts=pcgts) pcgts=pcgts)
self.logger = logger
self.dir_models = dir_models
self.model_dir_of_enhancement = dirs.dir_models + "/eynollah-enhancement_20210425"
self.model_dir_of_enhancement = dir_models + "/eynollah-enhancement_20210425" self.model_dir_of_binarization = dirs.dir_models + "/eynollah-binarization_20210425"
self.model_dir_of_binarization = dir_models + "/eynollah-binarization_20210425" self.model_dir_of_col_classifier = dirs.dir_models + "/eynollah-column-classifier_20210425"
self.model_dir_of_col_classifier = dir_models + "/eynollah-column-classifier_20210425" self.model_region_dir_p = dirs.dir_models + "/eynollah-main-regions-aug-scaling_20210425"
self.model_region_dir_p = dir_models + "/eynollah-main-regions-aug-scaling_20210425" self.model_region_dir_p2 = dirs.dir_models + "/eynollah-main-regions-aug-rotation_20210425"
self.model_region_dir_p2 = dir_models + "/eynollah-main-regions-aug-rotation_20210425" self.model_region_dir_fully_np = dirs.dir_models + "/eynollah-full-regions-1column_20210425"
self.model_region_dir_fully_np = dir_models + "/eynollah-full-regions-1column_20210425" self.model_region_dir_fully = dirs.dir_models + "/eynollah-full-regions-3+column_20210425"
self.model_region_dir_fully = dir_models + "/eynollah-full-regions-3+column_20210425" self.model_page_dir = dirs.dir_models + "/eynollah-page-extraction_20210425"
self.model_page_dir = dir_models + "/eynollah-page-extraction_20210425" self.model_region_dir_p_ens = dirs.dir_models + "/eynollah-main-regions-ensembled_20210425"
self.model_region_dir_p_ens = dir_models + "/eynollah-main-regions-ensembled_20210425" self.model_region_dir_p_ens_light = dirs.dir_models + "/eynollah-main-regions_20220314"
self.model_region_dir_p_ens_light = dir_models + "/eynollah-main-regions_20220314"
if self.textline_light: if self.textline_light:
self.model_textline_dir = dir_models + "/eynollah-textline_light_20210425" self.model_textline_dir = dirs.dir_models + "/eynollah-textline_light_20210425"
else: else:
self.model_textline_dir = dir_models + "/eynollah-textline_20210425" self.model_textline_dir = dirs.dir_models + "/eynollah-textline_20210425"
self.model_tables = dir_models + "/eynollah-tables_20210319" self.model_tables = dirs.dir_models + "/eynollah-tables_20210319"
self.models : dict[str, tf.keras.Model] = {} self.models : dict[str, tf.keras.Model] = {}
if dir_in and light_version: if self.dirs.dir_in and light_version:
config = tf.compat.v1.ConfigProto() config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config) session = tf.compat.v1.Session(config=config)
@ -190,9 +174,9 @@ class Eynollah():
self.model_region_fl_np = self.our_load_model(self.model_region_dir_fully_np) self.model_region_fl_np = self.our_load_model(self.model_region_dir_fully_np)
self.model_region_fl = self.our_load_model(self.model_region_dir_fully) self.model_region_fl = self.our_load_model(self.model_region_dir_fully)
self.ls_imgs = listdir(self.dir_in) self.ls_imgs = listdir(self.dirs.dir_in)
if dir_in and not light_version: if self.dirs.dir_in and not light_version:
config = tf.compat.v1.ConfigProto() config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config) session = tf.compat.v1.Session(config=config)
@ -208,7 +192,7 @@ class Eynollah():
self.model_region_fl = self.our_load_model(self.model_region_dir_fully) self.model_region_fl = self.our_load_model(self.model_region_dir_fully)
self.model_enhancement = self.our_load_model(self.model_dir_of_enhancement) self.model_enhancement = self.our_load_model(self.model_dir_of_enhancement)
self.ls_imgs = listdir(self.dir_in) self.ls_imgs = listdir(self.dirs.dir_in)
def _cache_images(self, image_filename=None, image_pil=None): def _cache_images(self, image_filename=None, image_pil=None):
@ -228,21 +212,14 @@ class Eynollah():
self._imgs = self._cache_images(image_filename=image_filename) self._imgs = self._cache_images(image_filename=image_filename)
self.image_filename = image_filename self.image_filename = image_filename
self.plotter = None if not self.enable_plotting else EynollahPlotter( self.plotter = None if not self.enable_plotting else EynollahPlotter(self.dirs, image_filename_stem=Path(Path(image_filename).name).stem)
dir_out=self.dir_out,
dir_of_all=self.dir_of_all,
dir_save_page=self.dir_save_page,
dir_of_deskewed=self.dir_of_deskewed,
dir_of_cropped_images=self.dir_of_cropped_images,
dir_of_layout=self.dir_of_layout,
image_filename_stem=Path(Path(image_filename).name).stem)
self.writer = EynollahXmlWriter( self.writer = EynollahXmlWriter(
dir_out=self.dir_out, dir_out=self.dirs.dir_out,
image_filename=self.image_filename, image_filename=self.image_filename,
curved_line=self.curved_line, curved_line=self.curved_line,
textline_light = self.textline_light, textline_light = self.textline_light,
pcgts=self.pcgts) pcgts=self.pcgts)
def imread(self, grayscale=False, uint8=True): def imread(self, grayscale=False, uint8=True):
key = 'img' key = 'img'
if grayscale: if grayscale:
@ -415,7 +392,7 @@ class Eynollah():
img = self.imread() img = self.imread()
_, page_coord = self.early_page_for_num_of_column_classification(img) _, page_coord = self.early_page_for_num_of_column_classification(img)
if not self.dir_in: if not self.dirs.dir_in:
model_num_classifier = self.load_model(self.model_dir_of_col_classifier) model_num_classifier = self.load_model(self.model_dir_of_col_classifier)
if self.input_binary: if self.input_binary:
img_in = np.copy(img) img_in = np.copy(img)
@ -439,7 +416,7 @@ class Eynollah():
img_in[0, :, :, 1] = img_1ch[:, :] img_in[0, :, :, 1] = img_1ch[:, :]
img_in[0, :, :, 2] = img_1ch[:, :] img_in[0, :, :, 2] = img_1ch[:, :]
if not self.dir_in: if not self.dirs.dir_in:
label_p_pred = model_num_classifier.predict(img_in, verbose=0) label_p_pred = model_num_classifier.predict(img_in, verbose=0)
else: else:
label_p_pred = self.model_classifier.predict(img_in, verbose=0) label_p_pred = self.model_classifier.predict(img_in, verbose=0)
@ -462,7 +439,7 @@ class Eynollah():
self.logger.info("Detected %s DPI", dpi) self.logger.info("Detected %s DPI", dpi)
if self.input_binary: if self.input_binary:
img = self.imread() img = self.imread()
if self.dir_in: if self.dirs.dir_in:
prediction_bin = self.do_prediction(True, img, self.model_bin) prediction_bin = self.do_prediction(True, img, self.model_bin)
else: else:
@ -484,7 +461,7 @@ class Eynollah():
t1 = time.time() t1 = time.time()
_, page_coord = self.early_page_for_num_of_column_classification(img_bin) _, page_coord = self.early_page_for_num_of_column_classification(img_bin)
if not self.dir_in: if not self.dirs.dir_in:
model_num_classifier = self.load_model(self.model_dir_of_col_classifier) model_num_classifier = self.load_model(self.model_dir_of_col_classifier)
if self.input_binary: if self.input_binary:
@ -506,7 +483,7 @@ class Eynollah():
img_in[0, :, :, 2] = img_1ch[:, :] img_in[0, :, :, 2] = img_1ch[:, :]
if self.dir_in: if self.dirs.dir_in:
label_p_pred = self.model_classifier.predict(img_in, verbose=0) label_p_pred = self.model_classifier.predict(img_in, verbose=0)
else: else:
label_p_pred = model_num_classifier.predict(img_in, verbose=0) label_p_pred = model_num_classifier.predict(img_in, verbose=0)
@ -896,10 +873,10 @@ class Eynollah():
if not self.ignore_page_extraction: if not self.ignore_page_extraction:
img = cv2.GaussianBlur(self.image, (5, 5), 0) img = cv2.GaussianBlur(self.image, (5, 5), 0)
if not self.dir_in: if not self.dirs.dir_in:
model_page = self.load_model(self.model_page_dir) model_page = self.load_model(self.model_page_dir)
if not self.dir_in: if not self.dirs.dir_in:
img_page_prediction = self.do_prediction(False, img, model_page) img_page_prediction = self.do_prediction(False, img, model_page)
else: else:
img_page_prediction = self.do_prediction(False, img, self.model_page) img_page_prediction = self.do_prediction(False, img, self.model_page)
@ -944,11 +921,11 @@ class Eynollah():
img = img.astype(np.uint8) img = img.astype(np.uint8)
else: else:
img = self.imread() img = self.imread()
if not self.dir_in: if not self.dirs.dir_in:
model_page = self.load_model(self.model_page_dir) model_page = self.load_model(self.model_page_dir)
img = cv2.GaussianBlur(img, (5, 5), 0) img = cv2.GaussianBlur(img, (5, 5), 0)
if self.dir_in: if self.dirs.dir_in:
img_page_prediction = self.do_prediction(False, img, self.model_page) img_page_prediction = self.do_prediction(False, img, self.model_page)
else: else:
img_page_prediction = self.do_prediction(False, img, model_page) img_page_prediction = self.do_prediction(False, img, model_page)
@ -977,7 +954,7 @@ class Eynollah():
self.logger.debug("enter extract_text_regions") self.logger.debug("enter extract_text_regions")
img_height_h = img.shape[0] img_height_h = img.shape[0]
img_width_h = img.shape[1] img_width_h = img.shape[1]
if not self.dir_in: if not self.dirs.dir_in:
model_region = self.load_model(self.model_region_dir_fully if patches else self.model_region_dir_fully_np) model_region = self.load_model(self.model_region_dir_fully if patches else self.model_region_dir_fully_np)
else: else:
model_region = self.model_region_fl if patches else self.model_region_fl_np model_region = self.model_region_fl if patches else self.model_region_fl_np
@ -1444,19 +1421,19 @@ class Eynollah():
def textline_contours(self, img, patches, scaler_h, scaler_w): def textline_contours(self, img, patches, scaler_h, scaler_w):
self.logger.debug('enter textline_contours') self.logger.debug('enter textline_contours')
if not self.dir_in: if not self.dirs.dir_in:
model_textline = self.load_model(self.model_textline_dir if patches else self.model_textline_dir_np) model_textline = self.load_model(self.model_textline_dir if patches else self.model_textline_dir_np)
img = img.astype(np.uint8) img = img.astype(np.uint8)
img_org = np.copy(img) img_org = np.copy(img)
img_h = img_org.shape[0] img_h = img_org.shape[0]
img_w = img_org.shape[1] img_w = img_org.shape[1]
img = resize_image(img_org, int(img_org.shape[0] * scaler_h), int(img_org.shape[1] * scaler_w)) img = resize_image(img_org, int(img_org.shape[0] * scaler_h), int(img_org.shape[1] * scaler_w))
if not self.dir_in: if not self.dirs.dir_in:
prediction_textline = self.do_prediction(patches, img, model_textline) prediction_textline = self.do_prediction(patches, img, model_textline)
else: else:
prediction_textline = self.do_prediction(patches, img, self.model_textline) prediction_textline = self.do_prediction(patches, img, self.model_textline)
prediction_textline = resize_image(prediction_textline, img_h, img_w) prediction_textline = resize_image(prediction_textline, img_h, img_w)
if not self.dir_in: if not self.dirs.dir_in:
prediction_textline_longshot = self.do_prediction(False, img, model_textline) prediction_textline_longshot = self.do_prediction(False, img, model_textline)
else: else:
prediction_textline_longshot = self.do_prediction(False, img, self.model_textline) prediction_textline_longshot = self.do_prediction(False, img, self.model_textline)
@ -1502,6 +1479,7 @@ class Eynollah():
q.put(slopes_sub) q.put(slopes_sub)
poly.put(poly_sub) poly.put(poly_sub)
box_sub.put(boxes_sub_new) box_sub.put(boxes_sub_new)
def get_regions_light_v(self,img,is_image_enhanced, num_col_classifier): def get_regions_light_v(self,img,is_image_enhanced, num_col_classifier):
self.logger.debug("enter get_regions_light_v") self.logger.debug("enter get_regions_light_v")
erosion_hurts = False erosion_hurts = False
@ -1536,7 +1514,7 @@ class Eynollah():
img_h_new = int(img_org.shape[0] / float(img_org.shape[1]) * img_w_new) img_h_new = int(img_org.shape[0] / float(img_org.shape[1]) * img_w_new)
img_resized = resize_image(img,img_h_new, img_w_new ) img_resized = resize_image(img,img_h_new, img_w_new )
if not self.dir_in: if not self.dirs.dir_in:
model_bin = self.load_model(self.model_dir_of_binarization) model_bin = self.load_model(self.model_dir_of_binarization)
prediction_bin = self.do_prediction(True, img_resized, model_bin) prediction_bin = self.do_prediction(True, img_resized, model_bin)
else: else:
@ -1555,7 +1533,7 @@ class Eynollah():
textline_mask_tot_ea = self.run_textline(img_bin) textline_mask_tot_ea = self.run_textline(img_bin)
if not self.dir_in: if not self.dirs.dir_in:
model_region = self.load_model(self.model_region_dir_p_ens_light) model_region = self.load_model(self.model_region_dir_p_ens_light)
prediction_regions_org = self.do_prediction_new_concept(True, img_bin, model_region) prediction_regions_org = self.do_prediction_new_concept(True, img_bin, model_region)
else: else:
@ -1600,14 +1578,14 @@ class Eynollah():
img_height_h = img_org.shape[0] img_height_h = img_org.shape[0]
img_width_h = img_org.shape[1] img_width_h = img_org.shape[1]
if not self.dir_in: if not self.dirs.dir_in:
model_region = self.load_model(self.model_region_dir_p_ens) model_region = self.load_model(self.model_region_dir_p_ens)
ratio_y=1.3 ratio_y=1.3
ratio_x=1 ratio_x=1
img = resize_image(img_org, int(img_org.shape[0]*ratio_y), int(img_org.shape[1]*ratio_x)) img = resize_image(img_org, int(img_org.shape[0]*ratio_y), int(img_org.shape[1]*ratio_x))
if not self.dir_in: if not self.dirs.dir_in:
prediction_regions_org_y = self.do_prediction(True, img, model_region) prediction_regions_org_y = self.do_prediction(True, img, model_region)
else: else:
prediction_regions_org_y = self.do_prediction(True, img, self.model_region) prediction_regions_org_y = self.do_prediction(True, img, self.model_region)
@ -1629,7 +1607,7 @@ class Eynollah():
img = resize_image(img_org, int(img_org.shape[0]), int(img_org.shape[1]*(1.2 if is_image_enhanced else 1))) img = resize_image(img_org, int(img_org.shape[0]), int(img_org.shape[1]*(1.2 if is_image_enhanced else 1)))
if self.dir_in: if self.dirs.dir_in:
prediction_regions_org = self.do_prediction(True, img, self.model_region) prediction_regions_org = self.do_prediction(True, img, self.model_region)
else: else:
prediction_regions_org = self.do_prediction(True, img, model_region) prediction_regions_org = self.do_prediction(True, img, model_region)
@ -1639,12 +1617,12 @@ class Eynollah():
prediction_regions_org[(prediction_regions_org[:,:]==1) & (mask_zeros_y[:,:]==1)]=0 prediction_regions_org[(prediction_regions_org[:,:]==1) & (mask_zeros_y[:,:]==1)]=0
if not self.dir_in: if not self.dirs.dir_in:
model_region = self.load_model(self.model_region_dir_p2) model_region = self.load_model(self.model_region_dir_p2)
img = resize_image(img_org, int(img_org.shape[0]), int(img_org.shape[1])) img = resize_image(img_org, int(img_org.shape[0]), int(img_org.shape[1]))
if self.dir_in: if self.dirs.dir_in:
prediction_regions_org2 = self.do_prediction(True, img, self.model_region_p2, 0.2) prediction_regions_org2 = self.do_prediction(True, img, self.model_region_p2, 0.2)
else: else:
prediction_regions_org2 = self.do_prediction(True, img, model_region, 0.2) prediction_regions_org2 = self.do_prediction(True, img, model_region, 0.2)
@ -1678,7 +1656,7 @@ class Eynollah():
if self.input_binary: if self.input_binary:
prediction_bin = np.copy(img_org) prediction_bin = np.copy(img_org)
else: else:
if not self.dir_in: if not self.dirs.dir_in:
model_bin = self.load_model(self.model_dir_of_binarization) model_bin = self.load_model(self.model_dir_of_binarization)
prediction_bin = self.do_prediction(True, img_org, model_bin) prediction_bin = self.do_prediction(True, img_org, model_bin)
else: else:
@ -1691,7 +1669,7 @@ class Eynollah():
prediction_bin =np.repeat(prediction_bin[:, :, np.newaxis], 3, axis=2) prediction_bin =np.repeat(prediction_bin[:, :, np.newaxis], 3, axis=2)
if not self.dir_in: if not self.dirs.dir_in:
model_region = self.load_model(self.model_region_dir_p_ens) model_region = self.load_model(self.model_region_dir_p_ens)
ratio_y=1 ratio_y=1
ratio_x=1 ratio_x=1
@ -1699,7 +1677,7 @@ class Eynollah():
img = resize_image(prediction_bin, int(img_org.shape[0]*ratio_y), int(img_org.shape[1]*ratio_x)) img = resize_image(prediction_bin, int(img_org.shape[0]*ratio_y), int(img_org.shape[1]*ratio_x))
if not self.dir_in: if not self.dirs.dir_in:
prediction_regions_org = self.do_prediction(True, img, model_region) prediction_regions_org = self.do_prediction(True, img, model_region)
else: else:
prediction_regions_org = self.do_prediction(True, img, self.model_region) prediction_regions_org = self.do_prediction(True, img, self.model_region)
@ -1731,7 +1709,7 @@ class Eynollah():
if self.input_binary: if self.input_binary:
prediction_bin = np.copy(img_org) prediction_bin = np.copy(img_org)
if not self.dir_in: if not self.dirs.dir_in:
model_bin = self.load_model(self.model_dir_of_binarization) model_bin = self.load_model(self.model_dir_of_binarization)
prediction_bin = self.do_prediction(True, img_org, model_bin) prediction_bin = self.do_prediction(True, img_org, model_bin)
else: else:
@ -1746,7 +1724,7 @@ class Eynollah():
prediction_bin =np.repeat(prediction_bin[:, :, np.newaxis], 3, axis=2) prediction_bin =np.repeat(prediction_bin[:, :, np.newaxis], 3, axis=2)
if not self.dir_in: if not self.dirs.dir_in:
model_region = self.load_model(self.model_region_dir_p_ens) model_region = self.load_model(self.model_region_dir_p_ens)
else: else:
@ -1756,7 +1734,7 @@ class Eynollah():
img = resize_image(prediction_bin, int(img_org.shape[0]*ratio_y), int(img_org.shape[1]*ratio_x)) img = resize_image(prediction_bin, int(img_org.shape[0]*ratio_y), int(img_org.shape[1]*ratio_x))
if not self.dir_in: if not self.dirs.dir_in:
prediction_regions_org = self.do_prediction(True, img, model_region) prediction_regions_org = self.do_prediction(True, img, model_region)
else: else:
prediction_regions_org = self.do_prediction(True, img, self.model_region) prediction_regions_org = self.do_prediction(True, img, self.model_region)
@ -2755,13 +2733,13 @@ class Eynollah():
t0_tot = time.time() t0_tot = time.time()
if not self.dir_in: if not self.dirs.dir_in:
self.ls_imgs = [1] self.ls_imgs = [1]
for img_name in self.ls_imgs: for img_name in self.ls_imgs:
t0 = time.time() t0 = time.time()
if self.dir_in: if self.dirs.dir_in:
self.reset_file_name_dir(join(self.dir_in,img_name)) self.reset_file_name_dir(join(self.dirs.dir_in,img_name))
img_res, is_image_enhanced, num_col_classifier, num_column_is_classified = self.run_enhancement(self.light_version) img_res, is_image_enhanced, num_col_classifier, num_column_is_classified = self.run_enhancement(self.light_version)
self.logger.info("Enhancing took %.1fs ", time.time() - t0) self.logger.info("Enhancing took %.1fs ", time.time() - t0)
@ -2789,7 +2767,7 @@ class Eynollah():
self.logger.info("No columns detected, outputting an empty PAGE-XML") self.logger.info("No columns detected, outputting an empty PAGE-XML")
pcgts = self.writer.build_pagexml_no_full_layout([], page_coord, [], [], [], [], [], [], [], [], [], [], cont_page, [], []) pcgts = self.writer.build_pagexml_no_full_layout([], page_coord, [], [], [], [], [], [], [], [], [], [], cont_page, [], [])
self.logger.info("Job done in %.1fs", time.time() - t1) self.logger.info("Job done in %.1fs", time.time() - t1)
if self.dir_in: if self.dirs.dir_in:
self.writer.write_pagexml(pcgts) self.writer.write_pagexml(pcgts)
continue continue
else: else:
@ -3017,7 +2995,7 @@ class Eynollah():
pcgts = self.writer.build_pagexml_full_layout(contours_only_text_parent, contours_only_text_parent_h, page_coord, order_text_new, id_of_texts_tot, all_found_textline_polygons, all_found_textline_polygons_h, all_box_coord, all_box_coord_h, polygons_of_images, contours_tables, polygons_of_drop_capitals, polygons_of_marginals, all_found_textline_polygons_marginals, all_box_coord_marginals, slopes, slopes_h, slopes_marginals, cont_page, polygons_lines_xml) pcgts = self.writer.build_pagexml_full_layout(contours_only_text_parent, contours_only_text_parent_h, page_coord, order_text_new, id_of_texts_tot, all_found_textline_polygons, all_found_textline_polygons_h, all_box_coord, all_box_coord_h, polygons_of_images, contours_tables, polygons_of_drop_capitals, polygons_of_marginals, all_found_textline_polygons_marginals, all_box_coord_marginals, slopes, slopes_h, slopes_marginals, cont_page, polygons_lines_xml)
self.logger.info("Job done in %.1fs", time.time() - t0) self.logger.info("Job done in %.1fs", time.time() - t0)
if not self.dir_in: if not self.dirs.dir_in:
return pcgts return pcgts
else: else:
contours_only_text_parent_h = None contours_only_text_parent_h = None
@ -3028,11 +3006,11 @@ class Eynollah():
order_text_new, id_of_texts_tot = self.do_order_of_regions(contours_only_text_parent_d_ordered, contours_only_text_parent_h, boxes_d, textline_mask_tot_d) order_text_new, id_of_texts_tot = self.do_order_of_regions(contours_only_text_parent_d_ordered, contours_only_text_parent_h, boxes_d, textline_mask_tot_d)
pcgts = self.writer.build_pagexml_no_full_layout(txt_con_org, page_coord, order_text_new, id_of_texts_tot, all_found_textline_polygons, all_box_coord, polygons_of_images, polygons_of_marginals, all_found_textline_polygons_marginals, all_box_coord_marginals, slopes, slopes_marginals, cont_page, polygons_lines_xml, contours_tables) pcgts = self.writer.build_pagexml_no_full_layout(txt_con_org, page_coord, order_text_new, id_of_texts_tot, all_found_textline_polygons, all_box_coord, polygons_of_images, polygons_of_marginals, all_found_textline_polygons_marginals, all_box_coord_marginals, slopes, slopes_marginals, cont_page, polygons_lines_xml, contours_tables)
self.logger.info("Job done in %.1fs", time.time() - t0) self.logger.info("Job done in %.1fs", time.time() - t0)
if not self.dir_in: if not self.dirs.dir_in:
return pcgts return pcgts
if self.dir_in: if self.dirs.dir_in:
self.writer.write_pagexml(pcgts) self.writer.write_pagexml(pcgts)
#self.logger.info("Job done in %.1fs", time.time() - t0) #self.logger.info("Job done in %.1fs", time.time() - t0)
if self.dir_in: if self.dirs.dir_in:
self.logger.info("All jobs done in %.1fs", time.time() - t0_tot) self.logger.info("All jobs done in %.1fs", time.time() - t0_tot)

@ -8,6 +8,7 @@ from scipy.ndimage import gaussian_filter1d
from .utils import crop_image_inside_box from .utils import crop_image_inside_box
from .utils.rotate import rotate_image_different from .utils.rotate import rotate_image_different
from .utils.resize import resize_image from .utils.resize import resize_image
from .utils.dirs import EynollahDirs
class EynollahPlotter(): class EynollahPlotter():
""" """
@ -17,23 +18,13 @@ class EynollahPlotter():
def __init__( def __init__(
self, self,
*, *,
dir_out, dirs : EynollahDirs,
dir_of_all,
dir_save_page,
dir_of_deskewed,
dir_of_layout,
dir_of_cropped_images,
image_filename_stem, image_filename_stem,
image_org=None, image_org=None,
scale_x=1, scale_x=1,
scale_y=1, scale_y=1,
): ):
self.dir_out = dir_out self.dirs = dirs
self.dir_of_all = dir_of_all
self.dir_save_page = dir_save_page
self.dir_of_layout = dir_of_layout
self.dir_of_cropped_images = dir_of_cropped_images
self.dir_of_deskewed = dir_of_deskewed
self.image_filename_stem = image_filename_stem self.image_filename_stem = image_filename_stem
# XXX TODO hacky these cannot be set at init time # XXX TODO hacky these cannot be set at init time
self.image_org = image_org self.image_org = image_org
@ -41,7 +32,7 @@ class EynollahPlotter():
self.scale_y = scale_y self.scale_y = scale_y
def save_plot_of_layout_main(self, text_regions_p, image_page): def save_plot_of_layout_main(self, text_regions_p, image_page):
if self.dir_of_layout is not None: if self.dirs.dir_of_layout is not None:
values = np.unique(text_regions_p[:, :]) values = np.unique(text_regions_p[:, :])
# pixels=['Background' , 'Main text' , 'Heading' , 'Marginalia' ,'Drop capitals' , 'Images' , 'Seperators' , 'Tables', 'Graphics'] # pixels=['Background' , 'Main text' , 'Heading' , 'Marginalia' ,'Drop capitals' , 'Images' , 'Seperators' , 'Tables', 'Graphics']
pixels=['Background' , 'Main text' , 'Image' , 'Separator','Marginalia'] pixels=['Background' , 'Main text' , 'Image' , 'Separator','Marginalia']
@ -52,11 +43,11 @@ class EynollahPlotter():
colors = [im.cmap(im.norm(value)) for value in values] colors = [im.cmap(im.norm(value)) for value in values]
patches = [mpatches.Patch(color=colors[np.where(values == i)[0][0]], label="{l}".format(l=pixels[int(np.where(values_indexes == i)[0][0])])) for i in values] patches = [mpatches.Patch(color=colors[np.where(values == i)[0][0]], label="{l}".format(l=pixels[int(np.where(values_indexes == i)[0][0])])) for i in values]
plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0, fontsize=40) plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0, fontsize=40)
plt.savefig(os.path.join(self.dir_of_layout, self.image_filename_stem + "_layout_main.png")) plt.savefig(os.path.join(self.dirs.dir_of_layout, self.image_filename_stem + "_layout_main.png"))
def save_plot_of_layout_main_all(self, text_regions_p, image_page): def save_plot_of_layout_main_all(self, text_regions_p, image_page):
if self.dir_of_all is not None: if self.dirs.dir_of_all is not None:
values = np.unique(text_regions_p[:, :]) values = np.unique(text_regions_p[:, :])
# pixels=['Background' , 'Main text' , 'Heading' , 'Marginalia' ,'Drop capitals' , 'Images' , 'Seperators' , 'Tables', 'Graphics'] # pixels=['Background' , 'Main text' , 'Heading' , 'Marginalia' ,'Drop capitals' , 'Images' , 'Seperators' , 'Tables', 'Graphics']
pixels=['Background' , 'Main text' , 'Image' , 'Separator','Marginalia'] pixels=['Background' , 'Main text' , 'Image' , 'Separator','Marginalia']
@ -70,10 +61,10 @@ class EynollahPlotter():
colors = [im.cmap(im.norm(value)) for value in values] colors = [im.cmap(im.norm(value)) for value in values]
patches = [mpatches.Patch(color=colors[np.where(values == i)[0][0]], label="{l}".format(l=pixels[int(np.where(values_indexes == i)[0][0])])) for i in values] patches = [mpatches.Patch(color=colors[np.where(values == i)[0][0]], label="{l}".format(l=pixels[int(np.where(values_indexes == i)[0][0])])) for i in values]
plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0, fontsize=60) plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0, fontsize=60)
plt.savefig(os.path.join(self.dir_of_all, self.image_filename_stem + "_layout_main_and_page.png")) plt.savefig(os.path.join(self.dirs.dir_of_all, self.image_filename_stem + "_layout_main_and_page.png"))
def save_plot_of_layout(self, text_regions_p, image_page): def save_plot_of_layout(self, text_regions_p, image_page):
if self.dir_of_layout is not None: if self.dirs.dir_of_layout is not None:
values = np.unique(text_regions_p[:, :]) values = np.unique(text_regions_p[:, :])
# pixels=['Background' , 'Main text' , 'Heading' , 'Marginalia' ,'Drop capitals' , 'Images' , 'Seperators' , 'Tables', 'Graphics'] # pixels=['Background' , 'Main text' , 'Heading' , 'Marginalia' ,'Drop capitals' , 'Images' , 'Seperators' , 'Tables', 'Graphics']
pixels = ["Background", "Main text", "Header", "Marginalia", "Drop capital", "Image", "Separator", "Tables"] pixels = ["Background", "Main text", "Header", "Marginalia", "Drop capital", "Image", "Separator", "Tables"]
@ -84,10 +75,10 @@ class EynollahPlotter():
colors = [im.cmap(im.norm(value)) for value in values] colors = [im.cmap(im.norm(value)) for value in values]
patches = [mpatches.Patch(color=colors[np.where(values == i)[0][0]], label="{l}".format(l=pixels[int(np.where(values_indexes == i)[0][0])])) for i in values] patches = [mpatches.Patch(color=colors[np.where(values == i)[0][0]], label="{l}".format(l=pixels[int(np.where(values_indexes == i)[0][0])])) for i in values]
plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0, fontsize=40) plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0, fontsize=40)
plt.savefig(os.path.join(self.dir_of_layout, self.image_filename_stem + "_layout.png")) plt.savefig(os.path.join(self.dirs.dir_of_layout, self.image_filename_stem + "_layout.png"))
def save_plot_of_layout_all(self, text_regions_p, image_page): def save_plot_of_layout_all(self, text_regions_p, image_page):
if self.dir_of_all is not None: if self.dirs.dir_of_all is not None:
values = np.unique(text_regions_p[:, :]) values = np.unique(text_regions_p[:, :])
# pixels=['Background' , 'Main text' , 'Heading' , 'Marginalia' ,'Drop capitals' , 'Images' , 'Seperators' , 'Tables', 'Graphics'] # pixels=['Background' , 'Main text' , 'Heading' , 'Marginalia' ,'Drop capitals' , 'Images' , 'Seperators' , 'Tables', 'Graphics']
pixels = ["Background", "Main text", "Header", "Marginalia", "Drop capital", "Image", "Separator", "Tables"] pixels = ["Background", "Main text", "Header", "Marginalia", "Drop capital", "Image", "Separator", "Tables"]
@ -101,10 +92,10 @@ class EynollahPlotter():
colors = [im.cmap(im.norm(value)) for value in values] colors = [im.cmap(im.norm(value)) for value in values]
patches = [mpatches.Patch(color=colors[np.where(values == i)[0][0]], label="{l}".format(l=pixels[int(np.where(values_indexes == i)[0][0])])) for i in values] patches = [mpatches.Patch(color=colors[np.where(values == i)[0][0]], label="{l}".format(l=pixels[int(np.where(values_indexes == i)[0][0])])) for i in values]
plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0, fontsize=60) plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0, fontsize=60)
plt.savefig(os.path.join(self.dir_of_all, self.image_filename_stem + "_layout_and_page.png")) plt.savefig(os.path.join(self.dirs.dir_of_all, self.image_filename_stem + "_layout_and_page.png"))
def save_plot_of_textlines(self, textline_mask_tot_ea, image_page): def save_plot_of_textlines(self, textline_mask_tot_ea, image_page):
if self.dir_of_all is not None: if self.dirs.dir_of_all is not None:
values = np.unique(textline_mask_tot_ea[:, :]) values = np.unique(textline_mask_tot_ea[:, :])
pixels = ["Background", "Textlines"] pixels = ["Background", "Textlines"]
values_indexes = [0, 1] values_indexes = [0, 1]
@ -117,25 +108,25 @@ class EynollahPlotter():
colors = [im.cmap(im.norm(value)) for value in values] colors = [im.cmap(im.norm(value)) for value in values]
patches = [mpatches.Patch(color=colors[np.where(values == i)[0][0]], label="{l}".format(l=pixels[int(np.where(values_indexes == i)[0][0])])) for i in values] patches = [mpatches.Patch(color=colors[np.where(values == i)[0][0]], label="{l}".format(l=pixels[int(np.where(values_indexes == i)[0][0])])) for i in values]
plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0, fontsize=60) plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0, fontsize=60)
plt.savefig(os.path.join(self.dir_of_all, self.image_filename_stem + "_textline_and_page.png")) plt.savefig(os.path.join(self.dirs.dir_of_all, self.image_filename_stem + "_textline_and_page.png"))
def save_deskewed_image(self, slope_deskew): def save_deskewed_image(self, slope_deskew):
if self.dir_of_all is not None: if self.dirs.dir_of_all is not None:
cv2.imwrite(os.path.join(self.dir_of_all, self.image_filename_stem + "_org.png"), self.image_org) cv2.imwrite(os.path.join(self.dirs.dir_of_all, self.image_filename_stem + "_org.png"), self.image_org)
if self.dir_of_deskewed is not None: if self.dirs.dir_of_deskewed is not None:
img_rotated = rotate_image_different(self.image_org, slope_deskew) img_rotated = rotate_image_different(self.image_org, slope_deskew)
cv2.imwrite(os.path.join(self.dir_of_deskewed, self.image_filename_stem + "_deskewed.png"), img_rotated) cv2.imwrite(os.path.join(self.dirs.dir_of_deskewed, self.image_filename_stem + "_deskewed.png"), img_rotated)
def save_page_image(self, image_page): def save_page_image(self, image_page):
if self.dir_of_all is not None: if self.dirs.dir_of_all is not None:
cv2.imwrite(os.path.join(self.dir_of_all, self.image_filename_stem + "_page.png"), image_page) cv2.imwrite(os.path.join(self.dirs.dir_of_all, self.image_filename_stem + "_page.png"), image_page)
if self.dir_save_page is not None: if self.dirs.dir_save_page is not None:
cv2.imwrite(os.path.join(self.dir_save_page, self.image_filename_stem + "_page.png"), image_page) cv2.imwrite(os.path.join(self.dirs.dir_save_page, self.image_filename_stem + "_page.png"), image_page)
def save_enhanced_image(self, img_res): def save_enhanced_image(self, img_res):
cv2.imwrite(os.path.join(self.dir_out, self.image_filename_stem + "_enhanced.png"), img_res) cv2.imwrite(os.path.join(self.dirs.dir_out, self.image_filename_stem + "_enhanced.png"), img_res)
def save_plot_of_textline_density(self, img_patch_org): def save_plot_of_textline_density(self, img_patch_org):
if self.dir_of_all is not None: if self.dirs.dir_of_all is not None:
plt.figure(figsize=(80,40)) plt.figure(figsize=(80,40))
plt.rcParams['font.size']='50' plt.rcParams['font.size']='50'
plt.subplot(1,2,1) plt.subplot(1,2,1)
@ -146,10 +137,10 @@ class EynollahPlotter():
plt.ylabel('Height',fontsize=60) plt.ylabel('Height',fontsize=60)
plt.yticks([0,len(gaussian_filter1d(img_patch_org.sum(axis=1), 3))]) plt.yticks([0,len(gaussian_filter1d(img_patch_org.sum(axis=1), 3))])
plt.gca().invert_yaxis() plt.gca().invert_yaxis()
plt.savefig(os.path.join(self.dir_of_all, self.image_filename_stem+'_density_of_textline.png')) plt.savefig(os.path.join(self.dirs.dir_of_all, self.image_filename_stem+'_density_of_textline.png'))
def save_plot_of_rotation_angle(self, angels, var_res): def save_plot_of_rotation_angle(self, angels, var_res):
if self.dir_of_all is not None: if self.dirs.dir_of_all is not None:
plt.figure(figsize=(60,30)) plt.figure(figsize=(60,30))
plt.rcParams['font.size']='50' plt.rcParams['font.size']='50'
plt.plot(angels,np.array(var_res),'-o',markersize=25,linewidth=4) plt.plot(angels,np.array(var_res),'-o',markersize=25,linewidth=4)
@ -157,10 +148,10 @@ class EynollahPlotter():
plt.ylabel('variance of sum of rotated textline in direction of x axis',fontsize=50) plt.ylabel('variance of sum of rotated textline in direction of x axis',fontsize=50)
plt.plot(angels[np.argmax(var_res)],var_res[np.argmax(np.array(var_res))] ,'*',markersize=50,label='Angle of deskewing=' +str("{:.2f}".format(angels[np.argmax(var_res)]))+r'$\degree$') plt.plot(angels[np.argmax(var_res)],var_res[np.argmax(np.array(var_res))] ,'*',markersize=50,label='Angle of deskewing=' +str("{:.2f}".format(angels[np.argmax(var_res)]))+r'$\degree$')
plt.legend(loc='best') plt.legend(loc='best')
plt.savefig(os.path.join(self.dir_of_all, self.image_filename_stem+'_rotation_angle.png')) plt.savefig(os.path.join(self.dirs.dir_of_all, self.image_filename_stem+'_rotation_angle.png'))
def write_images_into_directory(self, img_contours, image_page): def write_images_into_directory(self, img_contours, image_page):
if self.dir_of_cropped_images is not None: if self.dirs.dir_of_cropped_images is not None:
index = 0 index = 0
for cont_ind in img_contours: for cont_ind in img_contours:
x, y, w, h = cv2.boundingRect(cont_ind) x, y, w, h = cv2.boundingRect(cont_ind)
@ -169,7 +160,7 @@ class EynollahPlotter():
croped_page = resize_image(croped_page, int(croped_page.shape[0] / self.scale_y), int(croped_page.shape[1] / self.scale_x)) croped_page = resize_image(croped_page, int(croped_page.shape[0] / self.scale_y), int(croped_page.shape[1] / self.scale_x))
path = os.path.join(self.dir_of_cropped_images, self.image_filename_stem + "_" + str(index) + ".jpg") path = os.path.join(self.dirs.dir_of_cropped_images, self.image_filename_stem + "_" + str(index) + ".jpg")
cv2.imwrite(path, croped_page) cv2.imwrite(path, croped_page)
index += 1 index += 1

@ -3,6 +3,8 @@ from ocrd.processor.ocrd_page_result import OcrdPageResult
from ocrd_models import OcrdPage from ocrd_models import OcrdPage
from ocrd import Processor from ocrd import Processor
from qurator.eynollah.utils.dirs import EynollahDirs
from .eynollah import Eynollah from .eynollah import Eynollah
class EynollahProcessor(Processor): class EynollahProcessor(Processor):
@ -20,7 +22,9 @@ class EynollahProcessor(Processor):
# page_image, _, _ = self.workspace.image_from_page(page, page_id, feature_filter='binarized') # page_image, _, _ = self.workspace.image_from_page(page, page_id, feature_filter='binarized')
image_filename = self.workspace.download_file(next(self.workspace.mets.find_files(local_filename=page.imageFilename))).local_filename image_filename = self.workspace.download_file(next(self.workspace.mets.find_files(local_filename=page.imageFilename))).local_filename
Eynollah( Eynollah(
self.resolve_resource(self.parameter['models']), EynollahDirs(
dir_models=self.resolve_resource(self.parameter['models']),
),
self.logger, self.logger,
allow_enhancement=self.parameter['allow_enhancement'], allow_enhancement=self.parameter['allow_enhancement'],
curved_line=self.parameter['curved_line'], curved_line=self.parameter['curved_line'],

@ -0,0 +1,19 @@
from dataclasses import dataclass
from typing import Optional
@dataclass()
class EynollahDirs():
"""
Wrapper for all the dir_ kwargs everywhere
"""
dir_models : str
dir_out : Optional[str] = None
dir_in : Optional[str] = None
dir_of_cropped_images : Optional[str] = None
dir_of_layout : Optional[str] = None
dir_of_deskewed : Optional[str] = None
dir_of_all : Optional[str] = None
dir_save_page : Optional[str] = None

@ -2,6 +2,9 @@
# pylint: disable=import-error # pylint: disable=import-error
from pathlib import Path from pathlib import Path
import os.path import os.path
from typing import Optional
from ocrd_models import OcrdPage
from .utils.xml import create_page_xml, xml_reading_order from .utils.xml import create_page_xml, xml_reading_order
from .utils.counter import EynollahIdCounter from .utils.counter import EynollahIdCounter
@ -22,7 +25,15 @@ import numpy as np
class EynollahXmlWriter(): class EynollahXmlWriter():
def __init__(self, *, dir_out, image_filename, curved_line,textline_light, pcgts=None): def __init__(
self,
*,
image_filename : str,
dir_out : Optional[str],
curved_line : bool,
textline_light : bool,
pcgts : Optional[OcrdPage] = None
):
self.logger = getLogger('eynollah.writer') self.logger = getLogger('eynollah.writer')
self.counter = EynollahIdCounter() self.counter = EynollahIdCounter()
self.dir_out = dir_out self.dir_out = dir_out

Loading…
Cancel
Save