Skip to content

Commit db55366

Browse files
author
Robert Sachunsky
committed
binarize/dewarp/recognize: move getLogger to processing context / introduce setup method
1 parent c80f6da commit db55366

File tree

3 files changed

+67
-63
lines changed

3 files changed

+67
-63
lines changed

ocrd_cis/ocropy/binarize.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,16 @@ def __init__(self, *args, **kwargs):
7676
kwargs['ocrd_tool'] = self.ocrd_tool['tools'][TOOL]
7777
kwargs['version'] = self.ocrd_tool['version']
7878
super(OcropyBinarize, self).__init__(*args, **kwargs)
79-
LOG = getLogger('processor.OcropyBinarize')
8079
if hasattr(self, 'output_file_grp'):
81-
if self.parameter['grayscale'] and self.parameter['method'] != 'ocropy':
82-
LOG.critical('requested method %s does not support grayscale normalized output',
83-
self.parameter['method'])
84-
raise Exception('only method=ocropy allows grayscale=true')
80+
# processing context
81+
self.setup()
82+
83+
def setup(self):
84+
self.logger = getLogger('processor.OcropyBinarize')
85+
if self.parameter['grayscale'] and self.parameter['method'] != 'ocropy':
86+
self.logger.critical('requested method %s does not support grayscale normalized output',
87+
self.parameter['method'])
88+
raise Exception('only method=ocropy allows grayscale=true')
8589

8690
def process(self):
8791
"""Binarize (and optionally deskew/despeckle) the pages/regions/lines of the workspace.
@@ -105,13 +109,12 @@ def process(self):
105109
106110
Produce a new output file by serialising the resulting hierarchy.
107111
"""
108-
LOG = getLogger('processor.OcropyBinarize')
109112
level = self.parameter['level-of-operation']
110113
assert_file_grp_cardinality(self.input_file_grp, 1)
111114
assert_file_grp_cardinality(self.output_file_grp, 1)
112115

113116
for (n, input_file) in enumerate(self.input_files):
114-
LOG.info("INPUT FILE %i / %s", n, input_file.pageId or input_file.ID)
117+
self.logger.info("INPUT FILE %i / %s", n, input_file.pageId or input_file.ID)
115118
file_id = make_file_id(input_file, self.output_file_grp)
116119

117120
pcgts = page_from_file(self.workspace.download_file(input_file))
@@ -139,7 +142,7 @@ def process(self):
139142
dpi = page_image_info.resolution
140143
if page_image_info.resolutionUnit == 'cm':
141144
dpi *= 2.54
142-
LOG.info('Page "%s" uses %f DPI', page_id, dpi)
145+
self.logger.info('Page "%s" uses %f DPI', page_id, dpi)
143146
zoom = 300.0/dpi
144147
else:
145148
zoom = 1
@@ -151,7 +154,7 @@ def process(self):
151154
regions = page.get_TextRegion() + (
152155
page.get_TableRegion() if level == 'region' else [])
153156
if not regions:
154-
LOG.warning('Page "%s" contains no text regions', page_id)
157+
self.logger.warning('Page "%s" contains no text regions', page_id)
155158
for region in regions:
156159
region_image, region_xywh = self.workspace.image_from_segment(
157160
region, page_image, page_xywh, feature_filter='binarized')
@@ -161,7 +164,8 @@ def process(self):
161164
continue
162165
lines = region.get_TextLine()
163166
if not lines:
164-
LOG.warning('Page "%s" region "%s" contains no text lines', page_id, region.id)
167+
self.logger.warning('Page "%s" region "%s" contains no text lines',
168+
page_id, region.id)
165169
for line in lines:
166170
line_image, line_xywh = self.workspace.image_from_segment(
167171
line, region_image, region_xywh, feature_filter='binarized')
@@ -179,12 +183,11 @@ def process(self):
179183
local_filename=file_path,
180184
mimetype=MIMETYPE_PAGE,
181185
content=to_xml(pcgts))
182-
LOG.info('created file ID: %s, file_grp: %s, path: %s',
183-
file_id, self.output_file_grp, out.local_filename)
186+
self.logger.info('created file ID: %s, file_grp: %s, path: %s',
187+
file_id, self.output_file_grp, out.local_filename)
184188

185189
def process_page(self, page, page_image, page_xywh, zoom, page_id, file_id):
186-
LOG = getLogger('processor.OcropyBinarize')
187-
LOG.info("About to binarize page '%s'", page_id)
190+
self.logger.info("About to binarize page '%s'", page_id)
188191
features = page_xywh['features']
189192
if 'angle' in page_xywh and page_xywh['angle']:
190193
# orientation has already been annotated (by previous deskewing),
@@ -229,8 +232,7 @@ def process_page(self, page, page_image, page_xywh, zoom, page_id, file_id):
229232
comments=features))
230233

231234
def process_region(self, region, region_image, region_xywh, zoom, page_id, file_id):
232-
LOG = getLogger('processor.OcropyBinarize')
233-
LOG.info("About to binarize page '%s' region '%s'", page_id, region.id)
235+
self.logger.info("About to binarize page '%s' region '%s'", page_id, region.id)
234236
features = region_xywh['features']
235237
if 'angle' in region_xywh and region_xywh['angle']:
236238
# orientation has already been annotated (by previous deskewing),
@@ -277,9 +279,8 @@ def process_region(self, region, region_image, region_xywh, zoom, page_id, file_
277279
comments=features))
278280

279281
def process_line(self, line, line_image, line_xywh, zoom, page_id, region_id, file_id):
280-
LOG = getLogger('processor.OcropyBinarize')
281-
LOG.info("About to binarize page '%s' region '%s' line '%s'",
282-
page_id, region_id, line.id)
282+
self.logger.info("About to binarize page '%s' region '%s' line '%s'",
283+
page_id, region_id, line.id)
283284
features = line_xywh['features']
284285
bin_image, angle = binarize(line_image,
285286
method=self.parameter['method'],
@@ -294,8 +295,8 @@ def process_line(self, line, line_image, line_xywh, zoom, page_id, region_id, fi
294295
#orientation = -angle
295296
#orientation = 180 - (180 - orientation) % 360 # map to [-179.999,180]
296297
#line.set_orientation(orientation) # does not exist on line level!
297-
LOG.warning("cannot add orientation %.2f to page '%s' region '%s' line '%s'",
298-
-angle, page_id, region_id, line.id)
298+
self.logger.warning("cannot add orientation %.2f to page '%s' region '%s' line '%s'",
299+
-angle, page_id, region_id, line.id)
299300
bin_image = remove_noise(bin_image,
300301
maxsize=self.parameter['noise_maxsize'])
301302
if self.parameter['noise_maxsize']:

ocrd_cis/ocropy/dewarp.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,14 @@ def __init__(self, *args, **kwargs):
7676
kwargs['version'] = self.ocrd_tool['version']
7777
super(OcropyDewarp, self).__init__(*args, **kwargs)
7878
if hasattr(self, 'output_file_grp'):
79-
# defaults from ocrolib.lineest:
80-
range_ = self.parameter['range']
81-
self.lnorm = lineest.CenterNormalizer(params=(range_, 1.0, 0.3))
79+
# processing context
80+
self.setup()
81+
82+
def setup(self):
83+
# defaults from ocrolib.lineest:
84+
range_ = self.parameter['range']
85+
self.lnorm = lineest.CenterNormalizer(params=(range_, 1.0, 0.3))
86+
self.logger = getLogger('processor.OcropyDewarp')
8287

8388
def process(self):
8489
"""Dewarp the lines of the workspace.
@@ -99,12 +104,11 @@ def process(self):
99104
100105
Produce a new output file by serialising the resulting hierarchy.
101106
"""
102-
LOG = getLogger('processor.OcropyDewarp')
103107
assert_file_grp_cardinality(self.input_file_grp, 1)
104108
assert_file_grp_cardinality(self.output_file_grp, 1)
105109

106110
for (n, input_file) in enumerate(self.input_files):
107-
LOG.info("INPUT FILE %i / %s", n, input_file.pageId or input_file.ID)
111+
self.logger.info("INPUT FILE %i / %s", n, input_file.pageId or input_file.ID)
108112
file_id = make_file_id(input_file, self.output_file_grp)
109113

110114
pcgts = page_from_file(self.workspace.download_file(input_file))
@@ -132,36 +136,36 @@ def process(self):
132136
dpi = page_image_info.resolution
133137
if page_image_info.resolutionUnit == 'cm':
134138
dpi *= 2.54
135-
LOG.info('Page "%s" uses %f DPI', page_id, dpi)
139+
self.logger.info('Page "%s" uses %f DPI', page_id, dpi)
136140
zoom = 300.0/dpi
137141
else:
138142
zoom = 1
139143

140144
regions = page.get_TextRegion()
141145
if not regions:
142-
LOG.warning('Page "%s" contains no text regions', page_id)
146+
self.logger.warning('Page "%s" contains no text regions', page_id)
143147
for region in regions:
144148
region_image, region_xywh = self.workspace.image_from_segment(
145149
region, page_image, page_xywh)
146150

147151
lines = region.get_TextLine()
148152
if not lines:
149-
LOG.warning('Region %s contains no text lines', region.id)
153+
self.logger.warning('Region %s contains no text lines', region.id)
150154
for line in lines:
151155
line_image, line_xywh = self.workspace.image_from_segment(
152156
line, region_image, region_xywh)
153157

154-
LOG.info("About to dewarp page '%s' region '%s' line '%s'",
155-
page_id, region.id, line.id)
158+
self.logger.info("About to dewarp page '%s' region '%s' line '%s'",
159+
page_id, region.id, line.id)
156160
try:
157161
dew_image = dewarp(line_image, self.lnorm, check=True,
158162
max_neighbour=self.parameter['max_neighbour'],
159163
zoom=zoom)
160164
except InvalidLine as err:
161-
LOG.error('cannot dewarp line "%s": %s', line.id, err)
165+
self.logger.error('cannot dewarp line "%s": %s', line.id, err)
162166
continue
163167
except InadequateLine as err:
164-
LOG.warning('cannot dewarp line "%s": %s', line.id, err)
168+
self.logger.warning('cannot dewarp line "%s": %s', line.id, err)
165169
# as a fallback, simply pad the image vertically
166170
# (just as dewarping would do on average, so at least
167171
# this line has similar margins as the others):
@@ -188,5 +192,5 @@ def process(self):
188192
local_filename=file_path,
189193
mimetype=MIMETYPE_PAGE,
190194
content=to_xml(pcgts))
191-
LOG.info('created file ID: %s, file_grp: %s, path: %s',
192-
file_id, self.output_file_grp, out.local_filename)
195+
self.logger.info('created file ID: %s, file_grp: %s, path: %s',
196+
file_id, self.output_file_grp, out.local_filename)

ocrd_cis/ocropy/recognize.py

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,19 @@ def __init__(self, *args, **kwargs):
8989
kwargs['ocrd_tool'] = self.ocrd_tool['tools'][TOOL]
9090
kwargs['version'] = self.ocrd_tool['version']
9191
super(OcropyRecognize, self).__init__(*args, **kwargs)
92+
if hasattr(self, 'output_file_grp'):
93+
# processing context
94+
self.setup()
95+
96+
def setup(self):
97+
self.logger = getLogger('processor.OcropyRecognize')
98+
# from ocropus-rpred:
99+
self.network = load_object(self.get_model(), verbose=1)
100+
for x in self.network.walk():
101+
x.postLoad()
102+
for x in self.network.walk():
103+
if isinstance(x, lstm.LSTM):
104+
x.allocate(5000)
92105

93106
def get_model(self):
94107
"""Search for the model file. First checks if
@@ -106,7 +119,6 @@ def get_model(self):
106119
return model
107120

108121
def process(self):
109-
110122
"""Recognize lines / words / glyphs of the workspace.
111123
112124
Open and deserialise each PAGE input file and its respective image,
@@ -131,24 +143,13 @@ def process(self):
131143
132144
Produce a new output file by serialising the resulting hierarchy.
133145
"""
134-
LOG = getLogger('processor.OcropyRecognize')
135-
136146
assert_file_grp_cardinality(self.input_file_grp, 1)
137147
assert_file_grp_cardinality(self.output_file_grp, 1)
138-
139-
# from ocropus-rpred:
140-
self.network = load_object(self.get_model(), verbose=1)
141-
for x in self.network.walk():
142-
x.postLoad()
143-
for x in self.network.walk():
144-
if isinstance(x, lstm.LSTM):
145-
x.allocate(5000)
146-
147148
maxlevel = self.parameter['textequiv_level']
148149

149-
# LOG.info("Using model %s in %s for recognition", model)
150+
# self.logger.info("Using model %s in %s for recognition", model)
150151
for (n, input_file) in enumerate(self.input_files):
151-
LOG.info("INPUT FILE %i / %s", n, input_file.pageId or input_file.ID)
152+
self.logger.info("INPUT FILE %i / %s", n, input_file.pageId or input_file.ID)
152153
pcgts = page_from_file(self.workspace.download_file(input_file))
153154
page_id = pcgts.pcGtsId or input_file.pageId or input_file.ID # (PageType has no id)
154155
page = pcgts.get_Page()
@@ -169,11 +170,11 @@ def process(self):
169170
page_image, page_coords, _ = self.workspace.image_from_page(
170171
page, page_id)
171172

172-
LOG.info("Recognizing text in page '%s'", page_id)
173+
self.logger.info("Recognizing text in page '%s'", page_id)
173174
# region, line, word, or glyph level:
174175
regions = page.get_TextRegion()
175176
if not regions:
176-
LOG.warning("Page '%s' contains no text regions", page_id)
177+
self.logger.warning("Page '%s' contains no text regions", page_id)
177178
self.process_regions(regions, maxlevel, page_image, page_coords)
178179

179180
# update METS (add the PAGE file):
@@ -187,21 +188,20 @@ def process(self):
187188
local_filename=file_path,
188189
mimetype=MIMETYPE_PAGE,
189190
content=to_xml(pcgts))
190-
LOG.info('created file ID: %s, file_grp: %s, path: %s',
191-
file_id, self.output_file_grp, out.local_filename)
191+
self.logger.info('created file ID: %s, file_grp: %s, path: %s',
192+
file_id, self.output_file_grp, out.local_filename)
192193

193194
def process_regions(self, regions, maxlevel, page_image, page_coords):
194-
LOG = getLogger('processor.OcropyRecognize')
195195
edits = 0
196196
lengs = 0
197197
for region in regions:
198198
region_image, region_coords = self.workspace.image_from_segment(
199199
region, page_image, page_coords)
200200

201-
LOG.info("Recognizing text in region '%s'", region.id)
201+
self.logger.info("Recognizing text in region '%s'", region.id)
202202
textlines = region.get_TextLine()
203203
if not textlines:
204-
LOG.warning("Region '%s' contains no text lines", region.id)
204+
self.logger.warning("Region '%s' contains no text lines", region.id)
205205
else:
206206
edits_, lengs_ = self.process_lines(textlines, maxlevel, region_image, region_coords)
207207
edits += edits_
@@ -212,28 +212,27 @@ def process_regions(self, regions, maxlevel, page_image, page_coords):
212212
else u'' for line in textlines)
213213
region.set_TextEquiv([TextEquivType(Unicode=region_unicode)])
214214
if lengs > 0:
215-
LOG.info('CER: %.1f%%', 100.0 * edits / lengs)
215+
self.logger.info('CER: %.1f%%', 100.0 * edits / lengs)
216216

217217
def process_lines(self, textlines, maxlevel, region_image, region_coords):
218-
LOG = getLogger('processor.OcropyRecognize')
219218
edits = 0
220219
lengs = 0
221220
for line in textlines:
222221
line_image, line_coords = self.workspace.image_from_segment(
223222
line, region_image, region_coords)
224223

225-
LOG.info("Recognizing text in line '%s'", line.id)
224+
self.logger.info("Recognizing text in line '%s'", line.id)
226225
if line.get_TextEquiv():
227226
linegt = line.TextEquiv[0].Unicode
228227
else:
229228
linegt = ''
230-
LOG.debug("GT '%s': '%s'", line.id, linegt)
229+
self.logger.debug("GT '%s': '%s'", line.id, linegt)
231230
# remove existing annotation below line level:
232231
line.set_TextEquiv([])
233232
line.set_Word([])
234233

235234
if line_image.size[1] < 16:
236-
LOG.debug("ERROR: bounding box is too narrow at line %s", line.id)
235+
self.logger.debug("ERROR: bounding box is too narrow at line %s", line.id)
237236
continue
238237
# resize image to 48 pixel height
239238
final_img, scale = resize_keep_ratio(line_image)
@@ -243,9 +242,9 @@ def process_lines(self, textlines, maxlevel, region_image, region_coords):
243242
linepred, clist, rlist, confidlist = recognize(
244243
final_img, self.pad, self.network, check=True)
245244
except Exception as err:
246-
LOG.debug('ERROR: error processing line "%s": %s', line.id, err)
245+
self.logger.debug('error processing line "%s": %s', line.id, err)
247246
continue
248-
LOG.debug("OCR '%s': '%s'", line.id, linepred)
247+
self.logger.debug("OCR '%s': '%s'", line.id, linepred)
249248
edits += Levenshtein.distance(linepred, linegt)
250249
lengs += len(linegt)
251250

0 commit comments

Comments
 (0)