This commit is contained in:
Robert Sachunsky 2025-08-21 13:01:31 +02:00 committed by GitHub
commit 03e2a7dfc1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 235 additions and 587 deletions

View file

@ -73,6 +73,8 @@ from .utils.contour import (
return_contours_of_interested_region_by_min_size, return_contours_of_interested_region_by_min_size,
return_contours_of_interested_textline, return_contours_of_interested_textline,
return_parent_contours, return_parent_contours,
dilate_textregion_contours,
dilate_textline_contours,
) )
from .utils.rotate import ( from .utils.rotate import (
rotate_image, rotate_image,
@ -1711,9 +1713,9 @@ class Eynollah:
mask_texts_only = (prediction_regions_org[:,:] ==1)*1 mask_texts_only = (prediction_regions_org[:,:] ==1)*1
mask_images_only=(prediction_regions_org[:,:] ==2)*1 mask_images_only=(prediction_regions_org[:,:] ==2)*1
polygons_lines_xml, hir_lines_xml = return_contours_of_image(mask_lines_only) polygons_seplines, hir_seplines = return_contours_of_image(mask_lines_only)
polygons_lines_xml = textline_con_fil = filter_contours_area_of_image( polygons_seplines = filter_contours_area_of_image(
mask_lines_only, polygons_lines_xml, hir_lines_xml, max_area=1, min_area=0.00001) mask_lines_only, polygons_seplines, hir_seplines, max_area=1, min_area=0.00001, dilate=1)
polygons_of_only_texts = return_contours_of_interested_region(mask_texts_only,1,0.00001) polygons_of_only_texts = return_contours_of_interested_region(mask_texts_only,1,0.00001)
polygons_of_only_lines = return_contours_of_interested_region(mask_lines_only,1,0.00001) polygons_of_only_lines = return_contours_of_interested_region(mask_lines_only,1,0.00001)
@ -1777,7 +1779,7 @@ class Eynollah:
[page_coord_img[2], page_coord_img[1]]])) [page_coord_img[2], page_coord_img[1]]]))
self.logger.debug("exit get_regions_extract_images_only") self.logger.debug("exit get_regions_extract_images_only")
return text_regions_p_true, erosion_hurts, polygons_lines_xml, polygons_of_images_fin, image_page, page_coord, cont_page return text_regions_p_true, erosion_hurts, polygons_seplines, polygons_of_images_fin, image_page, page_coord, cont_page
def get_regions_light_v(self,img,is_image_enhanced, num_col_classifier, skip_layout_and_reading_order=False): def get_regions_light_v(self,img,is_image_enhanced, num_col_classifier, skip_layout_and_reading_order=False):
self.logger.debug("enter get_regions_light_v") self.logger.debug("enter get_regions_light_v")
@ -1893,31 +1895,31 @@ class Eynollah:
mask_texts_only = cv2.dilate(mask_texts_only, kernel=np.ones((2,2), np.uint8), iterations=1) mask_texts_only = cv2.dilate(mask_texts_only, kernel=np.ones((2,2), np.uint8), iterations=1)
mask_images_only=(prediction_regions_org[:,:] ==2)*1 mask_images_only=(prediction_regions_org[:,:] ==2)*1
polygons_lines_xml, hir_lines_xml = return_contours_of_image(mask_lines_only) polygons_seplines, hir_seplines = return_contours_of_image(mask_lines_only)
test_khat = np.zeros(prediction_regions_org.shape) test_khat = np.zeros(prediction_regions_org.shape)
test_khat = cv2.fillPoly(test_khat, pts=polygons_lines_xml, color=(1,1,1)) test_khat = cv2.fillPoly(test_khat, pts=polygons_seplines, color=(1,1,1))
#plt.imshow(test_khat[:,:]) #plt.imshow(test_khat[:,:])
#plt.show() #plt.show()
#for jv in range(1): #for jv in range(1):
#print(jv, hir_lines_xml[0][232][3]) #print(jv, hir_seplines[0][232][3])
#test_khat = np.zeros(prediction_regions_org.shape) #test_khat = np.zeros(prediction_regions_org.shape)
#test_khat = cv2.fillPoly(test_khat, pts = [polygons_lines_xml[232]], color=(1,1,1)) #test_khat = cv2.fillPoly(test_khat, pts = [polygons_seplines[232]], color=(1,1,1))
#plt.imshow(test_khat[:,:]) #plt.imshow(test_khat[:,:])
#plt.show() #plt.show()
polygons_lines_xml = filter_contours_area_of_image( polygons_seplines = filter_contours_area_of_image(
mask_lines_only, polygons_lines_xml, hir_lines_xml, max_area=1, min_area=0.00001) mask_lines_only, polygons_seplines, hir_seplines, max_area=1, min_area=0.00001, dilate=1)
test_khat = np.zeros(prediction_regions_org.shape) test_khat = np.zeros(prediction_regions_org.shape)
test_khat = cv2.fillPoly(test_khat, pts = polygons_lines_xml, color=(1,1,1)) test_khat = cv2.fillPoly(test_khat, pts = polygons_seplines, color=(1,1,1))
#plt.imshow(test_khat[:,:]) #plt.imshow(test_khat[:,:])
#plt.show() #plt.show()
#sys.exit() #sys.exit()
polygons_of_only_texts = return_contours_of_interested_region(mask_texts_only,1,0.00001) polygons_of_only_texts = return_contours_of_interested_region(mask_texts_only,1,0.00001)
##polygons_of_only_texts = self.dilate_textregions_contours(polygons_of_only_texts) ##polygons_of_only_texts = dilate_textregion_contours(polygons_of_only_texts)
polygons_of_only_lines = return_contours_of_interested_region(mask_lines_only,1,0.00001) polygons_of_only_lines = return_contours_of_interested_region(mask_lines_only,1,0.00001)
text_regions_p_true = np.zeros(prediction_regions_org.shape) text_regions_p_true = np.zeros(prediction_regions_org.shape)
@ -1935,7 +1937,7 @@ class Eynollah:
#plt.show() #plt.show()
#print("inside 4 ", time.time()-t_in) #print("inside 4 ", time.time()-t_in)
self.logger.debug("exit get_regions_light_v") self.logger.debug("exit get_regions_light_v")
return text_regions_p_true, erosion_hurts, polygons_lines_xml, textline_mask_tot_ea, img_bin, confidence_matrix return text_regions_p_true, erosion_hurts, polygons_seplines, textline_mask_tot_ea, img_bin, confidence_matrix
else: else:
img_bin = resize_image(img_bin,img_height_h, img_width_h ) img_bin = resize_image(img_bin,img_height_h, img_width_h )
self.logger.debug("exit get_regions_light_v") self.logger.debug("exit get_regions_light_v")
@ -2018,9 +2020,9 @@ class Eynollah:
mask_texts_only=(prediction_regions_org[:,:]==1)*1 mask_texts_only=(prediction_regions_org[:,:]==1)*1
mask_images_only=(prediction_regions_org[:,:]==2)*1 mask_images_only=(prediction_regions_org[:,:]==2)*1
polygons_lines_xml, hir_lines_xml = return_contours_of_image(mask_lines_only) polygons_seplines, hir_seplines = return_contours_of_image(mask_lines_only)
polygons_lines_xml = filter_contours_area_of_image( polygons_seplines = filter_contours_area_of_image(
mask_lines_only, polygons_lines_xml, hir_lines_xml, max_area=1, min_area=0.00001) mask_lines_only, polygons_seplines, hir_seplines, max_area=1, min_area=0.00001, dilate=1)
polygons_of_only_texts = return_contours_of_interested_region(mask_texts_only, 1, 0.00001) polygons_of_only_texts = return_contours_of_interested_region(mask_texts_only, 1, 0.00001)
polygons_of_only_lines = return_contours_of_interested_region(mask_lines_only, 1, 0.00001) polygons_of_only_lines = return_contours_of_interested_region(mask_lines_only, 1, 0.00001)
@ -2032,7 +2034,7 @@ class Eynollah:
text_regions_p_true=cv2.fillPoly(text_regions_p_true,pts=polygons_of_only_texts, color=(1,1,1)) text_regions_p_true=cv2.fillPoly(text_regions_p_true,pts=polygons_of_only_texts, color=(1,1,1))
self.logger.debug("exit get_regions_from_xy_2models") self.logger.debug("exit get_regions_from_xy_2models")
return text_regions_p_true, erosion_hurts, polygons_lines_xml return text_regions_p_true, erosion_hurts, polygons_seplines
except: except:
if self.input_binary: if self.input_binary:
prediction_bin = np.copy(img_org) prediction_bin = np.copy(img_org)
@ -2067,9 +2069,9 @@ class Eynollah:
mask_texts_only = (prediction_regions_org == 1)*1 mask_texts_only = (prediction_regions_org == 1)*1
mask_images_only= (prediction_regions_org == 2)*1 mask_images_only= (prediction_regions_org == 2)*1
polygons_lines_xml, hir_lines_xml = return_contours_of_image(mask_lines_only) polygons_seplines, hir_seplines = return_contours_of_image(mask_lines_only)
polygons_lines_xml = filter_contours_area_of_image( polygons_seplines = filter_contours_area_of_image(
mask_lines_only, polygons_lines_xml, hir_lines_xml, max_area=1, min_area=0.00001) mask_lines_only, polygons_seplines, hir_seplines, max_area=1, min_area=0.00001, dilate=1)
polygons_of_only_texts = return_contours_of_interested_region(mask_texts_only,1,0.00001) polygons_of_only_texts = return_contours_of_interested_region(mask_texts_only,1,0.00001)
polygons_of_only_lines = return_contours_of_interested_region(mask_lines_only,1,0.00001) polygons_of_only_lines = return_contours_of_interested_region(mask_lines_only,1,0.00001)
@ -2082,7 +2084,7 @@ class Eynollah:
erosion_hurts = True erosion_hurts = True
self.logger.debug("exit get_regions_from_xy_2models") self.logger.debug("exit get_regions_from_xy_2models")
return text_regions_p_true, erosion_hurts, polygons_lines_xml return text_regions_p_true, erosion_hurts, polygons_seplines
def do_order_of_regions_full_layout( def do_order_of_regions_full_layout(
self, contours_only_text_parent, contours_only_text_parent_h, boxes, textline_mask_tot): self, contours_only_text_parent, contours_only_text_parent_h, boxes, textline_mask_tot):
@ -2925,12 +2927,10 @@ class Eynollah:
#print(textline_mask_tot_ea.shape, 'textline_mask_tot_ea deskew') #print(textline_mask_tot_ea.shape, 'textline_mask_tot_ea deskew')
slope_deskew = return_deskew_slop(cv2.erode(textline_mask_tot_ea, KERNEL, iterations=2), 2, 30, True, slope_deskew = return_deskew_slop(cv2.erode(textline_mask_tot_ea, KERNEL, iterations=2), 2, 30, True,
map=self.executor.map, logger=self.logger, plotter=self.plotter) map=self.executor.map, logger=self.logger, plotter=self.plotter)
slope_first = 0
if self.plotter: if self.plotter:
self.plotter.save_deskewed_image(slope_deskew) self.plotter.save_deskewed_image(slope_deskew)
self.logger.info("slope_deskew: %.2f°", slope_deskew) self.logger.info("slope_deskew: %.2f°", slope_deskew)
return slope_deskew, slope_first return slope_deskew
def run_marginals( def run_marginals(
self, image_page, textline_mask_tot_ea, mask_images, mask_lines, self, image_page, textline_mask_tot_ea, mask_images, mask_lines,
@ -3669,312 +3669,6 @@ class Eynollah:
return x_differential_new return x_differential_new
def dilate_textregions_contours_textline_version(self, all_found_textline_polygons):
#print(all_found_textline_polygons)
for j in range(len(all_found_textline_polygons)):
for ij in range(len(all_found_textline_polygons[j])):
con_ind = all_found_textline_polygons[j][ij]
area = cv2.contourArea(con_ind)
con_ind = con_ind.astype(float)
x_differential = np.diff( con_ind[:,0,0])
y_differential = np.diff( con_ind[:,0,1])
x_differential = gaussian_filter1d(x_differential, 0.1)
y_differential = gaussian_filter1d(y_differential, 0.1)
x_min = float(np.min( con_ind[:,0,0] ))
y_min = float(np.min( con_ind[:,0,1] ))
x_max = float(np.max( con_ind[:,0,0] ))
y_max = float(np.max( con_ind[:,0,1] ))
x_differential_mask_nonzeros = [ ind/abs(ind) if ind!=0 else ind for ind in x_differential]
y_differential_mask_nonzeros = [ ind/abs(ind) if ind!=0 else ind for ind in y_differential]
abs_diff=abs(abs(x_differential)- abs(y_differential) )
inc_x = np.zeros(len(x_differential)+1)
inc_y = np.zeros(len(x_differential)+1)
if (y_max-y_min) <= (x_max-x_min):
dilation_m1 = round(area / (x_max-x_min) * 0.12)
else:
dilation_m1 = round(area / (y_max-y_min) * 0.12)
if dilation_m1>8:
dilation_m1 = 8
if dilation_m1<6:
dilation_m1 = 6
#print(dilation_m1, 'dilation_m1')
dilation_m1 = 6
dilation_m2 = int(dilation_m1/2.) +1
for i in range(len(x_differential)):
if abs_diff[i]==0:
inc_x[i+1] = dilation_m2*(-1*y_differential_mask_nonzeros[i])
inc_y[i+1] = dilation_m2*(x_differential_mask_nonzeros[i])
elif abs_diff[i]!=0 and x_differential_mask_nonzeros[i]==0 and y_differential_mask_nonzeros[i]!=0:
inc_x[i+1]= dilation_m1*(-1*y_differential_mask_nonzeros[i])
elif abs_diff[i]!=0 and x_differential_mask_nonzeros[i]!=0 and y_differential_mask_nonzeros[i]==0:
inc_y[i+1] = dilation_m1*(x_differential_mask_nonzeros[i])
elif abs_diff[i]!=0 and abs_diff[i]>=3:
if abs(x_differential[i])>abs(y_differential[i]):
inc_y[i+1] = dilation_m1*(x_differential_mask_nonzeros[i])
else:
inc_x[i+1]= dilation_m1*(-1*y_differential_mask_nonzeros[i])
else:
inc_x[i+1] = dilation_m2*(-1*y_differential_mask_nonzeros[i])
inc_y[i+1] = dilation_m2*(x_differential_mask_nonzeros[i])
inc_x[0] = inc_x[-1]
inc_y[0] = inc_y[-1]
con_scaled = con_ind*1
con_scaled[:,0, 0] = con_ind[:,0,0] + np.array(inc_x)[:]
con_scaled[:,0, 1] = con_ind[:,0,1] + np.array(inc_y)[:]
con_scaled[:,0, 1][con_scaled[:,0, 1]<0] = 0
con_scaled[:,0, 0][con_scaled[:,0, 0]<0] = 0
area_scaled = cv2.contourArea(con_scaled.astype(np.int32))
con_ind = con_ind.astype(np.int32)
results = [cv2.pointPolygonTest(con_ind, (con_scaled[ind,0, 0], con_scaled[ind,0, 1]), False)
for ind in range(len(con_scaled[:,0, 1])) ]
results = np.array(results)
#print(results,'results')
results[results==0] = 1
diff_result = np.diff(results)
indices_2 = [ind for ind in range(len(diff_result)) if diff_result[ind]==2]
indices_m2 = [ind for ind in range(len(diff_result)) if diff_result[ind]==-2]
if results[0]==1:
con_scaled[:indices_m2[0]+1,0, 1] = con_ind[:indices_m2[0]+1,0,1]
con_scaled[:indices_m2[0]+1,0, 0] = con_ind[:indices_m2[0]+1,0,0]
#indices_2 = indices_2[1:]
indices_m2 = indices_m2[1:]
if len(indices_2)>len(indices_m2):
con_scaled[indices_2[-1]+1:,0, 1] = con_ind[indices_2[-1]+1:,0,1]
con_scaled[indices_2[-1]+1:,0, 0] = con_ind[indices_2[-1]+1:,0,0]
indices_2 = indices_2[:-1]
for ii in range(len(indices_2)):
con_scaled[indices_2[ii]+1:indices_m2[ii]+1,0, 1] = con_scaled[indices_2[ii],0, 1]
con_scaled[indices_2[ii]+1:indices_m2[ii]+1,0, 0] = con_scaled[indices_2[ii],0, 0]
all_found_textline_polygons[j][ij][:,0,1] = con_scaled[:,0, 1]
all_found_textline_polygons[j][ij][:,0,0] = con_scaled[:,0, 0]
return all_found_textline_polygons
def dilate_textregions_contours(self, all_found_textline_polygons):
#print(all_found_textline_polygons)
for j in range(len(all_found_textline_polygons)):
con_ind = all_found_textline_polygons[j]
#print(len(con_ind[:,0,0]),'con_ind[:,0,0]')
area = cv2.contourArea(con_ind)
con_ind = con_ind.astype(float)
x_differential = np.diff( con_ind[:,0,0])
y_differential = np.diff( con_ind[:,0,1])
x_differential = gaussian_filter1d(x_differential, 0.1)
y_differential = gaussian_filter1d(y_differential, 0.1)
x_min = float(np.min( con_ind[:,0,0] ))
y_min = float(np.min( con_ind[:,0,1] ))
x_max = float(np.max( con_ind[:,0,0] ))
y_max = float(np.max( con_ind[:,0,1] ))
x_differential_mask_nonzeros = [ ind/abs(ind) if ind!=0 else ind for ind in x_differential]
y_differential_mask_nonzeros = [ ind/abs(ind) if ind!=0 else ind for ind in y_differential]
abs_diff=abs(abs(x_differential)- abs(y_differential) )
inc_x = np.zeros(len(x_differential)+1)
inc_y = np.zeros(len(x_differential)+1)
if (y_max-y_min) <= (x_max-x_min):
dilation_m1 = round(area / (x_max-x_min) * 0.12)
else:
dilation_m1 = round(area / (y_max-y_min) * 0.12)
if dilation_m1>8:
dilation_m1 = 8
if dilation_m1<6:
dilation_m1 = 6
#print(dilation_m1, 'dilation_m1')
dilation_m1 = 6
dilation_m2 = int(dilation_m1/2.) +1
for i in range(len(x_differential)):
if abs_diff[i]==0:
inc_x[i+1] = dilation_m2*(-1*y_differential_mask_nonzeros[i])
inc_y[i+1] = dilation_m2*(x_differential_mask_nonzeros[i])
elif abs_diff[i]!=0 and x_differential_mask_nonzeros[i]==0 and y_differential_mask_nonzeros[i]!=0:
inc_x[i+1]= dilation_m1*(-1*y_differential_mask_nonzeros[i])
elif abs_diff[i]!=0 and x_differential_mask_nonzeros[i]!=0 and y_differential_mask_nonzeros[i]==0:
inc_y[i+1] = dilation_m1*(x_differential_mask_nonzeros[i])
elif abs_diff[i]!=0 and abs_diff[i]>=3:
if abs(x_differential[i])>abs(y_differential[i]):
inc_y[i+1] = dilation_m1*(x_differential_mask_nonzeros[i])
else:
inc_x[i+1]= dilation_m1*(-1*y_differential_mask_nonzeros[i])
else:
inc_x[i+1] = dilation_m2*(-1*y_differential_mask_nonzeros[i])
inc_y[i+1] = dilation_m2*(x_differential_mask_nonzeros[i])
inc_x[0] = inc_x[-1]
inc_y[0] = inc_y[-1]
con_scaled = con_ind*1
con_scaled[:,0, 0] = con_ind[:,0,0] + np.array(inc_x)[:]
con_scaled[:,0, 1] = con_ind[:,0,1] + np.array(inc_y)[:]
con_scaled[:,0, 1][con_scaled[:,0, 1]<0] = 0
con_scaled[:,0, 0][con_scaled[:,0, 0]<0] = 0
area_scaled = cv2.contourArea(con_scaled.astype(np.int32))
con_ind = con_ind.astype(np.int32)
results = [cv2.pointPolygonTest(con_ind, (con_scaled[ind,0, 0], con_scaled[ind,0, 1]), False)
for ind in range(len(con_scaled[:,0, 1])) ]
results = np.array(results)
#print(results,'results')
results[results==0] = 1
diff_result = np.diff(results)
indices_2 = [ind for ind in range(len(diff_result)) if diff_result[ind]==2]
indices_m2 = [ind for ind in range(len(diff_result)) if diff_result[ind]==-2]
if results[0]==1:
con_scaled[:indices_m2[0]+1,0, 1] = con_ind[:indices_m2[0]+1,0,1]
con_scaled[:indices_m2[0]+1,0, 0] = con_ind[:indices_m2[0]+1,0,0]
#indices_2 = indices_2[1:]
indices_m2 = indices_m2[1:]
if len(indices_2)>len(indices_m2):
con_scaled[indices_2[-1]+1:,0, 1] = con_ind[indices_2[-1]+1:,0,1]
con_scaled[indices_2[-1]+1:,0, 0] = con_ind[indices_2[-1]+1:,0,0]
indices_2 = indices_2[:-1]
for ii in range(len(indices_2)):
con_scaled[indices_2[ii]+1:indices_m2[ii]+1,0, 1] = con_scaled[indices_2[ii],0, 1]
con_scaled[indices_2[ii]+1:indices_m2[ii]+1,0, 0] = con_scaled[indices_2[ii],0, 0]
all_found_textline_polygons[j][:,0,1] = con_scaled[:,0, 1]
all_found_textline_polygons[j][:,0,0] = con_scaled[:,0, 0]
return all_found_textline_polygons
def dilate_textline_contours(self, all_found_textline_polygons):
for j in range(len(all_found_textline_polygons)):
for ij in range(len(all_found_textline_polygons[j])):
con_ind = all_found_textline_polygons[j][ij]
area = cv2.contourArea(con_ind)
con_ind = con_ind.astype(float)
x_differential = np.diff( con_ind[:,0,0])
y_differential = np.diff( con_ind[:,0,1])
x_differential = gaussian_filter1d(x_differential, 3)
y_differential = gaussian_filter1d(y_differential, 3)
x_min = float(np.min( con_ind[:,0,0] ))
y_min = float(np.min( con_ind[:,0,1] ))
x_max = float(np.max( con_ind[:,0,0] ))
y_max = float(np.max( con_ind[:,0,1] ))
x_differential_mask_nonzeros = [ ind/abs(ind) if ind!=0 else ind for ind in x_differential]
y_differential_mask_nonzeros = [ ind/abs(ind) if ind!=0 else ind for ind in y_differential]
abs_diff=abs(abs(x_differential)- abs(y_differential) )
inc_x = np.zeros(len(x_differential)+1)
inc_y = np.zeros(len(x_differential)+1)
if (y_max-y_min) <= (x_max-x_min):
dilation_m1 = round(area / (x_max-x_min) * 0.35)
else:
dilation_m1 = round(area / (y_max-y_min) * 0.35)
if dilation_m1>12:
dilation_m1 = 12
if dilation_m1<4:
dilation_m1 = 4
#print(dilation_m1, 'dilation_m1')
dilation_m2 = int(dilation_m1/2.) +1
for i in range(len(x_differential)):
if abs_diff[i]==0:
inc_x[i+1] = dilation_m2*(-1*y_differential_mask_nonzeros[i])
inc_y[i+1] = dilation_m2*(x_differential_mask_nonzeros[i])
elif abs_diff[i]!=0 and x_differential_mask_nonzeros[i]==0 and y_differential_mask_nonzeros[i]!=0:
inc_x[i+1]= dilation_m1*(-1*y_differential_mask_nonzeros[i])
elif abs_diff[i]!=0 and x_differential_mask_nonzeros[i]!=0 and y_differential_mask_nonzeros[i]==0:
inc_y[i+1] = dilation_m1*(x_differential_mask_nonzeros[i])
elif abs_diff[i]!=0 and abs_diff[i]>=3:
if abs(x_differential[i])>abs(y_differential[i]):
inc_y[i+1] = dilation_m1*(x_differential_mask_nonzeros[i])
else:
inc_x[i+1]= dilation_m1*(-1*y_differential_mask_nonzeros[i])
else:
inc_x[i+1] = dilation_m2*(-1*y_differential_mask_nonzeros[i])
inc_y[i+1] = dilation_m2*(x_differential_mask_nonzeros[i])
inc_x[0] = inc_x[-1]
inc_y[0] = inc_y[-1]
con_scaled = con_ind*1
con_scaled[:,0, 0] = con_ind[:,0,0] + np.array(inc_x)[:]
con_scaled[:,0, 1] = con_ind[:,0,1] + np.array(inc_y)[:]
con_scaled[:,0, 1][con_scaled[:,0, 1]<0] = 0
con_scaled[:,0, 0][con_scaled[:,0, 0]<0] = 0
con_ind = con_ind.astype(np.int32)
results = [cv2.pointPolygonTest(con_ind, (con_scaled[ind,0, 0], con_scaled[ind,0, 1]), False)
for ind in range(len(con_scaled[:,0, 1])) ]
results = np.array(results)
results[results==0] = 1
diff_result = np.diff(results)
indices_2 = [ind for ind in range(len(diff_result)) if diff_result[ind]==2]
indices_m2 = [ind for ind in range(len(diff_result)) if diff_result[ind]==-2]
if results[0]==1:
con_scaled[:indices_m2[0]+1,0, 1] = con_ind[:indices_m2[0]+1,0,1]
con_scaled[:indices_m2[0]+1,0, 0] = con_ind[:indices_m2[0]+1,0,0]
indices_m2 = indices_m2[1:]
if len(indices_2)>len(indices_m2):
con_scaled[indices_2[-1]+1:,0, 1] = con_ind[indices_2[-1]+1:,0,1]
con_scaled[indices_2[-1]+1:,0, 0] = con_ind[indices_2[-1]+1:,0,0]
indices_2 = indices_2[:-1]
for ii in range(len(indices_2)):
con_scaled[indices_2[ii]+1:indices_m2[ii]+1,0, 1] = con_scaled[indices_2[ii],0, 1]
con_scaled[indices_2[ii]+1:indices_m2[ii]+1,0, 0] = con_scaled[indices_2[ii],0, 0]
all_found_textline_polygons[j][ij][:,0,1] = con_scaled[:,0, 1]
all_found_textline_polygons[j][ij][:,0,0] = con_scaled[:,0, 0]
return all_found_textline_polygons
def filter_contours_inside_a_bigger_one(self,contours, contours_d_ordered, image, marginal_cnts=None, type_contour="textregion"): def filter_contours_inside_a_bigger_one(self,contours, contours_d_ordered, image, marginal_cnts=None, type_contour="textregion"):
if type_contour=="textregion": if type_contour=="textregion":
areas = [cv2.contourArea(contours[j]) for j in range(len(contours))] areas = [cv2.contourArea(contours[j]) for j in range(len(contours))]
@ -4112,121 +3806,6 @@ class Eynollah:
return contours, text_con_org, conf_contours_textregions, contours_textline, contours_only_text_parent_d_ordered, np.array(range(len(contours))) return contours, text_con_org, conf_contours_textregions, contours_textline, contours_only_text_parent_d_ordered, np.array(range(len(contours)))
def dilate_textlines(self, all_found_textline_polygons):
for j in range(len(all_found_textline_polygons)):
for i in range(len(all_found_textline_polygons[j])):
con_ind = all_found_textline_polygons[j][i]
con_ind = con_ind.astype(float)
x_differential = np.diff( con_ind[:,0,0])
y_differential = np.diff( con_ind[:,0,1])
x_min = float(np.min( con_ind[:,0,0] ))
y_min = float(np.min( con_ind[:,0,1] ))
x_max = float(np.max( con_ind[:,0,0] ))
y_max = float(np.max( con_ind[:,0,1] ))
if (y_max - y_min) > (x_max - x_min) and (x_max - x_min)<70:
x_biger_than_x = np.abs(x_differential) > np.abs(y_differential)
mult = x_biger_than_x*x_differential
arg_min_mult = np.argmin(mult)
arg_max_mult = np.argmax(mult)
if y_differential[0]==0:
y_differential[0] = 0.1
if y_differential[-1]==0:
y_differential[-1]= 0.1
y_differential = [y_differential[ind] if y_differential[ind] != 0
else 0.5 * (y_differential[ind-1] + y_differential[ind+1])
for ind in range(len(y_differential))]
if y_differential[0]==0.1:
y_differential[0] = y_differential[1]
if y_differential[-1]==0.1:
y_differential[-1] = y_differential[-2]
y_differential.append(y_differential[0])
y_differential = [-1 if y_differential[ind] < 0 else 1
for ind in range(len(y_differential))]
y_differential = self.return_it_in_two_groups(y_differential)
y_differential = np.array(y_differential)
con_scaled = con_ind*1
con_scaled[:,0, 0] = con_ind[:,0,0] - 8*y_differential
con_scaled[arg_min_mult,0, 1] = con_ind[arg_min_mult,0,1] + 8
con_scaled[arg_min_mult+1,0, 1] = con_ind[arg_min_mult+1,0,1] + 8
try:
con_scaled[arg_min_mult-1,0, 1] = con_ind[arg_min_mult-1,0,1] + 5
con_scaled[arg_min_mult+2,0, 1] = con_ind[arg_min_mult+2,0,1] + 5
except:
pass
con_scaled[arg_max_mult,0, 1] = con_ind[arg_max_mult,0,1] - 8
con_scaled[arg_max_mult+1,0, 1] = con_ind[arg_max_mult+1,0,1] - 8
try:
con_scaled[arg_max_mult-1,0, 1] = con_ind[arg_max_mult-1,0,1] - 5
con_scaled[arg_max_mult+2,0, 1] = con_ind[arg_max_mult+2,0,1] - 5
except:
pass
else:
y_biger_than_x = np.abs(y_differential) > np.abs(x_differential)
mult = y_biger_than_x*y_differential
arg_min_mult = np.argmin(mult)
arg_max_mult = np.argmax(mult)
if x_differential[0]==0:
x_differential[0] = 0.1
if x_differential[-1]==0:
x_differential[-1]= 0.1
x_differential = [x_differential[ind] if x_differential[ind] != 0
else 0.5 * (x_differential[ind-1] + x_differential[ind+1])
for ind in range(len(x_differential))]
if x_differential[0]==0.1:
x_differential[0] = x_differential[1]
if x_differential[-1]==0.1:
x_differential[-1] = x_differential[-2]
x_differential.append(x_differential[0])
x_differential = [-1 if x_differential[ind] < 0 else 1
for ind in range(len(x_differential))]
x_differential = self.return_it_in_two_groups(x_differential)
x_differential = np.array(x_differential)
con_scaled = con_ind*1
con_scaled[:,0, 1] = con_ind[:,0,1] + 8*x_differential
con_scaled[arg_min_mult,0, 0] = con_ind[arg_min_mult,0,0] + 8
con_scaled[arg_min_mult+1,0, 0] = con_ind[arg_min_mult+1,0,0] + 8
try:
con_scaled[arg_min_mult-1,0, 0] = con_ind[arg_min_mult-1,0,0] + 5
con_scaled[arg_min_mult+2,0, 0] = con_ind[arg_min_mult+2,0,0] + 5
except:
pass
con_scaled[arg_max_mult,0, 0] = con_ind[arg_max_mult,0,0] - 8
con_scaled[arg_max_mult+1,0, 0] = con_ind[arg_max_mult+1,0,0] - 8
try:
con_scaled[arg_max_mult-1,0, 0] = con_ind[arg_max_mult-1,0,0] - 5
con_scaled[arg_max_mult+2,0, 0] = con_ind[arg_max_mult+2,0,0] - 5
except:
pass
con_scaled[:,0, 1][con_scaled[:,0, 1]<0] = 0
con_scaled[:,0, 0][con_scaled[:,0, 0]<0] = 0
all_found_textline_polygons[j][i][:,0,1] = con_scaled[:,0, 1]
all_found_textline_polygons[j][i][:,0,0] = con_scaled[:,0, 0]
return all_found_textline_polygons
def delete_regions_without_textlines( def delete_regions_without_textlines(
self, slopes, all_found_textline_polygons, boxes_text, txt_con_org, self, slopes, all_found_textline_polygons, boxes_text, txt_con_org,
contours_only_text_parent, index_by_text_par_con): contours_only_text_parent, index_by_text_par_con):
@ -4297,7 +3876,7 @@ class Eynollah:
img_res, is_image_enhanced, num_col_classifier, num_column_is_classified = self.run_enhancement(self.light_version) img_res, is_image_enhanced, num_col_classifier, num_column_is_classified = self.run_enhancement(self.light_version)
self.logger.info("Enhancing took %.1fs ", time.time() - t0) self.logger.info("Enhancing took %.1fs ", time.time() - t0)
if self.extract_only_images: if self.extract_only_images:
text_regions_p_1, erosion_hurts, polygons_lines_xml, polygons_of_images, image_page, page_coord, cont_page = \ text_regions_p_1, erosion_hurts, polygons_seplines, polygons_of_images, image_page, page_coord, cont_page = \
self.get_regions_light_v_extract_only_images(img_res, is_image_enhanced, num_col_classifier) self.get_regions_light_v_extract_only_images(img_res, is_image_enhanced, num_col_classifier)
ocr_all_textlines = None ocr_all_textlines = None
pcgts = self.writer.build_pagexml_no_full_layout( pcgts = self.writer.build_pagexml_no_full_layout(
@ -4325,8 +3904,7 @@ class Eynollah:
all_found_textline_polygons=[ all_found_textline_polygons ] all_found_textline_polygons=[ all_found_textline_polygons ]
all_found_textline_polygons = self.dilate_textregions_contours_textline_version( all_found_textline_polygons = dilate_textline_contours(all_found_textline_polygons)
all_found_textline_polygons)
all_found_textline_polygons = self.filter_contours_inside_a_bigger_one( all_found_textline_polygons = self.filter_contours_inside_a_bigger_one(
all_found_textline_polygons, None, textline_mask_tot_ea, type_contour="textline") all_found_textline_polygons, None, textline_mask_tot_ea, type_contour="textline")
@ -4340,7 +3918,7 @@ class Eynollah:
polygons_of_marginals = [] polygons_of_marginals = []
all_found_textline_polygons_marginals = [] all_found_textline_polygons_marginals = []
all_box_coord_marginals = [] all_box_coord_marginals = []
polygons_lines_xml = [] polygons_seplines = []
contours_tables = [] contours_tables = []
ocr_all_textlines = None ocr_all_textlines = None
conf_contours_textregions =None conf_contours_textregions =None
@ -4348,13 +3926,13 @@ class Eynollah:
cont_page, page_coord, order_text_new, id_of_texts_tot, cont_page, page_coord, order_text_new, id_of_texts_tot,
all_found_textline_polygons, page_coord, polygons_of_images, polygons_of_marginals, all_found_textline_polygons, page_coord, polygons_of_images, polygons_of_marginals,
all_found_textline_polygons_marginals, all_box_coord_marginals, slopes, slopes_marginals, all_found_textline_polygons_marginals, all_box_coord_marginals, slopes, slopes_marginals,
cont_page, polygons_lines_xml, contours_tables, ocr_all_textlines, conf_contours_textregions) cont_page, polygons_seplines, contours_tables, ocr_all_textlines, conf_contours_textregions)
return pcgts return pcgts
#print("text region early -1 in %.1fs", time.time() - t0) #print("text region early -1 in %.1fs", time.time() - t0)
t1 = time.time() t1 = time.time()
if self.light_version: if self.light_version:
text_regions_p_1 ,erosion_hurts, polygons_lines_xml, textline_mask_tot_ea, img_bin_light, confidence_matrix = \ text_regions_p_1, erosion_hurts, polygons_seplines, textline_mask_tot_ea, img_bin_light, confidence_matrix = \
self.get_regions_light_v(img_res, is_image_enhanced, num_col_classifier) self.get_regions_light_v(img_res, is_image_enhanced, num_col_classifier)
#print("text region early -2 in %.1fs", time.time() - t0) #print("text region early -2 in %.1fs", time.time() - t0)
@ -4367,9 +3945,9 @@ class Eynollah:
textline_mask_tot_ea_deskew = resize_image(textline_mask_tot_ea,img_h_new, img_w_new ) textline_mask_tot_ea_deskew = resize_image(textline_mask_tot_ea,img_h_new, img_w_new )
slope_deskew, slope_first = self.run_deskew(textline_mask_tot_ea_deskew) slope_deskew = self.run_deskew(textline_mask_tot_ea_deskew)
else: else:
slope_deskew, slope_first = self.run_deskew(textline_mask_tot_ea) slope_deskew = self.run_deskew(textline_mask_tot_ea)
#print("text region early -2,5 in %.1fs", time.time() - t0) #print("text region early -2,5 in %.1fs", time.time() - t0)
#self.logger.info("Textregion detection took %.1fs ", time.time() - t1t) #self.logger.info("Textregion detection took %.1fs ", time.time() - t1t)
num_col, num_col_classifier, img_only_regions, page_coord, image_page, mask_images, mask_lines, \ num_col, num_col_classifier, img_only_regions, page_coord, image_page, mask_images, mask_lines, \
@ -4381,7 +3959,7 @@ class Eynollah:
textline_mask_tot_ea_org = np.copy(textline_mask_tot_ea) textline_mask_tot_ea_org = np.copy(textline_mask_tot_ea)
#print("text region early -4 in %.1fs", time.time() - t0) #print("text region early -4 in %.1fs", time.time() - t0)
else: else:
text_regions_p_1 ,erosion_hurts, polygons_lines_xml = \ text_regions_p_1, erosion_hurts, polygons_seplines = \
self.get_regions_from_xy_2models(img_res, is_image_enhanced, self.get_regions_from_xy_2models(img_res, is_image_enhanced,
num_col_classifier) num_col_classifier)
self.logger.info("Textregion detection took %.1fs ", time.time() - t1) self.logger.info("Textregion detection took %.1fs ", time.time() - t1)
@ -4410,7 +3988,7 @@ class Eynollah:
textline_mask_tot_ea = self.run_textline(image_page) textline_mask_tot_ea = self.run_textline(image_page)
self.logger.info("textline detection took %.1fs", time.time() - t1) self.logger.info("textline detection took %.1fs", time.time() - t1)
t1 = time.time() t1 = time.time()
slope_deskew, slope_first = self.run_deskew(textline_mask_tot_ea) slope_deskew = self.run_deskew(textline_mask_tot_ea)
self.logger.info("deskewing took %.1fs", time.time() - t1) self.logger.info("deskewing took %.1fs", time.time() - t1)
elif num_col_classifier in (1,2): elif num_col_classifier in (1,2):
org_h_l_m = textline_mask_tot_ea.shape[0] org_h_l_m = textline_mask_tot_ea.shape[0]
@ -4450,14 +4028,14 @@ class Eynollah:
boxes, boxes_d, polygons_of_marginals, contours_tables = \ boxes, boxes_d, polygons_of_marginals, contours_tables = \
self.run_boxes_no_full_layout(image_page, textline_mask_tot, text_regions_p, slope_deskew, self.run_boxes_no_full_layout(image_page, textline_mask_tot, text_regions_p, slope_deskew,
num_col_classifier, table_prediction, erosion_hurts) num_col_classifier, table_prediction, erosion_hurts)
###polygons_of_marginals = self.dilate_textregions_contours(polygons_of_marginals) ###polygons_of_marginals = dilate_textregion_contours(polygons_of_marginals)
else: else:
polygons_of_images, img_revised_tab, text_regions_p_1_n, textline_mask_tot_d, regions_without_separators_d, \ polygons_of_images, img_revised_tab, text_regions_p_1_n, textline_mask_tot_d, regions_without_separators_d, \
regions_fully, regions_without_separators, polygons_of_marginals, contours_tables = \ regions_fully, regions_without_separators, polygons_of_marginals, contours_tables = \
self.run_boxes_full_layout(image_page, textline_mask_tot, text_regions_p, slope_deskew, self.run_boxes_full_layout(image_page, textline_mask_tot, text_regions_p, slope_deskew,
num_col_classifier, img_only_regions, table_prediction, erosion_hurts, num_col_classifier, img_only_regions, table_prediction, erosion_hurts,
img_bin_light if self.light_version else None) img_bin_light if self.light_version else None)
###polygons_of_marginals = self.dilate_textregions_contours(polygons_of_marginals) ###polygons_of_marginals = dilate_textregion_contours(polygons_of_marginals)
if self.light_version: if self.light_version:
drop_label_in_full_layout = 4 drop_label_in_full_layout = 4
textline_mask_tot_ea_org[img_revised_tab==drop_label_in_full_layout] = 0 textline_mask_tot_ea_org[img_revised_tab==drop_label_in_full_layout] = 0
@ -4580,31 +4158,30 @@ class Eynollah:
[], [], page_coord, [], [], [], [], [], [], [], [], page_coord, [], [], [], [], [], [],
polygons_of_images, contours_tables, [], polygons_of_images, contours_tables, [],
polygons_of_marginals, empty_marginals, empty_marginals, [], [], [], polygons_of_marginals, empty_marginals, empty_marginals, [], [], [],
cont_page, polygons_lines_xml, [], [], []) cont_page, polygons_seplines, [], [], [])
else: else:
pcgts = self.writer.build_pagexml_no_full_layout( pcgts = self.writer.build_pagexml_no_full_layout(
[], page_coord, [], [], [], [], [], page_coord, [], [], [], [],
polygons_of_images, polygons_of_images,
polygons_of_marginals, empty_marginals, empty_marginals, [], [], polygons_of_marginals, empty_marginals, empty_marginals, [], [],
cont_page, polygons_lines_xml, contours_tables, [], []) cont_page, polygons_seplines, contours_tables, [], [])
return pcgts return pcgts
#print("text region early 3 in %.1fs", time.time() - t0) #print("text region early 3 in %.1fs", time.time() - t0)
if self.light_version: if self.light_version:
contours_only_text_parent = self.dilate_textregions_contours( contours_only_text_parent = dilate_textregion_contours(contours_only_text_parent)
contours_only_text_parent)
contours_only_text_parent , contours_only_text_parent_d_ordered = self.filter_contours_inside_a_bigger_one( contours_only_text_parent , contours_only_text_parent_d_ordered = self.filter_contours_inside_a_bigger_one(
contours_only_text_parent, contours_only_text_parent_d_ordered, text_only, marginal_cnts=polygons_of_marginals) contours_only_text_parent, contours_only_text_parent_d_ordered, text_only, marginal_cnts=polygons_of_marginals)
#print("text region early 3.5 in %.1fs", time.time() - t0) #print("text region early 3.5 in %.1fs", time.time() - t0)
txt_con_org , conf_contours_textregions = get_textregion_contours_in_org_image_light( txt_con_org , conf_contours_textregions = get_textregion_contours_in_org_image_light(
contours_only_text_parent, self.image, slope_first, confidence_matrix, map=self.executor.map) contours_only_text_parent, self.image, confidence_matrix, map=self.executor.map)
#txt_con_org = self.dilate_textregions_contours(txt_con_org) #txt_con_org = dilate_textregion_contours(txt_con_org)
#contours_only_text_parent = self.dilate_textregions_contours(contours_only_text_parent) #contours_only_text_parent = dilate_textregion_contours(contours_only_text_parent)
else: else:
txt_con_org , conf_contours_textregions = get_textregion_contours_in_org_image_light( txt_con_org , conf_contours_textregions = get_textregion_contours_in_org_image_light(
contours_only_text_parent, self.image, slope_first, confidence_matrix, map=self.executor.map) contours_only_text_parent, self.image, confidence_matrix, map=self.executor.map)
#print("text region early 4 in %.1fs", time.time() - t0) #print("text region early 4 in %.1fs", time.time() - t0)
boxes_text, _ = get_text_region_boxes_by_given_contours(contours_only_text_parent) boxes_text, _ = get_text_region_boxes_by_given_contours(contours_only_text_parent)
boxes_marginals, _ = get_text_region_boxes_by_given_contours(polygons_of_marginals) boxes_marginals, _ = get_text_region_boxes_by_given_contours(polygons_of_marginals)
@ -4628,14 +4205,10 @@ class Eynollah:
#slopes_marginals, all_found_textline_polygons_marginals, boxes_marginals, polygons_of_marginals, polygons_of_marginals, _ = \ #slopes_marginals, all_found_textline_polygons_marginals, boxes_marginals, polygons_of_marginals, polygons_of_marginals, _ = \
# self.delete_regions_without_textlines(slopes_marginals, all_found_textline_polygons_marginals, # self.delete_regions_without_textlines(slopes_marginals, all_found_textline_polygons_marginals,
# boxes_marginals, polygons_of_marginals, polygons_of_marginals, np.array(range(len(polygons_of_marginals)))) # boxes_marginals, polygons_of_marginals, polygons_of_marginals, np.array(range(len(polygons_of_marginals))))
#all_found_textline_polygons = self.dilate_textlines(all_found_textline_polygons) all_found_textline_polygons = dilate_textline_contours(all_found_textline_polygons)
#####all_found_textline_polygons = self.dilate_textline_contours(all_found_textline_polygons)
all_found_textline_polygons = self.dilate_textregions_contours_textline_version(
all_found_textline_polygons)
all_found_textline_polygons = self.filter_contours_inside_a_bigger_one( all_found_textline_polygons = self.filter_contours_inside_a_bigger_one(
all_found_textline_polygons, None, textline_mask_tot_ea_org, type_contour="textline") all_found_textline_polygons, None, textline_mask_tot_ea_org, type_contour="textline")
all_found_textline_polygons_marginals = self.dilate_textregions_contours_textline_version( all_found_textline_polygons_marginals = dilate_textline_contours(all_found_textline_polygons_marginals)
all_found_textline_polygons_marginals)
contours_only_text_parent, txt_con_org, conf_contours_textregions, all_found_textline_polygons, contours_only_text_parent_d_ordered, \ contours_only_text_parent, txt_con_org, conf_contours_textregions, all_found_textline_polygons, contours_only_text_parent_d_ordered, \
index_by_text_par_con = self.filter_contours_without_textline_inside( index_by_text_par_con = self.filter_contours_without_textline_inside(
contours_only_text_parent, txt_con_org, all_found_textline_polygons, contours_only_text_parent_d_ordered, conf_contours_textregions) contours_only_text_parent, txt_con_org, all_found_textline_polygons, contours_only_text_parent_d_ordered, conf_contours_textregions)
@ -4779,7 +4352,7 @@ class Eynollah:
all_found_textline_polygons, all_found_textline_polygons_h, all_box_coord, all_box_coord_h, all_found_textline_polygons, all_found_textline_polygons_h, all_box_coord, all_box_coord_h,
polygons_of_images, contours_tables, polygons_of_drop_capitals, polygons_of_marginals, polygons_of_images, contours_tables, polygons_of_drop_capitals, polygons_of_marginals,
all_found_textline_polygons_marginals, all_box_coord_marginals, slopes, slopes_h, slopes_marginals, all_found_textline_polygons_marginals, all_box_coord_marginals, slopes, slopes_h, slopes_marginals,
cont_page, polygons_lines_xml, ocr_all_textlines, conf_contours_textregions, conf_contours_textregions_h) cont_page, polygons_seplines, ocr_all_textlines, conf_contours_textregions, conf_contours_textregions_h)
return pcgts return pcgts
contours_only_text_parent_h = None contours_only_text_parent_h = None
@ -4858,7 +4431,7 @@ class Eynollah:
txt_con_org, page_coord, order_text_new, id_of_texts_tot, txt_con_org, page_coord, order_text_new, id_of_texts_tot,
all_found_textline_polygons, all_box_coord, polygons_of_images, polygons_of_marginals, all_found_textline_polygons, all_box_coord, polygons_of_images, polygons_of_marginals,
all_found_textline_polygons_marginals, all_box_coord_marginals, slopes, slopes_marginals, all_found_textline_polygons_marginals, all_box_coord_marginals, slopes, slopes_marginals,
cont_page, polygons_lines_xml, contours_tables, ocr_all_textlines, conf_contours_textregions) cont_page, polygons_seplines, contours_tables, ocr_all_textlines, conf_contours_textregions)
return pcgts return pcgts

