Introduction

The KADMOS Developer kit has a strong modular design. Three main modules form the KADMOS architecture, REC, REL, and REP. The names of the REC, REL, and REP modules are chosen according to their functionality:

Rec = REcognize Character
REL = REcognize Line
REP = REcognize Page
REC
At the base level there is the REC module for recognition of properly isolated or segmented single characters. This module requires as input information an image, provided in a data structure ReImage. Character codes are delivered as recognition output with alternatives if necessary in the structure RecData.
REL
For recognition of segmented text lines the REL module is used. As input, an image, provided in a data structure ReImage, is required. REL segments the text line into single characters and, for each character, calls the REC module to recognize it. A structure of the text line with possible alternatives of segmentation together with individual character recognition results is returned in a structure RelData.
REP
For recognition of multi-line text, the REP module is used. It isolates single text lines from the given image and passes them to the REL module for recognition. Input information again consists of an image, provided in a data structure ReImage. An array of results from the REL module related to the recognition of each text line is returned in a structure RepData

For all supported C/C++ compilers, the REC, REL, and REP modules are made as a run-time library or DLL when it is available. They can be linked into any application. Data exchange with the calling program is implemented via related data structures RecData, RelData, and RepData. In these structures, the images for recognition are required as input, with the corresponding results returned after recognition. To call any module, i.e. REC, REL, or REP, a classifier for recognition must be specified and initialized. This must be done so that each data structure RecData, RelData, or RepData is firmly linked to a specific classifier. If an application wants to recognize several text areas (for example, one numeric and one alphanumeric) with different classifiers, data structures for each zone (text area) must be declared and used.

Parameters used for finer control of the recognition process can be passed via the data structure ReParm. Recognition results are always found in the last part of the RecData, RelData, or RepData data structures. For RecData the last part of the structure contains the recognition results for an isolated character. RelData and RepData deliver pointers to data structures RelGrid, RelGraph, RelResult, and RepResult, where the recognition results are located. A detailed description of the parameters can be found in section "Parameters and Functions". For the verification of the results of line recognition the module RESPELL is provided. It compares these results with the content of a dictionary. RESPELL returns its results in the same convention as REL. But here the provided alternatives are the words from the dictionary, if found.

Links to the datasheets:

The Integration

Sample Integration of REC into Console and UNIX Programs
#include <stdio.h>
#include "KADMOS.h"

RecData rec={0};

/* ****************** */
   void main (void) { 
/* ****************** */
  rec_init(&rec, "numplus.rec");
  rec.image.imgtype=IMGTYPE_PIXELARRAY // falls Bilder als Punktmatrix erwartet werden
  for (;;) { 
    // hier eigenen Code zur Besetzung von rec.image einfügen.
    rec.image.data=...; 
    rec.image.width=...;
    rec.image.height=...;
    rec_do(&rec);
    printf("\nErkannt: %s", rec.rec_char[0]); 
  }
  rec_end(&rec); 
}    
          
Sample Integration of REC into Windows Programs
#include <windows.h>
#include "KADMOS.h"
BOOL RcInit=FALSE; RecData rec={0};
// Prozedurteil für die Initialisierung des Klassifikators
...
if (!RcInit){
  if (rec_init(&rec, "numpluseu.rec")==RE_SUCCESS) RcInit=TRUE;
  else {
    MessageBox(NULL, "rec_init() fehlerhaft", "Beoispiel", MB_OK); 
    return FALSE;
  }
} 

// Prozedurteil für Klassifikation.
rec.parm.labels=(char *) ...;
rec.image.data=...;
rec.image.imgtype=IMGTYPE_PIXELARRAY;
// falls Bilder als Punktmatrix erwartet werden. 
rec.image.width=...;
rec.image.height=...;

if rec_do(&rec)!=RE_SUCCESS) {
  MessageBox(NULL, "rec_do() fehlerhaft", "Beispiel", MB_OK); 
  return FALSE;
}
// Bei 'rec.rec_char' und 'rec.rec_value' können nun die 
// Resultate abgeholt werden. rec.rec_char[0] enthält das 
// erste erkannte Zeichen. rec.rec_value[0] enthält einen Wert 
// für die Sicherheit der Erkennung. Werte unter 100 sind gut, 
// grössere Werte sind schlecht ... Prozedurteil für Abschluss
if (RcInit) {
  if (rec_end(&rec)!=RE_SUCCESS) {
    MessageBox(NULL, "rec_end() fehlerhaft", "Beispiel", MB_OK); 
    return FALSE;
  }
  RcInit=FALSE;
}
        
