johnlockejrr commited on
Commit
f39454e
·
verified ·
1 Parent(s): 9368698

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -4
app.py CHANGED
@@ -20,10 +20,6 @@ from jinja2 import Template
20
  import re
21
  import time
22
 
23
- # Add parent directory to path to import seg_rec_kraken
24
- sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
25
- from seg_rec_kraken import seg_rec_image, PAGEXML_TEMPLATE
26
-
27
  # Configure logging
28
  logging.basicConfig(level=logging.WARNING)
29
  logging.getLogger('kraken').setLevel(logging.WARNING)
@@ -36,11 +32,127 @@ MODELS_DIR = Path("models")
36
  SEG_MODELS_DIR = MODELS_DIR / "seg"
37
  REC_MODELS_DIR = MODELS_DIR / "rec"
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  # Create Jinja environment
40
  TEMPLATE_DIR = Path("templates")
41
  TEMPLATE_DIR.mkdir(exist_ok=True)
42
  _ENV = Environment(loader=FileSystemLoader(str(TEMPLATE_DIR)))
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  # Create template files
45
  def create_templates():
46
  """Create Jinja templates for visualization."""
 
20
  import re
21
  import time
22
 
 
 
 
 
23
  # Configure logging
24
  logging.basicConfig(level=logging.WARNING)
25
  logging.getLogger('kraken').setLevel(logging.WARNING)
 
32
  SEG_MODELS_DIR = MODELS_DIR / "seg"
33
  REC_MODELS_DIR = MODELS_DIR / "rec"
34
 
35
+ # Embedded template
36
+ PAGEXML_TEMPLATE = '''{%+ macro render_line(line) +%}
37
+ <TextLine id="{{ line.id }}" {% if line.tags and "type" in line.tags %}custom="structure {type:{{ line.tags["type"] }};}"{% endif %}>
38
+ {% if line.boundary %}
39
+ <Coords points="{% for point in line.boundary %}{{ point|join(',') }}{% if not loop.last %} {% endif %}{% endfor %}"/>
40
+ {% endif %}
41
+ {% if line.baseline %}
42
+ <Baseline points="{% for point in line.baseline %}{{ point|join(',') }}{% if not loop.last %} {% endif %}{% endfor %}"/>
43
+ {% endif %}
44
+ {% if line.text is string %}
45
+ <TextEquiv{% if line.confidences|length %} conf="{{ (line.confidences|sum / line.confidences|length)|round(4) }}"{% endif %}><Unicode>{{ line.text|e }}</Unicode></TextEquiv>
46
+ {% else %}
47
+ {% for segment in line.recognition %}
48
+ <Word id="segment_{{ segment.index }}">
49
+ {% if segment.boundary %}
50
+ <Coords points="{% for point in segment.boundary %}{{ point|join(',') }}{% if not loop.last %} {% endif %}{% endfor %}"/>
51
+ {% else %}
52
+ <Coords points="{{ segment.bbox[0] }},{{ segment.bbox[1] }} {{ segment.bbox[0] }},{{ segment.bbox[3] }} {{ segment.bbox[2] }},{{ segment.bbox[3] }} {{ segment.bbox[2] }},{{ segment.bbox[1] }}"/>
53
+ {% endif %}
54
+ {% for char in segment.recognition %}
55
+ <Glyph id="char_{{ char.index }}">
56
+ <Coords points="{% for point in char.boundary %}{{ point|join(',') }}{% if not loop.last %} {% endif %}{% endfor %}"/>
57
+ <TextEquiv conf="{{ char.confidence|round(4) }}"><Unicode>{{ char.text|e }}</Unicode></TextEquiv>
58
+ </Glyph>
59
+ {% endfor %}
60
+ <TextEquiv conf="{{ (segment.confidences|sum / segment.confidences|length)|round(4) }}"><Unicode>{{ segment.text|e }}</Unicode></TextEquiv>
61
+ </Word>
62
+ {% endfor %}
63
+ {%+ if line.confidences|length %}<TextEquiv conf="{{ (line.confidences|sum / line.confidences|length)|round(4) }}"><Unicode>{% for segment in line.recognition %}{{ segment.text|e }}{% endfor %}</Unicode></TextEquiv>{% endif +%}
64
+ {% endif %}
65
+ </TextLine>
66
+ {%+ endmacro %}
67
+ <?xml version="1.0" encoding="UTF-8"?>
68
+ <PcGts xmlns="http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15 http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15/pagecontent.xsd">
69
+ <Metadata>
70
+ <Creator>kraken {{ metadata.version }}</Creator>
71
+ <Created>{{ page.date }}</Created>
72
+ <LastChange>{{ page.date }}</LastChange>
73
+ </Metadata>
74
+ <Page imageFilename="{{ page.name }}" imageWidth="{{ page.size[0] }}" imageHeight="{{ page.size[1] }}" {% if page.base_dir %}readingDirection="{{ page.base_dir }}"{% endif %}>
75
+ {% for entity in page.entities %}
76
+ {% if entity.type == "region" %}
77
+ {% if loop.previtem and loop.previtem.type == 'line' %}
78
+ </TextRegion>
79
+ {% endif %}
80
+ <TextRegion id="{{ entity.id }}" {% if entity.tags and "type" in entity.tags %}custom="structure {type:{{ entity.tags["type"] }};}"{% endif %}>
81
+ {% if entity.boundary %}<Coords points="{% for point in entity.boundary %}{{ point|join(',') }}{% if not loop.last %} {% endif %}{% endfor %}"/>{% endif %}
82
+ {%- for line in entity.lines -%}
83
+ {{ render_line(line) }}
84
+ {%- endfor %}
85
+ </TextRegion>
86
+ {% else %}
87
+ {% if not loop.previtem or loop.previtem.type != 'line' %}
88
+ <TextRegion id="textblock_{{ loop.index }}">
89
+ <Coords points="0,0 0,{{ page.size[1] }} {{ page.size[0] }},{{ page.size[1] }} {{ page.size[0] }},0"/>
90
+ {% endif %}
91
+ {{ render_line(entity) }}
92
+ {% if loop.last %}
93
+ </TextRegion>
94
+ {% endif %}
95
+ {% endif %}
96
+ {% endfor %}
97
+ </Page>
98
+ </PcGts>'''
99
+
100
  # Create Jinja environment
