CLIs: move --device option to group level

This commit is contained in:
Robert Sachunsky 2026-05-12 18:41:21 +02:00
parent 7ed1a1ebac
commit 21ecb043f7
6 changed files with 18 additions and 36 deletions

View file

@ -15,6 +15,7 @@ class EynollahCliCtx:
Holds options relevant for all eynollah subcommands Holds options relevant for all eynollah subcommands
""" """
model_zoo: EynollahModelZoo model_zoo: EynollahModelZoo
device: str = ''
log_level : Union[str, None] = 'INFO' log_level : Union[str, None] = 'INFO'
@ -35,6 +36,11 @@ class EynollahCliCtx:
type=(str, str, str), type=(str, str, str),
multiple=True, multiple=True,
) )
@click.option(
"--device",
"-D",
help="placement of computations in predictors for each model type; if none (by default), will try to use first available GPU or fall back to CPU; set string to force using a device (e.g. 'GPU0', 'GPU1' or 'CPU'). Can also be a comma-separated list of model category to device mappings (e.g. 'col_classifier:CPU,page:GPU0,*:GPU1')",
)
@click.option( @click.option(
"--log_level", "--log_level",
"-l", "-l",
@ -42,7 +48,7 @@ class EynollahCliCtx:
help="Override log level globally to this", help="Override log level globally to this",
) )
@click.pass_context @click.pass_context
def main(ctx, model_basedir, model_overrides, log_level): def main(ctx, model_basedir, model_overrides, device, log_level):
""" """
eynollah - Document Layout Analysis, Image Enhancement, OCR eynollah - Document Layout Analysis, Image Enhancement, OCR
""" """
@ -58,6 +64,7 @@ def main(ctx, model_basedir, model_overrides, log_level):
# Initialize CLI context # Initialize CLI context
ctx.obj = EynollahCliCtx( ctx.obj = EynollahCliCtx(
model_zoo=model_zoo, model_zoo=model_zoo,
device=device,
log_level=log_level, log_level=log_level,
) )

View file

