layout/extract-images/processor: write AlternativeImage if binarized…

- layout/extract-images: when running with `input_binary`, then
  pass the binarized image of the full page to the writer
- writer: if there is a binarized image, then add an `AlternativeImage`
  to the top-level of the output PAGE (with the array instead of a
  file name)
- writer.write_xml (standalone CLIs): save the image in the same
  directory as the output file, but with `.bin.png` isntead of
  `.xml` as suffix
- processor: convert the binarized image array to PIL and pass over
  as OcrdPageResultImage for the final path name
This commit is contained in:
Robert Sachunsky 2026-07-19 21:40:57 +02:00
parent f1505f5ae6
commit 63fbfc01b5
4 changed files with 25 additions and 1 deletions

View file

@ -252,6 +252,7 @@ class EynollahImageExtractor(Eynollah):
images = [image for image in images if image.area]
pcgts = writer.build_pagexml(
page=page,
img_bin=self.imread(image, binary=True) if self.input_binary else None,
num_col=num_col_classifier,
images=images,
)

View file

@ -2098,6 +2098,7 @@ class Eynollah:
pcgts = writer.build_pagexml(
page=page,
img_bin=self.imread(image, binary=True) if self.input_binary else None,
num_col=num_col_classifier,
order_of_texts=[0],
textregions=textregions,
@ -2170,6 +2171,7 @@ class Eynollah:
pcgts = writer.build_pagexml(
page=page,
img_bin=self.imread(image, binary=True) if self.input_binary else None,
num_col=0,
)
if writer.pcgts is None:
@ -2370,6 +2372,7 @@ class Eynollah:
self.logger.info("Step 5/5: Output Generation")
pcgts = writer.build_pagexml(
page=page,
img_bin=self.imread(image, binary=True) if self.input_binary else None,
num_col=num_col_classifier,
order_of_texts=order_text,
textregions=textregions,

View file

@ -1,5 +1,6 @@
from functools import cached_property
from typing import Optional
from PIL import Image
from ocrd_models import OcrdPage
from ocrd import OcrdPageResultImage, Processor, OcrdPageResult
@ -95,4 +96,9 @@ class EynollahProcessor(Processor):
img_pil=page_image, pcgts=pcgts,
# ocrd.Processor will handle OCRD_EXISTING_OUTPUT more flexibly
overwrite=True)
if self.parameter['binarize'] and (img_alt := next(
(img for img in pcgts.Page.AlternativeImage
if img.comments == "binarized"), None)):
result.images.append(OcrdPageResultImage(
Image.fromarray(img_alt.filename), '.IMG-BIN', img_alt))
return result

View file

@ -4,12 +4,14 @@ from pathlib import Path
import os.path
import logging
from typing import Optional, List, Tuple
import numpy as np
import cv2
from shapely import affinity, clip_by_rect
from ocrd_utils import points_from_polygon
from ocrd_models.ocrd_page import (
AlternativeImageType,
BorderType,
CoordsType,
TextLineType,
@ -80,6 +82,13 @@ class EynollahXmlWriter:
def write_pagexml(self, pcgts):
self.logger.info("output filename: '%s'", self.output_filename)
if img_alt := next(
(img for img in pcgts.Page.AlternativeImage
if img.comments == "binarized"
and isinstance(img.filename, np.ndarray)), None):
img_alt_filename = self.output_filename[:-4] + '.bin.png'
cv2.imwrite(img_alt_filename, img_alt.filename)
img_alt.filename = os.path.basename(img_alt_filename)
with open(self.output_filename, 'w') as f:
f.write(to_xml(pcgts))
@ -87,7 +96,8 @@ class EynollahXmlWriter:
self,
*,
page: Region,
num_col=1,
img_bin: Optional[np.ndarray] = None,
num_col: int = 1,
order_of_texts: List[int] = [],
textregions: List[TextRegion] = [],
textregions_h: List[TextRegion] = [],
@ -104,6 +114,10 @@ class EynollahXmlWriter:
pcgts = self.pcgts if self.pcgts else create_page_xml(
self.image_filename, self.image_height, self.image_width)
pcgts.Metadata.Comments = "num_col %d" % num_col
if img_bin is not None:
img_alt = AlternativeImageType(filename=img_bin, # will be replaced later
comments="binarized")
pcgts.Page.add_AlternativeImage(img_alt)
pcgts.Page.set_custom('layout {num_col:%d;} ' % num_col)
pcgts.Page.set_orientation(-page.skew)
pcgts.Page.set_Border(BorderType(Coords=CoordsType(