File size: 3,644 Bytes
3d29a86
993cb76
 
3d29a86
993cb76
8fd5003
24f3c38
906452e
0db7bb0
fd39222
993cb76
 
 
 
2a4cecb
24f3c38
 
637d19f
993cb76
2a4cecb
993cb76
 
2a4cecb
24f3c38
 
 
 
 
 
 
 
 
 
2a4cecb
f265616
24f3c38
 
 
 
2a4cecb
 
 
24f3c38
 
2a4cecb
 
 
 
f265616
2a4cecb
24f3c38
2a4cecb
9d2ded2
637d19f
24f3c38
9d2ded2
321e4a9
24f3c38
 
 
 
 
 
f265616
637d19f
24f3c38
 
 
2a4cecb
f265616
ced7804
993cb76
24f3c38
 
906452e
3d29a86
c412d41
321e4a9
24f3c38
c412d41
24f3c38
f265616
cdadefd
 
24f3c38
2a4cecb
24f3c38
cdadefd
 
 
24f3c38
3d29a86
4673f8c
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
import gradio as gr
from doctr.models import ocr_predictor
import numpy as np

model = ocr_predictor(det_arch='db_resnet50', reco_arch='crnn_vgg16_bn', pretrained=True)

def extract_word_ready_table(image):
    if image is None:
        return "Please upload an image."
    
    img_array = np.array(image)
    result = model([img_array])
    json_export = result.export()
    
    markdown_rows = []
    # Boundaries for Name | Code | Statement | Group | Sub-Group | Normally
    col_bounds = [0.28, 0.35, 0.48, 0.62, 0.88] 

    for page in json_export['pages']:
        words_list = []
        for block in page['blocks']:
            for line in block['lines']:
                for word in line['words']:
                    y_top = word['geometry'][0][1]
                    y_bot = word['geometry'][1][1]
                    x_mid = (word['geometry'][0][0] + word['geometry'][1][0]) / 2
                    words_list.append({
                        'text': word['value'], 
                        'y_top': y_top, 
                        'y_bot': y_bot, 
                        'y_mid': (y_top + y_bot) / 2,
                        'x_mid': x_mid
                    })
        
        if not words_list: continue
        words_list.sort(key=lambda w: w['y_mid'])
        
        # 1. Smarter Row Grouping: We use a larger threshold (0.02) 
        # to catch text that is slightly above or below the main line
        rows = []
        current_row = [words_list[0]]
        for i in range(1, len(words_list)):
            # If word overlaps vertically with the current row, it's the SAME row
            if words_list[i]['y_top'] < current_row[-1]['y_bot'] + 0.01:
                current_row.append(words_list[i])
            else:
                rows.append(current_row)
                current_row = [words_list[i]]
        rows.append(current_row)
        
        # 2. Build the line
        for row in rows:
            slots = ["", "", "", "", "", ""]
            for w in row:
                x = w['x_mid']
                t = w['text']
                
                if x < col_bounds[0]: slots[0] += t + " "
                elif x < col_bounds[1]: slots[1] += t + " "
                elif x < col_bounds[2]: slots[2] += t + " "
                elif x < col_bounds[3]: slots[3] += t + " "
                elif x < col_bounds[4]: slots[4] += t + " "
                else: slots[5] += t + " "
            
            clean_slots = [s.strip() for s in slots]
            if any(clean_slots):
                # We use the Pipe (|) as the only separator
                markdown_rows.append("| " + " | ".join(clean_slots) + " |")

    return "\n".join(markdown_rows)

with gr.Blocks() as demo:
    gr.Markdown("## ๐Ÿ“‘ Word-Ready Accountancy Extractor")
    gr.Markdown("Forces wrapped text into a single line to prevent Word from merging cells incorrectly.")
    
    with gr.Row():
        with gr.Column():
            img_in = gr.Image(type="pil")
            btn = gr.Button("Extract for Word", variant="primary")
        with gr.Column():
            out = gr.Textbox(label="Result (One Line Per Row)", lines=25, elem_id="out_box")
            copy_btn = gr.Button("๐Ÿ“‹ Copy Table")
            copy_btn.click(None, None, None, js="""
                () => {
                    const text = document.querySelector('#output-text textarea').value;
                    navigator.clipboard.writeText(text);
                    alert('Copied! Now use Insert > Table > Convert Text to Table in Word.');
                }
            """)

    btn.click(extract_word_ready_table, inputs=img_in, outputs=out)

demo.launch()