Sample Image Collection using Hook Functions

To help test your program and to collect character images from live documents, KADMOS provides some simple APIs in a module RE_COLLECT. Similar to other recognition functions, image collection initialization has to be started using re_collect_init() with the appropriate image file name to be created. End the process by calling re_collect_end(). Control of the actual process is handled using a recognition confidence rec_value() threshold setting. If characters from a text line are to be collected, the API rel_collect_kernel() is used. The API rec_collect_kernel() is used to collect character images following a call to rec_do(). The calls of re_collect() are described in the sources of recwin, recdemo ....

For good segmentation it is not sufficient to describe the segmented characters or lines by their surrounding rectangles. If there is a need for direct access to the segmented images, then they must be stored separately. This intermediate storage is activated by setting TYPO_KEEPIMG in the related parameter structure RelData or RepData under typograph. In the line module REL after each call to rel_do(), the segmented images can be accessed through result_image, result_height, and result_width. By subsequent calls to rel_do() or rel_end() these images are deleted and the allocated memory is freed. Alternatively, users can call rel_freeimages() to delete the images and free the memory directly. The images provided under result_image are binary images with one byte per pixel and stored line by line.

For a more detailed explanation of this procedure, see the sample program reldemo as provided with the developer kit and copy the related lines into your program. Inspection of the collected images can be performed with the program sichten.exe. If you have your own routines for performing line and character segmentation, inspection of the resulting isolated characters can provide valuable hints to possible line or character cuttings. If the images are ok, but classifier results are not, please do not hesitate at sending or e-mailing the images to Kadmos GmbH for further analysis.

// Modul REP, Initialisierung:
if (re_collect_init("images.ras", 0, 0)!=RE_SUCCESS)...;
rep->rel_hook=rel_collect_kernel;
rep->parm.typograph|=TYPO_KEEPIMG;

// Modul REP, Sammlung wird von rep_do() durch Hook-Funktion erledigt:
if (rep_do(rep)!=RE_SUCCESS) ...;

// Modul REP, Abschluss:
if (re_collect_end()!=RE_SUCCESS)...;          
        
Links to the datasheets:
Sample Image Collection without Hook Functions

For developers who want to use their own hook function.

// Modul REC oder REL, Initialisierung:
if (re_collect_init("Bilder.ras", 0, 0)!=RE_SUCCESS)...; 

// Modul REC, Sammlung nach dem Aufruf von rec_do():
if (rec_do(&rec)!=RE_SUCCESS) ...;
if (rec_collect_kernel(&rec)!=RE_SUCCESS) ...; 

// Modul REL, Sammlung nach dem Aufruf von rel_do():
rel->parm.typograph|=TYPO_KEEPIMG; 
if (rel_do(&rel)!=RE_SUCCESS) ...;

if (rel_collect_kernel(&rel)!=RE_SUCCESS)...;
if (rel_freeimages (&rel)!=RE_SUCCESS) ...; 

// Modul REC oder REL, Abschluss:
if (re_collect_end()!=RE_SUCCESS) ...;
        

With every call to re_collect_init(), re_collect_winit() , an image file is created. If this file already exists, it will first be cleared, i.e. overwritten. Unless terminated by re_collect_end(), this file will receive all collected images. rec_collect_kernel() and rel_collect_kernel() are able to handle as many data structures RecData or RelData as necessary, allowing several different classifiers to be used simultaneously for data collection.

// Initialisierung:
if (re_collect_init("Bilder.ras", value_min, value_max)!=RE_SUCCESSS) ...;          
        

Samples with a confidence value rec_value[0] between lower_bound and upper_bound will be collected. A single threshold different of zero can be used to collect all good (lower_bound==0) or bad (upper_bound==0) image samples.

Links to the datasheets:
Sample Image Collection with kadmos.ini

The KADMOS modules are looking at every initialization re?_init() for the file kadmos.ini in the following directories:

  1. Directory specified by the environment variable KADMOS*.
  2. Directory of the calling program (current directory).
  3. Directory above the current directory.
  4. Working directory.
  5. System directory.
  6. Under Windows in the Windows directory.
[saveimg]
mode= REC, REL, REP
Save the images passed to the character recognizer as Bmp file.
mode= OFF
(or anything else) - don't save anything.
file=
Specify a name for the file to take the bitmap. It is recommended to specify the path too. If not specified (or the path only), a file name will be generated. This files can take one image only. So only the last image under recognition is stored.
[collect]
mode= REC, REL, REP
Save the images passed to the character recognizer as Ras file.
mode= OFF
(or anything else) - don't save anything.
file=
Specify a name for the file to take the collected images. It is recommended to specify the path, too. If not specified (or the path only), a file name will be generated.
value_min=, value_max=If specified and not zero, only images with rec_value[0] within the specified bounds are collected.

The modules have uniform calls. In detail these are:

Modules REC, REL und REP:

rec_init(), rel_init(), rep_init()🗏
Activate (load) a classifier.
rec_info(), rel_info(), rep_info()🗏
Information about the character classes known by the classifier.
rec_filetitle(), rel_filetitle(), rep_filetitle()🗏
Return the classifier name.
rec_do(), rel_do(), rep_do()🗏
Feature formation, classification and segmentation (REL, REP).
rec_group_labels(), rel_group_labels(), rep_group_labels(), repr_group_labels()🗏
Convert base identifiers to group identifiers.
rec_end(), rel_end(), rep_end()🗏
Deactivation of the classifier, memory deallocation.
rec_get_features()🗏
Returns pointers to internal features.
rel_freeimages()
Memory deallocate of collected single character images.
rel_lineshadow()🗏
Classify written material by hand or typescript.

Module RESPELL:

respell_init()🗏
Loading a dictionary.
respell_do()🗏
Verification or improvement of the results of rel_do() or rep_do() by comparison with the content of a connected dictionary.
respell_end()🗏
Disable the loaded dictionary.
respell_codepage()🗏
Return the codepage of the dictionary.
respell_filetitle()🗏
returns the filename of the loaded dictionary.
respell_lookup()🗏
The function searches for the given word in the activated dictionary and returns the results of the dictionary search.
respell_wordchars()🗏
This function returns the character set of the dictionary.

Most functions return the value RE_SUCCESS after correct work, in case of error a corresponding error type. The integration of the modules into a calling program always takes place according to the following scheme, which is shown here by way of example for the module REC:

#include "KADMOS.h" 
RecData rec={0}; 
... 
rec_init&rec, "numpluseu.rec"); 
for (;;) { 
  // hier eigenes Programm zur Besetzung von 'image' einfügen
  rec.image.data=...; 
  rec_do(&rec); 
  printf("\nrecognized: %s", rec.rec_char[0]); 
} 
rec_end(&rec);         
      

The classifier used (in the example numpluseu.rec) is addressed via a data structure RecData. This structure is - like the structures RelData and RepData - declared in KADMOS.h. In practice, there are cases where there are multiple read fields on a form that need to be recognized with different classifiers. For each classifier you need your own data structure. with this then the specific initialization and detection is performed. In the following example of a line recognition, a typewriter field and an OCRA field can be recognized.

#include "KADMOS.h" 
RelData rel_ttfde={0}; 
RelData rel_ocra={0};

rel_ttfde.init.rel_graph_maxlen=...; 
rel_ttfde.init.rel_result_maxlen=...; 
rel_ttfde.rel_graph=...; 
rel_ttfde.rel_result=...;
...
rel_init(&rel_ttfde, "ttfde.rec");

rel_ocra.init.rel_graph_maxlen=...; 
rel_ocra.init.rel_result_maxlen=...; 
rel_ocra.rel_graph=...;
rel_ocra.rel_result=...; 
rel_init(&rel_ocra, "ocra.rec");
... 
for (;;) 
{ 
  rel_ttfde.image.data=...; 
  rel_ttfde.image.imagetype=...;
  rel_do(&rel_ttfde); ... 
  rel_ocra.image.data=...;
  rel_ocra.imiage.imagetype=...;
  rel_do(&rel_ocra); 
... 
} 
rel_end(&rel_ocra); 
rel_end(&rel_ttfde);