@ -33,11 +33,6 @@ import click
help="overwrite (instead of skipping) if output xml exists", help="overwrite (instead of skipping) if output xml exists",
is_flag=True, is_flag=True,
) )
@click.option(
"--device",
"-D",
help="placement of computations in predictors for each model type; if none (by default), will try to use first available GPU or fall back to CPU; set string to force using a device (e.g. 'GPU0', 'GPU1' or 'CPU'). Can also be a comma-separated list of model category to device mappings (e.g. 'col_classifier:CPU,page:GPU0,*:GPU1')",
)
@click.pass_context @click.pass_context
def binarize_cli( def binarize_cli(
ctx, ctx,
@ -46,14 +41,14 @@ def binarize_cli(
dir_in, dir_in,
output, output,
overwrite, overwrite,
device,
): ):
""" """
Binarize images with a ML model Binarize images with a ML model
""" """
from ..sbb_binarize import SbbBinarizer from ..sbb_binarize import SbbBinarizer
assert bool(input_image) != bool(dir_in), "Either -i (single input) or -di (directory) must be provided, but not both." assert bool(input_image) != bool(dir_in), "Either -i (single input) or -di (directory) must be provided, but not both."
binarizer = SbbBinarizer(model_zoo=ctx.obj.model_zoo, device=device) binarizer = SbbBinarizer(model_zoo=ctx.obj.model_zoo,
device=ctx.obj.device)
binarizer.run( binarizer.run(
image_filename=input_image, image_filename=input_image,
use_patches=patches, use_patches=patches,

View file

@ -48,13 +48,8 @@ import click
is_flag=True, is_flag=True,
help="save the enhanced image in original image size", help="save the enhanced image in original image size",
) )
@click.option(
"--device",
"-D",
help="placement of computations in predictors for each model type; if none (by default), will try to use first available GPU or fall back to CPU; set string to force using a device (e.g. 'GPU0', 'GPU1' or 'CPU'). Can also be a comma-separated list of model category to device mappings (e.g. 'col_classifier:CPU,page:GPU0,*:GPU1')",
)
@click.pass_context @click.pass_context
def enhance_cli(ctx, image, out, overwrite, dir_in, num_col_upper, num_col_lower, save_org_scale, device): def enhance_cli(ctx, image, out, overwrite, dir_in, num_col_upper, num_col_lower, save_org_scale):
""" """
Enhance image Enhance image
""" """
@ -62,10 +57,10 @@ def enhance_cli(ctx, image, out, overwrite, dir_in, num_col_upper, num_col_lower
from ..image_enhancer import Enhancer from ..image_enhancer import Enhancer
enhancer = Enhancer( enhancer = Enhancer(
model_zoo=ctx.obj.model_zoo, model_zoo=ctx.obj.model_zoo,
device=ctx.obj.device,
num_col_upper=num_col_upper, num_col_upper=num_col_upper,
num_col_lower=num_col_lower, num_col_lower=num_col_lower,
save_org_scale=save_org_scale, save_org_scale=save_org_scale,
device=device,
) )
enhancer.run(overwrite=overwrite, enhancer.run(overwrite=overwrite,
dir_in=dir_in, dir_in=dir_in,

View file

@ -172,11 +172,6 @@ import click
type=click.FloatRange(min=0), type=click.FloatRange(min=0),
help="abort when number of failed images exceeds this value (if >=1) or ratio of failed over total images exceeds this value (if <1); 0 means ignore failures", help="abort when number of failed images exceeds this value (if >=1) or ratio of failed over total images exceeds this value (if <1); 0 means ignore failures",
) )
@click.option(
"--device",
"-D",
help="placement of computations in predictors for each model type; if none (by default), will try to use first available GPU or fall back to CPU; set string to force using a device (e.g. 'GPU0', 'GPU1' or 'CPU'). Can also be a comma-separated list of model category to device mappings (e.g. 'col_classifier:CPU,page:GPU0,*:GPU1')",
)
@click.pass_context @click.pass_context
def layout_cli( def layout_cli(
ctx, ctx,
@ -207,7 +202,6 @@ def layout_cli(
ignore_page_extraction, ignore_page_extraction,
num_jobs, num_jobs,
halt_fail, halt_fail,
device,
): ):
""" """
Detect Layout (with optional image enhancement and reading order detection) Detect Layout (with optional image enhancement and reading order detection)
@ -223,7 +217,7 @@ def layout_cli(
assert bool(image) != bool(dir_in), "Either -i (single input) or -di (directory) must be provided, but not both." assert bool(image) != bool(dir_in), "Either -i (single input) or -di (directory) must be provided, but not both."
eynollah = Eynollah( eynollah = Eynollah(
model_zoo=ctx.obj.model_zoo, model_zoo=ctx.obj.model_zoo,
device=device, device=ctx.obj.device,
enable_plotting=enable_plotting, enable_plotting=enable_plotting,
allow_enhancement=allow_enhancement, allow_enhancement=allow_enhancement,
curved_line=curved_line, curved_line=curved_line,

View file

@ -73,11 +73,6 @@ import click
type=click.FloatRange(min=0.0, max=1.0), type=click.FloatRange(min=0.0, max=1.0),
help="minimum OCR confidence threshold. Text lines with a lower confidence value will not be included in the output XML file.", help="minimum OCR confidence threshold. Text lines with a lower confidence value will not be included in the output XML file.",
) )
@click.option(
"--device",
"-D",
help="placement of computations in predictors for each model type; if none (by default), will try to use first available GPU or fall back to CPU; set string to force using a device (e.g. 'GPU0', 'GPU1' or 'CPU'). Can also be a comma-separated list of model category to device mappings (e.g. 'col_classifier:CPU,page:GPU0,*:GPU1')",
)
@click.pass_context @click.pass_context
def ocr_cli( def ocr_cli(
ctx, ctx,
@ -92,7 +87,6 @@ def ocr_cli(
do_not_mask_with_textline_contour, do_not_mask_with_textline_contour,
batch_size, batch_size,
min_conf_value_of_textline_text, min_conf_value_of_textline_text,
device,
): ):
""" """
Recognize text with a CNN/RNN or transformer ML model. Recognize text with a CNN/RNN or transformer ML model.
@ -101,11 +95,12 @@ def ocr_cli(
from ..eynollah_ocr import Eynollah_ocr from ..eynollah_ocr import Eynollah_ocr
eynollah_ocr = Eynollah_ocr( eynollah_ocr = Eynollah_ocr(
model_zoo=ctx.obj.model_zoo, model_zoo=ctx.obj.model_zoo,
device=ctx.obj.device,
tr_ocr=tr_ocr, tr_ocr=tr_ocr,
do_not_mask_with_textline_contour=do_not_mask_with_textline_contour, do_not_mask_with_textline_contour=do_not_mask_with_textline_contour,
batch_size=batch_size, batch_size=batch_size,
min_conf_value_of_textline_text=min_conf_value_of_textline_text, min_conf_value_of_textline_text=min_conf_value_of_textline_text,
device=device) )
eynollah_ocr.run(overwrite=overwrite, eynollah_ocr.run(overwrite=overwrite,
dir_in=dir_in, dir_in=dir_in,
dir_in_bin=dir_in_bin, dir_in_bin=dir_in_bin,

View file

@ -22,19 +22,15 @@ import click
type=click.Path(exists=True, file_okay=False), type=click.Path(exists=True, file_okay=False),
required=True, required=True,
) )
@click.option(
"--device",
"-D",
help="placement of computations in predictors for each model type; if none (by default), will try to use first available GPU or fall back to CPU; set string to force using a device (e.g. 'GPU0', 'GPU1' or 'CPU'). Can also be a comma-separated list of model category to device mappings (e.g. 'col_classifier:CPU,page:GPU0,*:GPU1')",
)
@click.pass_context @click.pass_context
def readingorder_cli(ctx, input, dir_in, out, device): def readingorder_cli(ctx, input, dir_in, out):
""" """
Generate ReadingOrder with a ML model Generate ReadingOrder with a ML model
""" """
from ..mb_ro_on_layout import Reorder from ..mb_ro_on_layout import Reorder
assert bool(input) != bool(dir_in), "Either -i (single input) or -di (directory) must be provided, but not both." assert bool(input) != bool(dir_in), "Either -i (single input) or -di (directory) must be provided, but not both."
orderer = Reorder(model_zoo=ctx.obj.model_zoo, device=device) orderer = Reorder(model_zoo=ctx.obj.model_zoo,
device=ctx.obj.device)
orderer.run(xml_filename=input, orderer.run(xml_filename=input,
dir_in=dir_in, dir_in=dir_in,
dir_out=out, dir_out=out,