View file

@ -955,11 +955,11 @@ def check_any_text_region_in_model_one_is_main_or_header_light(
regions_model_full = cv2.resize(regions_model_full, (regions_model_full.shape[1] // zoom, regions_model_full = cv2.resize(regions_model_full, (regions_model_full.shape[1] // zoom,
regions_model_full.shape[0] // zoom), regions_model_full.shape[0] // zoom),
interpolation=cv2.INTER_NEAREST) interpolation=cv2.INTER_NEAREST)
contours_only_text_parent = [(i / zoom).astype(int) for i in contours_only_text_parent] contours_only_text_parent_z = [(cnt / zoom).astype(int) for cnt in contours_only_text_parent]
### ###
cx_main, cy_main, x_min_main, x_max_main, y_min_main, y_max_main, y_corr_x_min_from_argmin = \ cx_main, cy_main, x_min_main, x_max_main, y_min_main, y_max_main, y_corr_x_min_from_argmin = \
find_new_features_of_contours(contours_only_text_parent) find_new_features_of_contours(contours_only_text_parent_z)
length_con=x_max_main-x_min_main length_con=x_max_main-x_min_main
height_con=y_max_main-y_min_main height_con=y_max_main-y_min_main
@ -982,8 +982,7 @@ def check_any_text_region_in_model_one_is_main_or_header_light(
contours_only_text_parent_main_d=[] contours_only_text_parent_main_d=[]
contours_only_text_parent_head_d=[] contours_only_text_parent_head_d=[]
for ii in range(len(contours_only_text_parent)): for ii, con in enumerate(contours_only_text_parent_z):
con=contours_only_text_parent[ii]
img=np.zeros((regions_model_1.shape[0], regions_model_1.shape[1], 3)) img=np.zeros((regions_model_1.shape[0], regions_model_1.shape[1], 3))
img = cv2.fillPoly(img, pts=[con], color=(255, 255, 255)) img = cv2.fillPoly(img, pts=[con], color=(255, 255, 255))
@ -994,23 +993,22 @@ def check_any_text_region_in_model_one_is_main_or_header_light(
if (pixels_header/float(pixels_main)>=0.3) and ( (length_con[ii]/float(height_con[ii]) )>=1.3 ): if (pixels_header/float(pixels_main)>=0.3) and ( (length_con[ii]/float(height_con[ii]) )>=1.3 ):
regions_model_1[:,:][(regions_model_1[:,:]==1) & (img[:,:,0]==255) ]=2 regions_model_1[:,:][(regions_model_1[:,:]==1) & (img[:,:,0]==255) ]=2
contours_only_text_parent_head.append(con) contours_only_text_parent_head.append(contours_only_text_parent[ii])
conf_contours_head.append(None) # why not conf_contours[ii], too?
if contours_only_text_parent_d_ordered is not None: if contours_only_text_parent_d_ordered is not None:
contours_only_text_parent_head_d.append(contours_only_text_parent_d_ordered[ii]) contours_only_text_parent_head_d.append(contours_only_text_parent_d_ordered[ii])
all_box_coord_head.append(all_box_coord[ii]) all_box_coord_head.append(all_box_coord[ii])
slopes_head.append(slopes[ii]) slopes_head.append(slopes[ii])
all_found_textline_polygons_head.append(all_found_textline_polygons[ii]) all_found_textline_polygons_head.append(all_found_textline_polygons[ii])
conf_contours_head.append(None)
else: else:
regions_model_1[:,:][(regions_model_1[:,:]==1) & (img[:,:,0]==255) ]=1 regions_model_1[:,:][(regions_model_1[:,:]==1) & (img[:,:,0]==255) ]=1
contours_only_text_parent_main.append(con) contours_only_text_parent_main.append(contours_only_text_parent[ii])
conf_contours_main.append(conf_contours[ii]) conf_contours_main.append(conf_contours[ii])
if contours_only_text_parent_d_ordered is not None: if contours_only_text_parent_d_ordered is not None:
contours_only_text_parent_main_d.append(contours_only_text_parent_d_ordered[ii]) contours_only_text_parent_main_d.append(contours_only_text_parent_d_ordered[ii])
all_box_coord_main.append(all_box_coord[ii]) all_box_coord_main.append(all_box_coord[ii])
slopes_main.append(slopes[ii]) slopes_main.append(slopes[ii])
all_found_textline_polygons_main.append(all_found_textline_polygons[ii]) all_found_textline_polygons_main.append(all_found_textline_polygons[ii])
#print(all_pixels,pixels_main,pixels_header) #print(all_pixels,pixels_main,pixels_header)
### to make it faster ### to make it faster
@ -1018,8 +1016,6 @@ def check_any_text_region_in_model_one_is_main_or_header_light(
# regions_model_full = cv2.resize(img, (regions_model_full.shape[1] // zoom, # regions_model_full = cv2.resize(img, (regions_model_full.shape[1] // zoom,
# regions_model_full.shape[0] // zoom), # regions_model_full.shape[0] // zoom),
# interpolation=cv2.INTER_NEAREST) # interpolation=cv2.INTER_NEAREST)
contours_only_text_parent_head = [(i * zoom).astype(int) for i in contours_only_text_parent_head]
contours_only_text_parent_main = [(i * zoom).astype(int) for i in contours_only_text_parent_main]
### ###
return (regions_model_1, return (regions_model_1,
@ -1742,6 +1738,7 @@ def return_boxes_of_images_by_order_of_reading_new(
x_ending = np.array(x_ending) x_ending = np.array(x_ending)
y_type_2 = np.array(y_type_2) y_type_2 = np.array(y_type_2)
y_diff_type_2 = np.array(y_diff_type_2) y_diff_type_2 = np.array(y_diff_type_2)
all_columns = set(range(len(peaks_neg_tot) - 1))
if ((reading_order_type==1) or if ((reading_order_type==1) or
(reading_order_type==0 and (reading_order_type==0 and
@ -1863,19 +1860,16 @@ def return_boxes_of_images_by_order_of_reading_new(
x_end_by_order.append(len(peaks_neg_tot)-2) x_end_by_order.append(len(peaks_neg_tot)-2)
else: else:
#print(x_start_without_mother,x_end_without_mother,peaks_neg_tot,'dodo') #print(x_start_without_mother,x_end_without_mother,peaks_neg_tot,'dodo')
columns_covered_by_mothers = [] columns_covered_by_mothers = set()
for dj in range(len(x_start_without_mother)): for dj in range(len(x_start_without_mother)):
columns_covered_by_mothers = columns_covered_by_mothers + \ columns_covered_by_mothers.update(
list(range(x_start_without_mother[dj], range(x_start_without_mother[dj],
x_end_without_mother[dj])) x_end_without_mother[dj]))
columns_covered_by_mothers = list(set(columns_covered_by_mothers)) columns_not_covered = list(all_columns - columns_covered_by_mothers)
all_columns=np.arange(len(peaks_neg_tot)-1)
columns_not_covered=list(set(all_columns) - set(columns_covered_by_mothers))
y_type_2 = np.append(y_type_2, [int(splitter_y_new[i])] * (len(columns_not_covered) + len(x_start_without_mother))) y_type_2 = np.append(y_type_2, [int(splitter_y_new[i])] * (len(columns_not_covered) + len(x_start_without_mother)))
##y_lines_by_order = np.append(y_lines_by_order, [int(splitter_y_new[i])] * len(columns_not_covered)) ##y_lines_by_order = np.append(y_lines_by_order, [int(splitter_y_new[i])] * len(columns_not_covered))
##x_start_by_order = np.append(x_start_by_order, [0] * len(columns_not_covered)) ##x_start_by_order = np.append(x_start_by_order, [0] * len(columns_not_covered))
x_starting = np.append(x_starting, columns_not_covered) x_starting = np.append(x_starting, np.array(columns_not_covered, x_starting.dtype))
x_starting = np.append(x_starting, x_start_without_mother) x_starting = np.append(x_starting, x_start_without_mother)
x_ending = np.append(x_ending, np.array(columns_not_covered) + 1) x_ending = np.append(x_ending, np.array(columns_not_covered) + 1)
x_ending = np.append(x_ending, x_end_without_mother) x_ending = np.append(x_ending, x_end_without_mother)
@ -1906,32 +1900,26 @@ def return_boxes_of_images_by_order_of_reading_new(
x_end_by_order.append(x_end_column_sort[ii]-1) x_end_by_order.append(x_end_column_sort[ii]-1)
else: else:
#print(x_start_without_mother,x_end_without_mother,peaks_neg_tot,'dodo') #print(x_start_without_mother,x_end_without_mother,peaks_neg_tot,'dodo')
columns_covered_by_mothers = [] columns_covered_by_mothers = set()
for dj in range(len(x_start_without_mother)): for dj in range(len(x_start_without_mother)):
columns_covered_by_mothers = columns_covered_by_mothers + \ columns_covered_by_mothers.update(
list(range(x_start_without_mother[dj], range(x_start_without_mother[dj],
x_end_without_mother[dj])) x_end_without_mother[dj]))
columns_covered_by_mothers = list(set(columns_covered_by_mothers)) columns_not_covered = list(all_columns - columns_covered_by_mothers)
all_columns=np.arange(len(peaks_neg_tot)-1)
columns_not_covered=list(set(all_columns) - set(columns_covered_by_mothers))
y_type_2 = np.append(y_type_2, [int(splitter_y_new[i])] * (len(columns_not_covered) + len(x_start_without_mother))) y_type_2 = np.append(y_type_2, [int(splitter_y_new[i])] * (len(columns_not_covered) + len(x_start_without_mother)))
##y_lines_by_order = np.append(y_lines_by_order, [int(splitter_y_new[i])] * len(columns_not_covered)) ##y_lines_by_order = np.append(y_lines_by_order, [int(splitter_y_new[i])] * len(columns_not_covered))
##x_start_by_order = np.append(x_start_by_order, [0] * len(columns_not_covered)) ##x_start_by_order = np.append(x_start_by_order, [0] * len(columns_not_covered))
x_starting = np.append(x_starting, columns_not_covered) x_starting = np.append(x_starting, np.array(columns_not_covered, x_starting.dtype))
x_starting = np.append(x_starting, x_start_without_mother) x_starting = np.append(x_starting, x_start_without_mother)
x_ending = np.append(x_ending, np.array(columns_not_covered) + 1) x_ending = np.append(x_ending, np.array(columns_not_covered, x_ending.dtype) + 1)
x_ending = np.append(x_ending, x_end_without_mother) x_ending = np.append(x_ending, x_end_without_mother)
columns_covered_by_with_child_no_mothers = [] columns_covered_by_with_child_no_mothers = set()
for dj in range(len(x_end_with_child_without_mother)): for dj in range(len(x_end_with_child_without_mother)):
columns_covered_by_with_child_no_mothers = columns_covered_by_with_child_no_mothers + \ columns_covered_by_with_child_no_mothers.update(
list(range(x_start_with_child_without_mother[dj], range(x_start_with_child_without_mother[dj],
x_end_with_child_without_mother[dj])) x_end_with_child_without_mother[dj]))
columns_covered_by_with_child_no_mothers = list(set(columns_covered_by_with_child_no_mothers)) columns_not_covered_child_no_mother = list(all_columns - columns_covered_by_with_child_no_mothers)
all_columns = np.arange(len(peaks_neg_tot)-1)
columns_not_covered_child_no_mother = list(set(all_columns) - set(columns_covered_by_with_child_no_mothers))
#indexes_to_be_spanned=[] #indexes_to_be_spanned=[]
for i_s in range(len(x_end_with_child_without_mother)): for i_s in range(len(x_end_with_child_without_mother)):
columns_not_covered_child_no_mother.append(x_start_with_child_without_mother[i_s]) columns_not_covered_child_no_mother.append(x_start_with_child_without_mother[i_s])
@ -1967,21 +1955,19 @@ def return_boxes_of_images_by_order_of_reading_new(
if len(x_diff_all_between_nm_wc)>0: if len(x_diff_all_between_nm_wc)>0:
biggest=np.argmax(x_diff_all_between_nm_wc) biggest=np.argmax(x_diff_all_between_nm_wc)
columns_covered_by_mothers = [] columns_covered_by_mothers = set()
for dj in range(len(x_starting_all_between_nm_wc)): for dj in range(len(x_starting_all_between_nm_wc)):
columns_covered_by_mothers = columns_covered_by_mothers + \ columns_covered_by_mothers.update(
list(range(x_starting_all_between_nm_wc[dj], range(x_starting_all_between_nm_wc[dj],
x_ending_all_between_nm_wc[dj])) x_ending_all_between_nm_wc[dj]))
columns_covered_by_mothers = list(set(columns_covered_by_mothers)) child_columns = set(range(i_s_nc, x_end_biggest_column))
columns_not_covered = list(child_columns - columns_covered_by_mothers)
all_columns=np.arange(i_s_nc, x_end_biggest_column)
columns_not_covered = list(set(all_columns) - set(columns_covered_by_mothers))
should_longest_line_be_extended=0 should_longest_line_be_extended=0
if (len(x_diff_all_between_nm_wc) > 0 and if (len(x_diff_all_between_nm_wc) > 0 and
set(list(range(x_starting_all_between_nm_wc[biggest], set(list(range(x_starting_all_between_nm_wc[biggest],
x_ending_all_between_nm_wc[biggest])) + x_ending_all_between_nm_wc[biggest])) +
list(columns_not_covered)) != set(all_columns)): list(columns_not_covered)) != child_columns):
should_longest_line_be_extended=1 should_longest_line_be_extended=1
index_lines_so_close_to_top_separator = \ index_lines_so_close_to_top_separator = \
np.arange(len(y_all_between_nm_wc))[(y_all_between_nm_wc>y_column_nc[i_c]) & np.arange(len(y_all_between_nm_wc))[(y_all_between_nm_wc>y_column_nc[i_c]) &
@ -2092,36 +2078,31 @@ def return_boxes_of_images_by_order_of_reading_new(
x_start_by_order=[] x_start_by_order=[]
x_end_by_order=[] x_end_by_order=[]
if len(x_starting)>0: if len(x_starting)>0:
all_columns = np.arange(len(peaks_neg_tot)-1) columns_covered_by_lines_covered_more_than_2col = set()
columns_covered_by_lines_covered_more_than_2col = []
for dj in range(len(x_starting)): for dj in range(len(x_starting)):
if set(list(range(x_starting[dj],x_ending[dj]))) == set(all_columns): if set(range(x_starting[dj], x_ending[dj])) != all_columns:
pass columns_covered_by_lines_covered_more_than_2col.update(
else: range(x_starting[dj], x_ending[dj]))
columns_covered_by_lines_covered_more_than_2col = columns_covered_by_lines_covered_more_than_2col + \ columns_not_covered = list(all_columns - columns_covered_by_lines_covered_more_than_2col)
list(range(x_starting[dj],x_ending[dj]))
columns_covered_by_lines_covered_more_than_2col = list(set(columns_covered_by_lines_covered_more_than_2col))
columns_not_covered = list(set(all_columns) - set(columns_covered_by_lines_covered_more_than_2col))
y_type_2 = np.append(y_type_2, [int(splitter_y_new[i])] * (len(columns_not_covered) + 1)) y_type_2 = np.append(y_type_2, [int(splitter_y_new[i])] * (len(columns_not_covered) + 1))
##y_lines_by_order = np.append(y_lines_by_order, [int(splitter_y_new[i])] * len(columns_not_covered)) ##y_lines_by_order = np.append(y_lines_by_order, [int(splitter_y_new[i])] * len(columns_not_covered))
##x_start_by_order = np.append(x_start_by_order, [0] * len(columns_not_covered)) ##x_start_by_order = np.append(x_start_by_order, [0] * len(columns_not_covered))
x_starting = np.append(x_starting, columns_not_covered) x_starting = np.append(x_starting, np.array(columns_not_covered, x_starting.dtype))
x_ending = np.append(x_ending, np.array(columns_not_covered) + 1) x_ending = np.append(x_ending, np.array(columns_not_covered, x_ending.dtype) + 1)
if len(new_main_sep_y) > 0: if len(new_main_sep_y) > 0:
x_starting = np.append(x_starting, 0) x_starting = np.append(x_starting, 0)
x_ending = np.append(x_ending, len(peaks_neg_tot)-1) x_ending = np.append(x_ending, len(peaks_neg_tot) - 1)
else: else:
x_starting = np.append(x_starting, x_starting[0]) x_starting = np.append(x_starting, x_starting[0])
x_ending = np.append(x_ending, x_ending[0]) x_ending = np.append(x_ending, x_ending[0])
else: else:
all_columns = np.arange(len(peaks_neg_tot)-1) columns_not_covered = list(all_columns)
columns_not_covered = list(set(all_columns))
y_type_2 = np.append(y_type_2, [int(splitter_y_new[i])] * len(columns_not_covered)) y_type_2 = np.append(y_type_2, [int(splitter_y_new[i])] * len(columns_not_covered))
##y_lines_by_order = np.append(y_lines_by_order, [int(splitter_y_new[i])] * len(columns_not_covered)) ##y_lines_by_order = np.append(y_lines_by_order, [int(splitter_y_new[i])] * len(columns_not_covered))
##x_start_by_order = np.append(x_start_by_order, [0] * len(columns_not_covered)) ##x_start_by_order = np.append(x_start_by_order, [0] * len(columns_not_covered))
x_starting = np.append(x_starting, columns_not_covered) x_starting = np.append(x_starting, np.array(columns_not_covered, x_starting.dtype))
x_ending = np.append(x_ending, np.array(columns_not_covered) + 1) x_ending = np.append(x_ending, np.array(columns_not_covered, x_ending.dtype) + 1)
ind_args=np.array(range(len(y_type_2))) ind_args=np.array(range(len(y_type_2)))
#ind_args=np.array(ind_args) #ind_args=np.array(ind_args)

View file

@ -1,7 +1,15 @@
from typing import Sequence, Union
from numbers import Number
from functools import partial from functools import partial
import itertools
import cv2 import cv2
import numpy as np import numpy as np
from shapely import geometry from scipy.sparse.csgraph import minimum_spanning_tree
from shapely.geometry import Polygon, LineString
from shapely.geometry.polygon import orient
from shapely import set_precision
from shapely.ops import unary_union, nearest_points
from .rotate import rotate_image, rotation_image_new from .rotate import rotate_image, rotation_image_new
@ -37,29 +45,28 @@ def get_text_region_boxes_by_given_contours(contours):
return boxes, contours_new return boxes, contours_new
def filter_contours_area_of_image(image, contours, hierarchy, max_area, min_area): def filter_contours_area_of_image(image, contours, hierarchy, max_area=1.0, min_area=0.0, dilate=0):
found_polygons_early = [] found_polygons_early = []
for jv,c in enumerate(contours): for jv, contour in enumerate(contours):
if len(c) < 3: # A polygon cannot have less than 3 points if len(contour) < 3: # A polygon cannot have less than 3 points
continue continue
polygon = geometry.Polygon([point[0] for point in c]) polygon = contour2polygon(contour, dilate=dilate)
area = polygon.area area = polygon.area
if (area >= min_area * np.prod(image.shape[:2]) and if (area >= min_area * np.prod(image.shape[:2]) and
area <= max_area * np.prod(image.shape[:2]) and area <= max_area * np.prod(image.shape[:2]) and
hierarchy[0][jv][3] == -1): hierarchy[0][jv][3] == -1):
found_polygons_early.append(np.array([[point] found_polygons_early.append(polygon2contour(polygon))
for point in polygon.exterior.coords], dtype=np.uint))
return found_polygons_early return found_polygons_early
def filter_contours_area_of_image_tables(image, contours, hierarchy, max_area, min_area): def filter_contours_area_of_image_tables(image, contours, hierarchy, max_area=1.0, min_area=0.0, dilate=0):
found_polygons_early = [] found_polygons_early = []
for jv,c in enumerate(contours): for jv, contour in enumerate(contours):
if len(c) < 3: # A polygon cannot have less than 3 points if len(contour) < 3: # A polygon cannot have less than 3 points
continue continue
polygon = geometry.Polygon([point[0] for point in c]) polygon = contour2polygon(contour, dilate=dilate)
# area = cv2.contourArea(c) # area = cv2.contourArea(contour)
area = polygon.area area = polygon.area
##print(np.prod(thresh.shape[:2])) ##print(np.prod(thresh.shape[:2]))
# Check that polygon has area greater than minimal area # Check that polygon has area greater than minimal area
@ -68,9 +75,8 @@ def filter_contours_area_of_image_tables(image, contours, hierarchy, max_area, m
area <= max_area * np.prod(image.shape[:2]) and area <= max_area * np.prod(image.shape[:2]) and
# hierarchy[0][jv][3]==-1 # hierarchy[0][jv][3]==-1
True): True):
# print(c[0][0][1]) # print(contour[0][0][1])
found_polygons_early.append(np.array([[point] found_polygons_early.append(polygon2contour(polygon))
for point in polygon.exterior.coords], dtype=np.int32))
return found_polygons_early return found_polygons_early
def find_new_features_of_contours(contours_main): def find_new_features_of_contours(contours_main):
@ -247,23 +253,16 @@ def do_back_rotation_and_get_cnt_back(contour_par, index_r_con, img, slope_first
cont_int[0][:, 0, 1] = cont_int[0][:, 0, 1] + np.abs(img_copy.shape[0] - img.shape[0]) cont_int[0][:, 0, 1] = cont_int[0][:, 0, 1] + np.abs(img_copy.shape[0] - img.shape[0])
return cont_int[0], index_r_con, confidence_contour return cont_int[0], index_r_con, confidence_contour
def get_textregion_contours_in_org_image_light(cnts, img, slope_first, confidence_matrix, map=map): def get_textregion_contours_in_org_image_light(cnts, img, confidence_matrix, map=map):
if not len(cnts): if not len(cnts):
return [], [] return [], []
confidence_matrix = cv2.resize(confidence_matrix, (int(img.shape[1]/6), int(img.shape[0]/6)), interpolation=cv2.INTER_NEAREST) confs = []
img = cv2.resize(img, (int(img.shape[1]/6), int(img.shape[0]/6)), interpolation=cv2.INTER_NEAREST) for cnt in cnts:
##cnts = list( (np.array(cnts)/2).astype(np.int16) ) cnt_mask = np.zeros(confidence_matrix.shape)
#cnts = cnts/2 cnt_mask = cv2.fillPoly(cnt_mask, pts=[cnt], color=1.0)
cnts = [(i/6).astype(int) for i in cnts] confs.append(np.sum(confidence_matrix * cnt_mask) / np.sum(cnt_mask))
results = map(partial(do_back_rotation_and_get_cnt_back, return cnts, confs
img=img,
slope_first=slope_first,
confidence_matrix=confidence_matrix,
),
cnts, range(len(cnts)))
contours, indexes, conf_contours = tuple(zip(*results))
return [i*6 for i in contours], list(conf_contours)
def return_contours_of_interested_textline(region_pre_p, pixel): def return_contours_of_interested_textline(region_pre_p, pixel):
# pixels of images are identified by 5 # pixels of images are identified by 5
@ -332,3 +331,96 @@ def return_contours_of_interested_region_by_size(region_pre_p, pixel, min_area,
return img_ret[:, :, 0] return img_ret[:, :, 0]
def dilate_textline_contours(all_found_textline_polygons):
return [[polygon2contour(contour2polygon(contour, dilate=6))
for contour in region]
for region in all_found_textline_polygons]
def dilate_textregion_contours(all_found_textline_polygons):
return [polygon2contour(contour2polygon(contour, dilate=6))
for contour in all_found_textline_polygons]
def contour2polygon(contour: Union[np.ndarray, Sequence[Sequence[Sequence[Number]]]], dilate=0):
polygon = Polygon([point[0] for point in contour])
if dilate:
polygon = polygon.buffer(dilate)
if polygon.geom_type == 'GeometryCollection':
# heterogeneous result: filter zero-area shapes (LineString, Point)
polygon = unary_union([geom for geom in polygon.geoms if geom.area > 0])
if polygon.geom_type == 'MultiPolygon':
# homogeneous result: construct convex hull to connect
polygon = join_polygons(polygon.geoms)
return make_valid(polygon)
def polygon2contour(polygon: Polygon) -> np.ndarray:
return np.array(polygon.exterior.coords[:-1], dtype=np.uint)[:, np.newaxis]
def make_valid(polygon: Polygon) -> Polygon:
"""Ensures shapely.geometry.Polygon object is valid by repeated rearrangement/simplification/enlargement."""
def isint(x):
return isinstance(x, int) or int(x) == x
# make sure rounding does not invalidate
if not all(map(isint, np.array(polygon.exterior.coords).flat)) and polygon.minimum_clearance < 1.0:
polygon = Polygon(np.round(polygon.exterior.coords))
points = list(polygon.exterior.coords[:-1])
# try by re-arranging points
for split in range(1, len(points)):
if polygon.is_valid or polygon.simplify(polygon.area).is_valid:
break
# simplification may not be possible (at all) due to ordering
# in that case, try another starting point
polygon = Polygon(points[-split:]+points[:-split])
# try by simplification
for tolerance in range(int(polygon.area + 1.5)):
if polygon.is_valid:
break
# simplification may require a larger tolerance
polygon = polygon.simplify(tolerance + 1)
# try by enlarging
for tolerance in range(1, int(polygon.area + 2.5)):
if polygon.is_valid:
break
# enlargement may require a larger tolerance
polygon = polygon.buffer(tolerance)
assert polygon.is_valid, polygon.wkt
return polygon
def join_polygons(polygons: Sequence[Polygon], scale=20) -> Polygon:
"""construct concave hull (alpha shape) from input polygons by connecting their pairwise nearest points"""
# ensure input polygons are simply typed and all oriented equally
polygons = [orient(poly)
for poly in itertools.chain.from_iterable(
[poly.geoms
if poly.geom_type in ['MultiPolygon', 'GeometryCollection']
else [poly]
for poly in polygons])]
npoly = len(polygons)
if npoly == 1:
return polygons[0]
# find min-dist path through all polygons (travelling salesman)
pairs = itertools.combinations(range(npoly), 2)
dists = np.zeros((npoly, npoly), dtype=float)
for i, j in pairs:
dist = polygons[i].distance(polygons[j])
if dist < 1e-5:
dist = 1e-5 # if pair merely touches, we still need to get an edge
dists[i, j] = dist
dists[j, i] = dist
dists = minimum_spanning_tree(dists, overwrite=True)
# add bridge polygons (where necessary)
for prevp, nextp in zip(*dists.nonzero()):
prevp = polygons[prevp]
nextp = polygons[nextp]
nearest = nearest_points(prevp, nextp)
bridgep = orient(LineString(nearest).buffer(max(1, scale/5), resolution=1), -1)
polygons.append(bridgep)
jointp = unary_union(polygons)
assert jointp.geom_type == 'Polygon', jointp.wkt
# follow-up calculations will necessarily be integer;
# so anticipate rounding here and then ensure validity
jointp2 = set_precision(jointp, 1.0)
if jointp2.geom_type != 'Polygon' or not jointp2.is_valid:
jointp2 = Polygon(np.round(jointp.exterior.coords))
jointp2 = make_valid(jointp2)
assert jointp2.geom_type == 'Polygon', jointp2.wkt
return jointp2

View file

@ -1345,24 +1345,26 @@ def textline_contours_postprocessing(textline_mask, slope, contour_text_interest
return contours_rotated_clean return contours_rotated_clean
def separate_lines_new2(img_path, thetha, num_col, slope_region, logger=None, plotter=None): def separate_lines_new2(img_crop, thetha, num_col, slope_region, logger=None, plotter=None):
if logger is None: if logger is None:
logger = getLogger(__package__) logger = getLogger(__package__)
if not np.prod(img_crop.shape):
return img_crop
if num_col == 1: if num_col == 1:
num_patches = int(img_path.shape[1] / 200.0) num_patches = int(img_crop.shape[1] / 200.0)
else: else:
num_patches = int(img_path.shape[1] / 140.0) num_patches = int(img_crop.shape[1] / 140.0)
# num_patches=int(img_path.shape[1]/200.) # num_patches=int(img_crop.shape[1]/200.)
if num_patches == 0: if num_patches == 0:
num_patches = 1 num_patches = 1
img_patch_ineterst = img_path[:, :] # [peaks_neg_true[14]-dis_up:peaks_neg_true[15]+dis_down ,:] img_patch_interest = img_crop[:, :] # [peaks_neg_true[14]-dis_up:peaks_neg_true[15]+dis_down ,:]
# plt.imshow(img_patch_ineterst) # plt.imshow(img_patch_interest)
# plt.show() # plt.show()
length_x = int(img_path.shape[1] / float(num_patches)) length_x = int(img_crop.shape[1] / float(num_patches))
# margin = int(0.04 * length_x) just recently this was changed because it break lines into 2 # margin = int(0.04 * length_x) just recently this was changed because it break lines into 2
margin = int(0.04 * length_x) margin = int(0.04 * length_x)
# if margin<=4: # if margin<=4:
@ -1370,7 +1372,7 @@ def separate_lines_new2(img_path, thetha, num_col, slope_region, logger=None, pl
# margin=0 # margin=0
width_mid = length_x - 2 * margin width_mid = length_x - 2 * margin
nxf = img_path.shape[1] / float(width_mid) nxf = img_crop.shape[1] / float(width_mid)
if nxf > int(nxf): if nxf > int(nxf):
nxf = int(nxf) + 1 nxf = int(nxf) + 1
@ -1386,12 +1388,12 @@ def separate_lines_new2(img_path, thetha, num_col, slope_region, logger=None, pl
index_x_d = i * width_mid index_x_d = i * width_mid
index_x_u = index_x_d + length_x index_x_u = index_x_d + length_x
if index_x_u > img_path.shape[1]: if index_x_u > img_crop.shape[1]:
index_x_u = img_path.shape[1] index_x_u = img_crop.shape[1]
index_x_d = img_path.shape[1] - length_x index_x_d = img_crop.shape[1] - length_x
# img_patch = img[index_y_d:index_y_u, index_x_d:index_x_u, :] # img_patch = img[index_y_d:index_y_u, index_x_d:index_x_u, :]
img_xline = img_patch_ineterst[:, index_x_d:index_x_u] img_xline = img_patch_interest[:, index_x_d:index_x_u]
try: try:
assert img_xline.any() assert img_xline.any()
@ -1407,9 +1409,9 @@ def separate_lines_new2(img_path, thetha, num_col, slope_region, logger=None, pl
img_line_rotated = rotate_image(img_xline, slope_xline) img_line_rotated = rotate_image(img_xline, slope_xline)
img_line_rotated[:, :][img_line_rotated[:, :] != 0] = 1 img_line_rotated[:, :][img_line_rotated[:, :] != 0] = 1
img_patch_ineterst = img_path[:, :] # [peaks_neg_true[14]-dis_up:peaks_neg_true[14]+dis_down ,:] img_patch_interest = img_crop[:, :] # [peaks_neg_true[14]-dis_up:peaks_neg_true[14]+dis_down ,:]
img_patch_ineterst_revised = np.zeros(img_patch_ineterst.shape) img_patch_interest_revised = np.zeros(img_patch_interest.shape)
for i in range(nxf): for i in range(nxf):
if i == 0: if i == 0:
@ -1419,11 +1421,11 @@ def separate_lines_new2(img_path, thetha, num_col, slope_region, logger=None, pl
index_x_d = i * width_mid index_x_d = i * width_mid
index_x_u = index_x_d + length_x index_x_u = index_x_d + length_x
if index_x_u > img_path.shape[1]: if index_x_u > img_crop.shape[1]:
index_x_u = img_path.shape[1] index_x_u = img_crop.shape[1]
index_x_d = img_path.shape[1] - length_x index_x_d = img_crop.shape[1] - length_x
img_xline = img_patch_ineterst[:, index_x_d:index_x_u] img_xline = img_patch_interest[:, index_x_d:index_x_u]
img_int = np.zeros((img_xline.shape[0], img_xline.shape[1])) img_int = np.zeros((img_xline.shape[0], img_xline.shape[1]))
img_int[:, :] = img_xline[:, :] # img_patch_org[:,:,0] img_int[:, :] = img_xline[:, :] # img_patch_org[:,:,0]
@ -1446,9 +1448,9 @@ def separate_lines_new2(img_path, thetha, num_col, slope_region, logger=None, pl
int(img_int.shape[1] * (1.0)) : int(img_int.shape[1] * (1.0)) + img_int.shape[1]] int(img_int.shape[1] * (1.0)) : int(img_int.shape[1] * (1.0)) + img_int.shape[1]]
img_patch_separated_returned_true_size = img_patch_separated_returned_true_size[:, margin : length_x - margin] img_patch_separated_returned_true_size = img_patch_separated_returned_true_size[:, margin : length_x - margin]
img_patch_ineterst_revised[:, index_x_d + margin : index_x_u - margin] = img_patch_separated_returned_true_size img_patch_interest_revised[:, index_x_d + margin : index_x_u - margin] = img_patch_separated_returned_true_size
return img_patch_ineterst_revised return img_patch_interest_revised
def do_image_rotation(angle, img, sigma_des, logger=None): def do_image_rotation(angle, img, sigma_des, logger=None):
if logger is None: if logger is None:
@ -1546,7 +1548,7 @@ def do_work_of_slopes_new(
img_int_p = all_text_region_raw[:,:] img_int_p = 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)
if 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 = 0
slope_for_all = slope_deskew slope_for_all = slope_deskew
all_text_region_raw = textline_mask_tot_ea[y: y + h, x: x + w] all_text_region_raw = textline_mask_tot_ea[y: y + h, x: x + w]
@ -1603,7 +1605,7 @@ def do_work_of_slopes_new_curved(
# plt.imshow(img_int_p) # plt.imshow(img_int_p)
# plt.show() # plt.show()
if 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 = 0
slope_for_all = slope_deskew slope_for_all = slope_deskew
else: else: