forked from javvi51/edocr2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_all.py
262 lines (221 loc) · 10.6 KB
/
test_all.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
import json, os, glob, cv2, time, csv, math
import numpy as np
from edocr2 import tools
from pdf2image import convert_from_path
def process_json_labels(folder_path):
def order_points_clockwise(points):
# Find the point with the lowest x value (and lowest y if tied)
start_point = min(points, key=lambda p: (p[0], p[1]))
# Calculate the centroid of the polygon (for angle sorting)
centroid_x = sum(p[0] for p in points) / len(points)
centroid_y = sum(p[1] for p in points) / len(points)
# Function to calculate the angle from the start point to the point
def angle_from_start(point):
# Calculate the angle using atan2 to get the angle relative to the start point
return math.atan2(point[1] - start_point[1], point[0] - start_point[0])
# Sort points based on the angle relative to the start point
# Exclude the start point from the sorting
sorted_points = sorted((p for p in points if p != start_point), key=angle_from_start)
# Construct the final ordered list starting with the lowest x point
ordered_points = [start_point] + sorted_points
return ordered_points
def convert_json_to_coordinates(json_data):
converted_data = []
for shape in json_data['shapes']:
if shape['shape_type'] == 'rectangle':
label = shape['label']
# Extract the top-left and bottom-right points
(x1, y1), (x2, y2) = shape['points']
# Calculate the top-right and bottom-left points
x3, y3 = x2, y1 # top-right
x4, y4 = x1, y2 # bottom-left
# Append the formatted output: x1, y1, x2, y2, x3, y3, x4, y4, label
converted_data.append([x1, y1, x3, y3, x2, y2, x4, y4, label])
elif shape['shape_type'] == 'polygon':
label = shape['label']
# Extract all points in the polygon
points = shape['points']
# Order them in clockwise direction
ordered_points = order_points_clockwise(points)
# Flatten the ordered points and append the label
flattened_points = [coord for point in ordered_points for coord in point]
converted_data.append(flattened_points + [label])
return converted_data
json_files = glob.glob(os.path.join(folder_path, '*.json'))
for file in json_files:
with open(file, 'r') as f:
json_data = json.load(f)
converted_data = convert_json_to_coordinates(json_data)
output_csv_file = os.path.splitext(file)[0] + '.csv'
# Write the converted data to the respective text file
with open(output_csv_file, 'w', newline='') as csvfile:
csvwriter = csv.writer(csvfile)
# Write each converted row into the CSV
for item in converted_data:
item_int = [int(x) if isinstance(x, float) else x for x in item]
csvwriter.writerow(item_int)
def compute_metrics(filename, predictions, mask_img, iou_thres = 0.2):
correct_detections = 0
detection_iou_scores = []
total_chars, correct_chars = 0, 0
cum_gt, cum_pred = '', ''
with open(filename, newline='') as csvfile:
ground_truth = []
csvreader = csv.reader(csvfile)
for row in csvreader:
# Convert coordinates to int and append label
ground_truth.append((row[8], np.array([[row[0], row[1]], [row[2], row[3]], [row[4], row[5]], [row[6], row[7]]])))
for gt in ground_truth:
best_pred = None
best_iou = 0
for pred in predictions:
iou = tools.train_tools.calculate_iou(pred[1], gt[1])
if iou > best_iou:
best_iou = iou
best_pred = pred
if best_iou >= iou_thres:
if gt[0] != 'other_info' and best_pred[0] != 'other_info': #If dimension detected and correct acc. to gt
#Detection
correct_detections += 1
detection_iou_scores.append(best_iou)
#Recognition
label = gt[0]
recog = best_pred[0]
cum_gt += label
cum_pred += recog
correct_char = tools.train_tools.compare_characters(label, recog)
total_chars += len(label)
correct_chars += correct_char
gt_dim = [gt for gt in ground_truth if gt[0] != 'other_info']
predictions_dim = [pr for pr in predictions if pr[0] != 'other_info']
precision = correct_detections / len(predictions_dim) if len(predictions_dim) > 0 else 0
recall = correct_detections / len(gt_dim) if len(gt_dim) > 0 else 0
average_iou = np.mean(detection_iou_scores)
dim_metrics = {'precision':precision, "recall": recall, 'IoU': average_iou}
char_recall = (correct_chars / total_chars) * 100 if total_chars > 0 else 0
cer = tools.train_tools.get_cer(cum_pred, cum_gt)
recog_metrics = {'char_recall': char_recall, 'CER': cer}
for gt in ground_truth:
box = gt[1]
pts=np.array([(box[0]),(box[1]),(box[2]),(box[3])]).astype(np.int64)
mask_img = cv2.polylines(mask_img, [pts], isClosed=True, color=(0, 255, 0), thickness=2)
return dim_metrics, recog_metrics, mask_img, [correct_detections, len(predictions_dim), len(gt_dim), detection_iou_scores, correct_chars, total_chars, cum_pred, cum_gt]
folder_path = 'tests/test_samples/'
process_json_labels(folder_path)
language = 'eng'
#region Set Session ##############################
start_time = time.time()
#os.environ['TF_XLA_FLAGS'] = '--tf_xla_enable_xla_devices'
import tensorflow as tf
from edocr2.keras_ocr.recognition import Recognizer
from edocr2.keras_ocr.detection import Detector
# Configure GPU memory growth
gpus = tf.config.list_physical_devices('GPU')
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
# Load models
gdt_model = 'edocr2/models/recognizer_gdts.keras'
dim_model = 'edocr2/models/recognizer_dimensions_2.keras'
detector_model = None #'edocr2/models/detector_12_46.keras'
recognizer_gdt = Recognizer(alphabet=tools.ocr_pipelines.read_alphabet(gdt_model))
recognizer_gdt.model.load_weights(gdt_model)
alphabet_dim = tools.ocr_pipelines.read_alphabet(dim_model)
recognizer_dim = Recognizer(alphabet=alphabet_dim)
recognizer_dim.model.load_weights(dim_model)
detector = Detector()
if detector_model:
detector.model.load_weights(detector_model)
end_time = time.time()
print(f"\033[1;33mLoading session took {end_time - start_time:.6f} seconds to run.\033[0m")
#endregion
precision =[]
recall=[]
iou=[]
char_recall=[]
cer=[]
metrics_tools=[]
times = []
for file in os.listdir(folder_path):
if file.endswith(".jpg") or file.endswith(".png"):
start_time = time.time()
#Loading drawing
if file.endswith('.pdf') or file.endswith(".PDF"):
img = convert_from_path(os.path.join(folder_path, file))
img = np.array(img[0])
else:
img = cv2.imread(os.path.join(folder_path, file))
filename = os.path.splitext(os.path.basename(file))[0]
#Segmentation
img_boxes, frame, gdt_boxes, tables, dim_boxes = tools.layer_segm.segment_img(img, autoframe = True, frame_thres=0.7, GDT_thres = 0.02, binary_thres=127)
#Tables
process_img = img.copy()
table_results, updated_tables, process_img= tools.ocr_pipelines.ocr_tables(tables, process_img , language)
#G&DTs
gdt_results, updated_gdt_boxes, process_img = tools.ocr_pipelines.ocr_gdt(process_img, gdt_boxes, recognizer_gdt)
#Dimensions
process_img = process_img[frame.y : frame.y + frame.h, frame.x : frame.x + frame.w]
dimensions, other_info, process_img, dim_pyt = tools.ocr_pipelines.ocr_dimensions(process_img, detector, recognizer_dim, alphabet_dim, dim_boxes, cluster_thres=20, max_img_size=1240, language=language, backg_save=False)
#Masking
mask_img = tools.output_tools.mask_img(img, updated_gdt_boxes, tables, dimensions, frame, other_info)
end_time = time.time()
times.append(end_time-start_time)
#Postprocessing for metric computation
if frame:
offset = (frame.x, frame.y)
else:
offset = (0, 0)
update_dimensions = []
for dim in dimensions:
box = dim[1]
pts=np.array([(box[0] + offset), (box[1] + offset), (box[2] + offset), (box[3] + offset)])
update_dimensions.append([dim[0], pts])
for dim in other_info:
box = dim[1]
pts=np.array([(box[0] + offset), (box[1] + offset), (box[2] + offset), (box[3] + offset)])
update_dimensions.append(['other_info', pts])
#Metrics computation
dim_metrics, recog_metrics, mask_img, m_t = compute_metrics(os.path.join(folder_path, filename + '.csv'), update_dimensions, mask_img)
#Dimensions
for d in dimensions:
print(d[0])
#Other info
print('---------Other info:----------')
for o in other_info:
print(o[0])
print(dim_metrics)
print(recog_metrics)
precision.append(dim_metrics['precision'])
recall.append(dim_metrics['recall'])
iou.append(dim_metrics['IoU'])
char_recall.append(recog_metrics['char_recall'])
cer.append(recog_metrics['CER'])
metrics_tools.append(m_t)
#Display
#cv2.imwrite(file + '.png', mask_img)
'''cv2.imshow('boxes', mask_img)
cv2.waitKey(0)
cv2.destroyAllWindows()'''
print('------------------')
print('Micro Average Results')
print('Precision:', np.mean(precision)*100, '%')
print('Recall:', np.mean(recall)*100, '%')
print('IoU', np.mean(iou)*100, '%')
print('Character Recall', np.mean(char_recall))
print('CER', np.mean(cer)*100, '%')
print('------------------')
print('Macro Average Results')
correct_detections = sum(row[0] for row in metrics_tools)
predictions = sum(row[1] for row in metrics_tools)
print('Precision:', correct_detections/predictions*100, '%')
gt = sum(row[2] for row in metrics_tools)
print('Recall:', correct_detections/gt*100, '%')
iou = [item for row in metrics_tools for item in row[3]]
print('IoU:', np.mean(iou)*100, '%')
correct_char = sum(row[4] for row in metrics_tools)
total_chars = sum(row[5] for row in metrics_tools)
print('Character Recall:', correct_char/total_chars*100, '%')
cum_pred = ''.join(row[6] for row in metrics_tools)
cum_gt = ''.join(row[7] for row in metrics_tools)
print('CER:',tools.train_tools.get_cer(cum_pred, cum_gt)*100, '%')
print('------------------')
print('Average time:', np.mean(times), 's')