mirror of
https://github.com/qurator-spk/eynollah.git
synced 2025-12-15 15:44:13 +01:00
Merge 9fdae72e96 into 38c028c6b5
This commit is contained in:
commit
92897c5f4b
9 changed files with 1327 additions and 1588 deletions
|
|
@ -79,18 +79,28 @@ def machine_based_reading_order(input, dir_in, out, model, log_level):
|
|||
type=click.Path(file_okay=True, dir_okay=True),
|
||||
required=True,
|
||||
)
|
||||
@click.option(
|
||||
"--overwrite",
|
||||
"-O",
|
||||
help="overwrite (instead of skipping) if output xml exists",
|
||||
is_flag=True,
|
||||
)
|
||||
@click.option(
|
||||
"--log_level",
|
||||
"-l",
|
||||
type=click.Choice(['OFF', 'DEBUG', 'INFO', 'WARN', 'ERROR']),
|
||||
help="Override log level globally to this",
|
||||
)
|
||||
def binarization(patches, model_dir, input_image, dir_in, output, log_level):
|
||||
def binarization(patches, model_dir, input_image, dir_in, output, overwrite, log_level):
|
||||
assert bool(input_image) != bool(dir_in), "Either -i (single input) or -di (directory) must be provided, but not both."
|
||||
binarizer = SbbBinarizer(model_dir)
|
||||
if log_level:
|
||||
binarizer.log.setLevel(getLevelName(log_level))
|
||||
binarizer.run(image_path=input_image, use_patches=patches, output=output, dir_in=dir_in)
|
||||
binarizer.logger.setLevel(getLevelName(log_level))
|
||||
binarizer.run(overwrite=overwrite,
|
||||
use_patches=patches,
|
||||
image_path=input_image,
|
||||
output=output,
|
||||
dir_in=dir_in)
|
||||
|
||||
|
||||
@main.command()
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -70,7 +70,7 @@ class SbbBinarizeProcessor(Processor):
|
|||
|
||||
if oplevel == 'page':
|
||||
self.logger.info("Binarizing on 'page' level in page '%s'", page_id)
|
||||
page_image_bin = cv2pil(self.binarizer.run(image=pil2cv(page_image), use_patches=True))
|
||||
page_image_bin = cv2pil(self.binarizer.run_single(image=pil2cv(page_image), use_patches=True))
|
||||
# update PAGE (reference the image file):
|
||||
page_image_ref = AlternativeImageType(comments=page_xywh['features'] + ',binarized,clipped')
|
||||
page.add_AlternativeImage(page_image_ref)
|
||||
|
|
@ -83,7 +83,7 @@ class SbbBinarizeProcessor(Processor):
|
|||
for region in regions:
|
||||
region_image, region_xywh = self.workspace.image_from_segment(
|
||||
region, page_image, page_xywh, feature_filter='binarized')
|
||||
region_image_bin = cv2pil(self.binarizer.run(image=pil2cv(region_image), use_patches=True))
|
||||
region_image_bin = cv2pil(self.binarizer.run_single(image=pil2cv(region_image), use_patches=True))
|
||||
# update PAGE (reference the image file):
|
||||
region_image_ref = AlternativeImageType(comments=region_xywh['features'] + ',binarized')
|
||||
region.add_AlternativeImage(region_image_ref)
|
||||
|
|
@ -95,7 +95,7 @@ class SbbBinarizeProcessor(Processor):
|
|||
self.logger.warning("Page '%s' contains no text lines", page_id)
|
||||
for line in lines:
|
||||
line_image, line_xywh = self.workspace.image_from_segment(line, page_image, page_xywh, feature_filter='binarized')
|
||||
line_image_bin = cv2pil(self.binarizer.run(image=pil2cv(line_image), use_patches=True))
|
||||
line_image_bin = cv2pil(self.binarizer.run_single(image=pil2cv(line_image), use_patches=True))
|
||||
# update PAGE (reference the image file):
|
||||
line_image_ref = AlternativeImageType(comments=line_xywh['features'] + ',binarized')
|
||||
line.add_AlternativeImage(region_image_ref)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class SbbBinarizer:
|
|||
|
||||
def __init__(self, model_dir, logger=None):
|
||||
self.model_dir = model_dir
|
||||
self.log = logger if logger else logging.getLogger('SbbBinarizer')
|
||||
self.logger = logger if logger else logging.getLogger('SbbBinarizer')
|
||||
|
||||
self.start_new_session()
|
||||
|
||||
|
|
@ -315,47 +315,30 @@ class SbbBinarizer:
|
|||
prediction_true = prediction_true.astype(np.uint8)
|
||||
return prediction_true[:,:,0]
|
||||
|
||||
def run(self, image=None, image_path=None, output=None, use_patches=False, dir_in=None):
|
||||
# print(dir_in,'dir_in')
|
||||
if not dir_in:
|
||||
if (image is not None and image_path is not None) or \
|
||||
(image is None and image_path is None):
|
||||
raise ValueError("Must pass either a opencv2 image or an image_path")
|
||||
if image_path is not None:
|
||||
image = cv2.imread(image_path)
|
||||
img_last = 0
|
||||
for n, (model, model_file) in enumerate(zip(self.models, self.model_files)):
|
||||
self.log.info('Predicting with model %s [%s/%s]' % (model_file, n + 1, len(self.model_files)))
|
||||
|
||||
res = self.predict(model, image, use_patches)
|
||||
|
||||
img_fin = np.zeros((res.shape[0], res.shape[1], 3))
|
||||
res[:, :][res[:, :] == 0] = 2
|
||||
res = res - 1
|
||||
res = res * 255
|
||||
img_fin[:, :, 0] = res
|
||||
img_fin[:, :, 1] = res
|
||||
img_fin[:, :, 2] = res
|
||||
|
||||
img_fin = img_fin.astype(np.uint8)
|
||||
img_fin = (res[:, :] == 0) * 255
|
||||
img_last = img_last + img_fin
|
||||
|
||||
kernel = np.ones((5, 5), np.uint8)
|
||||
img_last[:, :][img_last[:, :] > 0] = 255
|
||||
img_last = (img_last[:, :] == 0) * 255
|
||||
if output:
|
||||
cv2.imwrite(output, img_last)
|
||||
return img_last
|
||||
def run(self, image_path=None, output=None, dir_in=None, use_patches=False, overwrite=False):
|
||||
if dir_in:
|
||||
ls_imgs = [(os.path.join(dir_in, image_filename),
|
||||
os.path.join(output, os.path.splitext(image_filename)[0] + '.png'))
|
||||
for image_filename in filter(is_image_filename,
|
||||
os.listdir(dir_in))]
|
||||
else:
|
||||
ls_imgs = list(filter(is_image_filename, os.listdir(dir_in)))
|
||||
for image_name in ls_imgs:
|
||||
image_stem = image_name.split('.')[0]
|
||||
print(image_name,'image_name')
|
||||
image = cv2.imread(os.path.join(dir_in,image_name) )
|
||||
ls_imgs = [(image_path, output)]
|
||||
|
||||
for input_path, output_path in ls_imgs:
|
||||
print(input_path, 'image_name')
|
||||
if os.path.exists(output_path):
|
||||
if overwrite:
|
||||
self.logger.warning("will overwrite existing output file '%s'", output_path)
|
||||
else:
|
||||
self.logger.warning("will skip input for existing output file '%s'", output_path)
|
||||
image = cv2.imread(input_path)
|
||||
result = self.run_single(image, use_patches)
|
||||
cv2.imwrite(output_path, result)
|
||||
|
||||
def run_single(self, image: np.ndarray, use_patches=False):
|
||||
img_last = 0
|
||||
for n, (model, model_file) in enumerate(zip(self.models, self.model_files)):
|
||||
self.log.info('Predicting with model %s [%s/%s]' % (model_file, n + 1, len(self.model_files)))
|
||||
self.logger.info('Predicting with model %s [%s/%s]' % (model_file, n + 1, len(self.model_files)))
|
||||
|
||||
res = self.predict(model, image, use_patches)
|
||||
|
||||
|
|
@ -374,5 +357,4 @@ class SbbBinarizer:
|
|||
kernel = np.ones((5, 5), np.uint8)
|
||||
img_last[:, :][img_last[:, :] > 0] = 255
|
||||
img_last = (img_last[:, :] == 0) * 255
|
||||
|
||||
cv2.imwrite(os.path.join(output, image_stem + '.png'), img_last)
|
||||
return img_last
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -14,21 +14,16 @@ from shapely.ops import unary_union, nearest_points
|
|||
from .rotate import rotate_image, rotation_image_new
|
||||
|
||||
def contours_in_same_horizon(cy_main_hor):
|
||||
X1 = np.zeros((len(cy_main_hor), len(cy_main_hor)))
|
||||
X2 = np.zeros((len(cy_main_hor), len(cy_main_hor)))
|
||||
|
||||
X1[0::1, :] = cy_main_hor[:]
|
||||
X2 = X1.T
|
||||
|
||||
X_dif = np.abs(X2 - X1)
|
||||
args_help = np.array(range(len(cy_main_hor)))
|
||||
all_args = []
|
||||
for i in range(len(cy_main_hor)):
|
||||
list_h = list(args_help[X_dif[i, :] <= 20])
|
||||
list_h.append(i)
|
||||
if len(list_h) > 1:
|
||||
all_args.append(list(set(list_h)))
|
||||
return np.unique(np.array(all_args, dtype=object))
|
||||
"""
|
||||
Takes an array of y coords, identifies all pairs among them
|
||||
which are close to each other, and returns all such pairs
|
||||
by index into the array.
|
||||
"""
|
||||
sort = np.argsort(cy_main_hor)
|
||||
same = np.diff(cy_main_hor[sort]) <= 20
|
||||
# groups = np.split(sort, np.arange(len(cy_main_hor) - 1)[~same] + 1)
|
||||
same = np.flatnonzero(same)
|
||||
return np.stack((sort[:-1][same], sort[1:][same])).T
|
||||
|
||||
def find_contours_mean_y_diff(contours_main):
|
||||
M_main = [cv2.moments(contours_main[j]) for j in range(len(contours_main))]
|
||||
|
|
|
|||
|
|
@ -403,14 +403,14 @@ def separate_lines(img_patch, contour_text_interest, thetha, x_help, y_help):
|
|||
point_down_rot3=point_down_rot3-y_help
|
||||
point_down_rot4=point_down_rot4-y_help
|
||||
|
||||
textline_boxes_rot.append(np.array([[int(x_min_rot1), int(point_up_rot1)],
|
||||
[int(x_max_rot2), int(point_up_rot2)],
|
||||
[int(x_max_rot3), int(point_down_rot3)],
|
||||
[int(x_min_rot4), int(point_down_rot4)]]))
|
||||
textline_boxes.append(np.array([[int(x_min), int(point_up)],
|
||||
[int(x_max), int(point_up)],
|
||||
[int(x_max), int(point_down)],
|
||||
[int(x_min), int(point_down)]]))
|
||||
textline_boxes_rot.append(np.array([[[int(x_min_rot1), int(point_up_rot1)]],
|
||||
[[int(x_max_rot2), int(point_up_rot2)]],
|
||||
[[int(x_max_rot3), int(point_down_rot3)]],
|
||||
[[int(x_min_rot4), int(point_down_rot4)]]]))
|
||||
textline_boxes.append(np.array([[[int(x_min), int(point_up)]],
|
||||
[[int(x_max), int(point_up)]],
|
||||
[[int(x_max), int(point_down)]],
|
||||
[[int(x_min), int(point_down)]]]))
|
||||
elif len(peaks) < 1:
|
||||
pass
|
||||
|
||||
|
|
@ -462,14 +462,14 @@ def separate_lines(img_patch, contour_text_interest, thetha, x_help, y_help):
|
|||
point_down_rot3=point_down_rot3-y_help
|
||||
point_down_rot4=point_down_rot4-y_help
|
||||
|
||||
textline_boxes_rot.append(np.array([[int(x_min_rot1), int(point_up_rot1)],
|
||||
[int(x_max_rot2), int(point_up_rot2)],
|
||||
[int(x_max_rot3), int(point_down_rot3)],
|
||||
[int(x_min_rot4), int(point_down_rot4)]]))
|
||||
textline_boxes.append(np.array([[int(x_min), int(y_min)],
|
||||
[int(x_max), int(y_min)],
|
||||
[int(x_max), int(y_max)],
|
||||
[int(x_min), int(y_max)]]))
|
||||
textline_boxes_rot.append(np.array([[[int(x_min_rot1), int(point_up_rot1)]],
|
||||
[[int(x_max_rot2), int(point_up_rot2)]],
|
||||
[[int(x_max_rot3), int(point_down_rot3)]],
|
||||
[[int(x_min_rot4), int(point_down_rot4)]]]))
|
||||
textline_boxes.append(np.array([[[int(x_min), int(y_min)]],
|
||||
[[int(x_max), int(y_min)]],
|
||||
[[int(x_max), int(y_max)]],
|
||||
[[int(x_min), int(y_max)]]]))
|
||||
elif len(peaks) == 2:
|
||||
dis_to_next = np.abs(peaks[1] - peaks[0])
|
||||
for jj in range(len(peaks)):
|
||||
|
|
@ -530,14 +530,14 @@ def separate_lines(img_patch, contour_text_interest, thetha, x_help, y_help):
|
|||
point_down_rot3=point_down_rot3-y_help
|
||||
point_down_rot4=point_down_rot4-y_help
|
||||
|
||||
textline_boxes_rot.append(np.array([[int(x_min_rot1), int(point_up_rot1)],
|
||||
[int(x_max_rot2), int(point_up_rot2)],
|
||||
[int(x_max_rot3), int(point_down_rot3)],
|
||||
[int(x_min_rot4), int(point_down_rot4)]]))
|
||||
textline_boxes.append(np.array([[int(x_min), int(point_up)],
|
||||
[int(x_max), int(point_up)],
|
||||
[int(x_max), int(point_down)],
|
||||
[int(x_min), int(point_down)]]))
|
||||
textline_boxes_rot.append(np.array([[[int(x_min_rot1), int(point_up_rot1)]],
|
||||
[[int(x_max_rot2), int(point_up_rot2)]],
|
||||
[[int(x_max_rot3), int(point_down_rot3)]],
|
||||
[[int(x_min_rot4), int(point_down_rot4)]]]))
|
||||
textline_boxes.append(np.array([[[int(x_min), int(point_up)]],
|
||||
[[int(x_max), int(point_up)]],
|
||||
[[int(x_max), int(point_down)]],
|
||||
[[int(x_min), int(point_down)]]]))
|
||||
else:
|
||||
for jj in range(len(peaks)):
|
||||
if jj == 0:
|
||||
|
|
@ -606,14 +606,14 @@ def separate_lines(img_patch, contour_text_interest, thetha, x_help, y_help):
|
|||
point_down_rot3=point_down_rot3-y_help
|
||||
point_down_rot4=point_down_rot4-y_help
|
||||
|
||||
textline_boxes_rot.append(np.array([[int(x_min_rot1), int(point_up_rot1)],
|
||||
[int(x_max_rot2), int(point_up_rot2)],
|
||||
[int(x_max_rot3), int(point_down_rot3)],
|
||||
[int(x_min_rot4), int(point_down_rot4)]]))
|
||||
textline_boxes.append(np.array([[int(x_min), int(point_up)],
|
||||
[int(x_max), int(point_up)],
|
||||
[int(x_max), int(point_down)],
|
||||
[int(x_min), int(point_down)]]))
|
||||
textline_boxes_rot.append(np.array([[[int(x_min_rot1), int(point_up_rot1)]],
|
||||
[[int(x_max_rot2), int(point_up_rot2)]],
|
||||
[[int(x_max_rot3), int(point_down_rot3)]],
|
||||
[[int(x_min_rot4), int(point_down_rot4)]]]))
|
||||
textline_boxes.append(np.array([[[int(x_min), int(point_up)]],
|
||||
[[int(x_max), int(point_up)]],
|
||||
[[int(x_max), int(point_down)]],
|
||||
[[int(x_min), int(point_down)]]]))
|
||||
return peaks, textline_boxes_rot
|
||||
|
||||
def separate_lines_vertical(img_patch, contour_text_interest, thetha):
|
||||
|
|
@ -785,14 +785,14 @@ def separate_lines_vertical(img_patch, contour_text_interest, thetha):
|
|||
if point_up_rot2 < 0:
|
||||
point_up_rot2 = 0
|
||||
|
||||
textline_boxes_rot.append(np.array([[int(x_min_rot1), int(point_up_rot1)],
|
||||
[int(x_max_rot2), int(point_up_rot2)],
|
||||
[int(x_max_rot3), int(point_down_rot3)],
|
||||
[int(x_min_rot4), int(point_down_rot4)]]))
|
||||
textline_boxes.append(np.array([[int(x_min), int(point_up)],
|
||||
[int(x_max), int(point_up)],
|
||||
[int(x_max), int(point_down)],
|
||||
[int(x_min), int(point_down)]]))
|
||||
textline_boxes_rot.append(np.array([[[int(x_min_rot1), int(point_up_rot1)]],
|
||||
[[int(x_max_rot2), int(point_up_rot2)]],
|
||||
[[int(x_max_rot3), int(point_down_rot3)]],
|
||||
[[int(x_min_rot4), int(point_down_rot4)]]]))
|
||||
textline_boxes.append(np.array([[[int(x_min), int(point_up)]],
|
||||
[[int(x_max), int(point_up)]],
|
||||
[[int(x_max), int(point_down)]],
|
||||
[[int(x_min), int(point_down)]]]))
|
||||
elif len(peaks) < 1:
|
||||
pass
|
||||
elif len(peaks) == 1:
|
||||
|
|
@ -821,14 +821,14 @@ def separate_lines_vertical(img_patch, contour_text_interest, thetha):
|
|||
if point_up_rot2 < 0:
|
||||
point_up_rot2 = 0
|
||||
|
||||
textline_boxes_rot.append(np.array([[int(x_min_rot1), int(point_up_rot1)],
|
||||
[int(x_max_rot2), int(point_up_rot2)],
|
||||
[int(x_max_rot3), int(point_down_rot3)],
|
||||
[int(x_min_rot4), int(point_down_rot4)]]))
|
||||
textline_boxes.append(np.array([[int(x_min), int(y_min)],
|
||||
[int(x_max), int(y_min)],
|
||||
[int(x_max), int(y_max)],
|
||||
[int(x_min), int(y_max)]]))
|
||||
textline_boxes_rot.append(np.array([[[int(x_min_rot1), int(point_up_rot1)]],
|
||||
[[int(x_max_rot2), int(point_up_rot2)]],
|
||||
[[int(x_max_rot3), int(point_down_rot3)]],
|
||||
[[int(x_min_rot4), int(point_down_rot4)]]]))
|
||||
textline_boxes.append(np.array([[[int(x_min), int(y_min)]],
|
||||
[[int(x_max), int(y_min)]],
|
||||
[[int(x_max), int(y_max)]],
|
||||
[[int(x_min), int(y_max)]]]))
|
||||
elif len(peaks) == 2:
|
||||
dis_to_next = np.abs(peaks[1] - peaks[0])
|
||||
for jj in range(len(peaks)):
|
||||
|
|
@ -876,14 +876,14 @@ def separate_lines_vertical(img_patch, contour_text_interest, thetha):
|
|||
if point_up_rot2 < 0:
|
||||
point_up_rot2 = 0
|
||||
|
||||
textline_boxes_rot.append(np.array([[int(x_min_rot1), int(point_up_rot1)],
|
||||
[int(x_max_rot2), int(point_up_rot2)],
|
||||
[int(x_max_rot3), int(point_down_rot3)],
|
||||
[int(x_min_rot4), int(point_down_rot4)]]))
|
||||
textline_boxes.append(np.array([[int(x_min), int(point_up)],
|
||||
[int(x_max), int(point_up)],
|
||||
[int(x_max), int(point_down)],
|
||||
[int(x_min), int(point_down)]]))
|
||||
textline_boxes_rot.append(np.array([[[int(x_min_rot1), int(point_up_rot1)]],
|
||||
[[int(x_max_rot2), int(point_up_rot2)]],
|
||||
[[int(x_max_rot3), int(point_down_rot3)]],
|
||||
[[int(x_min_rot4), int(point_down_rot4)]]]))
|
||||
textline_boxes.append(np.array([[[int(x_min), int(point_up)]],
|
||||
[[int(x_max), int(point_up)]],
|
||||
[[int(x_max), int(point_down)]],
|
||||
[[int(x_min), int(point_down)]]]))
|
||||
else:
|
||||
for jj in range(len(peaks)):
|
||||
if jj == 0:
|
||||
|
|
@ -942,14 +942,14 @@ def separate_lines_vertical(img_patch, contour_text_interest, thetha):
|
|||
if point_up_rot2 < 0:
|
||||
point_up_rot2 = 0
|
||||
|
||||
textline_boxes_rot.append(np.array([[int(x_min_rot1), int(point_up_rot1)],
|
||||
[int(x_max_rot2), int(point_up_rot2)],
|
||||
[int(x_max_rot3), int(point_down_rot3)],
|
||||
[int(x_min_rot4), int(point_down_rot4)]]))
|
||||
textline_boxes.append(np.array([[int(x_min), int(point_up)],
|
||||
[int(x_max), int(point_up)],
|
||||
[int(x_max), int(point_down)],
|
||||
[int(x_min), int(point_down)]]))
|
||||
textline_boxes_rot.append(np.array([[[int(x_min_rot1), int(point_up_rot1)]],
|
||||
[[int(x_max_rot2), int(point_up_rot2)]],
|
||||
[[int(x_max_rot3), int(point_down_rot3)]],
|
||||
[[int(x_min_rot4), int(point_down_rot4)]]]))
|
||||
textline_boxes.append(np.array([[[int(x_min), int(point_up)]],
|
||||
[[int(x_max), int(point_up)]],
|
||||
[[int(x_max), int(point_down)]],
|
||||
[[int(x_min), int(point_down)]]]))
|
||||
return peaks, textline_boxes_rot
|
||||
|
||||
def separate_lines_new_inside_tiles2(img_patch, thetha):
|
||||
|
|
@ -1564,6 +1564,9 @@ def return_deskew_slop(img_patch_org, sigma_des,n_tot_angles=100,
|
|||
angle2, var2 = get_smallest_skew(img_resized, sigma_des, angles2, map=map, logger=logger, plotter=plotter)
|
||||
if var2 > var:
|
||||
angle = angle2
|
||||
# precision stage:
|
||||
angles = np.linspace(angle - 2.5, angle + 2.5, n_tot_angles // 2)
|
||||
angle, _ = get_smallest_skew(img_resized, sigma_des, angles, map=map, logger=logger, plotter=plotter)
|
||||
return angle
|
||||
|
||||
def get_smallest_skew(img, sigma_des, angles, logger=None, plotter=None, map=map):
|
||||
|
|
|
|||
|
|
@ -369,8 +369,8 @@ def break_curved_line_into_small_pieces_and_then_merge(img_curved, mask_curved,
|
|||
return img_curved, img_bin_curved
|
||||
|
||||
def return_textline_contour_with_added_box_coordinate(textline_contour, box_ind):
|
||||
textline_contour[:,0] = textline_contour[:,0] + box_ind[2]
|
||||
textline_contour[:,1] = textline_contour[:,1] + box_ind[0]
|
||||
textline_contour[:,:,0] += box_ind[2]
|
||||
textline_contour[:,:,1] += box_ind[0]
|
||||
return textline_contour
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
from pathlib import Path
|
||||
import os.path
|
||||
import xml.etree.ElementTree as ET
|
||||
from .utils.xml import create_page_xml, xml_reading_order
|
||||
from .utils.counter import EynollahIdCounter
|
||||
import numpy as np
|
||||
from shapely import affinity, clip_by_rect
|
||||
|
||||
from ocrd_utils import getLogger
|
||||
from ocrd_utils import getLogger, points_from_polygon
|
||||
from ocrd_models.ocrd_page import (
|
||||
BorderType,
|
||||
CoordsType,
|
||||
|
|
@ -19,7 +19,10 @@ from ocrd_models.ocrd_page import (
|
|||
SeparatorRegionType,
|
||||
to_xml
|
||||
)
|
||||
import numpy as np
|
||||
|
||||
from .utils.xml import create_page_xml, xml_reading_order
|
||||
from .utils.counter import EynollahIdCounter
|
||||
from .utils.contour import contour2polygon, make_valid
|
||||
|
||||
class EynollahXmlWriter:
|
||||
|
||||
|
|
@ -41,20 +44,14 @@ class EynollahXmlWriter:
|
|||
def image_filename_stem(self):
|
||||
return Path(Path(self.image_filename).name).stem
|
||||
|
||||
def calculate_page_coords(self, cont_page):
|
||||
self.logger.debug('enter calculate_page_coords')
|
||||
points_page_print = ""
|
||||
for _, contour in enumerate(cont_page[0]):
|
||||
if len(contour) == 2:
|
||||
points_page_print += str(int((contour[0]) / self.scale_x))
|
||||
points_page_print += ','
|
||||
points_page_print += str(int((contour[1]) / self.scale_y))
|
||||
else:
|
||||
points_page_print += str(int((contour[0][0]) / self.scale_x))
|
||||
points_page_print += ','
|
||||
points_page_print += str(int((contour[0][1] ) / self.scale_y))
|
||||
points_page_print = points_page_print + ' '
|
||||
return points_page_print[:-1]
|
||||
def calculate_points(self, contour, offset=None):
|
||||
self.logger.debug('enter calculate_points')
|
||||
poly = contour2polygon(contour)
|
||||
if offset is not None:
|
||||
poly = affinity.translate(poly, *offset)
|
||||
poly = affinity.scale(poly, xfact=1 / self.scale_x, yfact=1 / self.scale_y, origin=(0, 0))
|
||||
poly = make_valid(clip_by_rect(poly, 0, 0, self.width_org, self.height_org))
|
||||
return points_from_polygon(poly.exterior.coords[:-1])
|
||||
|
||||
def serialize_lines_in_region(self, text_region, all_found_textline_polygons, region_idx, page_coord, all_box_coord, slopes, counter, ocr_all_textlines_textregion):
|
||||
self.logger.debug('enter serialize_lines_in_region')
|
||||
|
|
@ -67,20 +64,12 @@ class EynollahXmlWriter:
|
|||
text_region.add_TextLine(textline)
|
||||
text_region.set_orientation(-slopes[region_idx])
|
||||
region_bboxes = all_box_coord[region_idx]
|
||||
points_co = ''
|
||||
for point in polygon_textline:
|
||||
if len(point) != 2:
|
||||
point = point[0]
|
||||
point_x = point[0] + page_coord[2]
|
||||
point_y = point[1] + page_coord[0]
|
||||
offset = [page_coord[2], page_coord[0]]
|
||||
# FIXME: or actually... not self.textline_light and not self.curved_line or np.abs(slopes[region_idx]) > 45?
|
||||
if not self.textline_light and not (self.curved_line and np.abs(slopes[region_idx]) <= 45):
|
||||
point_x += region_bboxes[2]
|
||||
point_y += region_bboxes[0]
|
||||
point_x = max(0, int(point_x / self.scale_x))
|
||||
point_y = max(0, int(point_y / self.scale_y))
|
||||
points_co += str(point_x) + ',' + str(point_y) + ' '
|
||||
coords.set_points(points_co[:-1])
|
||||
offset[0] += region_bboxes[2]
|
||||
offset[1] += region_bboxes[0]
|
||||
coords.set_points(self.calculate_points(polygon_textline, offset))
|
||||
|
||||
def write_pagexml(self, pcgts):
|
||||
self.logger.info("output filename: '%s'", self.output_filename)
|
||||
|
|
@ -89,7 +78,7 @@ class EynollahXmlWriter:
|
|||
|
||||
def build_pagexml_no_full_layout(
|
||||
self, found_polygons_text_region,
|
||||
page_coord, order_of_texts, id_of_texts,
|
||||
page_coord, order_of_texts,
|
||||
all_found_textline_polygons,
|
||||
all_box_coord,
|
||||
found_polygons_text_region_img,
|
||||
|
|
@ -102,7 +91,7 @@ class EynollahXmlWriter:
|
|||
**kwargs):
|
||||
return self.build_pagexml_full_layout(
|
||||
found_polygons_text_region, [],
|
||||
page_coord, order_of_texts, id_of_texts,
|
||||
page_coord, order_of_texts,
|
||||
all_found_textline_polygons, [],
|
||||
all_box_coord, [],
|
||||
found_polygons_text_region_img, found_polygons_tables, [],
|
||||
|
|
@ -116,7 +105,7 @@ class EynollahXmlWriter:
|
|||
def build_pagexml_full_layout(
|
||||
self,
|
||||
found_polygons_text_region, found_polygons_text_region_h,
|
||||
page_coord, order_of_texts, id_of_texts,
|
||||
page_coord, order_of_texts,
|
||||
all_found_textline_polygons, all_found_textline_polygons_h,
|
||||
all_box_coord, all_box_coord_h,
|
||||
found_polygons_text_region_img, found_polygons_tables, found_polygons_drop_capitals,
|
||||
|
|
@ -135,8 +124,13 @@ class EynollahXmlWriter:
|
|||
# create the file structure
|
||||
pcgts = self.pcgts if self.pcgts else create_page_xml(self.image_filename, self.height_org, self.width_org)
|
||||
page = pcgts.get_Page()
|
||||
page.set_Border(BorderType(Coords=CoordsType(points=self.calculate_page_coords(cont_page))))
|
||||
if len(cont_page):
|
||||
page.set_Border(BorderType(Coords=CoordsType(points=self.calculate_points(cont_page[0]))))
|
||||
|
||||
if skip_layout_reading_order:
|
||||
offset = None
|
||||
else:
|
||||
offset = [page_coord[2], page_coord[0]]
|
||||
counter = EynollahIdCounter()
|
||||
if len(order_of_texts):
|
||||
_counter_marginals = EynollahIdCounter(region_idx=len(order_of_texts))
|
||||
|
|
@ -149,8 +143,7 @@ class EynollahXmlWriter:
|
|||
for mm, region_contour in enumerate(found_polygons_text_region):
|
||||
textregion = TextRegionType(
|
||||
id=counter.next_region_id, type_='paragraph',
|
||||
Coords=CoordsType(points=self.calculate_polygon_coords(region_contour, page_coord,
|
||||
skip_layout_reading_order))
|
||||
Coords=CoordsType(points=self.calculate_points(region_contour, offset))
|
||||
)
|
||||
if conf_contours_textregions:
|
||||
textregion.Coords.set_conf(conf_contours_textregions[mm])
|
||||
|
|
@ -166,7 +159,7 @@ class EynollahXmlWriter:
|
|||
for mm, region_contour in enumerate(found_polygons_text_region_h):
|
||||
textregion = TextRegionType(
|
||||
id=counter.next_region_id, type_='heading',
|
||||
Coords=CoordsType(points=self.calculate_polygon_coords(region_contour, page_coord))
|
||||
Coords=CoordsType(points=self.calculate_points(region_contour, offset))
|
||||
)
|
||||
if conf_contours_textregions_h:
|
||||
textregion.Coords.set_conf(conf_contours_textregions_h[mm])
|
||||
|
|
@ -181,7 +174,7 @@ class EynollahXmlWriter:
|
|||
for mm, region_contour in enumerate(found_polygons_marginals_left):
|
||||
marginal = TextRegionType(
|
||||
id=counter.next_region_id, type_='marginalia',
|
||||
Coords=CoordsType(points=self.calculate_polygon_coords(region_contour, page_coord))
|
||||
Coords=CoordsType(points=self.calculate_points(region_contour, offset))
|
||||
)
|
||||
page.add_TextRegion(marginal)
|
||||
if ocr_all_textlines_marginals_left:
|
||||
|
|
@ -193,7 +186,7 @@ class EynollahXmlWriter:
|
|||
for mm, region_contour in enumerate(found_polygons_marginals_right):
|
||||
marginal = TextRegionType(
|
||||
id=counter.next_region_id, type_='marginalia',
|
||||
Coords=CoordsType(points=self.calculate_polygon_coords(region_contour, page_coord))
|
||||
Coords=CoordsType(points=self.calculate_points(region_contour, offset))
|
||||
)
|
||||
page.add_TextRegion(marginal)
|
||||
if ocr_all_textlines_marginals_right:
|
||||
|
|
@ -206,7 +199,7 @@ class EynollahXmlWriter:
|
|||
for mm, region_contour in enumerate(found_polygons_drop_capitals):
|
||||
dropcapital = TextRegionType(
|
||||
id=counter.next_region_id, type_='drop-capital',
|
||||
Coords=CoordsType(points=self.calculate_polygon_coords(region_contour, page_coord))
|
||||
Coords=CoordsType(points=self.calculate_points(region_contour, offset))
|
||||
)
|
||||
page.add_TextRegion(dropcapital)
|
||||
all_box_coord_drop = [[0, 0, 0, 0]]
|
||||
|
|
@ -221,33 +214,17 @@ class EynollahXmlWriter:
|
|||
for region_contour in found_polygons_text_region_img:
|
||||
page.add_ImageRegion(
|
||||
ImageRegionType(id=counter.next_region_id,
|
||||
Coords=CoordsType(points=self.calculate_polygon_coords(region_contour, page_coord))))
|
||||
Coords=CoordsType(points=self.calculate_points(region_contour, offset))))
|
||||
|
||||
for region_contour in polygons_seplines:
|
||||
page.add_SeparatorRegion(
|
||||
SeparatorRegionType(id=counter.next_region_id,
|
||||
Coords=CoordsType(points=self.calculate_polygon_coords(region_contour, [0, 0, 0, 0]))))
|
||||
Coords=CoordsType(points=self.calculate_points(region_contour, None))))
|
||||
|
||||
for region_contour in found_polygons_tables:
|
||||
page.add_TableRegion(
|
||||
TableRegionType(id=counter.next_region_id,
|
||||
Coords=CoordsType(points=self.calculate_polygon_coords(region_contour, page_coord))))
|
||||
Coords=CoordsType(points=self.calculate_points(region_contour, offset))))
|
||||
|
||||
return pcgts
|
||||
|
||||
def calculate_polygon_coords(self, contour, page_coord, skip_layout_reading_order=False):
|
||||
self.logger.debug('enter calculate_polygon_coords')
|
||||
coords = ''
|
||||
for point in contour:
|
||||
if len(point) != 2:
|
||||
point = point[0]
|
||||
point_x = point[0]
|
||||
point_y = point[1]
|
||||
if not skip_layout_reading_order:
|
||||
point_x += page_coord[2]
|
||||
point_y += page_coord[0]
|
||||
point_x = int(point_x / self.scale_x)
|
||||
point_y = int(point_y / self.scale_y)
|
||||
coords += str(point_x) + ',' + str(point_y) + ' '
|
||||
return coords[:-1]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue