File size: 5,750 Bytes
1ee396e
 
 
 
 
 
 
 
 
 
abc6868
 
1ee396e
 
 
 
 
4784f3b
1ee396e
 
4784f3b
1ee396e
 
 
 
 
abc6868
1ee396e
abc6868
 
1f2982b
1ee396e
 
 
1f2982b
 
 
a4274f6
1f2982b
 
 
 
 
a4274f6
1f2982b
 
 
 
 
 
 
a4274f6
1f2982b
 
 
8d5fa5e
a4274f6
1f2982b
 
 
8d5fa5e
a4274f6
1f2982b
a4274f6
1f2982b
 
1ee396e
1f2982b
a4274f6
1ee396e
08efe9a
1ee396e
a4274f6
1ee396e
 
 
 
 
 
 
 
 
 
 
 
9b52dc7
 
 
 
 
 
 
 
 
 
1ee396e
 
 
 
 
 
 
 
 
 
abc6868
 
 
 
 
1ee396e
 
 
 
08efe9a
1ee396e
08efe9a
 
1ee396e
 
 
 
 
 
 
 
9a49dcc
 
 
1ee396e
 
 
 
 
abc6868
1ee396e
 
 
 
 
 
 
 
 
 
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
import os

# Redirect cache to a writable path inside container
os.environ["XDG_CACHE_HOME"] = "/tmp/.cache"

import gradio as gr
from impresso_pipelines.ocrqa import OCRQAPipeline

pipeline = OCRQAPipeline()

LANGUAGES = ["en", "de", "fr"]

# Example OCR text (German text with typical OCR errors)
EXAMPLE_TEXT = """Vieles Seltsame geschieht auf Erden :
Nichts Seltsameres sieht der Mond
Als das Glück, das im Knopfloch wohnt.
Zaubrisch faßt es den ernsten Mann.
Ohne nach Weib u. Kinjd zu fragen
Reitet er aus, nach dem Glück zu jagen,
Nur nacb ihm war stets sein Vegehr.
Aber neben ihm 1reitet der Dämon her
Des Ehrgeizes mit finsterer Tücke,
Und so jagt er zuletzt auf die Brücke,
Die über dem Abgrund, d:m nächtlich schwarzen
Jählings abbricht."""

def process_ocr_qa(text, lang_choice):
    try:
        lang = None if lang_choice == "Auto-detect" else lang_choice
        result = pipeline(text, language=lang, diagnostics=True)

        # Format the output for better readability
        if isinstance(result, dict):
            output_lines = []
            
            # Language detection
            if 'language' in result:
                output_lines.append(f"🌍 Language: {result['language']}")
            
            # Quality score
            if 'score' in result:
                score = result['score']
                score_emoji = "🟢" if score >= 0.8 else "🟡" if score >= 0.5 else "🔴"
                output_lines.append(f"{score_emoji} Quality Score: {score:.1f}")
            
            # Diagnostics section
            if 'diagnostics' in result and result['diagnostics']:
                diagnostics = result['diagnostics']
                
                # Model information
                if 'model_id' in diagnostics:
                    output_lines.append(f"🤖 Model: {diagnostics['model_id']}")
                
                # Known tokens
                if 'known_tokens' in diagnostics and diagnostics['known_tokens']:
                    known_tokens = diagnostics['known_tokens']
                    output_lines.append(f"✅ Known tokens ({len(known_tokens)}): {', '.join(known_tokens)}")
                
                # Unknown tokens (potential OCR errors)
                if 'unknown_tokens' in diagnostics and diagnostics['unknown_tokens']:
                    unknown_tokens = diagnostics['unknown_tokens']
                    output_lines.append(f"❌ Potential OCR errors ({len(unknown_tokens)}): {', '.join(unknown_tokens)}")
                elif 'unknown_tokens' in diagnostics:
                    output_lines.append("✨ No potential OCR errors detected!")
            
            # Other fields
            for key, value in result.items():
                if key not in ['language', 'score', 'diagnostics']:
                    output_lines.append(f"🔍 {key.replace('_', ' ').title()}: {value}")
            
            return "\n\n".join(output_lines)
        else:
            return f"✨ Processed Result:\n{result}"
            
    except Exception as e:
        print("❌ Pipeline error:", e)
        return f"Error: {e}"

# Create the interface with logo and improved description
with gr.Blocks(title="OCR QA Demo") as demo:
    # Add logo at the top
    gr.Image("logo.jpeg", label=None, show_label=False, container=False, height=100)
    
    gr.Markdown(
        """
    # 🔍 OCR Quality Assessment Demo

    This demo showcases the **OCR Quality Assessment (OCRQA)** pipeline developed as part of the [Impresso Project](https://impresso-project.ch). The pipeline evaluates the quality of text extracted via **Optical Character Recognition (OCR)** by estimating the proportion of recognizable words.

    It returns:
    - a **quality score** between **0.0 (poor)** and **1.0 (excellent)**, and
    - a list of **potential OCR errors** (unrecognized tokens).

    You can try the example below (a German text containing typical OCR errors), or paste your own OCR-processed text to assess its quality.
    """
    )
    
    with gr.Row():
        with gr.Column():
            text_input = gr.Textbox(
                label="Enter OCR Text", 
                value=EXAMPLE_TEXT,
                lines=8,
                placeholder="Enter your OCR text here..."
            )
            lang_dropdown = gr.Dropdown(
                choices=["Auto-detect"] + LANGUAGES, 
                value="de", 
                label="Language"
            )
            submit_btn = gr.Button("🔍 Analyze OCR Quality", variant="primary")
        
        with gr.Column():
            with gr.Row():
                output = gr.Textbox(
                    label="Analysis Results", 
                    lines=15,
                    placeholder="Results will appear here...",
                    scale=10
                )
                info_btn = gr.Button("Pipeline Info", size="sm", scale=1)
    
    # Info modal/accordion for pipeline details
    with gr.Accordion("📝 About the OCR QA Pipeline", open=False, visible=False) as info_accordion:
        gr.Markdown(
            """
            - **Quality Score**: Evaluates the overall quality of OCR text. From 0.0 (poor) to 1.0 (excellent)
            - **Known tokens**: Words recognized as valid in the selected language
            - **Potential OCR errors**: Identifies common OCR mistakes and artifacts
            """
        )
    
    submit_btn.click(
        fn=process_ocr_qa,
        inputs=[text_input, lang_dropdown],
        outputs=output
    )
    
    # Toggle info visibility when info button is clicked
    info_btn.click(
        fn=lambda: gr.Accordion(visible=True, open=True),
        outputs=info_accordion
    )

demo.launch(server_name="0.0.0.0", server_port=7860)