layout: refactor into new function do_order_of_regions_heuristic

- calls `run_boxes_order()` and `do_order_of_regions()`
- gets called w/ original or deskewed contours/masks
- heading contours as empty list instead of `None`
This commit is contained in:
Robert Sachunsky 2026-07-20 02:06:48 +02:00
parent 198552e100
commit 282095f921
2 changed files with 41 additions and 21 deletions

View file

@ -1617,7 +1617,7 @@ class Eynollah:
num_col_classifier, num_col_classifier,
erosion_hurts, erosion_hurts,
regions_without_separators, regions_without_separators,
contours_h=None, contours_h=[],
label_seps_fl=6, label_seps_fl=6,
): ):
if not erosion_hurts: if not erosion_hurts:
@ -1822,6 +1822,29 @@ class Eynollah:
else: else:
return ordered return ordered
def do_order_of_regions_heuristic(
self,
textregions_cont,
textregions_h_cont,
drop_caps_cont,
text_regions_p,
regions_without_separators,
num_col_classifier,
erosion_hurts,
):
boxes = self.run_boxes_order(text_regions_p,
num_col_classifier,
erosion_hurts,
regions_without_separators,
contours_h=textregions_h_cont)
order_text = self.do_order_of_regions(
textregions_cont,
textregions_h_cont,
drop_caps_cont,
boxes,
regions_without_separators) #textline_mask_tot_ea)
return order_text
def filter_small_regions(self, textregions: List[Region], textregions_d: List[Region], area_factor: float, marginals: List[Region]) -> Tuple[List[Region], List[Region]]: def filter_small_regions(self, textregions: List[Region], textregions_d: List[Region], area_factor: float, marginals: List[Region]) -> Tuple[List[Region], List[Region]]:
""" """
Split list of contours (and optionally deskewed contours) into Split list of contours (and optionally deskewed contours) into
@ -2342,31 +2365,28 @@ class Eynollah:
self.logger.info("Using machine-based detection") self.logger.info("Using machine-based detection")
order_text = self.do_order_of_regions_with_model( order_text = self.do_order_of_regions_with_model(
contours(textregions), contours(textregions),
contours(textregions_h), contours(textregions_h) if not self.headers_off else [],
contours(drop_caps), contours(drop_caps),
text_regions_p) text_regions_p)
else: else:
if np.abs(slope_deskew) < SLOPE_THRESHOLD: if np.abs(slope_deskew) < SLOPE_THRESHOLD:
boxes = self.run_boxes_order(text_regions_p, num_col_classifier, erosion_hurts, order_text = self.do_order_of_regions_heuristic(
regions_without_separators,
contours_h=(None if self.headers_off or not self.full_layout
else contours(textregions_h)))
order_text = self.do_order_of_regions(
contours(textregions), contours(textregions),
contours(textregions_h), contours(textregions_h) if not self.headers_off else [],
contours(drop_caps), contours(drop_caps),
boxes, regions_without_separators) #textline_mask_tot_ea) text_regions_p,
regions_without_separators,
num_col_classifier,
erosion_hurts)
else: else:
boxes_d = self.run_boxes_order(text_regions_p_d, num_col_classifier, erosion_hurts, order_text = self.do_order_of_regions_heuristic(
regions_without_separators_d,
contours_h=(None if self.headers_off or not self.full_layout
else contours(textregions_h_d)))
order_text = self.do_order_of_regions(
contours(textregions_d), contours(textregions_d),
contours(textregions_h_d), contours(textregions_h_d) if not self.headers_off else [],
contours(drop_caps), contours(drop_caps),
boxes_d, regions_without_separators_d) #textline_mask_tot_ea_d) text_regions_p_d,
regions_without_separators_d,
num_col_classifier,
erosion_hurts)
self.logger.info(f"Detection of reading order took {time.time() - t_order:.1f}s") self.logger.info(f"Detection of reading order took {time.time() - t_order:.1f}s")
self.logger.info("Step 5/5: Output Generation") self.logger.info("Step 5/5: Output Generation")

View file

@ -1219,7 +1219,7 @@ def find_number_of_columns_in_document(
separator_mask: np.ndarray, separator_mask: np.ndarray,
num_col_classifier: int, num_col_classifier: int,
tables: bool, tables: bool,
contours_h: List[np.ndarray] = None, contours_h: List[np.ndarray] = [],
logger=None logger=None
) -> Tuple[int, List[int], np.ndarray, List[int], np.ndarray]: ) -> Tuple[int, List[int], np.ndarray, List[int], np.ndarray]:
""" """
@ -1230,7 +1230,7 @@ def find_number_of_columns_in_document(
* separator_mask: mask of (separator-only) region labels * separator_mask: mask of (separator-only) region labels
* num_col_classifier: predicted (expected) number of columns of the page * num_col_classifier: predicted (expected) number of columns of the page
* tables: whether tables may be present * tables: whether tables may be present
* contours_h: polygons of potential headings (serving as additional horizontal separators) * contours_h: contours of potential headings (serving as additional horizontal separators)
* logger * logger
Returns: a tuple of Returns: a tuple of
@ -1353,7 +1353,7 @@ def find_number_of_columns_in_document(
matrix_of_seps_ch[len(cy_seps_hor):,8]=dist_y_ver matrix_of_seps_ch[len(cy_seps_hor):,8]=dist_y_ver
matrix_of_seps_ch[len(cy_seps_hor):,9]=1 matrix_of_seps_ch[len(cy_seps_hor):,9]=1
if contours_h is not None: if len(contours_h):
_, dist_x_head, x_min_head, x_max_head, cy_head, _, y_min_head, y_max_head, _ = \ _, dist_x_head, x_min_head, x_max_head, cy_head, _, y_min_head, y_max_head, _ = \
find_features_of_lines(contours_h) find_features_of_lines(contours_h)
matrix_l_n = np.zeros((len(cy_head), matrix_of_seps_ch.shape[1]), dtype=int) matrix_l_n = np.zeros((len(cy_head), matrix_of_seps_ch.shape[1]), dtype=int)
@ -1382,7 +1382,7 @@ def find_number_of_columns_in_document(
(x_max_seps_hor >= .84 * width)] (x_max_seps_hor >= .84 * width)]
cy_seps_splitters = np.append(cy_seps_splitters, special_separators) cy_seps_splitters = np.append(cy_seps_splitters, special_separators)
if contours_h is not None: if len(contours_h):
y_min_splitters_head = y_min_head[(x_min_head <= .16 * width) & y_min_splitters_head = y_min_head[(x_min_head <= .16 * width) &
(x_max_head >= .84 * width)] (x_max_head >= .84 * width)]
y_max_splitters_head = y_max_head[(x_min_head <= .16 * width) & y_max_splitters_head = y_max_head[(x_min_head <= .16 * width) &