101
  TEMPLATE_DIR = Path("templates")
102
  TEMPLATE_DIR.mkdir(exist_ok=True)
103
  _ENV = Environment(loader=FileSystemLoader(str(TEMPLATE_DIR)))
104
 
105
+ def seg_rec_image(image_path, seg_model, rec_model, output_dir=None):
106
+ try:
107
+ im = Image.open(image_path)
108
+ baseline_seg = blla.segment(im, model=seg_model)
109
+
110
+ # Run recognition and collect full BaselineOCRRecord objects
111
+ pred_it = rpred.rpred(network=rec_model, im=im, bounds=baseline_seg, pad=16)
112
+ records = [record for record in pred_it]
113
+
114
+ # Attach recognition results to segmentation lines
115
+ for line, rec_line in zip(baseline_seg.lines, records):
116
+ # Debug logging for recognition results
117
+ logger.debug(f'Recognition result - Prediction: {rec_line.prediction}')
118
+ logger.debug(f'Recognition result - Confidences: {rec_line.confidences}')
119
+
120
+ # Ensure the line has both prediction and confidence values
121
+ line.prediction = rec_line.prediction
122
+ line.text = rec_line.prediction # Set text field for serialization
123
+
124
+ # Store per-character confidences
125
+ line.confidences = rec_line.confidences # Keep the list of confidences
126
+
127
+ # Debug logging for line object
128
+ logger.debug(f'Line {line.id} - Prediction: {line.prediction}')
129
+ logger.debug(f'Line {line.id} - Confidences: {line.confidences}')
130
+
131
+ # Construct PAGE-XML segmentation only data
132
+ pagexml_seg_only = serialization.serialize(baseline_seg, image_size=im.size, template='pagexml', sub_line_segmentation=False)
133
+
134
+ # Serialize with recognition results
135
+ pagexml = serialization.serialize(baseline_seg,
136
+ image_size=im.size,
137
+ template='custom_pagexml',
138
+ template_source='custom',
139
+ sub_line_segmentation=False)
140
+
141
+ base_name = os.path.splitext(os.path.basename(image_path))[0]
142
+ if output_dir:
143
+ os.makedirs(output_dir, exist_ok=True)
144
+ output_path = os.path.join(output_dir, base_name + '.xml')
145
+ else:
146
+ output_path = os.path.splitext(image_path)[0] + '.xml'
147
+
148
+ with open(output_path, 'w') as fp:
149
+ fp.write(pagexml)
150
+ print(f"✅ Segmented/recognized: {os.path.basename(image_path)} → {os.path.basename(output_path)}")
151
+ except Exception as e:
152
+ print(f"❌ Failed to process {image_path}: {e}")
153
+ import traceback
154
+ traceback.print_exc()
155
+
156
  # Create template files
157
  def create_templates():
158
  """Create Jinja templates for visualization."""