mirror of
https://github.com/qurator-spk/eynollah.git
synced 2025-10-27 07:44:12 +01:00
Merge 19b2c3fa42 into 38c028c6b5
This commit is contained in:
commit
cf5a0bacd2
5 changed files with 1162 additions and 1117 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),
|
type=click.Path(file_okay=True, dir_okay=True),
|
||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"--overwrite",
|
||||||
|
"-O",
|
||||||
|
help="overwrite (instead of skipping) if output xml exists",
|
||||||
|
is_flag=True,
|
||||||
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"--log_level",
|
"--log_level",
|
||||||
"-l",
|
"-l",
|
||||||
type=click.Choice(['OFF', 'DEBUG', 'INFO', 'WARN', 'ERROR']),
|
type=click.Choice(['OFF', 'DEBUG', 'INFO', 'WARN', 'ERROR']),
|
||||||
help="Override log level globally to this",
|
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."
|
assert bool(input_image) != bool(dir_in), "Either -i (single input) or -di (directory) must be provided, but not both."
|
||||||
binarizer = SbbBinarizer(model_dir)
|
binarizer = SbbBinarizer(model_dir)
|
||||||
if log_level:
|
if log_level:
|
||||||
binarizer.log.setLevel(getLevelName(log_level))
|
binarizer.logger.setLevel(getLevelName(log_level))
|
||||||
binarizer.run(image_path=input_image, use_patches=patches, output=output, dir_in=dir_in)
|
binarizer.run(overwrite=overwrite,
|
||||||
|
use_patches=patches,
|
||||||
|
image_path=input_image,
|
||||||
|
output=output,
|
||||||
|
dir_in=dir_in)
|
||||||
|
|
||||||
|
|
||||||
@main.command()
|
@main.command()
|
||||||
|
|
|
||||||
|
|
@ -2507,6 +2507,7 @@ class Eynollah:
|
||||||
My_main[ii] < box[3])):
|
My_main[ii] < box[3])):
|
||||||
arg_text_con_main[ii] = jj
|
arg_text_con_main[ii] = jj
|
||||||
check_if_textregion_located_in_a_box = True
|
check_if_textregion_located_in_a_box = True
|
||||||
|
#print("main/matched", (mx_main[ii], Mx_main[ii], my_main[ii], My_main[ii]), "\tin", box, only_centers)
|
||||||
break
|
break
|
||||||
if not check_if_textregion_located_in_a_box:
|
if not check_if_textregion_located_in_a_box:
|
||||||
dists_tr_from_box = np.linalg.norm(c_boxes - np.array([[cy_main[ii]], [cx_main[ii]]]), axis=0)
|
dists_tr_from_box = np.linalg.norm(c_boxes - np.array([[cy_main[ii]], [cx_main[ii]]]), axis=0)
|
||||||
|
|
@ -2514,6 +2515,7 @@ class Eynollah:
|
||||||
(boxes[:, 0] <= cx_main[ii]) & (cx_main[ii] < boxes[:, 1]))
|
(boxes[:, 0] <= cx_main[ii]) & (cx_main[ii] < boxes[:, 1]))
|
||||||
ind_min = np.argmin(np.ma.masked_array(dists_tr_from_box, ~pcontained_in_box))
|
ind_min = np.argmin(np.ma.masked_array(dists_tr_from_box, ~pcontained_in_box))
|
||||||
arg_text_con_main[ii] = ind_min
|
arg_text_con_main[ii] = ind_min
|
||||||
|
#print("main/fallback", (mx_main[ii], Mx_main[ii], my_main[ii], My_main[ii]), "\tin", boxes[ind_min], only_centers)
|
||||||
args_contours_main = np.arange(len(contours_only_text_parent))
|
args_contours_main = np.arange(len(contours_only_text_parent))
|
||||||
order_by_con_main = np.zeros_like(arg_text_con_main)
|
order_by_con_main = np.zeros_like(arg_text_con_main)
|
||||||
|
|
||||||
|
|
@ -2531,6 +2533,7 @@ class Eynollah:
|
||||||
My_head[ii] < box[3])):
|
My_head[ii] < box[3])):
|
||||||
arg_text_con_head[ii] = jj
|
arg_text_con_head[ii] = jj
|
||||||
check_if_textregion_located_in_a_box = True
|
check_if_textregion_located_in_a_box = True
|
||||||
|
#print("head/matched", (mx_head[ii], Mx_head[ii], my_head[ii], My_head[ii]), "\tin", box, only_centers)
|
||||||
break
|
break
|
||||||
if not check_if_textregion_located_in_a_box:
|
if not check_if_textregion_located_in_a_box:
|
||||||
dists_tr_from_box = np.linalg.norm(c_boxes - np.array([[cy_head[ii]], [cx_head[ii]]]), axis=0)
|
dists_tr_from_box = np.linalg.norm(c_boxes - np.array([[cy_head[ii]], [cx_head[ii]]]), axis=0)
|
||||||
|
|
@ -2538,6 +2541,7 @@ class Eynollah:
|
||||||
(boxes[:, 0] <= cx_head[ii]) & (cx_head[ii] < boxes[:, 1]))
|
(boxes[:, 0] <= cx_head[ii]) & (cx_head[ii] < boxes[:, 1]))
|
||||||
ind_min = np.argmin(np.ma.masked_array(dists_tr_from_box, ~pcontained_in_box))
|
ind_min = np.argmin(np.ma.masked_array(dists_tr_from_box, ~pcontained_in_box))
|
||||||
arg_text_con_head[ii] = ind_min
|
arg_text_con_head[ii] = ind_min
|
||||||
|
#print("head/fallback", (mx_head[ii], Mx_head[ii], my_head[ii], My_head[ii]), "\tin", boxes[ind_min], only_centers)
|
||||||
args_contours_head = np.arange(len(contours_only_text_parent_h))
|
args_contours_head = np.arange(len(contours_only_text_parent_h))
|
||||||
order_by_con_head = np.zeros_like(arg_text_con_head)
|
order_by_con_head = np.zeros_like(arg_text_con_head)
|
||||||
|
|
||||||
|
|
@ -2553,7 +2557,7 @@ class Eynollah:
|
||||||
con_inter_box_h = contours_only_text_parent_h[args_contours_box_head]
|
con_inter_box_h = contours_only_text_parent_h[args_contours_box_head]
|
||||||
|
|
||||||
indexes_sorted, kind_of_texts_sorted, index_by_kind_sorted = order_of_regions(
|
indexes_sorted, kind_of_texts_sorted, index_by_kind_sorted = order_of_regions(
|
||||||
textline_mask_tot[ys, xs], con_inter_box, con_inter_box_h, box[2])
|
textline_mask_tot[ys, xs], con_inter_box, con_inter_box_h, box[2], box[0])
|
||||||
|
|
||||||
order_of_texts, id_of_texts = order_and_id_of_texts(
|
order_of_texts, id_of_texts = order_and_id_of_texts(
|
||||||
con_inter_box, con_inter_box_h,
|
con_inter_box, con_inter_box_h,
|
||||||
|
|
@ -2587,7 +2591,7 @@ class Eynollah:
|
||||||
try:
|
try:
|
||||||
results = match_boxes(False)
|
results = match_boxes(False)
|
||||||
except Exception as why:
|
except Exception as why:
|
||||||
self.logger.error(why)
|
self.logger.exception(why)
|
||||||
results = match_boxes(True)
|
results = match_boxes(True)
|
||||||
|
|
||||||
self.logger.debug("exit do_order_of_regions")
|
self.logger.debug("exit do_order_of_regions")
|
||||||
|
|
@ -2665,45 +2669,35 @@ class Eynollah:
|
||||||
|
|
||||||
return layout_org, contours_new
|
return layout_org, contours_new
|
||||||
|
|
||||||
def delete_separator_around(self, spliter_y,peaks_neg,image_by_region, pixel_line, pixel_table):
|
def delete_separator_around(self, splitter_y, peaks_neg, image_by_region, label_seps, label_table):
|
||||||
# format of subboxes: box=[x1, x2 , y1, y2]
|
# format of subboxes: box=[x1, x2 , y1, y2]
|
||||||
pix_del = 100
|
pix_del = 100
|
||||||
if len(image_by_region.shape)==3:
|
for i in range(len(splitter_y)-1):
|
||||||
for i in range(len(spliter_y)-1):
|
for j in range(1,len(peaks_neg[i])-1):
|
||||||
for j in range(1,len(peaks_neg[i])-1):
|
where = np.index_exp[splitter_y[i]:
|
||||||
ys = slice(int(spliter_y[i]),
|
splitter_y[i+1],
|
||||||
int(spliter_y[i+1]))
|
peaks_neg[i][j] - pix_del:
|
||||||
xs = slice(peaks_neg[i][j] - pix_del,
|
peaks_neg[i][j] + pix_del,
|
||||||
peaks_neg[i][j] + pix_del)
|
:]
|
||||||
image_by_region[ys,xs,0][image_by_region[ys,xs,0]==pixel_line] = 0
|
if image_by_region.ndim < 3:
|
||||||
image_by_region[ys,xs,0][image_by_region[ys,xs,1]==pixel_line] = 0
|
where = where[:2]
|
||||||
image_by_region[ys,xs,0][image_by_region[ys,xs,2]==pixel_line] = 0
|
else:
|
||||||
|
print("image_by_region ndim is 3!") # rs
|
||||||
image_by_region[ys,xs,0][image_by_region[ys,xs,0]==pixel_table] = 0
|
image_by_region[where][image_by_region[where] == label_seps] = 0
|
||||||
image_by_region[ys,xs,0][image_by_region[ys,xs,1]==pixel_table] = 0
|
image_by_region[where][image_by_region[where] == label_table] = 0
|
||||||
image_by_region[ys,xs,0][image_by_region[ys,xs,2]==pixel_table] = 0
|
|
||||||
else:
|
|
||||||
for i in range(len(spliter_y)-1):
|
|
||||||
for j in range(1,len(peaks_neg[i])-1):
|
|
||||||
ys = slice(int(spliter_y[i]),
|
|
||||||
int(spliter_y[i+1]))
|
|
||||||
xs = slice(peaks_neg[i][j] - pix_del,
|
|
||||||
peaks_neg[i][j] + pix_del)
|
|
||||||
image_by_region[ys,xs][image_by_region[ys,xs]==pixel_line] = 0
|
|
||||||
image_by_region[ys,xs][image_by_region[ys,xs]==pixel_table] = 0
|
|
||||||
return image_by_region
|
return image_by_region
|
||||||
|
|
||||||
def add_tables_heuristic_to_layout(
|
def add_tables_heuristic_to_layout(
|
||||||
self, image_regions_eraly_p, boxes,
|
self, image_regions_eraly_p, boxes,
|
||||||
slope_mean_hor, spliter_y, peaks_neg_tot, image_revised,
|
slope_mean_hor, splitter_y, peaks_neg_tot, image_revised,
|
||||||
num_col_classifier, min_area, pixel_line):
|
num_col_classifier, min_area, label_seps):
|
||||||
|
|
||||||
pixel_table =10
|
label_table =10
|
||||||
image_revised_1 = self.delete_separator_around(spliter_y, peaks_neg_tot, image_revised, pixel_line, pixel_table)
|
image_revised_1 = self.delete_separator_around(splitter_y, peaks_neg_tot, image_revised, label_seps, label_table)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
image_revised_1[:,:30][image_revised_1[:,:30]==pixel_line] = 0
|
image_revised_1[:,:30][image_revised_1[:,:30]==label_seps] = 0
|
||||||
image_revised_1[:,-30:][image_revised_1[:,-30:]==pixel_line] = 0
|
image_revised_1[:,-30:][image_revised_1[:,-30:]==label_seps] = 0
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
boxes = np.array(boxes, dtype=int) # to be on the safe side
|
boxes = np.array(boxes, dtype=int) # to be on the safe side
|
||||||
|
|
@ -2714,7 +2708,7 @@ class Eynollah:
|
||||||
_, thresh = cv2.threshold(image_col, 0, 255, 0)
|
_, thresh = cv2.threshold(image_col, 0, 255, 0)
|
||||||
contours,hirarchy=cv2.findContours(thresh.copy(), cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
|
contours,hirarchy=cv2.findContours(thresh.copy(), cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
|
||||||
|
|
||||||
if indiv==pixel_table:
|
if indiv==label_table:
|
||||||
main_contours = filter_contours_area_of_image_tables(thresh, contours, hirarchy,
|
main_contours = filter_contours_area_of_image_tables(thresh, contours, hirarchy,
|
||||||
max_area=1, min_area=0.001)
|
max_area=1, min_area=0.001)
|
||||||
else:
|
else:
|
||||||
|
|
@ -2730,11 +2724,11 @@ class Eynollah:
|
||||||
box_xs = slice(*boxes[i][0:2])
|
box_xs = slice(*boxes[i][0:2])
|
||||||
image_box = img_comm[box_ys, box_xs]
|
image_box = img_comm[box_ys, box_xs]
|
||||||
try:
|
try:
|
||||||
image_box_tabels_1 = (image_box == pixel_table) * 1
|
image_box_tabels_1 = (image_box == label_table) * 1
|
||||||
contours_tab,_=return_contours_of_image(image_box_tabels_1)
|
contours_tab,_=return_contours_of_image(image_box_tabels_1)
|
||||||
contours_tab=filter_contours_area_of_image_tables(image_box_tabels_1,contours_tab,_,1,0.003)
|
contours_tab=filter_contours_area_of_image_tables(image_box_tabels_1,contours_tab,_,1,0.003)
|
||||||
image_box_tabels_1 = (image_box == pixel_line).astype(np.uint8) * 1
|
image_box_tabels_1 = (image_box == label_seps).astype(np.uint8) * 1
|
||||||
image_box_tabels_and_m_text = ( (image_box == pixel_table) |
|
image_box_tabels_and_m_text = ( (image_box == label_table) |
|
||||||
(image_box == 1) ).astype(np.uint8) * 1
|
(image_box == 1) ).astype(np.uint8) * 1
|
||||||
|
|
||||||
image_box_tabels_1 = cv2.dilate(image_box_tabels_1, KERNEL, iterations=5)
|
image_box_tabels_1 = cv2.dilate(image_box_tabels_1, KERNEL, iterations=5)
|
||||||
|
|
@ -2796,7 +2790,7 @@ class Eynollah:
|
||||||
y_up_tabs=[]
|
y_up_tabs=[]
|
||||||
|
|
||||||
for ii in range(len(y_up_tabs)):
|
for ii in range(len(y_up_tabs)):
|
||||||
image_box[y_up_tabs[ii]:y_down_tabs[ii]] = pixel_table
|
image_box[y_up_tabs[ii]:y_down_tabs[ii]] = label_table
|
||||||
|
|
||||||
image_revised_last[box_ys, box_xs] = image_box
|
image_revised_last[box_ys, box_xs] = image_box
|
||||||
else:
|
else:
|
||||||
|
|
@ -2807,14 +2801,14 @@ class Eynollah:
|
||||||
image_revised_last[box_ys, box_xs] = image_box
|
image_revised_last[box_ys, box_xs] = image_box
|
||||||
|
|
||||||
if num_col_classifier==1:
|
if num_col_classifier==1:
|
||||||
img_tables_col_1 = (image_revised_last == pixel_table).astype(np.uint8)
|
img_tables_col_1 = (image_revised_last == label_table).astype(np.uint8)
|
||||||
contours_table_col1, _ = return_contours_of_image(img_tables_col_1)
|
contours_table_col1, _ = return_contours_of_image(img_tables_col_1)
|
||||||
|
|
||||||
_,_ ,_ , _, y_min_tab_col1 ,y_max_tab_col1, _= find_new_features_of_contours(contours_table_col1)
|
_,_ ,_ , _, y_min_tab_col1 ,y_max_tab_col1, _= find_new_features_of_contours(contours_table_col1)
|
||||||
|
|
||||||
if len(y_min_tab_col1)>0:
|
if len(y_min_tab_col1)>0:
|
||||||
for ijv in range(len(y_min_tab_col1)):
|
for ijv in range(len(y_min_tab_col1)):
|
||||||
image_revised_last[int(y_min_tab_col1[ijv]):int(y_max_tab_col1[ijv])] = pixel_table
|
image_revised_last[int(y_min_tab_col1[ijv]):int(y_max_tab_col1[ijv])] = label_table
|
||||||
return image_revised_last
|
return image_revised_last
|
||||||
|
|
||||||
def get_tables_from_model(self, img, num_col_classifier):
|
def get_tables_from_model(self, img, num_col_classifier):
|
||||||
|
|
@ -2976,7 +2970,7 @@ class Eynollah:
|
||||||
max(self.num_col_lower or num_col_classifier,
|
max(self.num_col_lower or num_col_classifier,
|
||||||
num_col_classifier))
|
num_col_classifier))
|
||||||
except Exception as why:
|
except Exception as why:
|
||||||
self.logger.error(why)
|
self.logger.exception(why)
|
||||||
num_col = None
|
num_col = None
|
||||||
#print("inside graphics 3 ", time.time() - t_in_gr)
|
#print("inside graphics 3 ", time.time() - t_in_gr)
|
||||||
return (num_col, num_col_classifier, img_only_regions, page_coord, image_page, mask_images, mask_lines,
|
return (num_col, num_col_classifier, img_only_regions, page_coord, image_page, mask_images, mask_lines,
|
||||||
|
|
@ -3044,7 +3038,7 @@ class Eynollah:
|
||||||
if not num_column_is_classified:
|
if not num_column_is_classified:
|
||||||
num_col_classifier = num_col + 1
|
num_col_classifier = num_col + 1
|
||||||
except Exception as why:
|
except Exception as why:
|
||||||
self.logger.error(why)
|
self.logger.exception(why)
|
||||||
num_col = None
|
num_col = None
|
||||||
return (num_col, num_col_classifier, img_only_regions, page_coord, image_page, mask_images, mask_lines,
|
return (num_col, num_col_classifier, img_only_regions, page_coord, image_page, mask_images, mask_lines,
|
||||||
text_regions_p_1, cont_page, table_prediction)
|
text_regions_p_1, cont_page, table_prediction)
|
||||||
|
|
@ -3149,14 +3143,14 @@ class Eynollah:
|
||||||
text_regions_p_1_n = None
|
text_regions_p_1_n = None
|
||||||
textline_mask_tot_d = None
|
textline_mask_tot_d = None
|
||||||
regions_without_separators_d = None
|
regions_without_separators_d = None
|
||||||
pixel_lines = 3
|
label_seps = 3
|
||||||
if np.abs(slope_deskew) < SLOPE_THRESHOLD:
|
if np.abs(slope_deskew) < SLOPE_THRESHOLD:
|
||||||
_, _, matrix_of_lines_ch, splitter_y_new, _ = find_number_of_columns_in_document(
|
_, _, matrix_of_seps_ch, splitter_y_new, _ = find_number_of_columns_in_document(
|
||||||
text_regions_p, num_col_classifier, self.tables, pixel_lines)
|
text_regions_p, num_col_classifier, self.tables, label_seps)
|
||||||
|
|
||||||
if np.abs(slope_deskew) >= SLOPE_THRESHOLD:
|
if np.abs(slope_deskew) >= SLOPE_THRESHOLD:
|
||||||
_, _, matrix_of_lines_ch_d, splitter_y_new_d, _ = find_number_of_columns_in_document(
|
_, _, matrix_of_seps_ch_d, splitter_y_new_d, _ = find_number_of_columns_in_document(
|
||||||
text_regions_p_1_n, num_col_classifier, self.tables, pixel_lines)
|
text_regions_p_1_n, num_col_classifier, self.tables, label_seps)
|
||||||
#print(time.time()-t_0_box,'time box in 2')
|
#print(time.time()-t_0_box,'time box in 2')
|
||||||
self.logger.info("num_col_classifier: %s", num_col_classifier)
|
self.logger.info("num_col_classifier: %s", num_col_classifier)
|
||||||
|
|
||||||
|
|
@ -3171,7 +3165,7 @@ class Eynollah:
|
||||||
t1 = time.time()
|
t1 = time.time()
|
||||||
if np.abs(slope_deskew) < SLOPE_THRESHOLD:
|
if np.abs(slope_deskew) < SLOPE_THRESHOLD:
|
||||||
boxes, peaks_neg_tot_tables = return_boxes_of_images_by_order_of_reading_new(
|
boxes, peaks_neg_tot_tables = return_boxes_of_images_by_order_of_reading_new(
|
||||||
splitter_y_new, regions_without_separators, matrix_of_lines_ch,
|
splitter_y_new, regions_without_separators, matrix_of_seps_ch,
|
||||||
num_col_classifier, erosion_hurts, self.tables, self.right2left)
|
num_col_classifier, erosion_hurts, self.tables, self.right2left)
|
||||||
boxes_d = None
|
boxes_d = None
|
||||||
self.logger.debug("len(boxes): %s", len(boxes))
|
self.logger.debug("len(boxes): %s", len(boxes))
|
||||||
|
|
@ -3183,17 +3177,17 @@ class Eynollah:
|
||||||
else:
|
else:
|
||||||
text_regions_p_tables = np.copy(text_regions_p)
|
text_regions_p_tables = np.copy(text_regions_p)
|
||||||
text_regions_p_tables[(table_prediction == 1)] = 10
|
text_regions_p_tables[(table_prediction == 1)] = 10
|
||||||
pixel_line = 3
|
label_seps = 3
|
||||||
img_revised_tab2 = self.add_tables_heuristic_to_layout(
|
img_revised_tab2 = self.add_tables_heuristic_to_layout(
|
||||||
text_regions_p_tables, boxes, 0, splitter_y_new, peaks_neg_tot_tables, text_regions_p_tables,
|
text_regions_p_tables, boxes, 0, splitter_y_new, peaks_neg_tot_tables, text_regions_p_tables,
|
||||||
num_col_classifier , 0.000005, pixel_line)
|
num_col_classifier , 0.000005, label_seps)
|
||||||
#print(time.time()-t_0_box,'time box in 3.2')
|
#print(time.time()-t_0_box,'time box in 3.2')
|
||||||
img_revised_tab2, contoures_tables = self.check_iou_of_bounding_box_and_contour_for_tables(
|
img_revised_tab2, contoures_tables = self.check_iou_of_bounding_box_and_contour_for_tables(
|
||||||
img_revised_tab2, table_prediction, 10, num_col_classifier)
|
img_revised_tab2, table_prediction, 10, num_col_classifier)
|
||||||
#print(time.time()-t_0_box,'time box in 3.3')
|
#print(time.time()-t_0_box,'time box in 3.3')
|
||||||
else:
|
else:
|
||||||
boxes_d, peaks_neg_tot_tables_d = return_boxes_of_images_by_order_of_reading_new(
|
boxes_d, peaks_neg_tot_tables_d = return_boxes_of_images_by_order_of_reading_new(
|
||||||
splitter_y_new_d, regions_without_separators_d, matrix_of_lines_ch_d,
|
splitter_y_new_d, regions_without_separators_d, matrix_of_seps_ch_d,
|
||||||
num_col_classifier, erosion_hurts, self.tables, self.right2left)
|
num_col_classifier, erosion_hurts, self.tables, self.right2left)
|
||||||
boxes = None
|
boxes = None
|
||||||
self.logger.debug("len(boxes): %s", len(boxes_d))
|
self.logger.debug("len(boxes): %s", len(boxes_d))
|
||||||
|
|
@ -3206,11 +3200,11 @@ class Eynollah:
|
||||||
text_regions_p_tables = np.round(text_regions_p_tables)
|
text_regions_p_tables = np.round(text_regions_p_tables)
|
||||||
text_regions_p_tables[(text_regions_p_tables != 3) & (table_prediction_n == 1)] = 10
|
text_regions_p_tables[(text_regions_p_tables != 3) & (table_prediction_n == 1)] = 10
|
||||||
|
|
||||||
pixel_line = 3
|
label_seps = 3
|
||||||
img_revised_tab2 = self.add_tables_heuristic_to_layout(
|
img_revised_tab2 = self.add_tables_heuristic_to_layout(
|
||||||
text_regions_p_tables, boxes_d, 0, splitter_y_new_d,
|
text_regions_p_tables, boxes_d, 0, splitter_y_new_d,
|
||||||
peaks_neg_tot_tables_d, text_regions_p_tables,
|
peaks_neg_tot_tables_d, text_regions_p_tables,
|
||||||
num_col_classifier, 0.000005, pixel_line)
|
num_col_classifier, 0.000005, label_seps)
|
||||||
img_revised_tab2_d,_ = self.check_iou_of_bounding_box_and_contour_for_tables(
|
img_revised_tab2_d,_ = self.check_iou_of_bounding_box_and_contour_for_tables(
|
||||||
img_revised_tab2, table_prediction_n, 10, num_col_classifier)
|
img_revised_tab2, table_prediction_n, 10, num_col_classifier)
|
||||||
|
|
||||||
|
|
@ -3329,14 +3323,14 @@ class Eynollah:
|
||||||
regions_without_separators = (text_regions_p[:,:] == 1)*1
|
regions_without_separators = (text_regions_p[:,:] == 1)*1
|
||||||
regions_without_separators[table_prediction == 1] = 1
|
regions_without_separators[table_prediction == 1] = 1
|
||||||
|
|
||||||
pixel_lines=3
|
label_seps=3
|
||||||
if np.abs(slope_deskew) < SLOPE_THRESHOLD:
|
if np.abs(slope_deskew) < SLOPE_THRESHOLD:
|
||||||
num_col, _, matrix_of_lines_ch, splitter_y_new, _ = find_number_of_columns_in_document(
|
num_col, _, matrix_of_lines_ch, splitter_y_new, _ = find_number_of_columns_in_document(
|
||||||
text_regions_p, num_col_classifier, self.tables, pixel_lines)
|
text_regions_p, num_col_classifier, self.tables, label_seps)
|
||||||
|
|
||||||
if np.abs(slope_deskew) >= SLOPE_THRESHOLD:
|
if np.abs(slope_deskew) >= SLOPE_THRESHOLD:
|
||||||
num_col_d, _, matrix_of_lines_ch_d, splitter_y_new_d, _ = find_number_of_columns_in_document(
|
num_col_d, _, matrix_of_lines_ch_d, splitter_y_new_d, _ = find_number_of_columns_in_document(
|
||||||
text_regions_p_1_n, num_col_classifier, self.tables, pixel_lines)
|
text_regions_p_1_n, num_col_classifier, self.tables, label_seps)
|
||||||
|
|
||||||
if num_col_classifier>=3:
|
if num_col_classifier>=3:
|
||||||
if np.abs(slope_deskew) < SLOPE_THRESHOLD:
|
if np.abs(slope_deskew) < SLOPE_THRESHOLD:
|
||||||
|
|
@ -3355,10 +3349,10 @@ class Eynollah:
|
||||||
num_col_classifier, erosion_hurts, self.tables, self.right2left)
|
num_col_classifier, erosion_hurts, self.tables, self.right2left)
|
||||||
text_regions_p_tables = np.copy(text_regions_p)
|
text_regions_p_tables = np.copy(text_regions_p)
|
||||||
text_regions_p_tables[:,:][(table_prediction[:,:]==1)] = 10
|
text_regions_p_tables[:,:][(table_prediction[:,:]==1)] = 10
|
||||||
pixel_line = 3
|
label_seps = 3
|
||||||
img_revised_tab2 = self.add_tables_heuristic_to_layout(
|
img_revised_tab2 = self.add_tables_heuristic_to_layout(
|
||||||
text_regions_p_tables, boxes, 0, splitter_y_new, peaks_neg_tot_tables, text_regions_p_tables,
|
text_regions_p_tables, boxes, 0, splitter_y_new, peaks_neg_tot_tables, text_regions_p_tables,
|
||||||
num_col_classifier , 0.000005, pixel_line)
|
num_col_classifier , 0.000005, label_seps)
|
||||||
|
|
||||||
img_revised_tab2,contoures_tables = self.check_iou_of_bounding_box_and_contour_for_tables(
|
img_revised_tab2,contoures_tables = self.check_iou_of_bounding_box_and_contour_for_tables(
|
||||||
img_revised_tab2, table_prediction, 10, num_col_classifier)
|
img_revised_tab2, table_prediction, 10, num_col_classifier)
|
||||||
|
|
@ -3370,11 +3364,11 @@ class Eynollah:
|
||||||
text_regions_p_tables = np.round(text_regions_p_tables)
|
text_regions_p_tables = np.round(text_regions_p_tables)
|
||||||
text_regions_p_tables[(text_regions_p_tables != 3) & (table_prediction_n == 1)] = 10
|
text_regions_p_tables[(text_regions_p_tables != 3) & (table_prediction_n == 1)] = 10
|
||||||
|
|
||||||
pixel_line = 3
|
label_seps = 3
|
||||||
img_revised_tab2 = self.add_tables_heuristic_to_layout(
|
img_revised_tab2 = self.add_tables_heuristic_to_layout(
|
||||||
text_regions_p_tables, boxes_d, 0, splitter_y_new_d,
|
text_regions_p_tables, boxes_d, 0, splitter_y_new_d,
|
||||||
peaks_neg_tot_tables_d, text_regions_p_tables,
|
peaks_neg_tot_tables_d, text_regions_p_tables,
|
||||||
num_col_classifier, 0.000005, pixel_line)
|
num_col_classifier, 0.000005, label_seps)
|
||||||
|
|
||||||
img_revised_tab2_d,_ = self.check_iou_of_bounding_box_and_contour_for_tables(
|
img_revised_tab2_d,_ = self.check_iou_of_bounding_box_and_contour_for_tables(
|
||||||
img_revised_tab2, table_prediction_n, 10, num_col_classifier)
|
img_revised_tab2, table_prediction_n, 10, num_col_classifier)
|
||||||
|
|
@ -4717,12 +4711,12 @@ class Eynollah:
|
||||||
regions_without_separators_d = cv2.erode(regions_without_separators_d[:, :], KERNEL, iterations=6)
|
regions_without_separators_d = cv2.erode(regions_without_separators_d[:, :], KERNEL, iterations=6)
|
||||||
|
|
||||||
if np.abs(slope_deskew) < SLOPE_THRESHOLD:
|
if np.abs(slope_deskew) < SLOPE_THRESHOLD:
|
||||||
boxes, peaks_neg_tot_tables = return_boxes_of_images_by_order_of_reading_new(
|
boxes, _ = return_boxes_of_images_by_order_of_reading_new(
|
||||||
splitter_y_new, regions_without_separators, matrix_of_lines_ch,
|
splitter_y_new, regions_without_separators, matrix_of_lines_ch,
|
||||||
num_col_classifier, erosion_hurts, self.tables, self.right2left,
|
num_col_classifier, erosion_hurts, self.tables, self.right2left,
|
||||||
logger=self.logger)
|
logger=self.logger)
|
||||||
else:
|
else:
|
||||||
boxes_d, peaks_neg_tot_tables_d = return_boxes_of_images_by_order_of_reading_new(
|
boxes_d, _ = return_boxes_of_images_by_order_of_reading_new(
|
||||||
splitter_y_new_d, regions_without_separators_d, matrix_of_lines_ch_d,
|
splitter_y_new_d, regions_without_separators_d, matrix_of_lines_ch_d,
|
||||||
num_col_classifier, erosion_hurts, self.tables, self.right2left,
|
num_col_classifier, erosion_hurts, self.tables, self.right2left,
|
||||||
logger=self.logger)
|
logger=self.logger)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class SbbBinarizer:
|
||||||
|
|
||||||
def __init__(self, model_dir, logger=None):
|
def __init__(self, model_dir, logger=None):
|
||||||
self.model_dir = model_dir
|
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()
|
self.start_new_session()
|
||||||
|
|
||||||
|
|
@ -315,64 +315,46 @@ class SbbBinarizer:
|
||||||
prediction_true = prediction_true.astype(np.uint8)
|
prediction_true = prediction_true.astype(np.uint8)
|
||||||
return prediction_true[:,:,0]
|
return prediction_true[:,:,0]
|
||||||
|
|
||||||
def run(self, image=None, image_path=None, output=None, use_patches=False, dir_in=None):
|
def run(self, image_path=None, output=None, dir_in=None, use_patches=False, overwrite=False):
|
||||||
# print(dir_in,'dir_in')
|
if dir_in:
|
||||||
if not dir_in:
|
ls_imgs = [(os.path.join(dir_in, image_filename),
|
||||||
if (image is not None and image_path is not None) or \
|
os.path.join(output, os.path.splitext(image_filename)[0] + '.png'))
|
||||||
(image is None and image_path is None):
|
for image_filename in filter(is_image_filename,
|
||||||
raise ValueError("Must pass either a opencv2 image or an image_path")
|
os.listdir(dir_in))]
|
||||||
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
|
|
||||||
else:
|
else:
|
||||||
ls_imgs = list(filter(is_image_filename, os.listdir(dir_in)))
|
ls_imgs = [(image_path, output)]
|
||||||
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) )
|
|
||||||
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)
|
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_ptah)
|
||||||
|
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)
|
||||||
|
|
||||||
img_fin = np.zeros((res.shape[0], res.shape[1], 3))
|
def run_single(self, image: np.ndarray, use_patches=False):
|
||||||
res[:, :][res[:, :] == 0] = 2
|
img_last = 0
|
||||||
res = res - 1
|
for n, (model, model_file) in enumerate(zip(self.models, self.model_files)):
|
||||||
res = res * 255
|
self.logger.info('Predicting with model %s [%s/%s]' % (model_file, n + 1, len(self.model_files)))
|
||||||
img_fin[:, :, 0] = res
|
|
||||||
img_fin[:, :, 1] = res
|
|
||||||
img_fin[:, :, 2] = res
|
|
||||||
|
|
||||||
img_fin = img_fin.astype(np.uint8)
|
res = self.predict(model, image, use_patches)
|
||||||
img_fin = (res[:, :] == 0) * 255
|
|
||||||
img_last = img_last + img_fin
|
|
||||||
|
|
||||||
kernel = np.ones((5, 5), np.uint8)
|
img_fin = np.zeros((res.shape[0], res.shape[1], 3))
|
||||||
img_last[:, :][img_last[:, :] > 0] = 255
|
res[:, :][res[:, :] == 0] = 2
|
||||||
img_last = (img_last[:, :] == 0) * 255
|
res = res - 1
|
||||||
|
res = res * 255
|
||||||
|
img_fin[:, :, 0] = res
|
||||||
|
img_fin[:, :, 1] = res
|
||||||
|
img_fin[:, :, 2] = res
|
||||||
|
|
||||||
cv2.imwrite(os.path.join(output, image_stem + '.png'), img_last)
|
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
|
||||||
|
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
|
from .rotate import rotate_image, rotation_image_new
|
||||||
|
|
||||||
def contours_in_same_horizon(cy_main_hor):
|
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)))
|
Takes an array of y coords, identifies all pairs among them
|
||||||
|
which are close to each other, and returns all such pairs
|
||||||
X1[0::1, :] = cy_main_hor[:]
|
by index into the array.
|
||||||
X2 = X1.T
|
"""
|
||||||
|
sort = np.argsort(cy_main_hor)
|
||||||
X_dif = np.abs(X2 - X1)
|
same = np.diff(cy_main_hor[sort] <= 20)
|
||||||
args_help = np.array(range(len(cy_main_hor)))
|
# groups = np.split(sort, np.arange(len(cy_main_hor) - 1)[~same] + 1)
|
||||||
all_args = []
|
same = np.flatnonzero(same)
|
||||||
for i in range(len(cy_main_hor)):
|
return np.stack((sort[:-1][same], sort[1:][same])).T
|
||||||
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))
|
|
||||||
|
|
||||||
def find_contours_mean_y_diff(contours_main):
|
def find_contours_mean_y_diff(contours_main):
|
||||||
M_main = [cv2.moments(contours_main[j]) for j in range(len(contours_main))]
|
M_main = [cv2.moments(contours_main[j]) for j in range(len(contours_main))]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue