Skip to content

Commit 94274c2

Browse files
committed
update codes and data
1 parent 5a19c68 commit 94274c2

File tree

371 files changed

+277483
-29
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

371 files changed

+277483
-29
lines changed

Images/fig3.png

308 KB
Loading

README.md

+70-29
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,70 @@
1-
# Deep-learning and graph-based approach to table structure recognition
2-
3-
## Table Structure Recognition results
4-
5-
### ICDAR 2019 competition dataset [Link](https://github.com/cndplab-founder/ICDAR2019_cTDaR)
6-
7-
| CascadeTabNet | TabStructNet | SPLERGE | Proposed |
8-
| ------------- | ------------ | ------- | -------- |
9-
| <img src="./Images/ICDAR2019/cascadetabnet_cTDaR_t10021.jpg" width="200"> | <img src="./Images/ICDAR2019/tabstructnet_cTDaR_t10021.jpg" width="200"> | <img src="./Images/ICDAR2019/splerge_cTDaR_t10021.jpg" width="200"> | <img src="./Images/ICDAR2019/proposed_cTDaR_t10021.jpg" width="200"> |
10-
11-
### Scanned ICDAR 2019 competition dataset
12-
13-
| CascadeTabNet | TabStructNet | SPLERGE | Proposed |
14-
| ------------- | ------------ | ------- | -------- |
15-
| <img src="./Images/ICDAR2019_scan/cascadetabnet_cTDaR_t10014.jpg" width="200"> | <img src="./Images/ICDAR2019_scan/tabstructnet_cTDaR_t10014.jpg" width="200"> | <img src="./Images/ICDAR2019_scan/splerge_cTDaR_t10014.jpg" width="200"> | <img src="./Images/ICDAR2019_scan/proposed_cTDaR_t10014.jpg" width="200"> |
16-
17-
### Scanned hospital receipts
18-
19-
| CascadeTabNet | TabStructNet | SPLERGE | Proposed |
20-
| ------------- | ------------ | ------- | -------- |
21-
| <img src="./Images/Receipt/cascadetabnet_test_07.jpg" width="200"> | <img src="./Images/Receipt/tabstructnet_test_07.jpg" width="200"> | <img src="./Images/Receipt/splerge_test_07.jpg" width="200"> | <img src="./Images/Receipt/proposed_test_07.jpg" width="200"> |
22-
23-
### Scanned hand-drawn documents
24-
25-
| CascadeTabNet | TabStructNet | SPLERGE | Proposed |
26-
| ------------- | ------------ | ------- | -------- |
27-
| <img src="./Images/Handdrawn/cascadetabnet_test_05.jpg" width="200"> | <img src="./Images/Handdrawn/tabstructnet_test_05.jpg" width="200"> | <img src="./Images/Handdrawn/splerge_test_05.jpg" width="200"> | <img src="./Images/Handdrawn/proposed_test_05.jpg" width="200"> |
28-
29-
1+
# Deep-learning and graph-based approach to table structure recognition
2+
3+
This is an official implementation of [Graph-based-TSR](https://link.springer.com/article/10.1007/s11042-021-11819-7) on Python 3, TensorFlow.
4+
5+
<img src="./Images/fig3.png>
6+
7+
## Requirements
8+
gurobipy
9+
10+
opencv-python
11+
12+
tqdm
13+
14+
sharedmem
15+
16+
## Data
17+
18+
Document data used in paper are stored in data folder.
19+
20+
See explanation in data/config.txt file.
21+
22+
## Execution
23+
24+
### Train
25+
26+
inside codes folder,
27+
28+
```
29+
python code_training/main.py --mode train --batch_size 6 --experiment_name model --data_dir ../data/ctdar19_B2_m/train/ --NUM_STACKS 2 --num_epochs EPOCHS --gpu GPU
30+
```
31+
32+
See detailed arguments in codes/code_training/set_default_training_options.py file.
33+
34+
### Test
35+
36+
inside codes folder,
37+
38+
```
39+
python code_training/main.py --mode test --batch_size 1 --experiment_name bordered --test_data_dir ../data/ctdar19_B2_m/test/SCAN/img/ --test_name test --test_scan True
40+
```
41+
42+
See detailed arguments in codes/code_training/set_default_training_options.py file.
43+
44+
## Table Structure Recognition results
45+
46+
### ICDAR 2019 competition dataset [Link](https://github.com/cndplab-founder/ICDAR2019_cTDaR)
47+
48+
| CascadeTabNet | TabStructNet | SPLERGE | Proposed |
49+
| ------------- | ------------ | ------- | -------- |
50+
| <img src="./Images/ICDAR2019/cascadetabnet_cTDaR_t10021.jpg" width="200"> | <img src="./Images/ICDAR2019/tabstructnet_cTDaR_t10021.jpg" width="200"> | <img src="./Images/ICDAR2019/splerge_cTDaR_t10021.jpg" width="200"> | <img src="./Images/ICDAR2019/proposed_cTDaR_t10021.jpg" width="200"> |
51+
52+
### Scanned ICDAR 2019 competition dataset
53+
54+
| CascadeTabNet | TabStructNet | SPLERGE | Proposed |
55+
| ------------- | ------------ | ------- | -------- |
56+
| <img src="./Images/ICDAR2019_scan/cascadetabnet_cTDaR_t10014.jpg" width="200"> | <img src="./Images/ICDAR2019_scan/tabstructnet_cTDaR_t10014.jpg" width="200"> | <img src="./Images/ICDAR2019_scan/splerge_cTDaR_t10014.jpg" width="200"> | <img src="./Images/ICDAR2019_scan/proposed_cTDaR_t10014.jpg" width="200"> |
57+
58+
### Scanned hospital receipts
59+
60+
| CascadeTabNet | TabStructNet | SPLERGE | Proposed |
61+
| ------------- | ------------ | ------- | -------- |
62+
| <img src="./Images/Receipt/cascadetabnet_test_07.jpg" width="200"> | <img src="./Images/Receipt/tabstructnet_test_07.jpg" width="200"> | <img src="./Images/Receipt/splerge_test_07.jpg" width="200"> | <img src="./Images/Receipt/proposed_test_07.jpg" width="200"> |
63+
64+
### Scanned hand-drawn documents
65+
66+
| CascadeTabNet | TabStructNet | SPLERGE | Proposed |
67+
| ------------- | ------------ | ------- | -------- |
68+
| <img src="./Images/Handdrawn/cascadetabnet_test_05.jpg" width="200"> | <img src="./Images/Handdrawn/tabstructnet_test_05.jpg" width="200"> | <img src="./Images/Handdrawn/splerge_test_05.jpg" width="200"> | <img src="./Images/Handdrawn/proposed_test_05.jpg" width="200"> |
69+
70+

codes/code_commons/auxiliary_ftns.py

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import functools
2+
import cv2
3+
import numpy as np
4+
from global_constants import *
5+
import os
6+
7+
drawthickline = True
8+
9+
10+
def ensure_dir(file_path):
11+
directory = os.path.dirname(file_path)
12+
if not os.path.exists(directory):
13+
os.makedirs(directory)
14+
15+
def get_available_gpus():
16+
from tensorflow.python.client import device_lib
17+
local_device_protos = device_lib.list_local_devices()
18+
result = [x.name for x in local_device_protos if x.device_type == 'GPU']
19+
if len(result) > 0: return result
20+
return [x.name for x in local_device_protos]
21+
22+
23+
def tensor_size(tensor):
24+
from operator import mul
25+
return functools.reduce(mul, (d.value for d in tensor.get_shape()), 1)
26+
27+
28+
def draw_contour( img, landmarks, start_idx, end_idx, c ):
29+
thickness = 1#np.random.randint(0,3) % 2+ 1
30+
if drawthickline is True:
31+
thickness = 2
32+
for j in range(start_idx,end_idx):
33+
pt1 = (landmarks[j,0], landmarks[j,1])
34+
pt2 = (landmarks[(j+1),0], landmarks[(j+1),1])
35+
cv2.line( img, pt1, pt2, color=c,thickness=thickness)
36+
pt1 = (landmarks[start_idx,0], landmarks[start_idx,1])
37+
pt2 = (landmarks[end_idx,0], landmarks[end_idx,1])
38+
cv2.line( img, pt1, pt2, color=c, thickness=thickness)
39+
40+
41+
def draw_junctions( junction_map, base_img = None ):
42+
import get_colors_with_names
43+
44+
if base_img is None:
45+
junction_img = np.zeros( shape=(HEATMAP_HEIGHT, HEATMAP_WIDTH, 3), dtype = np.float32 )
46+
else:
47+
junction_img = base_img
48+
junction_img = junction_img.astype( np.float32 )
49+
junction_img = cv2.resize( junction_img, (HEATMAP_WIDTH, HEATMAP_HEIGHT ))
50+
51+
52+
for i in range( HEATMAP_CHANNEL ):
53+
color = get_colors_with_names.get_color_with_name( COMMON_COLOR_NAMES[i] )
54+
junction_img[:,:,0] = junction_img[:,:,0] + color[2] * junction_map[...,i]
55+
junction_img[:,:,1] = junction_img[:,:,1] + color[1] * junction_map[...,i]
56+
junction_img[:,:,2] = junction_img[:,:,2] + color[0] * junction_map[...,i]
57+
58+
59+
junction_img = np.clip( junction_img, 0, 255 )
60+
junction_img = junction_img.astype( np.uint8 )
61+
return junction_img
62+
63+
64+
def draw_junctions_32f( junction_map, base_img = None ):
65+
import get_colors_with_names
66+
67+
rst = []
68+
69+
for i in range( junction_map.shape[0]):
70+
71+
if base_img is not None:
72+
junction_img = draw_junctions( junction_map[i], base_img[i] )
73+
else:
74+
junction_img = draw_junctions( junction_map[i] )
75+
junction_img = junction_img.astype( np.float32 ) / 255.0
76+
junction_img = cv2.resize( junction_img, (IMAGE_WIDTH,IMAGE_WIDTH))
77+
78+
rst.append( junction_img )
79+
80+
rst = np.array( rst )
81+
return rst

codes/code_commons/config.py

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
###### common ######
2+
# select junction candidates
3+
th_conf = 0.45
4+
rad_conf = 10
5+
6+
## set adjacent candidates
7+
#margin_adj = 6
8+
9+
# edge score for missing nodes
10+
lscore_extra = 0.15
11+
12+
# regularization scale for node score
13+
nscore_regul = 0.
14+
15+
# scale of the distance term in an edge score
16+
ep_dist = 0.5
17+
18+
# additional threshold of adjacent candidates
19+
mu_d = 14 #mu
20+
mu_s = 6 #8 #lambda
21+
22+
# scale of edge score
23+
scale_lscore = 1.1 #2.01
24+
25+
# character_height
26+
CH = 12
+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
def get_color_with_name( name ):
2+
cnames = {
3+
'aliceblue': '#F0F8FF',
4+
'antiquewhite': '#FAEBD7',
5+
'aqua': '#00FFFF',
6+
'aquamarine': '#7FFFD4',
7+
'azure': '#F0FFFF',
8+
'beige': '#F5F5DC',
9+
'bisque': '#FFE4C4',
10+
'black': '#000000',
11+
'blanchedalmond': '#FFEBCD',
12+
'blue': '#0000FF',
13+
'blueviolet': '#8A2BE2',
14+
'brown': '#A52A2A',
15+
'burlywood': '#DEB887',
16+
'cadetblue': '#5F9EA0',
17+
'chartreuse': '#7FFF00',
18+
'chocolate': '#D2691E',
19+
'coral': '#FF7F50',
20+
'cornflowerblue': '#6495ED',
21+
'cornsilk': '#FFF8DC',
22+
'crimson': '#DC143C',
23+
'cyan': '#00FFFF',
24+
'darkblue': '#00008B',
25+
'darkcyan': '#008B8B',
26+
'darkgoldenrod': '#B8860B',
27+
'darkgray': '#A9A9A9',
28+
'darkgreen': '#006400',
29+
'darkkhaki': '#BDB76B',
30+
'darkmagenta': '#8B008B',
31+
'darkolivegreen': '#556B2F',
32+
'darkorange': '#FF8C00',
33+
'darkorchid': '#9932CC',
34+
'darkred': '#8B0000',
35+
'darksalmon': '#E9967A',
36+
'darkseagreen': '#8FBC8F',
37+
'darkslateblue': '#483D8B',
38+
'darkslategray': '#2F4F4F',
39+
'darkturquoise': '#00CED1',
40+
'darkviolet': '#9400D3',
41+
'deeppink': '#FF1493',
42+
'deepskyblue': '#00BFFF',
43+
'dimgray': '#696969',
44+
'dodgerblue': '#1E90FF',
45+
'firebrick': '#B22222',
46+
'floralwhite': '#FFFAF0',
47+
'forestgreen': '#228B22',
48+
'fuchsia': '#FF00FF',
49+
'gainsboro': '#DCDCDC',
50+
'ghostwhite': '#F8F8FF',
51+
'gold': '#FFD700',
52+
'goldenrod': '#DAA520',
53+
'gray': '#808080',
54+
'green': '#008000',
55+
'greenyellow': '#ADFF2F',
56+
'honeydew': '#F0FFF0',
57+
'hotpink': '#FF69B4',
58+
'indianred': '#CD5C5C',
59+
'indigo': '#4B0082',
60+
'ivory': '#FFFFF0',
61+
'khaki': '#F0E68C',
62+
'lavender': '#E6E6FA',
63+
'lavenderblush': '#FFF0F5',
64+
'lawngreen': '#7CFC00',
65+
'lemonchiffon': '#FFFACD',
66+
'lightblue': '#ADD8E6',
67+
'lightcoral': '#F08080',
68+
'lightcyan': '#E0FFFF',
69+
'lightgoldenrodyellow': '#FAFAD2',
70+
'lightgreen': '#90EE90',
71+
'lightgray': '#D3D3D3',
72+
'lightpink': '#FFB6C1',
73+
'lightsalmon': '#FFA07A',
74+
'lightseagreen': '#20B2AA',
75+
'lightskyblue': '#87CEFA',
76+
'lightslategray': '#778899',
77+
'lightsteelblue': '#B0C4DE',
78+
'lightyellow': '#FFFFE0',
79+
'lime': '#00FF00',
80+
'limegreen': '#32CD32',
81+
'linen': '#FAF0E6',
82+
'magenta': '#FF00FF',
83+
'maroon': '#800000',
84+
'mediumaquamarine': '#66CDAA',
85+
'mediumblue': '#0000CD',
86+
'mediumorchid': '#BA55D3',
87+
'mediumpurple': '#9370DB',
88+
'mediumseagreen': '#3CB371',
89+
'mediumslateblue': '#7B68EE',
90+
'mediumspringgreen': '#00FA9A',
91+
'mediumturquoise': '#48D1CC',
92+
'mediumvioletred': '#C71585',
93+
'midnightblue': '#191970',
94+
'mintcream': '#F5FFFA',
95+
'mistyrose': '#FFE4E1',
96+
'moccasin': '#FFE4B5',
97+
'navajowhite': '#FFDEAD',
98+
'navy': '#000080',
99+
'oldlace': '#FDF5E6',
100+
'olive': '#808000',
101+
'olivedrab': '#6B8E23',
102+
'orange': '#FFA500',
103+
'orangered': '#FF4500',
104+
'orchid': '#DA70D6',
105+
'palegoldenrod': '#EEE8AA',
106+
'palegreen': '#98FB98',
107+
'paleturquoise': '#AFEEEE',
108+
'palevioletred': '#DB7093',
109+
'papayawhip': '#FFEFD5',
110+
'peachpuff': '#FFDAB9',
111+
'peru': '#CD853F',
112+
'pink': '#FFC0CB',
113+
'plum': '#DDA0DD',
114+
'powderblue': '#B0E0E6',
115+
'purple': '#800080',
116+
'red': '#FF0000',
117+
'rosybrown': '#BC8F8F',
118+
'royalblue': '#4169E1',
119+
'saddlebrown': '#8B4513',
120+
'salmon': '#FA8072',
121+
'sandybrown': '#FAA460',
122+
'seagreen': '#2E8B57',
123+
'seashell': '#FFF5EE',
124+
'sienna': '#A0522D',
125+
'silver': '#C0C0C0',
126+
'skyblue': '#87CEEB',
127+
'slateblue': '#6A5ACD',
128+
'slategray': '#708090',
129+
'snow': '#FFFAFA',
130+
'springgreen': '#00FF7F',
131+
'steelblue': '#4682B4',
132+
'tan': '#D2B48C',
133+
'teal': '#008080',
134+
'thistle': '#D8BFD8',
135+
'tomato': '#FF6347',
136+
'turquoise': '#40E0D0',
137+
'violet': '#EE82EE',
138+
'wheat': '#F5DEB3',
139+
'white': '#FFFFFF',
140+
'whitesmoke': '#F5F5F5',
141+
'yellow': '#FFFF00',
142+
'yellowgreen': '#9ACD32'}
143+
x = cnames[name]
144+
if x is None:
145+
raise Exception(f"there are no {name}")
146+
return ( int(x[5:7],16), int(x[3:5],16), int(x[1:3],16) )
147+
148+
149+
if __name__ == "__main__":
150+
x = get_color_with_name('bluex')
151+
print( x )

0 commit comments

Comments
 (0)