mirror of
https://github.com/qurator-spk/eynollah.git
synced 2026-04-30 19:22:03 +02:00
do_work_of_slopes_new_curved: improve deskewing…
- return early if textline mask is empty
- intersect textline mask with parent mask
(so neighbouring, truncated textlines
will not interfere)
- fix bug when resulting angle is small:
rather, compare with page angle
- if there is more than 1 line in the region,
* use median instead of mean to estimate y_diff
* if height dominates over width and x_diff
over y_diff, then assume 90°: transpose image,
deskew on that, then add 90° to result
- otherwise instead of just using page angle,
try to estimate single-line angle by approximating
slope of linear x-y regression on mask image;
again, if height dominates over width, then
assume +90° and use transposed image
- drop unused `scale` param
This commit is contained in:
parent
97d9b0ea50
commit
0dce1f24d2
2 changed files with 54 additions and 23 deletions
|
|
@ -1034,14 +1034,13 @@ class Eynollah:
|
||||||
slopes)
|
slopes)
|
||||||
|
|
||||||
def get_slopes_and_deskew_new_curved(self, contours_par, textline_mask_tot, boxes,
|
def get_slopes_and_deskew_new_curved(self, contours_par, textline_mask_tot, boxes,
|
||||||
num_col, scale_par, slope_deskew, name):
|
num_col, slope_deskew, name):
|
||||||
if not len(contours_par):
|
if not len(contours_par):
|
||||||
return [], [], []
|
return [], [], []
|
||||||
self.logger.debug("enter get_slopes_and_deskew_new_curved")
|
self.logger.debug("enter get_slopes_and_deskew_new_curved")
|
||||||
results = map(partial(do_work_of_slopes_new_curved,
|
results = map(partial(do_work_of_slopes_new_curved,
|
||||||
textline_mask_tot_ea=textline_mask_tot,
|
textline_mask_tot_ea=textline_mask_tot,
|
||||||
num_col=num_col,
|
num_col=num_col,
|
||||||
scale_par=scale_par,
|
|
||||||
slope_deskew=slope_deskew,
|
slope_deskew=slope_deskew,
|
||||||
MAX_SLOPE=MAX_SLOPE,
|
MAX_SLOPE=MAX_SLOPE,
|
||||||
KERNEL=KERNEL,
|
KERNEL=KERNEL,
|
||||||
|
|
@ -2503,20 +2502,19 @@ class Eynollah:
|
||||||
all_found_textline_polygons_marginals = dilate_textline_contours(
|
all_found_textline_polygons_marginals = dilate_textline_contours(
|
||||||
all_found_textline_polygons_marginals)
|
all_found_textline_polygons_marginals)
|
||||||
else:
|
else:
|
||||||
scale_param = 1
|
|
||||||
textline_mask_tot_ea_erode = cv2.erode(textline_mask_tot_ea, kernel=KERNEL, iterations=2)
|
textline_mask_tot_ea_erode = cv2.erode(textline_mask_tot_ea, kernel=KERNEL, iterations=2)
|
||||||
all_found_textline_polygons, \
|
all_found_textline_polygons, \
|
||||||
all_box_coord, slopes = self.get_slopes_and_deskew_new_curved(
|
all_box_coord, slopes = self.get_slopes_and_deskew_new_curved(
|
||||||
polygons_of_textregions, textline_mask_tot_ea_erode,
|
polygons_of_textregions, textline_mask_tot_ea_erode,
|
||||||
boxes_text,
|
boxes_text,
|
||||||
num_col_classifier, scale_param, slope_deskew, image['name'])
|
num_col_classifier, slope_deskew, image['name'])
|
||||||
all_found_textline_polygons = small_textlines_to_parent_adherence2(
|
all_found_textline_polygons = small_textlines_to_parent_adherence2(
|
||||||
all_found_textline_polygons, textline_mask_tot_ea, num_col_classifier)
|
all_found_textline_polygons, textline_mask_tot_ea, num_col_classifier)
|
||||||
all_found_textline_polygons_marginals, \
|
all_found_textline_polygons_marginals, \
|
||||||
all_box_coord_marginals, slopes_marginals = self.get_slopes_and_deskew_new_curved(
|
all_box_coord_marginals, slopes_marginals = self.get_slopes_and_deskew_new_curved(
|
||||||
polygons_of_marginals, textline_mask_tot_ea_erode,
|
polygons_of_marginals, textline_mask_tot_ea_erode,
|
||||||
boxes_marginals,
|
boxes_marginals,
|
||||||
num_col_classifier, scale_param, slope_deskew, image['name'])
|
num_col_classifier, slope_deskew, image['name'])
|
||||||
all_found_textline_polygons_marginals = small_textlines_to_parent_adherence2(
|
all_found_textline_polygons_marginals = small_textlines_to_parent_adherence2(
|
||||||
all_found_textline_polygons_marginals, textline_mask_tot_ea, num_col_classifier)
|
all_found_textline_polygons_marginals, textline_mask_tot_ea, num_col_classifier)
|
||||||
(polygons_of_textregions,
|
(polygons_of_textregions,
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import cv2
|
||||||
from scipy.signal import find_peaks
|
from scipy.signal import find_peaks
|
||||||
from scipy.ndimage import gaussian_filter1d
|
from scipy.ndimage import gaussian_filter1d
|
||||||
from .rotate import rotate_image
|
from .rotate import rotate_image
|
||||||
|
from scipy.stats import linregress
|
||||||
from .resize import resize_image
|
from .resize import resize_image
|
||||||
from .contour import (
|
from .contour import (
|
||||||
return_parent_contours,
|
return_parent_contours,
|
||||||
|
|
@ -13,6 +14,7 @@ from .contour import (
|
||||||
return_contours_of_image,
|
return_contours_of_image,
|
||||||
filter_contours_area_of_image,
|
filter_contours_area_of_image,
|
||||||
return_contours_of_interested_textline,
|
return_contours_of_interested_textline,
|
||||||
|
find_center_of_contours,
|
||||||
find_contours_mean_y_diff,
|
find_contours_mean_y_diff,
|
||||||
)
|
)
|
||||||
from . import (
|
from . import (
|
||||||
|
|
@ -1585,8 +1587,10 @@ def get_smallest_skew(img, sigma_des, angles, logger=None, plotter=None, name=No
|
||||||
def do_work_of_slopes_new_curved(
|
def do_work_of_slopes_new_curved(
|
||||||
box_text, contour_par,
|
box_text, contour_par,
|
||||||
textline_mask_tot_ea=None,
|
textline_mask_tot_ea=None,
|
||||||
num_col=1, scale_par=1.0, slope_deskew=0.0,
|
num_col=1, slope_deskew=0.0,
|
||||||
logger=None, MAX_SLOPE=999, KERNEL=None, plotter=None, name=None
|
logger=None, MAX_SLOPE=999,
|
||||||
|
KERNEL=None, plotter=None,
|
||||||
|
name=None,
|
||||||
):
|
):
|
||||||
if KERNEL is None:
|
if KERNEL is None:
|
||||||
KERNEL = np.ones((5, 5), np.uint8)
|
KERNEL = np.ones((5, 5), np.uint8)
|
||||||
|
|
@ -1595,38 +1599,67 @@ def do_work_of_slopes_new_curved(
|
||||||
logger.debug("enter do_work_of_slopes_new_curved")
|
logger.debug("enter do_work_of_slopes_new_curved")
|
||||||
|
|
||||||
x, y, w, h = box_text
|
x, y, w, h = box_text
|
||||||
all_text_region_raw = textline_mask_tot_ea[y: y + h, x: x + w].astype(np.uint8)
|
|
||||||
img_int_p = all_text_region_raw[:, :]
|
mask_parent = np.zeros((h, w), dtype=np.uint8)
|
||||||
|
mask_parent = cv2.fillPoly(mask_parent, pts=[contour_par - [x, y]], color=1)
|
||||||
|
all_text_region_raw = textline_mask_tot_ea[y: y + h, x: x + w] * mask_parent
|
||||||
|
if not np.any(all_text_region_raw):
|
||||||
|
return [], slope_deskew
|
||||||
|
img_int_p = np.copy(all_text_region_raw)
|
||||||
|
|
||||||
# img_int_p=cv2.erode(img_int_p,KERNEL,iterations = 2)
|
# img_int_p=cv2.erode(img_int_p,KERNEL,iterations = 2)
|
||||||
# plt.imshow(img_int_p)
|
# plt.imshow(img_int_p)
|
||||||
# plt.show()
|
# plt.show()
|
||||||
|
|
||||||
if not np.prod(img_int_p.shape) or img_int_p.shape[0] / img_int_p.shape[1] < 0.1:
|
if not np.prod(img_int_p.shape) or img_int_p.shape[0] / img_int_p.shape[1] < 0.1:
|
||||||
slope = 0
|
slope = slope_deskew
|
||||||
slope_for_all = slope_deskew
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
textline_con, hierarchy = return_contours_of_image(img_int_p)
|
textline_con, hierarchy = return_contours_of_image(img_int_p)
|
||||||
textline_con_fil = filter_contours_area_of_image(img_int_p, textline_con,
|
textline_con_fil = filter_contours_area_of_image(img_int_p, textline_con,
|
||||||
hierarchy,
|
hierarchy,
|
||||||
max_area=1, min_area=0.0008)
|
max_area=1, min_area=0.0008)
|
||||||
y_diff_mean = find_contours_mean_y_diff(textline_con_fil) if len(textline_con_fil) > 1 else np.NaN
|
if len(textline_con_fil) > 1:
|
||||||
if np.isnan(y_diff_mean):
|
cx, cy = find_center_of_contours(textline_con_fil)
|
||||||
slope_for_all = MAX_SLOPE
|
y_diff_mean = np.median(np.diff(np.sort(np.array(cy))))
|
||||||
|
x_diff_mean = np.median(np.diff(np.sort(np.array(cx))))
|
||||||
|
if h > w and x_diff_mean / w > 2 * y_diff_mean / h:
|
||||||
|
# print(len(textline_con_fil), "transposed", x_diff_mean, y_diff_mean)
|
||||||
|
transposed = True
|
||||||
|
img_int_p = img_int_p.T
|
||||||
|
sigma = x_diff_mean
|
||||||
|
else:
|
||||||
|
transposed = False
|
||||||
|
sigma = y_diff_mean
|
||||||
|
slope = return_deskew_slop(img_int_p, max(1.0, 0.1 * sigma),
|
||||||
|
logger=logger,
|
||||||
|
name=name,
|
||||||
|
plotter=plotter)
|
||||||
|
if transposed:
|
||||||
|
slope = -90 - slope if slope < 0 else 90 - slope
|
||||||
|
if abs(slope - slope_deskew) < 0.5:
|
||||||
|
slope = slope_deskew
|
||||||
else:
|
else:
|
||||||
sigma_des = max(1, int(y_diff_mean * (4.0 / 40.0)))
|
if h > 3 * w:
|
||||||
img_int_p[img_int_p > 0] = 1
|
# print(1, "transposed", h, w)
|
||||||
slope_for_all = return_deskew_slop(img_int_p, sigma_des, logger=logger, name=name, plotter=plotter)
|
transposed = True
|
||||||
if abs(slope_for_all) < 0.5:
|
img_int_p = img_int_p.T
|
||||||
slope_for_all = slope_deskew
|
else:
|
||||||
|
transposed = False
|
||||||
|
# do linear regression on mask to get slope
|
||||||
|
img_ys, img_xs = img_int_p.nonzero()
|
||||||
|
regression = linregress(x=img_xs, y=img_ys)
|
||||||
|
slope = 180 / np.pi * np.arctan(regression.slope)
|
||||||
|
# print(regression, regression.stderr)
|
||||||
|
if transposed:
|
||||||
|
slope = 90 - slope
|
||||||
|
if regression.stderr > 0.005:
|
||||||
|
slope = slope_deskew
|
||||||
except:
|
except:
|
||||||
logger.exception("cannot determine angle of contours")
|
logger.exception("cannot determine angle of contours")
|
||||||
slope_for_all = MAX_SLOPE
|
slope = slope_deskew
|
||||||
|
|
||||||
if slope_for_all == MAX_SLOPE:
|
# print(slope, slope_deskew)
|
||||||
slope_for_all = slope_deskew
|
|
||||||
slope = slope_for_all
|
|
||||||
|
|
||||||
crop_coor = box2rect(box_text)
|
crop_coor = box2rect(box_text)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue