ocrad-0.27/ 0000755 0000000 0000000 00000000000 13422012023 011215 5 ustar root root ocrad-0.27/histogram.h 0000644 0000000 0000000 00000003205 13415625447 013411 0 ustar root root /* GNU Ocrad - Optical Character Recognition program
Copyright (C) 2003-2019 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
class Histogram
{
unsigned samples_;
std::vector< int > distrib;
public:
Histogram() : samples_( 0 ) {}
int samples() const { return samples_; }
int size() const { return distrib.size(); }
bool empty() const { return distrib.empty(); }
int operator[]( const int i ) const { return distrib[i]; }
void reset() { samples_ = 0; distrib.clear(); }
void add_sample( const unsigned sample )
{
if( sample < INT_MAX && samples_ < INT_MAX )
{ if( sample >= distrib.size() ) distrib.resize( sample + 1 );
++distrib[sample]; ++samples_; }
}
int median() const
{
unsigned l = 0, cum = 0;
while( l < distrib.size() )
{ cum += distrib[l]; if( 2 * cum >= samples_ ) break; else ++l; }
unsigned r = l;
while( true )
{ if( 2 * cum > samples_ || r >= distrib.size() ) break;
cum += distrib[r]; ++r; }
return ( l + r ) / 2;
}
};
ocrad-0.27/feats.cc 0000644 0000000 0000000 00000025421 13415625447 012660 0 ustar root root /* GNU Ocrad - Optical Character Recognition program
Copyright (C) 2003-2019 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include "common.h"
#include "rectangle.h"
#include "segment.h"
#include "ucs.h"
#include "bitmap.h"
#include "blob.h"
#include "profile.h"
#include "feats.h"
Features::Features( const Blob & b_ )
: b( b_ ), hbar_initialized( false ), vbar_initialized( false ),
lp( b, Profile::left ),
tp( b, Profile::top ), rp( b, Profile::right ), bp( b, Profile::bottom ),
hp( b, Profile::height ), wp( b, Profile::width )
{}
void Features::row_scan_init() const
{
int l = -1; // begin of segment. -1 means no segment
row_scan.resize( b.height() );
for( int row = b.top(); row <= b.bottom(); ++row )
for( int col = b.left(); col <= b.right(); ++col )
{
bool black = b.get_bit( row, col );
if( l < 0 && black ) l = col; // begin of segment
if( l >= 0 && ( !black || col == b.right() ) ) // end of segment
{ row_scan[row-b.top()].push_back( Csegment( l, col - !black ) );
l = -1; }
}
}
void Features::col_scan_init() const
{
int t = -1; // begin of segment. -1 means no segment
col_scan.resize( b.width() );
for( int col = b.left(); col <= b.right(); ++col )
for( int row = b.top(); row <= b.bottom(); ++row )
{
bool black = b.get_bit( row, col );
if( t < 0 && black ) t = row; // begin of segment
if( t >= 0 && ( !black || row == b.bottom() ) ) // end of segment
{ col_scan[col-b.left()].push_back( Csegment( t, row - !black ) );
t = -1; }
}
}
int Features::hbars() const
{
if( !hbar_initialized )
{
hbar_initialized = true;
if( row_scan.empty() ) row_scan_init();
std::vector< Csegment > segv;
segv.reserve( b.height() );
for( unsigned i = 0; i < row_scan.size(); ++i )
{
if( row_scan[i].size() == 1 )
{ segv.push_back( row_scan[i][0] ); continue; }
int maxsize = 0, jmax = -1;
for( unsigned j = 0; j < row_scan[i].size(); ++j )
{
const int size = row_scan[i][j].size();
if( maxsize < size ) { maxsize = size; jmax = j; }
}
if( jmax >= 0 ) segv.push_back( row_scan[i][jmax] );
else segv.push_back( Csegment() );
}
const int limit = ( wp.max() + 1 ) / 2;
int state = 0, begin = 0, l = 0, r = 0;
for( int i = 0; i < b.height(); ++i )
{
Csegment & seg = segv[i];
switch( state )
{
case 0: if( seg.size() <= limit ) break;
state = 1; begin = i; l = seg.left; r = seg.right;
if( i < b.height() - 1 ) break;
case 1: if( seg.size() > limit &&
( i <= begin || seg.overlaps( segv[i-1] ) ) )
{
if( seg.left < l ) l = seg.left;
if( seg.right > r ) r = seg.right;
if( i < b.height() - 1 ) break;
}
state = 0;
int end = ( seg.size() <= limit ) ? i - 1 : i;
const int width = r - l + 1;
while( begin <= end && 3 * segv[begin].size() < 2 * width )
++begin;
while( begin <= end && 3 * segv[end].size() < 2 * width )
--end;
const int height = end - begin + 1;
if( height < 1 || height > width ) break;
const int margin = std::max( height, ( b.height() / 10 ) + 1 );
if( begin >= margin )
{
bool good = false;
for( int j = margin; j > 0; --j )
if( 3 * segv[begin-j].size() <= 2 * width )
{ good = true; break; }
if( !good ) break;
}
if( end + margin < b.height() )
{
bool good = false;
for( int j = margin; j > 0; --j )
if( 3 * segv[end+j].size() <= 2 * width )
{ good = true; break; }
if( !good ) break;
}
hbar_.push_back( Rectangle( l, begin+b.top(), r, end+b.top() ) );
break;
}
}
while( hbar_.size() > 3 ) // remove noise hbars
{
int wmin = hbar_[0].width();
for( unsigned i = 1; i < hbar_.size(); ++i )
if( hbar_[i].width() < wmin ) wmin = hbar_[i].width();
for( int i = hbar_.size() - 1; i >= 0; --i )
if( hbar_[i].width() == wmin ) hbar_.erase( hbar_.begin() + i );
}
}
return hbar_.size();
}
int Features::vbars() const // FIXME small gaps not detected
{
if( !vbar_initialized )
{
vbar_initialized = true;
int state = 0, begin = 0, limit = b.height();
limit -= ( b.height() < 40 ) ? 3 : b.height() / 10;
for( int col = b.left(); col <= b.right(); ++col )
{
int c = 0, c2 = 0, count = 0;
for( int row = b.top() + 1; row < b.bottom(); ++row )
{
if( b.get_bit( row, col ) )
{ ++c; if( row < b.bottom() - 1 ) continue; }
else if( ( col > b.left() && b.get_bit( row, col - 1 ) ) ||
( col < b.right() && b.get_bit( row, col + 1 ) ) )
{ ++c; ++c2; if( row < b.bottom() - 1 ) continue; }
if( c > count ) { count = c; } c = 0;
}
if( ( count - c2 ) * 3 < limit * 2 ) count = 0;
switch( state )
{
case 0: if( count >= limit ) { state = 3; begin = col; }
else if( count * 4 >= limit * 3 ) { state = 2; begin = col; }
else if( count * 3 >= limit * 2 ) { state = 1; begin = col; }
break;
case 1: if( count >= limit ) state = 3;
else if( count * 4 >= limit * 3 ) state = 2;
else if( count * 3 < limit * 2 ) state = 0;
else begin = col;
break;
case 2: if( count >= limit ) state = 3;
else if( count * 3 < limit * 2 ) state = 0;
else if( count * 4 < limit * 3 ) state = 1;
break;
case 3: if( count * 3 < limit * 2 || col == b.right() )
{
int end = ( count * 3 < limit * 2 ) ? col - 1 : col;
vbar_.push_back( Rectangle( begin, b.top(), end, b.bottom() ) );
state = 0;
}
}
}
}
return vbar_.size();
}
Csegment Features::v_segment( const int row, const int col ) const
{
const int segments = segments_in_col( col );
for( int i = 0; i < segments; ++i )
if( col_scan[col-b.left()][i].includes( row ) )
return col_scan[col-b.left()][i];
return Csegment();
}
int Features::test_misc( const Rectangle & charbox ) const
{
if( bp.minima() == 1 )
{
if( hbars() == 1 && hbar(0).top() <= b.top() + ( b.height() / 10 ) &&
4 * hbar(0).height() <= b.height() &&
5 * hbar(0).width() >= 4 * b.width() &&
rp[hbar(0).bottom()-b.top()+2] - rp[hbar(0).bottom()-b.top()] < b.width() / 4 &&
rp.increasing( hbar(0).vcenter() - b.top() + 1 ) )
return '7';
if( b.height() > b.width() && rp.increasing() && !tp.decreasing() &&
b.seek_left( b.vcenter(), b.hcenter() ) <= b.left() )
return '7';
}
if( tp.minima( b.height() / 4 ) == 1 && bp.minima( b.height() / 4 ) == 1 )
{
if( b.height() > 2 * b.width() && rp.increasing() &&
tp.decreasing() && lp.iscpit( 25 ) )
return '1';
if( hbars() == 1 ||
( hbars() == 2 && hbar(1).bottom() >= b.bottom() - 1 &&
3 * hbar(0).width() > 4 * hbar(1).width() ) )
if( 3 * hbar(0).height() < b.height() && hbar(0).top() <= b.top() + 1 )
{
int i = lp.pos( 40 );
if( 3 * wp[i] < b.width() && 5 * lp[i] > b.width() &&
5 * rp[i] > b.width() ) return 'T';
}
if( 3 * b.height() > 4 * b.width() &&
vbars() == 1 && vbar(0).width() >= 2 )
{
const int lg = vbar(0).left() - b.left();
const int rg = b.right() - vbar(0).right();
if( 2 * lg < b.width() && 2 * rg < b.width() &&
Ocrad::similar( lg, rg, 40 ) &&
4 * bp[bp.pos(25)] > 3 * b.height() &&
4 * tp[tp.pos(75)] > 3 * b.height() )
return 'l';
}
if( 5 * b.height() >= 4 * charbox.height() && b.height() > wp.max() &&
3 * wp[wp.pos(50)] < b.width() )
{
if( hbars() == 1 && hbar(0).bottom() >= b.bottom() - 1 &&
hbar(0).top() > b.vpos( 75 ) &&
Ocrad::similar( lp[lp.pos(50)], rp[rp.pos(50)], 20, 2 ) )
return 'l';
if( hbars() == 2 && hbar(0).bottom() < b.vpos( 25 ) &&
hbar(1).top() > b.vpos( 75 ) &&
hbar(1).bottom() >= b.bottom() - 1 /*&&
3 * hbar(0).width() < 4 * hbar(1).width()*/ )
{
if( hbar(0).right() <= hbar(1).hcenter() ) return 0;
if( 3 * hbar(0).width() <= 2 * hbar(1).width() ||
b.height() >= 3 * wp.max() ) return 'l';
return 'I';
}
}
if( ( hbars() == 2 || hbars() == 3 ) && hbar(0).top() <= b.top() + 1 &&
hbar(1).includes_vcenter( b ) &&
3 * hbar(0).width() > 4 * hbar(1).width() &&
( hbars() == 2 ||
( hbar(2).bottom() >= b.bottom() - 1 &&
3 * hbar(0).width() > 4 * hbar(2).width() ) ) ) return 'F';
if( b.height() > 3 * wp.max() )
{
if( rp.istip() && lp.ispit() )
{ if( lp.istpit() ) return '{'; else return '('; }
if( lp.istip() && rp.ispit() )
{ if( rp.istpit() ) return '}'; else return ')'; }
if( b.width() > 2 * wp.max() && rp.isconvex() ) return ')';
}
if( b.height() > 2 * b.width() && 5 * b.height() >= 4 * charbox.height() &&
lp.max() + rp.max() < b.width() )
{
if( 5 * rp[rp.pos(50)] > 2 * b.width() )
{
const int row = b.seek_top( b.vpos( 75 ), b.hpos( 75 ) );
if( ( b.top() < charbox.top() ||
b.bottom() <= charbox.bottom() + ( b.height() / 5 ) ) &&
row <= b.top() ) return 'L';
if( row > b.top() &&
b.seek_bottom( b.vpos( 75 ), b.hpos( 75 ) ) < b.bottom() )
return '[';
}
return '|';
}
}
return 0;
}
ocrad-0.27/ocradlib.h 0000644 0000000 0000000 00000007006 13415625447 013176 0 ustar root root /* Ocradlib - Optical Character Recognition library
Copyright (C) 2009-2019 Antonio Diaz Diaz.
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this library. If not, see .
*/
#ifdef __cplusplus
extern "C" {
#endif
const char * const OCRAD_version_string = "0.27";
/* OCRAD_Pixmap.data is a pointer to image data formed by "height" rows
of "width" pixels each.
The format for each pixel depends on mode like this:
OCRAD_bitmap --> 1 byte per pixel; 0 = white, 1 = black
OCRAD_greymap --> 1 byte per pixel; 256 level greymap (0 = black)
OCRAD_colormap --> 3 bytes per pixel; 16777216 colors RGB (0,0,0 = black) */
enum OCRAD_Pixmap_Mode { OCRAD_bitmap, OCRAD_greymap, OCRAD_colormap };
struct OCRAD_Pixmap
{
const unsigned char * data;
int height;
int width;
enum OCRAD_Pixmap_Mode mode;
};
enum OCRAD_Errno { OCRAD_ok = 0, OCRAD_bad_argument, OCRAD_mem_error,
OCRAD_sequence_error, OCRAD_library_error };
struct OCRAD_Descriptor;
const char * OCRAD_version( void );
/*--------------------- Functions ---------------------*/
struct OCRAD_Descriptor * OCRAD_open( void );
int OCRAD_close( struct OCRAD_Descriptor * const ocrdes );
enum OCRAD_Errno OCRAD_get_errno( struct OCRAD_Descriptor * const ocrdes );
int OCRAD_set_image( struct OCRAD_Descriptor * const ocrdes,
const struct OCRAD_Pixmap * const image,
const bool invert );
int OCRAD_set_image_from_file( struct OCRAD_Descriptor * const ocrdes,
const char * const filename,
const bool invert );
int OCRAD_set_utf8_format( struct OCRAD_Descriptor * const ocrdes,
const bool utf8 ); // 0 = byte, 1 = utf8
int OCRAD_set_threshold( struct OCRAD_Descriptor * const ocrdes,
const int threshold ); // 0..255, -1 = auto
int OCRAD_scale( struct OCRAD_Descriptor * const ocrdes, const int value );
int OCRAD_recognize( struct OCRAD_Descriptor * const ocrdes,
const bool layout );
int OCRAD_result_blocks( struct OCRAD_Descriptor * const ocrdes );
int OCRAD_result_lines( struct OCRAD_Descriptor * const ocrdes,
const int blocknum ); // 0..blocks-1
int OCRAD_result_chars_total( struct OCRAD_Descriptor * const ocrdes );
int OCRAD_result_chars_block( struct OCRAD_Descriptor * const ocrdes,
const int blocknum ); // 0..blocks-1
int OCRAD_result_chars_line( struct OCRAD_Descriptor * const ocrdes,
const int blocknum, // 0..blocks-1
const int linenum ); // 0..lines(block)-1
const char * OCRAD_result_line( struct OCRAD_Descriptor * const ocrdes,
const int blocknum, // 0..blocks-1
const int linenum ); // 0..lines(block)-1
int OCRAD_result_first_character( struct OCRAD_Descriptor * const ocrdes );
#ifdef __cplusplus
}
#endif
ocrad-0.27/profile.h 0000644 0000000 0000000 00000004230 13415625447 013053 0 ustar root root /* GNU Ocrad - Optical Character Recognition program
Copyright (C) 2003-2019 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
class Profile
{
public:
enum Type { left, top, right, bottom, height, width };
private:
const Bitmap & bm; // Bitmap to witch this profile belongs
// can be a Blob or a hole
Type type;
int limit_, max_, min_, mean_;
signed char isconcave_, isconvex_, isflat_, isflats_,
ispit_, istpit_, isupit_, isvpit_, istip_;
std::vector< int > data;
void initialize();
int mean();
public:
Profile( const Bitmap & bm_, const Type t );
// const Bitmap & bitmap() const { return bm; }
int limit() { if( limit_ < 0 ) initialize(); return limit_; }
int max();
int max( const int l, int r = -1 );
int min();
int min( const int l, int r = -1 );
int operator[]( int i );
int pos( const int p ) { return ( ( samples() - 1 ) * p ) / 100; }
int range() { return max() - min(); }
int samples() { if( limit_ < 0 ) initialize(); return data.size(); }
int area( const int l = 0, int r = -1 );
bool increasing( int i = 1, const int min_delta = 2 );
bool decreasing( int i = 1, int end = -1 );
bool isconcave();
bool isconvex();
bool isflat();
bool isflats();
bool ispit();
bool iscpit( const int cpos = 50 );
bool istpit();
bool isupit();
bool isvpit();
bool istip();
bool isctip( const int cpos = 50 );
bool isltip();
bool isrtip();
int imaximum();
int iminimum( const int m = 0, int th = -1 );
int minima( int th = -1 );
bool straight( int * const dyp );
};
ocrad-0.27/bitmap.h 0000644 0000000 0000000 00000005152 13415625447 012673 0 ustar root root /* GNU Ocrad - Optical Character Recognition program
Copyright (C) 2003-2019 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
class Bitmap : public Rectangle
{
std::vector< std::vector< uint8_t > > data; // faster than bool
public:
// Creates a blank Bitmap
Bitmap( const int l, const int t, const int r, const int b );
// Creates a Bitmap from part of another Bitmap
Bitmap( const Bitmap & source, const Rectangle & re );
using Rectangle::left;
using Rectangle::top;
using Rectangle::right;
using Rectangle::bottom;
using Rectangle::height;
using Rectangle::width;
void left ( const int l );
void top ( const int t );
void right ( const int r );
void bottom( const int b );
void height( const int h ) { bottom( top() + h - 1 ); }
void width ( const int w ) { right( left() + w - 1 ); }
void add_bitmap( const Bitmap & bm );
void add_point( const int row, const int col );
void add_rectangle( const Rectangle & re );
bool adjust_height();
bool adjust_width();
bool get_bit( const int row, const int col ) const
{ return data[row-top()][col-left()]; }
void set_bit( const int row, const int col, const bool bit )
{ data[row-top()][col-left()] = bit; }
int area() const; // 'area' means filled area
int area_octagon() const;
int size_octagon() const;
int seek_left ( const int row, const int col, const bool black = true ) const;
int seek_top ( const int row, const int col, const bool black = true ) const;
int seek_right ( const int row, const int col, const bool black = true ) const;
int seek_bottom( const int row, const int col, const bool black = true ) const;
bool escape_left ( int row, int col ) const;
bool escape_top ( int row, int col ) const;
bool escape_right ( int row, int col ) const;
bool escape_bottom( int row, int col ) const;
int follow_top ( int row, int col ) const;
int follow_bottom( int row, int col ) const;
bool top_hook ( int *hdiff ) const;
bool bottom_hook( int *hdiff ) const;
};
ocrad-0.27/segment.h 0000644 0000000 0000000 00000003134 13415625447 013057 0 ustar root root /* GNU Ocrad - Optical Character Recognition program
Copyright (C) 2003-2019 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
struct Csegment // cartesian (one-dimensional) segment
{
int left, right; // l > r means no segment
// in vertical segments, left is top
explicit Csegment( const int l = 1, const int r = 0 )
: left( l ), right( r ) {}
void add_point( const int col );
void add_csegment( const Csegment & seg );
bool valid() const { return ( left <= right ); }
int size() const { return ( left <= right ) ? right - left + 1 : 0; }
bool includes( const Csegment & seg ) const
{ return ( seg.valid() && left <= seg.left && seg.right <= right ); }
bool includes( const int col ) const
{ return ( left <= col && col <= right ); }
bool overlaps( const Csegment & seg ) const
{ return ( valid() && seg.valid() && left <= seg.right && right >= seg.left ); }
int distance( const Csegment & seg ) const;
int distance( const int col ) const;
};
ocrad-0.27/common.h 0000644 0000000 0000000 00000005160 13415625447 012706 0 ustar root root /* GNU Ocrad - Optical Character Recognition program
Copyright (C) 2003-2019 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
extern int verbosity;
namespace Ocrad {
void internal_error( const char * const msg );
bool similar( const int a, const int b,
const int percent_dif, const int abs_dif = 1 );
} // end namespace Ocrad
class Charset
{
int charset_;
public:
enum Value { ascii = 1, iso_8859_9 = 2, iso_8859_15 = 4 };
Charset() : charset_( 0 ) {}
bool enable( const char * const name );
bool enabled( const Value cset ) const;
bool only( const Value cset ) const;
void show_error( const char * const program_name,
const char * const arg ) const;
};
class Transformation
{
public:
enum Type { none, rotate90, rotate180, rotate270,
mirror_lr, mirror_tb, mirror_d1, mirror_d2 };
private:
Type type_;
public:
Transformation() : type_( none ) {}
bool set( const char * const name );
Type type() const { return type_; }
void show_error( const char * const program_name,
const char * const arg ) const;
};
class User_filter;
struct Filter
{
enum Type { letters, letters_only, numbers, numbers_only, same_height,
text_block, upper_num, upper_num_mark, upper_num_only, user };
const User_filter * user_filterp;
Type type;
explicit Filter( const User_filter * p )
: user_filterp( p ), type( user ) {}
explicit Filter( const Type t )
: user_filterp( 0 ), type( t ) {}
};
struct Control
{
Charset charset;
std::vector< Filter > filters;
FILE * outfile, * exportfile;
int debug_level;
char filetype;
bool utf8;
Control()
: outfile( stdout ), exportfile( 0 ),
debug_level( 0 ), filetype( '4' ), utf8( false ) {}
~Control();
bool add_filter( const char * const program_name, const char * const name );
int add_user_filter( const char * const program_name,
const char * const file_name );
bool set_format( const char * const name );
};
ocrad-0.27/arg_parser.h 0000644 0000000 0000000 00000007000 13412523347 013527 0 ustar root root /* Arg_parser - POSIX/GNU command line argument parser. (C++ version)
Copyright (C) 2006-2019 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided
that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* Arg_parser reads the arguments in 'argv' and creates a number of
option codes, option arguments and non-option arguments.
In case of error, 'error' returns a non-empty error message.
'options' is an array of 'struct Option' terminated by an element
containing a code which is zero. A null name means a short-only
option. A code value outside the unsigned char range means a
long-only option.
Arg_parser normally makes it appear as if all the option arguments
were specified before all the non-option arguments for the purposes
of parsing, even if the user of your program intermixed option and
non-option arguments. If you want the arguments in the exact order
the user typed them, call 'Arg_parser' with 'in_order' = true.
The argument '--' terminates all options; any following arguments are
treated as non-option arguments, even if they begin with a hyphen.
The syntax for optional option arguments is '-'
(without whitespace), or '--='.
*/
class Arg_parser
{
public:
enum Has_arg { no, yes, maybe };
struct Option
{
int code; // Short option letter or code ( code != 0 )
const char * name; // Long option name (maybe null)
Has_arg has_arg;
};
private:
struct Record
{
int code;
std::string argument;
explicit Record( const int c ) : code( c ) {}
explicit Record( const char * const arg ) : code( 0 ), argument( arg ) {}
};
std::string error_;
std::vector< Record > data;
bool parse_long_option( const char * const opt, const char * const arg,
const Option options[], int & argind );
bool parse_short_option( const char * const opt, const char * const arg,
const Option options[], int & argind );
public:
Arg_parser( const int argc, const char * const argv[],
const Option options[], const bool in_order = false );
// Restricted constructor. Parses a single token and argument (if any)
Arg_parser( const char * const opt, const char * const arg,
const Option options[] );
const std::string & error() const { return error_; }
// The number of arguments parsed (may be different from argc)
int arguments() const { return data.size(); }
// If code( i ) is 0, argument( i ) is a non-option.
// Else argument( i ) is the option's argument (or empty).
int code( const int i ) const
{
if( i >= 0 && i < arguments() ) return data[i].code;
else return 0;
}
const std::string & argument( const int i ) const
{
if( i >= 0 && i < arguments() ) return data[i].argument;
else return error_;
}
};
ocrad-0.27/textline.h 0000644 0000000 0000000 00000004711 13415625447 013253 0 ustar root root /* GNU Ocrad - Optical Character Recognition program
Copyright (C) 2003-2019 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
class Page_image;
class Rational;
class Textline : public Track
{
int big_initials_;
mutable std::vector< Character * > cpv;
void check_lower_ambiguous();
public:
Textline() : big_initials_( 0 ) {}
Textline( const Textline & tl );
Textline & operator=( const Textline & tl );
~Textline();
void set_track();
void verify_big_initials();
int big_initials() const { return big_initials_; }
Character & character( const int i ) const;
Character * character_at( const int col ) const;
int characters() const { return cpv.size(); }
Rectangle charbox( const Character & c ) const;
int width() const
{ return cpv.empty() ? 0 : cpv.back()->right() - cpv.front()->left(); }
bool is_key_character( const int i ) const; // isalnum of normal size
void delete_character( const int i );
int shift_characterp( Character * const p, const bool big = false );
bool insert_space( const int i, const bool tab = false );
void insert_spaces();
void join( Textline & tl );
int mean_height() const;
Rational mean_width() const;
Rational mean_gap_width( const int first = 0, int last = -1 ) const;
int mean_hcenter() const;
int mean_vcenter() const;
void print( const Control & control ) const;
void dprint( const Control & control, const bool graph,
const bool recursive ) const;
void xprint( const Control & control ) const;
void cmark( Page_image & page_image ) const;
void recognize1( const Charset & charset ) const;
void recognize2( const Charset & charset );
void apply_filter( const Filter::Type filter );
void apply_user_filter( const User_filter & user_filter );
void join_broken_unrecognized_characters();
void remove_leadind_trailing_duplicate_spaces();
};
ocrad-0.27/README 0000644 0000000 0000000 00000004064 13415625447 012127 0 ustar root root Description
GNU Ocrad is an OCR (Optical Character Recognition) program and library
based on a feature extraction method. It reads images in pbm (bitmap),
pgm (greyscale) or ppm (color) formats and produces text in byte (8-bit)
or UTF-8 formats. The pbm, pgm and ppm formats are collectively known as
pnm.
Ocrad includes a layout analyser able to separate the columns or blocks
of text normally found on printed pages.
For best results the characters should be at least 20 pixels high. If
they are smaller, try the --scale option. Scanning the image at 300 dpi
usually produces a character size good enough for ocrad.
See the file INSTALL for compilation and installation instructions.
Try "ocrad --help" for usage instructions.
Caveats.
Merged characters are always a problem. Try to avoid them.
Very bold or very light (broken) characters are also a problem.
Always see with your own eyes the pnm file before blaming ocrad for the
results. Remember the saying, "garbage in, garbage out".
Ideas, comments, patches, donations (hardware, money, etc), etc, are welcome.
---------------------------
Debug levels ( option -D )
100 - Show raw block list.
99 - Show recursive block list.
98 - Show main block list.
96..97 - reserved.
95 - Show all blocks from every character before recognition.
94 - Show main black blocks from every character before recognition.
90..93 - reserved.
89 - Show all blocks from every character.
88 - Show main black blocks from every character.
87 - Show guess list for every character.
86 - Show best guess for every character.
80..85 - reserved.
78..79 - reserved.
7X - X = 0 Show page as bitmap.
X = 1 Show page as bitmap with marked zones.
X = 2 Show page as bitmap with marked lines.
X = 4 Show page as bitmap with marked characters.
Copyright (C) 2003-2019 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy,
distribute and modify it.
The file Makefile.in is a data file used by configure to produce the
Makefile. It has the same copyright owner and permissions that configure
itself.
ocrad-0.27/testsuite/ 0000755 0000000 0000000 00000000000 13422012023 013246 5 ustar root root ocrad-0.27/testsuite/test.pbm 0000644 0000000 0000000 00000154233 12443027266 014756 0 ustar root root P4
560 792
@ > p ?