diff --git a/Products/TesseractOCR.framework/Versions/A/Headers/Tesseract.h b/Products/TesseractOCR.framework/Versions/A/Headers/Tesseract.h index 1df7673c..89b47697 100755 --- a/Products/TesseractOCR.framework/Versions/A/Headers/Tesseract.h +++ b/Products/TesseractOCR.framework/Versions/A/Headers/Tesseract.h @@ -31,7 +31,7 @@ // This NSDictionary uses NSValue encoded CGRects as keys and the recognized character (NSString) as the value // CGRects are in UIKit's coordinate space (origin is in the top left) -@property (nonatomic, readonly) NSDictionary *characterBoxes; +@property (nonatomic, readonly) NSArray *characterBoxes; @property (nonatomic, readonly) NSArray *getConfidenceByWord; @property (nonatomic, readonly) NSArray *getConfidenceBySymbol; diff --git a/Products/TesseractOCR.framework/Versions/A/Resources/Info.plist b/Products/TesseractOCR.framework/Versions/A/Resources/Info.plist index cd853834..ec9000cd 100644 Binary files a/Products/TesseractOCR.framework/Versions/A/Resources/Info.plist and b/Products/TesseractOCR.framework/Versions/A/Resources/Info.plist differ diff --git a/Products/TesseractOCR.framework/Versions/A/TesseractOCR b/Products/TesseractOCR.framework/Versions/A/TesseractOCR index 24dead03..d2f2da5f 100644 Binary files a/Products/TesseractOCR.framework/Versions/A/TesseractOCR and b/Products/TesseractOCR.framework/Versions/A/TesseractOCR differ diff --git a/Template Framework Project/Template Framework Project.xcodeproj/project.pbxproj b/Template Framework Project/Template Framework Project.xcodeproj/project.pbxproj index 512289f0..d2bd50c3 100644 --- a/Template Framework Project/Template Framework Project.xcodeproj/project.pbxproj +++ b/Template Framework Project/Template Framework Project.xcodeproj/project.pbxproj @@ -306,6 +306,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Template Framework Project/Template Framework Project-Prefix.pch"; INFOPLIST_FILE = "Template Framework Project/Template Framework Project-Info.plist"; + ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; @@ -324,6 +325,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Template Framework Project/Template Framework Project-Prefix.pch"; INFOPLIST_FILE = "Template Framework Project/Template Framework Project-Info.plist"; + ONLY_ACTIVE_ARCH = NO; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; diff --git a/Tesseract OCR iOS.xcodeproj/project.pbxproj b/Tesseract OCR iOS.xcodeproj/project.pbxproj index 2a297cc3..cfd56c71 100644 --- a/Tesseract OCR iOS.xcodeproj/project.pbxproj +++ b/Tesseract OCR iOS.xcodeproj/project.pbxproj @@ -787,7 +787,7 @@ 64F74CC1172FD75F0068E657 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0510; + LastUpgradeCheck = 0600; ORGANIZATIONNAME = "Daniele Galiotto - www.g8production.com"; }; buildConfigurationList = 64F74CC4172FD75F0068E657 /* Build configuration list for PBXProject "Tesseract OCR iOS" */; @@ -899,12 +899,12 @@ LINK_WITH_STANDARD_LIBRARIES = NO; MACH_O_TYPE = mh_object; MACOSX_DEPLOYMENT_TARGET = 10.8; - ONLY_ACTIVE_ARCH = NO; + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALID_ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT) x86_64 i386"; + VALID_ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT) i386 x86_64"; WRAPPER_EXTENSION = framework; }; name = Debug; @@ -933,11 +933,12 @@ LINK_WITH_STANDARD_LIBRARIES = NO; MACH_O_TYPE = mh_object; MACOSX_DEPLOYMENT_TARGET = 10.8; + ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALID_ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT) x86_64 i386"; + VALID_ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT) i386 x86_64"; WRAPPER_EXTENSION = framework; }; name = Release; @@ -962,6 +963,7 @@ buildSettings = { DEAD_CODE_STRIPPING = YES; LINK_WITH_STANDARD_LIBRARIES = YES; + ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = ( "-ObjC", "-lstdc++", @@ -996,7 +998,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 5.0; - ONLY_ACTIVE_ARCH = NO; + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "-ObjC", "-lstdc++", diff --git a/TesseractOCR/Tesseract.h b/TesseractOCR/Tesseract.h index 1df7673c..89b47697 100755 --- a/TesseractOCR/Tesseract.h +++ b/TesseractOCR/Tesseract.h @@ -31,7 +31,7 @@ // This NSDictionary uses NSValue encoded CGRects as keys and the recognized character (NSString) as the value // CGRects are in UIKit's coordinate space (origin is in the top left) -@property (nonatomic, readonly) NSDictionary *characterBoxes; +@property (nonatomic, readonly) NSArray *characterBoxes; @property (nonatomic, readonly) NSArray *getConfidenceByWord; @property (nonatomic, readonly) NSArray *getConfidenceBySymbol; diff --git a/TesseractOCR/Tesseract.mm b/TesseractOCR/Tesseract.mm index bc466569..45e4ed98 100755 --- a/TesseractOCR/Tesseract.mm +++ b/TesseractOCR/Tesseract.mm @@ -13,6 +13,7 @@ #import "environ.h" #import "pix.h" #import "ocrclass.h" +#import "allheaders.h" namespace tesseract { class TessBaseAPI; @@ -23,7 +24,8 @@ @interface Tesseract () { NSString* _language; NSMutableDictionary* _variables; tesseract::TessBaseAPI* _tesseract; - const UInt8 *_pixels; + //const UInt8 *_pixels; + Pix *currentPix; ETEXT_DESC *_monitor; } @@ -69,6 +71,9 @@ - (void)dealloc { delete _tesseract; _tesseract = nullptr; } + if (currentPix != nullptr) { + pixDestroy(¤tPix); + } } - (id)initWithDataPath:(NSString *)dataPath language:(NSString *)language { @@ -204,7 +209,7 @@ - (void)setImage:(UIImage *)image { CGImage *cgImage = image.CGImage; CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(cgImage)); - _pixels = CFDataGetBytePtr(data); + const UInt8 *_pixels = CFDataGetBytePtr(data); size_t bitsPerComponent = CGImageGetBitsPerComponent(cgImage); size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage); @@ -215,7 +220,11 @@ - (void)setImage:(UIImage *)image { assert(bytesPerRow < MAX_INT32); { imageThresholder->SetImage(_pixels,width,height,(int)(bitsPerPixel/bitsPerComponent),(int)bytesPerRow); - _tesseract->SetImage(imageThresholder->GetPixRect()); + if (currentPix != nullptr) { + pixDestroy(¤tPix); + } + currentPix = imageThresholder->GetPixRect(); + _tesseract->SetImage(currentPix); } imageThresholder->Clear(); @@ -240,11 +249,15 @@ - (NSString *)recognizedText { return text; } -- (NSDictionary *)characterBoxes { - NSMutableDictionary *recognizedTextBoxes = [NSMutableDictionary dictionary]; +- (NSArray *)characterBoxes { + NSMutableArray *recognizedTextBoxes = [[NSMutableArray alloc] init]; // Get box info char* boxText = _tesseract->GetBoxText(0); + if (!boxText) { + NSLog(@"No boxes recognized. Check that -[Tesseract setImage:] is passed an image bigger than 0x0."); + return nil; + } NSString *stringBoxes = [NSString stringWithUTF8String:boxText]; delete [] boxText; @@ -262,7 +275,10 @@ - (NSDictionary *)characterBoxes { CGFloat width = [boxComponents[3] floatValue] - [boxComponents[1] floatValue]; CGFloat height = [boxComponents[4] floatValue] - [boxComponents[2] floatValue]; CGRect box = CGRectMake(x, y, width, height); - [recognizedTextBoxes setObject:boxComponents[0] forKey:[NSValue valueWithCGRect:box]]; + NSMutableDictionary *resultDict = [[NSMutableDictionary alloc] init]; + resultDict[@"text"] = boxComponents[0]; + resultDict[@"box"] = [NSValue valueWithCGRect:box]; + [recognizedTextBoxes addObject: resultDict]; } } return recognizedTextBoxes; @@ -294,14 +310,15 @@ - (NSArray *)getConfidences:(tesseract::PageIteratorLevel)level { CGRect box = CGRectMake(x, y, width, height); word = ri->GetUTF8Text(level); - conf = ri->Confidence(level); - - [array addObject:@{ - @"text": [NSString stringWithUTF8String:word], - @"confidence": [NSNumber numberWithFloat:conf], - @"boundingbox": [NSValue valueWithCGRect:box] - }]; - + if (word != NULL) { + conf = ri->Confidence(level); + + [array addObject:@{ + @"text": [NSString stringWithUTF8String:word], + @"confidence": [NSNumber numberWithFloat:conf], + @"boundingbox": [NSValue valueWithCGRect:box] + }]; + } delete[] word; } while (ri->Next(level)); } diff --git a/TesseractOCR/include/leptonica/allheaders.h b/TesseractOCR/include/leptonica/allheaders.h old mode 100755 new mode 100644 index 16cc2411..aa850d6c --- a/TesseractOCR/include/leptonica/allheaders.h +++ b/TesseractOCR/include/leptonica/allheaders.h @@ -29,7 +29,7 @@ #define LIBLEPT_MAJOR_VERSION 1 -#define LIBLEPT_MINOR_VERSION 69 +#define LIBLEPT_MINOR_VERSION 70 #include "alltypes.h" @@ -76,7 +76,6 @@ LEPT_DLL extern PIX * pixAffineColor ( PIX *pixs, l_float32 *vc, l_uint32 colorv LEPT_DLL extern PIX * pixAffinePtaGray ( PIX *pixs, PTA *ptad, PTA *ptas, l_uint8 grayval ); LEPT_DLL extern PIX * pixAffineGray ( PIX *pixs, l_float32 *vc, l_uint8 grayval ); LEPT_DLL extern PIX * pixAffinePtaWithAlpha ( PIX *pixs, PTA *ptad, PTA *ptas, PIX *pixg, l_float32 fract, l_int32 border ); -LEPT_DLL extern PIX * pixAffinePtaGammaXform ( PIX *pixs, l_float32 gamma, PTA *ptad, PTA *ptas, l_float32 fract, l_int32 border ); LEPT_DLL extern l_int32 getAffineXformCoeffs ( PTA *ptas, PTA *ptad, l_float32 **pvc ); LEPT_DLL extern l_int32 affineInvertXform ( l_float32 *vc, l_float32 **pvci ); LEPT_DLL extern l_int32 affineXformSampledPt ( l_float32 *vc, l_int32 x, l_int32 y, l_int32 *pxp, l_int32 *pyp ); @@ -100,16 +99,6 @@ LEPT_DLL extern l_int32 l_productMatVec ( l_float32 *mat, l_float32 *vecs, l_flo LEPT_DLL extern l_int32 l_productMat2 ( l_float32 *mat1, l_float32 *mat2, l_float32 *matd, l_int32 size ); LEPT_DLL extern l_int32 l_productMat3 ( l_float32 *mat1, l_float32 *mat2, l_float32 *mat3, l_float32 *matd, l_int32 size ); LEPT_DLL extern l_int32 l_productMat4 ( l_float32 *mat1, l_float32 *mat2, l_float32 *mat3, l_float32 *mat4, l_float32 *matd, l_int32 size ); -LEPT_DLL extern void addConstantGrayLow ( l_uint32 *data, l_int32 w, l_int32 h, l_int32 d, l_int32 wpl, l_int32 val ); -LEPT_DLL extern void multConstantGrayLow ( l_uint32 *data, l_int32 w, l_int32 h, l_int32 d, l_int32 wpl, l_float32 val ); -LEPT_DLL extern void addGrayLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 d, l_int32 wpld, l_uint32 *datas, l_int32 wpls ); -LEPT_DLL extern void subtractGrayLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 d, l_int32 wpld, l_uint32 *datas, l_int32 wpls ); -LEPT_DLL extern void thresholdToValueLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 d, l_int32 wpld, l_int32 threshval, l_int32 setval ); -LEPT_DLL extern void finalAccumulateLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 d, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_uint32 offset ); -LEPT_DLL extern void finalAccumulateThreshLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_uint32 offset, l_uint32 threshold ); -LEPT_DLL extern void accumulateLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas, l_int32 d, l_int32 wpls, l_int32 op ); -LEPT_DLL extern void multConstAccumulateLow ( l_uint32 *data, l_int32 w, l_int32 h, l_int32 wpl, l_float32 factor, l_uint32 offset ); -LEPT_DLL extern void absDifferenceLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas1, l_uint32 *datas2, l_int32 d, l_int32 wpls1, l_int32 wpls2 ); LEPT_DLL extern l_int32 l_getDataBit ( void *line, l_int32 n ); LEPT_DLL extern void l_setDataBit ( void *line, l_int32 n ); LEPT_DLL extern void l_clearDataBit ( void *line, l_int32 n ); @@ -137,10 +126,16 @@ LEPT_DLL extern void bbufferDestroy ( BBUFFER **pbb ); LEPT_DLL extern l_uint8 * bbufferDestroyAndSaveData ( BBUFFER **pbb, size_t *pnbytes ); LEPT_DLL extern l_int32 bbufferRead ( BBUFFER *bb, l_uint8 *src, l_int32 nbytes ); LEPT_DLL extern l_int32 bbufferReadStream ( BBUFFER *bb, FILE *fp, l_int32 nbytes ); -LEPT_DLL extern l_int32 bbufferExtendArray ( BBUFFER *bb, l_int32 nbytes ); LEPT_DLL extern l_int32 bbufferWrite ( BBUFFER *bb, l_uint8 *dest, size_t nbytes, size_t *pnout ); LEPT_DLL extern l_int32 bbufferWriteStream ( BBUFFER *bb, FILE *fp, size_t nbytes, size_t *pnout ); LEPT_DLL extern l_int32 bbufferBytesToWrite ( BBUFFER *bb, size_t *pnbytes ); +LEPT_DLL extern l_int32 bbufferReadStdin ( l_uint8 **pdata, size_t *pnbytes ); +LEPT_DLL extern PIX * pixBilateral ( PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction ); +LEPT_DLL extern PIX * pixBilateralGray ( PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction ); +LEPT_DLL extern PIX * pixBilateralExact ( PIX *pixs, L_KERNEL *spatial_kel, L_KERNEL *range_kel ); +LEPT_DLL extern PIX * pixBilateralGrayExact ( PIX *pixs, L_KERNEL *spatial_kel, L_KERNEL *range_kel ); +LEPT_DLL extern PIX* pixBlockBilateralExact ( PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev ); +LEPT_DLL extern L_KERNEL * makeRangeKernel ( l_float32 range_stdev ); LEPT_DLL extern PIX * pixBilinearSampledPta ( PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor ); LEPT_DLL extern PIX * pixBilinearSampled ( PIX *pixs, l_float32 *vc, l_int32 incolor ); LEPT_DLL extern PIX * pixBilinearPta ( PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor ); @@ -150,7 +145,6 @@ LEPT_DLL extern PIX * pixBilinearColor ( PIX *pixs, l_float32 *vc, l_uint32 colo LEPT_DLL extern PIX * pixBilinearPtaGray ( PIX *pixs, PTA *ptad, PTA *ptas, l_uint8 grayval ); LEPT_DLL extern PIX * pixBilinearGray ( PIX *pixs, l_float32 *vc, l_uint8 grayval ); LEPT_DLL extern PIX * pixBilinearPtaWithAlpha ( PIX *pixs, PTA *ptad, PTA *ptas, PIX *pixg, l_float32 fract, l_int32 border ); -LEPT_DLL extern PIX * pixBilinearPtaGammaXform ( PIX *pixs, l_float32 gamma, PTA *ptad, PTA *ptas, l_float32 fract, l_int32 border ); LEPT_DLL extern l_int32 getBilinearXformCoeffs ( PTA *ptas, PTA *ptad, l_float32 **pvc ); LEPT_DLL extern l_int32 bilinearXformSampledPt ( l_float32 *vc, l_int32 x, l_int32 y, l_int32 *pxp, l_int32 *pyp ); LEPT_DLL extern l_int32 bilinearXformPt ( l_float32 *vc, l_int32 x, l_int32 y, l_float32 *pxp, l_float32 *pyp ); @@ -163,15 +157,9 @@ LEPT_DLL extern PIX * pixSauvolaGetThreshold ( PIX *pixm, PIX *pixms, l_float32 LEPT_DLL extern PIX * pixApplyLocalThreshold ( PIX *pixs, PIX *pixth, l_int32 redfactor ); LEPT_DLL extern PIX * pixExpandBinaryReplicate ( PIX *pixs, l_int32 factor ); LEPT_DLL extern PIX * pixExpandBinaryPower2 ( PIX *pixs, l_int32 factor ); -LEPT_DLL extern l_int32 expandBinaryPower2Low ( l_uint32 *datad, l_int32 wd, l_int32 hd, l_int32 wpld, l_uint32 *datas, l_int32 ws, l_int32 hs, l_int32 wpls, l_int32 factor ); -LEPT_DLL extern l_uint16 * makeExpandTab2x ( void ); -LEPT_DLL extern l_uint32 * makeExpandTab4x ( void ); -LEPT_DLL extern l_uint32 * makeExpandTab8x ( void ); LEPT_DLL extern PIX * pixReduceBinary2 ( PIX *pixs, l_uint8 *intab ); LEPT_DLL extern PIX * pixReduceRankBinaryCascade ( PIX *pixs, l_int32 level1, l_int32 level2, l_int32 level3, l_int32 level4 ); LEPT_DLL extern PIX * pixReduceRankBinary2 ( PIX *pixs, l_int32 level, l_uint8 *intab ); -LEPT_DLL extern void reduceBinary2Low ( l_uint32 *datad, l_int32 wpld, l_uint32 *datas, l_int32 hs, l_int32 wpls, l_uint8 *tab ); -LEPT_DLL extern void reduceRankBinary2Low ( l_uint32 *datad, l_int32 wpld, l_uint32 *datas, l_int32 hs, l_int32 wpls, l_uint8 *tab, l_int32 level ); LEPT_DLL extern l_uint8 * makeSubsampleTab2x ( void ); LEPT_DLL extern PIX * pixBlend ( PIX *pixs1, PIX *pixs2, l_int32 x, l_int32 y, l_float32 fract ); LEPT_DLL extern PIX * pixBlendMask ( PIX *pixd, PIX *pixs1, PIX *pixs2, l_int32 x, l_int32 y, l_float32 fract, l_int32 type ); @@ -187,6 +175,7 @@ LEPT_DLL extern PIX * pixBlendWithGrayMask ( PIX *pixs1, PIX *pixs2, PIX *pixg, LEPT_DLL extern PIX * pixBlendBackgroundToColor ( PIX *pixd, PIX *pixs, BOX *box, l_uint32 color, l_float32 gamma, l_int32 minval, l_int32 maxval ); LEPT_DLL extern PIX * pixMultiplyByColor ( PIX *pixd, PIX *pixs, BOX *box, l_uint32 color ); LEPT_DLL extern PIX * pixAlphaBlendUniform ( PIX *pixs, l_uint32 color ); +LEPT_DLL extern PIX * pixAddAlphaToBlend ( PIX *pixs, l_float32 fract, l_int32 invert ); LEPT_DLL extern PIX * pixSetAlphaOverWhite ( PIX *pixs ); LEPT_DLL extern L_BMF * bmfCreate ( const char *dir, l_int32 size ); LEPT_DLL extern void bmfDestroy ( L_BMF **pbmf ); @@ -207,6 +196,7 @@ LEPT_DLL extern BOX * boxClone ( BOX *box ); LEPT_DLL extern void boxDestroy ( BOX **pbox ); LEPT_DLL extern l_int32 boxGetGeometry ( BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph ); LEPT_DLL extern l_int32 boxSetGeometry ( BOX *box, l_int32 x, l_int32 y, l_int32 w, l_int32 h ); +LEPT_DLL extern l_int32 boxGetSideLocation ( BOX *box, l_int32 side, l_int32 *ploc ); LEPT_DLL extern l_int32 boxGetRefcount ( BOX *box ); LEPT_DLL extern l_int32 boxChangeRefcount ( BOX *box, l_int32 delta ); LEPT_DLL extern l_int32 boxIsValid ( BOX *box, l_int32 *pvalid ); @@ -221,9 +211,11 @@ LEPT_DLL extern l_int32 boxaGetValidCount ( BOXA *boxa ); LEPT_DLL extern BOX * boxaGetBox ( BOXA *boxa, l_int32 index, l_int32 accessflag ); LEPT_DLL extern BOX * boxaGetValidBox ( BOXA *boxa, l_int32 index, l_int32 accessflag ); LEPT_DLL extern l_int32 boxaGetBoxGeometry ( BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph ); +LEPT_DLL extern l_int32 boxaIsFull ( BOXA *boxa, l_int32 *pfull ); LEPT_DLL extern l_int32 boxaReplaceBox ( BOXA *boxa, l_int32 index, BOX *box ); LEPT_DLL extern l_int32 boxaInsertBox ( BOXA *boxa, l_int32 index, BOX *box ); LEPT_DLL extern l_int32 boxaRemoveBox ( BOXA *boxa, l_int32 index ); +LEPT_DLL extern l_int32 boxaRemoveBoxAndSave ( BOXA *boxa, l_int32 index, BOX **pbox ); LEPT_DLL extern l_int32 boxaInitFull ( BOXA *boxa, BOX *box ); LEPT_DLL extern l_int32 boxaClear ( BOXA *boxa ); LEPT_DLL extern BOXAA * boxaaCreate ( l_int32 n ); @@ -242,14 +234,17 @@ LEPT_DLL extern l_int32 boxaaReplaceBoxa ( BOXAA *baa, l_int32 index, BOXA *boxa LEPT_DLL extern l_int32 boxaaInsertBoxa ( BOXAA *baa, l_int32 index, BOXA *boxa ); LEPT_DLL extern l_int32 boxaaRemoveBoxa ( BOXAA *baa, l_int32 index ); LEPT_DLL extern l_int32 boxaaAddBox ( BOXAA *baa, l_int32 index, BOX *box, l_int32 accessflag ); +LEPT_DLL extern BOXAA * boxaaReadFromFiles ( const char *dirname, const char *substr, l_int32 first, l_int32 nfiles ); LEPT_DLL extern BOXAA * boxaaRead ( const char *filename ); LEPT_DLL extern BOXAA * boxaaReadStream ( FILE *fp ); LEPT_DLL extern l_int32 boxaaWrite ( const char *filename, BOXAA *baa ); LEPT_DLL extern l_int32 boxaaWriteStream ( FILE *fp, BOXAA *baa ); LEPT_DLL extern BOXA * boxaRead ( const char *filename ); LEPT_DLL extern BOXA * boxaReadStream ( FILE *fp ); +LEPT_DLL extern BOXA * boxaReadMem ( const l_uint8 *data, size_t size ); LEPT_DLL extern l_int32 boxaWrite ( const char *filename, BOXA *boxa ); LEPT_DLL extern l_int32 boxaWriteStream ( FILE *fp, BOXA *boxa ); +LEPT_DLL extern l_int32 boxaWriteMem ( l_uint8 **pdata, size_t *psize, BOXA *boxa ); LEPT_DLL extern l_int32 boxPrintStreamInfo ( FILE *fp, BOX *box ); LEPT_DLL extern l_int32 boxContains ( BOX *box1, BOX *box2, l_int32 *presult ); LEPT_DLL extern l_int32 boxIntersects ( BOX *box1, BOX *box2, l_int32 *presult ); @@ -260,18 +255,28 @@ LEPT_DLL extern BOXA * boxaCombineOverlaps ( BOXA *boxas ); LEPT_DLL extern BOX * boxOverlapRegion ( BOX *box1, BOX *box2 ); LEPT_DLL extern BOX * boxBoundingRegion ( BOX *box1, BOX *box2 ); LEPT_DLL extern l_int32 boxOverlapFraction ( BOX *box1, BOX *box2, l_float32 *pfract ); +LEPT_DLL extern l_int32 boxOverlapArea ( BOX *box1, BOX *box2, l_int32 *parea ); +LEPT_DLL extern BOXA * boxaHandleOverlaps ( BOXA *boxas, l_int32 op, l_int32 range, l_float32 min_overlap, l_float32 max_ratio, NUMA **pnamap ); +LEPT_DLL extern l_int32 boxSeparationDistance ( BOX *box1, BOX *box2, l_int32 *ph_sep, l_int32 *pv_sep ); LEPT_DLL extern l_int32 boxContainsPt ( BOX *box, l_float32 x, l_float32 y, l_int32 *pcontains ); LEPT_DLL extern BOX * boxaGetNearestToPt ( BOXA *boxa, l_int32 x, l_int32 y ); LEPT_DLL extern l_int32 boxGetCenter ( BOX *box, l_float32 *pcx, l_float32 *pcy ); LEPT_DLL extern l_int32 boxIntersectByLine ( BOX *box, l_int32 x, l_int32 y, l_float32 slope, l_int32 *px1, l_int32 *py1, l_int32 *px2, l_int32 *py2, l_int32 *pn ); LEPT_DLL extern BOX * boxClipToRectangle ( BOX *box, l_int32 wi, l_int32 hi ); +LEPT_DLL extern l_int32 boxClipToRectangleParams ( BOX *box, l_int32 w, l_int32 h, l_int32 *pxstart, l_int32 *pystart, l_int32 *pxend, l_int32 *pyend, l_int32 *pbw, l_int32 *pbh ); LEPT_DLL extern BOX * boxRelocateOneSide ( BOX *boxd, BOX *boxs, l_int32 loc, l_int32 sideflag ); LEPT_DLL extern BOX * boxAdjustSides ( BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot ); +LEPT_DLL extern BOXA * boxaSetSide ( BOXA *boxad, BOXA *boxas, l_int32 side, l_int32 val, l_int32 thresh ); +LEPT_DLL extern BOXA * boxaAdjustWidthToTarget ( BOXA *boxad, BOXA *boxas, l_int32 sides, l_int32 target, l_int32 thresh ); +LEPT_DLL extern BOXA * boxaAdjustHeightToTarget ( BOXA *boxad, BOXA *boxas, l_int32 sides, l_int32 target, l_int32 thresh ); LEPT_DLL extern l_int32 boxEqual ( BOX *box1, BOX *box2, l_int32 *psame ); LEPT_DLL extern l_int32 boxaEqual ( BOXA *boxa1, BOXA *boxa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame ); +LEPT_DLL extern l_int32 boxSimilar ( BOX *box1, BOX *box2, l_int32 leftdiff, l_int32 rightdiff, l_int32 topdiff, l_int32 botdiff, l_int32 *psimilar ); +LEPT_DLL extern l_int32 boxaSimilar ( BOXA *boxa1, BOXA *boxa2, l_int32 leftdiff, l_int32 rightdiff, l_int32 topdiff, l_int32 botdiff, l_int32 debugflag, l_int32 *psimilar ); LEPT_DLL extern l_int32 boxaJoin ( BOXA *boxad, BOXA *boxas, l_int32 istart, l_int32 iend ); -LEPT_DLL extern l_int32 boxaSplitEvenOdd ( BOXA *boxa, BOXA **pboxae, BOXA **pboxao ); -LEPT_DLL extern BOXA * boxaMergeEvenOdd ( BOXA *boxae, BOXA *boxao ); +LEPT_DLL extern l_int32 boxaaJoin ( BOXAA *baad, BOXAA *baas, l_int32 istart, l_int32 iend ); +LEPT_DLL extern l_int32 boxaSplitEvenOdd ( BOXA *boxa, l_int32 fillflag, BOXA **pboxae, BOXA **pboxao ); +LEPT_DLL extern BOXA * boxaMergeEvenOdd ( BOXA *boxae, BOXA *boxao, l_int32 fillflag ); LEPT_DLL extern BOXA * boxaTransform ( BOXA *boxas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley ); LEPT_DLL extern BOX * boxTransform ( BOX *box, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley ); LEPT_DLL extern BOXA * boxaTransformOrdered ( BOXA *boxas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 order ); @@ -287,9 +292,9 @@ LEPT_DLL extern l_int32 boxaExtractAsNuma ( BOXA *boxa, NUMA **pnax, NUMA **pnay LEPT_DLL extern l_int32 boxaExtractAsPta ( BOXA *boxa, PTA **pptal, PTA **pptat, PTA **pptar, PTA **pptab, l_int32 keepinvalid ); LEPT_DLL extern BOX * boxaGetRankSize ( BOXA *boxa, l_float32 fract ); LEPT_DLL extern BOX * boxaGetMedian ( BOXA *boxa ); -LEPT_DLL extern l_int32 boxaaGetExtent ( BOXAA *boxaa, l_int32 *pw, l_int32 *ph, BOX **pbox ); +LEPT_DLL extern l_int32 boxaaGetExtent ( BOXAA *baa, l_int32 *pw, l_int32 *ph, BOX **pbox, BOXA **pboxa ); LEPT_DLL extern BOXA * boxaaFlattenToBoxa ( BOXAA *baa, NUMA **pnaindex, l_int32 copyflag ); -LEPT_DLL extern BOXA * boxaaFlattenAligned ( BOXAA *baa, l_int32 num, l_int32 copyflag ); +LEPT_DLL extern BOXA * boxaaFlattenAligned ( BOXAA *baa, l_int32 num, BOX *fillerbox, l_int32 copyflag ); LEPT_DLL extern BOXAA * boxaEncapsulateAligned ( BOXA *boxa, l_int32 num, l_int32 copyflag ); LEPT_DLL extern l_int32 boxaaAlignBox ( BOXAA *baa, BOX *box, l_int32 delta, l_int32 *pindex ); LEPT_DLL extern PIX * pixMaskConnComp ( PIX *pixs, l_int32 connectivity, BOXA **pboxa ); @@ -300,11 +305,16 @@ LEPT_DLL extern PIX * pixPaintBoxaRandom ( PIX *pixs, BOXA *boxa ); LEPT_DLL extern PIX * pixBlendBoxaRandom ( PIX *pixs, BOXA *boxa, l_float32 fract ); LEPT_DLL extern PIX * pixDrawBoxa ( PIX *pixs, BOXA *boxa, l_int32 width, l_uint32 val ); LEPT_DLL extern PIX * pixDrawBoxaRandom ( PIX *pixs, BOXA *boxa, l_int32 width ); -LEPT_DLL extern PIX * boxaaDisplay ( BOXAA *boxaa, l_int32 linewba, l_int32 linewb, l_uint32 colorba, l_uint32 colorb, l_int32 w, l_int32 h ); +LEPT_DLL extern PIX * boxaaDisplay ( BOXAA *baa, l_int32 linewba, l_int32 linewb, l_uint32 colorba, l_uint32 colorb, l_int32 w, l_int32 h ); LEPT_DLL extern BOXA * pixSplitIntoBoxa ( PIX *pixs, l_int32 minsum, l_int32 skipdist, l_int32 delta, l_int32 maxbg, l_int32 maxcomps, l_int32 remainder ); LEPT_DLL extern BOXA * pixSplitComponentIntoBoxa ( PIX *pix, BOX *box, l_int32 minsum, l_int32 skipdist, l_int32 delta, l_int32 maxbg, l_int32 maxcomps, l_int32 remainder ); +LEPT_DLL extern l_int32 boxaCompareRegions ( BOXA *boxa1, BOXA *boxa2, l_int32 areathresh, l_int32 *pnsame, l_float32 *pdiffarea, l_float32 *pdiffxor, PIX **ppixdb ); +LEPT_DLL extern BOXA * boxaSelectRange ( BOXA *boxas, l_int32 first, l_int32 last, l_int32 copyflag ); +LEPT_DLL extern BOXAA * boxaaSelectRange ( BOXAA *baas, l_int32 first, l_int32 last, l_int32 copyflag ); LEPT_DLL extern BOXA * boxaSelectBySize ( BOXA *boxas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged ); LEPT_DLL extern NUMA * boxaMakeSizeIndicator ( BOXA *boxa, l_int32 width, l_int32 height, l_int32 type, l_int32 relation ); +LEPT_DLL extern BOXA * boxaSelectByArea ( BOXA *boxas, l_int32 area, l_int32 relation, l_int32 *pchanged ); +LEPT_DLL extern NUMA * boxaMakeAreaIndicator ( BOXA *boxa, l_int32 area, l_int32 relation ); LEPT_DLL extern BOXA * boxaSelectWithIndicator ( BOXA *boxas, NUMA *na, l_int32 *pchanged ); LEPT_DLL extern BOXA * boxaPermutePseudorandom ( BOXA *boxas ); LEPT_DLL extern BOXA * boxaPermuteRandom ( BOXA *boxad, BOXA *boxas ); @@ -314,11 +324,15 @@ LEPT_DLL extern BOXA * ptaConvertToBoxa ( PTA *pta, l_int32 ncorners ); LEPT_DLL extern BOXA * boxaSmoothSequence ( BOXA *boxas, l_float32 factor, l_int32 max_error, l_int32 debug ); LEPT_DLL extern BOXA * boxaLinearFit ( BOXA *boxas, l_float32 factor, l_int32 max_error, l_int32 debug ); LEPT_DLL extern BOXA * boxaConstrainSize ( BOXA *boxas, l_int32 width, l_int32 widthflag, l_int32 height, l_int32 heightflag ); +LEPT_DLL extern BOXA * boxaReconcileEvenOddHeight ( BOXA *boxas, l_int32 sides, l_int32 delh, l_int32 op, l_float32 factor ); LEPT_DLL extern l_int32 boxaPlotSides ( BOXA *boxa, const char *plotname, NUMA **pnal, NUMA **pnat, NUMA **pnar, NUMA **pnab, l_int32 outformat ); LEPT_DLL extern l_int32 boxaGetExtent ( BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox ); LEPT_DLL extern l_int32 boxaGetCoverage ( BOXA *boxa, l_int32 wc, l_int32 hc, l_int32 exactflag, l_float32 *pfract ); +LEPT_DLL extern l_int32 boxaaSizeRange ( BOXAA *baa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh ); LEPT_DLL extern l_int32 boxaSizeRange ( BOXA *boxa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh ); LEPT_DLL extern l_int32 boxaLocationRange ( BOXA *boxa, l_int32 *pminx, l_int32 *pminy, l_int32 *pmaxx, l_int32 *pmaxy ); +LEPT_DLL extern l_int32 boxaGetArea ( BOXA *boxa, l_int32 *parea ); +LEPT_DLL extern PIX * boxaDisplayTiled ( BOXA *boxa, PIXA *pixa, l_int32 maxwidth, l_int32 linewidth, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border, const char *fontdir ); LEPT_DLL extern L_BYTEA * l_byteaCreate ( size_t nbytes ); LEPT_DLL extern L_BYTEA * l_byteaInitFromMem ( l_uint8 *data, size_t size ); LEPT_DLL extern L_BYTEA * l_byteaInitFromFile ( const char *fname ); @@ -330,7 +344,6 @@ LEPT_DLL extern l_uint8 * l_byteaGetData ( L_BYTEA *ba, size_t *psize ); LEPT_DLL extern l_uint8 * l_byteaCopyData ( L_BYTEA *ba, size_t *psize ); LEPT_DLL extern l_int32 l_byteaAppendData ( L_BYTEA *ba, l_uint8 *newdata, size_t newbytes ); LEPT_DLL extern l_int32 l_byteaAppendString ( L_BYTEA *ba, char *str ); -LEPT_DLL extern l_int32 l_byteaExtendArrayToSize ( L_BYTEA *ba, size_t size ); LEPT_DLL extern l_int32 l_byteaJoin ( L_BYTEA *ba1, L_BYTEA **pba2 ); LEPT_DLL extern l_int32 l_byteaSplit ( L_BYTEA *ba1, size_t splitloc, L_BYTEA **pba2 ); LEPT_DLL extern l_int32 l_byteaFindEachSequence ( L_BYTEA *ba, l_uint8 *sequence, l_int32 seqlen, L_DNA **pda ); @@ -341,7 +354,6 @@ LEPT_DLL extern void ccbaDestroy ( CCBORDA **pccba ); LEPT_DLL extern CCBORD * ccbCreate ( PIX *pixs ); LEPT_DLL extern void ccbDestroy ( CCBORD **pccb ); LEPT_DLL extern l_int32 ccbaAddCcb ( CCBORDA *ccba, CCBORD *ccb ); -LEPT_DLL extern l_int32 ccbaExtendArray ( CCBORDA *ccba ); LEPT_DLL extern l_int32 ccbaGetCount ( CCBORDA *ccba ); LEPT_DLL extern CCBORD * ccbaGetCcb ( CCBORDA *ccba, l_int32 index ); LEPT_DLL extern CCBORDA * pixGetAllCCBorders ( PIX *pixs ); @@ -385,6 +397,12 @@ LEPT_DLL extern l_int32 pixColorFraction ( PIX *pixs, l_int32 darkthresh, l_int3 LEPT_DLL extern l_int32 pixNumSignificantGrayColors ( PIX *pixs, l_int32 darkthresh, l_int32 lightthresh, l_float32 minfract, l_int32 factor, l_int32 *pncolors ); LEPT_DLL extern l_int32 pixColorsForQuantization ( PIX *pixs, l_int32 thresh, l_int32 *pncolors, l_int32 *piscolor, l_int32 debug ); LEPT_DLL extern l_int32 pixNumColors ( PIX *pixs, l_int32 factor, l_int32 *pncolors ); +LEPT_DLL extern l_int32 pixGetMostPopulatedColors ( PIX *pixs, l_int32 sigbits, l_int32 factor, l_int32 ncolors, l_uint32 **parray, PIXCMAP **pcmap ); +LEPT_DLL extern PIX * pixSimpleColorQuantize ( PIX *pixs, l_int32 sigbits, l_int32 factor, l_int32 ncolors ); +LEPT_DLL extern NUMA * pixGetRGBHistogram ( PIX *pixs, l_int32 sigbits, l_int32 factor ); +LEPT_DLL extern l_int32 makeRGBIndexTables ( l_uint32 **prtab, l_uint32 **pgtab, l_uint32 **pbtab, l_int32 sigbits ); +LEPT_DLL extern l_int32 getRGBFromIndex ( l_uint32 index, l_int32 sigbits, l_int32 *prval, l_int32 *pgval, l_int32 *pbval ); +LEPT_DLL extern PIX * pixColorGrayRegions ( PIX *pixs, BOXA *boxa, l_int32 type, l_int32 thresh, l_int32 rval, l_int32 gval, l_int32 bval ); LEPT_DLL extern l_int32 pixColorGray ( PIX *pixs, BOX *box, l_int32 type, l_int32 thresh, l_int32 rval, l_int32 gval, l_int32 bval ); LEPT_DLL extern PIX * pixSnapColor ( PIX *pixd, PIX *pixs, l_uint32 srcval, l_uint32 dstval, l_int32 diff ); LEPT_DLL extern PIX * pixSnapColorCmap ( PIX *pixd, PIX *pixs, l_uint32 srcval, l_uint32 dstval, l_int32 diff ); @@ -399,6 +417,7 @@ LEPT_DLL extern PIXCMAP * pixcmapCreateLinear ( l_int32 d, l_int32 nlevels ); LEPT_DLL extern PIXCMAP * pixcmapCopy ( PIXCMAP *cmaps ); LEPT_DLL extern void pixcmapDestroy ( PIXCMAP **pcmap ); LEPT_DLL extern l_int32 pixcmapAddColor ( PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval ); +LEPT_DLL extern l_int32 pixcmapAddRGBA ( PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval ); LEPT_DLL extern l_int32 pixcmapAddNewColor ( PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex ); LEPT_DLL extern l_int32 pixcmapAddNearestColor ( PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex ); LEPT_DLL extern l_int32 pixcmapUsableColor ( PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pusable ); @@ -411,9 +430,12 @@ LEPT_DLL extern l_int32 pixcmapGetMinDepth ( PIXCMAP *cmap, l_int32 *pmindepth ) LEPT_DLL extern l_int32 pixcmapClear ( PIXCMAP *cmap ); LEPT_DLL extern l_int32 pixcmapGetColor ( PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval ); LEPT_DLL extern l_int32 pixcmapGetColor32 ( PIXCMAP *cmap, l_int32 index, l_uint32 *pval32 ); +LEPT_DLL extern l_int32 pixcmapGetRGBA ( PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval, l_int32 *paval ); +LEPT_DLL extern l_int32 pixcmapGetRGBA32 ( PIXCMAP *cmap, l_int32 index, l_uint32 *pval32 ); LEPT_DLL extern l_int32 pixcmapResetColor ( PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval ); LEPT_DLL extern l_int32 pixcmapGetIndex ( PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex ); LEPT_DLL extern l_int32 pixcmapHasColor ( PIXCMAP *cmap, l_int32 *pcolor ); +LEPT_DLL extern l_int32 pixcmapIsOpaque ( PIXCMAP *cmap, l_int32 *popaque ); LEPT_DLL extern l_int32 pixcmapCountGrayColors ( PIXCMAP *cmap, l_int32 *pngray ); LEPT_DLL extern l_int32 pixcmapGetRankIntensity ( PIXCMAP *cmap, l_float32 rankval, l_int32 *pindex ); LEPT_DLL extern l_int32 pixcmapGetNearestIndex ( PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex ); @@ -424,11 +446,11 @@ LEPT_DLL extern PIXCMAP * pixcmapGrayToColor ( l_uint32 color ); LEPT_DLL extern PIXCMAP * pixcmapColorToGray ( PIXCMAP *cmaps, l_float32 rwt, l_float32 gwt, l_float32 bwt ); LEPT_DLL extern PIXCMAP * pixcmapReadStream ( FILE *fp ); LEPT_DLL extern l_int32 pixcmapWriteStream ( FILE *fp, PIXCMAP *cmap ); -LEPT_DLL extern l_int32 pixcmapToArrays ( PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap ); +LEPT_DLL extern l_int32 pixcmapToArrays ( PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap, l_int32 **pamap ); LEPT_DLL extern l_int32 pixcmapToRGBTable ( PIXCMAP *cmap, l_uint32 **ptab, l_int32 *pncolors ); -LEPT_DLL extern l_int32 pixcmapSerializeToMemory ( PIXCMAP *cmap, l_int32 cpc, l_int32 *pncolors, l_uint8 **pdata, l_int32 *pnbytes ); -LEPT_DLL extern PIXCMAP * pixcmapDeserializeFromMemory ( l_uint8 *data, l_int32 ncolors, l_int32 nbytes ); -LEPT_DLL extern char * pixcmapConvertToHex ( l_uint8 *data, l_int32 nbytes, l_int32 ncolors ); +LEPT_DLL extern l_int32 pixcmapSerializeToMemory ( PIXCMAP *cmap, l_int32 cpc, l_int32 *pncolors, l_uint8 **pdata ); +LEPT_DLL extern PIXCMAP * pixcmapDeserializeFromMemory ( l_uint8 *data, l_int32 cpc, l_int32 ncolors ); +LEPT_DLL extern char * pixcmapConvertToHex ( l_uint8 *data, l_int32 ncolors ); LEPT_DLL extern l_int32 pixcmapGammaTRC ( PIXCMAP *cmap, l_float32 gamma, l_int32 minval, l_int32 maxval ); LEPT_DLL extern l_int32 pixcmapContrastTRC ( PIXCMAP *cmap, l_float32 factor ); LEPT_DLL extern l_int32 pixcmapShiftIntensity ( PIXCMAP *cmap, l_float32 fraction ); @@ -487,6 +509,7 @@ LEPT_DLL extern l_int32 convertYUVToRGB ( l_int32 yval, l_int32 uval, l_int32 vv LEPT_DLL extern l_int32 pixcmapConvertRGBToYUV ( PIXCMAP *cmap ); LEPT_DLL extern l_int32 pixcmapConvertYUVToRGB ( PIXCMAP *cmap ); LEPT_DLL extern l_int32 pixEqual ( PIX *pix1, PIX *pix2, l_int32 *psame ); +LEPT_DLL extern l_int32 pixEqualWithAlpha ( PIX *pix1, PIX *pix2, l_int32 use_alpha, l_int32 *psame ); LEPT_DLL extern l_int32 pixEqualWithCmap ( PIX *pix1, PIX *pix2, l_int32 *psame ); LEPT_DLL extern l_int32 pixUsesCmapColor ( PIX *pixs, l_int32 *pcolor ); LEPT_DLL extern l_int32 pixCorrelationBinary ( PIX *pix1, PIX *pix2, l_float32 *pval ); @@ -500,8 +523,10 @@ LEPT_DLL extern NUMA * pixCompareRankDifference ( PIX *pix1, PIX *pix2, l_int32 LEPT_DLL extern l_int32 pixTestForSimilarity ( PIX *pix1, PIX *pix2, l_int32 factor, l_int32 mindiff, l_float32 maxfract, l_float32 maxave, l_int32 *psimilar, l_int32 printstats ); LEPT_DLL extern l_int32 pixGetDifferenceStats ( PIX *pix1, PIX *pix2, l_int32 factor, l_int32 mindiff, l_float32 *pfractdiff, l_float32 *pavediff, l_int32 printstats ); LEPT_DLL extern NUMA * pixGetDifferenceHistogram ( PIX *pix1, PIX *pix2, l_int32 factor ); +LEPT_DLL extern l_int32 pixGetPerceptualDiff ( PIX *pixs1, PIX *pixs2, l_int32 sampling, l_int32 dilation, l_int32 mindiff, l_float32 *pfract, PIX **ppixdiff1, PIX **ppixdiff2 ); LEPT_DLL extern l_int32 pixGetPSNR ( PIX *pix1, PIX *pix2, l_int32 factor, l_float32 *ppsnr ); LEPT_DLL extern l_int32 pixCompareWithTranslation ( PIX *pix1, PIX *pix2, l_int32 thresh, l_int32 *pdelx, l_int32 *pdely, l_float32 *pscore, l_int32 debugflag ); +LEPT_DLL extern l_int32 pixBestCorrelation ( PIX *pix1, PIX *pix2, l_int32 area1, l_int32 area2, l_int32 etransx, l_int32 etransy, l_int32 maxshift, l_int32 *tab8, l_int32 *pdelx, l_int32 *pdely, l_float32 *pscore, l_int32 debugflag ); LEPT_DLL extern BOXA * pixConnComp ( PIX *pixs, PIXA **ppixa, l_int32 connectivity ); LEPT_DLL extern BOXA * pixConnCompPixa ( PIX *pixs, PIXA **ppixa, l_int32 connectivity ); LEPT_DLL extern BOXA * pixConnCompBB ( PIX *pixs, l_int32 connectivity ); @@ -535,41 +560,28 @@ LEPT_DLL extern PIX * pixConvolveRGB ( PIX *pixs, L_KERNEL *kel ); LEPT_DLL extern PIX * pixConvolveRGBSep ( PIX *pixs, L_KERNEL *kelx, L_KERNEL *kely ); LEPT_DLL extern FPIX * fpixConvolve ( FPIX *fpixs, L_KERNEL *kel, l_int32 normflag ); LEPT_DLL extern FPIX * fpixConvolveSep ( FPIX *fpixs, L_KERNEL *kelx, L_KERNEL *kely, l_int32 normflag ); +LEPT_DLL extern PIX * pixConvolveWithBias ( PIX *pixs, L_KERNEL *kel1, L_KERNEL *kel2, l_int32 force8, l_int32 *pbias ); LEPT_DLL extern void l_setConvolveSampling ( l_int32 xfact, l_int32 yfact ); +LEPT_DLL extern PIX * pixAddGaussianNoise ( PIX *pixs, l_float32 stdev ); +LEPT_DLL extern l_float32 gaussDistribSampling ( ); LEPT_DLL extern void blockconvLow ( l_uint32 *data, l_int32 w, l_int32 h, l_int32 wpl, l_uint32 *dataa, l_int32 wpla, l_int32 wc, l_int32 hc ); LEPT_DLL extern void blockconvAccumLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas, l_int32 d, l_int32 wpls ); LEPT_DLL extern void blocksumLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpl, l_uint32 *dataa, l_int32 wpla, l_int32 wc, l_int32 hc ); -LEPT_DLL extern l_float32 pixCorrelationScore ( PIX *pix1, PIX *pix2, l_int32 area1, l_int32 area2, l_float32 delx, l_float32 dely, l_int32 maxdiffw, l_int32 maxdiffh, l_int32 *tab ); +LEPT_DLL extern l_int32 pixCorrelationScore ( PIX *pix1, PIX *pix2, l_int32 area1, l_int32 area2, l_float32 delx, l_float32 dely, l_int32 maxdiffw, l_int32 maxdiffh, l_int32 *tab, l_float32 *pscore ); LEPT_DLL extern l_int32 pixCorrelationScoreThresholded ( PIX *pix1, PIX *pix2, l_int32 area1, l_int32 area2, l_float32 delx, l_float32 dely, l_int32 maxdiffw, l_int32 maxdiffh, l_int32 *tab, l_int32 *downcount, l_float32 score_threshold ); -LEPT_DLL extern l_float32 pixCorrelationScoreSimple ( PIX *pix1, PIX *pix2, l_int32 area1, l_int32 area2, l_float32 delx, l_float32 dely, l_int32 maxdiffw, l_int32 maxdiffh, l_int32 *tab ); -LEPT_DLL extern l_float32 pixCorrelationScoreShifted ( PIX *pix1, PIX *pix2, l_int32 area1, l_int32 area2, l_int32 delx, l_int32 dely, l_int32 *tab ); -LEPT_DLL extern l_int32 pixBestCorrelation ( PIX *pix1, PIX *pix2, l_int32 area1, l_int32 area2, l_int32 etransx, l_int32 etransy, l_int32 maxshift, l_int32 *tab8, l_int32 *pdelx, l_int32 *pdely, l_float32 *pscore, l_int32 debugflag ); +LEPT_DLL extern l_int32 pixCorrelationScoreSimple ( PIX *pix1, PIX *pix2, l_int32 area1, l_int32 area2, l_float32 delx, l_float32 dely, l_int32 maxdiffw, l_int32 maxdiffh, l_int32 *tab, l_float32 *pscore ); +LEPT_DLL extern l_int32 pixCorrelationScoreShifted ( PIX *pix1, PIX *pix2, l_int32 area1, l_int32 area2, l_int32 delx, l_int32 dely, l_int32 *tab, l_float32 *pscore ); LEPT_DLL extern L_DEWARP * dewarpCreate ( PIX *pixs, l_int32 pageno ); -LEPT_DLL extern L_DEWARP * dewarpCreateReference ( l_int32 pageno, l_int32 refpage ); +LEPT_DLL extern L_DEWARP * dewarpCreateRef ( l_int32 pageno, l_int32 refpage ); LEPT_DLL extern void dewarpDestroy ( L_DEWARP **pdew ); LEPT_DLL extern L_DEWARPA * dewarpaCreate ( l_int32 nptrs, l_int32 sampling, l_int32 redfactor, l_int32 minlines, l_int32 maxdist ); -LEPT_DLL extern L_DEWARPA * dewarpaCreateFromPixacomp ( PIXAC *pixac, l_int32 sampling, l_int32 minlines, l_int32 maxdist ); +LEPT_DLL extern L_DEWARPA * dewarpaCreateFromPixacomp ( PIXAC *pixac, l_int32 useboth, l_int32 sampling, l_int32 minlines, l_int32 maxdist ); LEPT_DLL extern void dewarpaDestroy ( L_DEWARPA **pdewa ); LEPT_DLL extern l_int32 dewarpaDestroyDewarp ( L_DEWARPA *dewa, l_int32 pageno ); LEPT_DLL extern l_int32 dewarpaInsertDewarp ( L_DEWARPA *dewa, L_DEWARP *dew ); -LEPT_DLL extern l_int32 dewarpaExtendArrayToSize ( L_DEWARPA *dewa, l_int32 size ); -LEPT_DLL extern l_int32 dewarpBuildModel ( L_DEWARP *dew, const char *debugfile ); -LEPT_DLL extern l_int32 dewarpFindVertDisparity ( L_DEWARP *dew, PTAA *ptaa ); -LEPT_DLL extern l_int32 dewarpFindHorizDisparity ( L_DEWARP *dew, PTAA *ptaa ); -LEPT_DLL extern PTAA * dewarpGetTextlineCenters ( PIX *pixs, l_int32 debugflag ); -LEPT_DLL extern PTAA * dewarpRemoveShortLines ( PIX *pixs, PTAA *ptaas, l_float32 fract, l_int32 debugflag ); -LEPT_DLL extern l_int32 dewarpaApplyDisparity ( L_DEWARPA *dewa, l_int32 pageno, PIX *pixs, const char *debugfile ); -LEPT_DLL extern l_int32 dewarpMinimize ( L_DEWARP *dew ); -LEPT_DLL extern l_int32 dewarpPopulateFullRes ( L_DEWARP *dew, PIX *pix ); LEPT_DLL extern L_DEWARP * dewarpaGetDewarp ( L_DEWARPA *dewa, l_int32 index ); -LEPT_DLL extern PIX * dewarpaGetResult ( L_DEWARPA *dewa, l_int32 index ); -LEPT_DLL extern PIX * dewarpGetResult ( L_DEWARP *dew ); -LEPT_DLL extern l_int32 dewarpaListPages ( L_DEWARPA *dewa ); -LEPT_DLL extern l_int32 dewarpaSetValidModels ( L_DEWARPA *dewa, l_int32 debug ); -LEPT_DLL extern l_int32 dewarpaInsertRefModels ( L_DEWARPA *dewa, l_int32 debug ); -LEPT_DLL extern l_int32 dewarpaStripRefModels ( L_DEWARPA *dewa ); -LEPT_DLL extern l_int32 dewarpaSetCurvatures ( L_DEWARPA *dewa, l_int32 min_medcurv, l_int32 max_medcurv, l_int32 max_leftcurv, l_int32 max_rightcurv ); -LEPT_DLL extern l_int32 dewarpaUseFullModel ( L_DEWARPA *dewa, l_int32 fullmodel ); +LEPT_DLL extern l_int32 dewarpaSetCurvatures ( L_DEWARPA *dewa, l_int32 max_linecurv, l_int32 min_diff_linecurv, l_int32 max_diff_linecurv, l_int32 max_edgecurv, l_int32 max_diff_edgecurv ); +LEPT_DLL extern l_int32 dewarpaUseBothArrays ( L_DEWARPA *dewa, l_int32 useboth ); LEPT_DLL extern l_int32 dewarpaSetMaxDistance ( L_DEWARPA *dewa, l_int32 maxdist ); LEPT_DLL extern L_DEWARP * dewarpRead ( const char *filename ); LEPT_DLL extern L_DEWARP * dewarpReadStream ( FILE *fp ); @@ -579,8 +591,24 @@ LEPT_DLL extern L_DEWARPA * dewarpaRead ( const char *filename ); LEPT_DLL extern L_DEWARPA * dewarpaReadStream ( FILE *fp ); LEPT_DLL extern l_int32 dewarpaWrite ( const char *filename, L_DEWARPA *dewa ); LEPT_DLL extern l_int32 dewarpaWriteStream ( FILE *fp, L_DEWARPA *dewa ); +LEPT_DLL extern l_int32 dewarpBuildPageModel ( L_DEWARP *dew, const char *debugfile ); +LEPT_DLL extern l_int32 dewarpFindVertDisparity ( L_DEWARP *dew, PTAA *ptaa, l_int32 rotflag ); +LEPT_DLL extern l_int32 dewarpFindHorizDisparity ( L_DEWARP *dew, PTAA *ptaa ); +LEPT_DLL extern PTAA * dewarpGetTextlineCenters ( PIX *pixs, l_int32 debugflag ); +LEPT_DLL extern PTAA * dewarpRemoveShortLines ( PIX *pixs, PTAA *ptaas, l_float32 fract, l_int32 debugflag ); +LEPT_DLL extern l_int32 dewarpBuildLineModel ( L_DEWARP *dew, l_int32 opensize, const char *debugfile ); +LEPT_DLL extern l_int32 dewarpaModelStatus ( L_DEWARPA *dewa, l_int32 pageno, l_int32 *pvsuccess, l_int32 *phsuccess ); +LEPT_DLL extern l_int32 dewarpaApplyDisparity ( L_DEWARPA *dewa, l_int32 pageno, PIX *pixs, l_int32 grayin, l_int32 x, l_int32 y, PIX **ppixd, const char *debugfile ); +LEPT_DLL extern l_int32 dewarpMinimize ( L_DEWARP *dew ); +LEPT_DLL extern l_int32 dewarpPopulateFullRes ( L_DEWARP *dew, PIX *pix, l_int32 x, l_int32 y ); +LEPT_DLL extern l_int32 dewarpSinglePage ( PIX *pixs, l_int32 thresh, l_int32 adaptive, l_int32 both, PIX **ppixd, L_DEWARPA **pdewa, l_int32 debug ); +LEPT_DLL extern l_int32 dewarpaListPages ( L_DEWARPA *dewa ); +LEPT_DLL extern l_int32 dewarpaSetValidModels ( L_DEWARPA *dewa, l_int32 notests, l_int32 debug ); +LEPT_DLL extern l_int32 dewarpaInsertRefModels ( L_DEWARPA *dewa, l_int32 notests, l_int32 debug ); +LEPT_DLL extern l_int32 dewarpaStripRefModels ( L_DEWARPA *dewa ); +LEPT_DLL extern l_int32 dewarpaRestoreModels ( L_DEWARPA *dewa ); LEPT_DLL extern l_int32 dewarpaInfo ( FILE *fp, L_DEWARPA *dewa ); -LEPT_DLL extern l_int32 dewarpaModelStats ( L_DEWARPA *dewa, l_int32 *pnnone, l_int32 *pnactual, l_int32 *pnvalid, l_int32 *pnref ); +LEPT_DLL extern l_int32 dewarpaModelStats ( L_DEWARPA *dewa, l_int32 *pnnone, l_int32 *pnvsuccess, l_int32 *pnvvalid, l_int32 *pnhsuccess, l_int32 *pnhvalid, l_int32 *pnref ); LEPT_DLL extern l_int32 dewarpaShowArrays ( L_DEWARPA *dewa, l_float32 scalefact, l_int32 first, l_int32 last ); LEPT_DLL extern l_int32 dewarpDebug ( L_DEWARP *dew, const char *subdir, l_int32 index ); LEPT_DLL extern l_int32 dewarpShowResults ( L_DEWARPA *dewa, SARRAY *sa, BOXA *boxa, l_int32 firstpage, l_int32 lastpage, const char *pdfout ); @@ -593,7 +621,6 @@ LEPT_DLL extern L_DNA * l_dnaCopy ( L_DNA *da ); LEPT_DLL extern L_DNA * l_dnaClone ( L_DNA *da ); LEPT_DLL extern l_int32 l_dnaEmpty ( L_DNA *da ); LEPT_DLL extern l_int32 l_dnaAddNumber ( L_DNA *da, l_float64 val ); -LEPT_DLL extern l_int32 l_dnaExtendArray ( L_DNA *da ); LEPT_DLL extern l_int32 l_dnaInsertNumber ( L_DNA *da, l_int32 index, l_float64 val ); LEPT_DLL extern l_int32 l_dnaRemoveNumber ( L_DNA *da, l_int32 index ); LEPT_DLL extern l_int32 l_dnaReplaceNumber ( L_DNA *da, l_int32 index, l_float64 val ); @@ -607,9 +634,9 @@ LEPT_DLL extern l_int32 * l_dnaGetIArray ( L_DNA *da ); LEPT_DLL extern l_float64 * l_dnaGetDArray ( L_DNA *da, l_int32 copyflag ); LEPT_DLL extern l_int32 l_dnaGetRefcount ( L_DNA *da ); LEPT_DLL extern l_int32 l_dnaChangeRefcount ( L_DNA *da, l_int32 delta ); -LEPT_DLL extern l_int32 l_dnaGetXParameters ( L_DNA *da, l_float64 *pstartx, l_float64 *pdelx ); -LEPT_DLL extern l_int32 l_dnaSetXParameters ( L_DNA *da, l_float64 startx, l_float64 delx ); -LEPT_DLL extern l_int32 l_dnaCopyXParameters ( L_DNA *dad, L_DNA *das ); +LEPT_DLL extern l_int32 l_dnaGetParameters ( L_DNA *da, l_float64 *pstartx, l_float64 *pdelx ); +LEPT_DLL extern l_int32 l_dnaSetParameters ( L_DNA *da, l_float64 startx, l_float64 delx ); +LEPT_DLL extern l_int32 l_dnaCopyParameters ( L_DNA *dad, L_DNA *das ); LEPT_DLL extern L_DNA * l_dnaRead ( const char *filename ); LEPT_DLL extern L_DNA * l_dnaReadStream ( FILE *fp ); LEPT_DLL extern l_int32 l_dnaWrite ( const char *filename, L_DNA *da ); @@ -617,7 +644,6 @@ LEPT_DLL extern l_int32 l_dnaWriteStream ( FILE *fp, L_DNA *da ); LEPT_DLL extern L_DNAA * l_dnaaCreate ( l_int32 n ); LEPT_DLL extern void l_dnaaDestroy ( L_DNAA **pdaa ); LEPT_DLL extern l_int32 l_dnaaAddDna ( L_DNAA *daa, L_DNA *da, l_int32 copyflag ); -LEPT_DLL extern l_int32 l_dnaaExtendArray ( L_DNAA *daa ); LEPT_DLL extern l_int32 l_dnaaGetCount ( L_DNAA *daa ); LEPT_DLL extern l_int32 l_dnaaGetDnaCount ( L_DNAA *daa, l_int32 index ); LEPT_DLL extern l_int32 l_dnaaGetNumberCount ( L_DNAA *daa ); @@ -632,6 +658,7 @@ LEPT_DLL extern l_int32 l_dnaaWriteStream ( FILE *fp, L_DNAA *daa ); LEPT_DLL extern L_DNA * l_dnaMakeDelta ( L_DNA *das ); LEPT_DLL extern NUMA * l_dnaConvertToNuma ( L_DNA *da ); LEPT_DLL extern L_DNA * numaConvertToDna ( NUMA *na ); +LEPT_DLL extern l_int32 l_dnaJoin ( L_DNA *dad, L_DNA *das, l_int32 istart, l_int32 iend ); LEPT_DLL extern PIX * pixMorphDwa_2 ( PIX *pixd, PIX *pixs, l_int32 operation, char *selname ); LEPT_DLL extern PIX * pixFMorphopGen_2 ( PIX *pixd, PIX *pixs, l_int32 operation, char *selname ); LEPT_DLL extern l_int32 fmorphopgen_low_2 ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_int32 index ); @@ -660,6 +687,8 @@ LEPT_DLL extern PIX * pixUnsharpMaskingGray2D ( PIX *pixs, l_int32 halfwidth, l_ LEPT_DLL extern PIX * pixModifyHue ( PIX *pixd, PIX *pixs, l_float32 fract ); LEPT_DLL extern PIX * pixModifySaturation ( PIX *pixd, PIX *pixs, l_float32 fract ); LEPT_DLL extern l_int32 pixMeasureSaturation ( PIX *pixs, l_int32 factor, l_float32 *psat ); +LEPT_DLL extern PIX * pixModifyBrightness ( PIX *pixd, PIX *pixs, l_float32 fract ); +LEPT_DLL extern PIX * pixColorShiftRGB ( PIX *pixs, l_float32 rfract, l_float32 gfract, l_float32 bfract ); LEPT_DLL extern PIX * pixMultConstantColor ( PIX *pixs, l_float32 rfact, l_float32 gfact, l_float32 bfact ); LEPT_DLL extern PIX * pixMultMatrixColor ( PIX *pixs, L_KERNEL *kel ); LEPT_DLL extern PIX * pixHalfEdgeByBandpass ( PIX *pixs, l_int32 sm1h, l_int32 sm1v, l_int32 sm2h, l_int32 sm2v ); @@ -709,8 +738,6 @@ LEPT_DLL extern FPIXA * fpixaCreate ( l_int32 n ); LEPT_DLL extern FPIXA * fpixaCopy ( FPIXA *fpixa, l_int32 copyflag ); LEPT_DLL extern void fpixaDestroy ( FPIXA **pfpixa ); LEPT_DLL extern l_int32 fpixaAddFPix ( FPIXA *fpixa, FPIX *fpix, l_int32 copyflag ); -LEPT_DLL extern l_int32 fpixaExtendArray ( FPIXA *fpixa ); -LEPT_DLL extern l_int32 fpixaExtendArrayToSize ( FPIXA *fpixa, l_int32 size ); LEPT_DLL extern l_int32 fpixaGetCount ( FPIXA *fpixa ); LEPT_DLL extern l_int32 fpixaChangeRefcount ( FPIXA *fpixa, l_int32 delta ); LEPT_DLL extern FPIX * fpixaGetFPix ( FPIXA *fpixa, l_int32 index, l_int32 accesstype ); @@ -772,11 +799,18 @@ LEPT_DLL extern FPIX * fpixAddMirroredBorder ( FPIX *fpixs, l_int32 left, l_int3 LEPT_DLL extern FPIX * fpixAddContinuedBorder ( FPIX *fpixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot ); LEPT_DLL extern FPIX * fpixAddSlopeBorder ( FPIX *fpixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot ); LEPT_DLL extern l_int32 fpixRasterop ( FPIX *fpixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, FPIX *fpixs, l_int32 sx, l_int32 sy ); +LEPT_DLL extern FPIX * fpixRotateOrth ( FPIX *fpixs, l_int32 quads ); +LEPT_DLL extern FPIX * fpixRotate180 ( FPIX *fpixd, FPIX *fpixs ); +LEPT_DLL extern FPIX * fpixRotate90 ( FPIX *fpixs, l_int32 direction ); +LEPT_DLL extern FPIX * fpixFlipLR ( FPIX *fpixd, FPIX *fpixs ); +LEPT_DLL extern FPIX * fpixFlipTB ( FPIX *fpixd, FPIX *fpixs ); LEPT_DLL extern FPIX * fpixAffinePta ( FPIX *fpixs, PTA *ptad, PTA *ptas, l_int32 border, l_float32 inval ); LEPT_DLL extern FPIX * fpixAffine ( FPIX *fpixs, l_float32 *vc, l_float32 inval ); LEPT_DLL extern FPIX * fpixProjectivePta ( FPIX *fpixs, PTA *ptad, PTA *ptas, l_int32 border, l_float32 inval ); LEPT_DLL extern FPIX * fpixProjective ( FPIX *fpixs, l_float32 *vc, l_float32 inval ); LEPT_DLL extern l_int32 linearInterpolatePixelFloat ( l_float32 *datas, l_int32 w, l_int32 h, l_float32 x, l_float32 y, l_float32 inval, l_float32 *pval ); +LEPT_DLL extern PIX * fpixThresholdToPix ( FPIX *fpix, l_float32 thresh ); +LEPT_DLL extern FPIX * pixComponentFunction ( PIX *pix, l_float32 rnum, l_float32 gnum, l_float32 bnum, l_float32 rdenom, l_float32 gdenom, l_float32 bdenom ); LEPT_DLL extern PIX * pixReadStreamGif ( FILE *fp ); LEPT_DLL extern l_int32 pixWriteStreamGif ( FILE *fp, PIX *pix ); LEPT_DLL extern PIX * pixReadMemGif ( const l_uint8 *cdata, size_t size ); @@ -796,14 +830,18 @@ LEPT_DLL extern l_int32 gplotWrite ( const char *filename, GPLOT *gplot ); LEPT_DLL extern PTA * generatePtaLine ( l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2 ); LEPT_DLL extern PTA * generatePtaWideLine ( l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width ); LEPT_DLL extern PTA * generatePtaBox ( BOX *box, l_int32 width ); -LEPT_DLL extern PTA * generatePtaHashBox ( BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline ); LEPT_DLL extern PTA * generatePtaBoxa ( BOXA *boxa, l_int32 width, l_int32 removedups ); +LEPT_DLL extern PTA * generatePtaHashBox ( BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline ); +LEPT_DLL extern PTA * generatePtaHashBoxa ( BOXA *boxa, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 removedups ); LEPT_DLL extern PTAA * generatePtaaBoxa ( BOXA *boxa ); LEPT_DLL extern PTAA * generatePtaaHashBoxa ( BOXA *boxa, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline ); LEPT_DLL extern PTA * generatePtaPolyline ( PTA *ptas, l_int32 width, l_int32 closeflag, l_int32 removedups ); +LEPT_DLL extern PTA * convertPtaLineTo4cc ( PTA *ptas ); LEPT_DLL extern PTA * generatePtaFilledCircle ( l_int32 radius ); +LEPT_DLL extern PTA * generatePtaFilledSquare ( l_int32 side ); LEPT_DLL extern PTA * generatePtaLineFromPt ( l_int32 x, l_int32 y, l_float64 length, l_float64 radang ); LEPT_DLL extern l_int32 locatePtRadially ( l_int32 xr, l_int32 yr, l_float64 dist, l_float64 radang, l_float64 *px, l_float64 *py ); +LEPT_DLL extern PTA * generatePlotPtaFromNuma ( NUMA *na, l_int32 orient, l_int32 width, l_int32 refpos, l_int32 max, l_int32 drawref ); LEPT_DLL extern l_int32 pixRenderPta ( PIX *pix, PTA *pta, l_int32 op ); LEPT_DLL extern l_int32 pixRenderPtaArb ( PIX *pix, PTA *pta, l_uint8 rval, l_uint8 gval, l_uint8 bval ); LEPT_DLL extern l_int32 pixRenderPtaBlend ( PIX *pix, PTA *pta, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_float32 fract ); @@ -813,16 +851,21 @@ LEPT_DLL extern l_int32 pixRenderLineBlend ( PIX *pix, l_int32 x1, l_int32 y1, l LEPT_DLL extern l_int32 pixRenderBox ( PIX *pix, BOX *box, l_int32 width, l_int32 op ); LEPT_DLL extern l_int32 pixRenderBoxArb ( PIX *pix, BOX *box, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval ); LEPT_DLL extern l_int32 pixRenderBoxBlend ( PIX *pix, BOX *box, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_float32 fract ); -LEPT_DLL extern l_int32 pixRenderHashBox ( PIX *pix, BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 op ); -LEPT_DLL extern l_int32 pixRenderHashBoxArb ( PIX *pix, BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval ); -LEPT_DLL extern l_int32 pixRenderHashBoxBlend ( PIX *pix, BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval, l_float32 fract ); LEPT_DLL extern l_int32 pixRenderBoxa ( PIX *pix, BOXA *boxa, l_int32 width, l_int32 op ); LEPT_DLL extern l_int32 pixRenderBoxaArb ( PIX *pix, BOXA *boxa, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval ); LEPT_DLL extern l_int32 pixRenderBoxaBlend ( PIX *pix, BOXA *boxa, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_float32 fract, l_int32 removedups ); +LEPT_DLL extern l_int32 pixRenderHashBox ( PIX *pix, BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 op ); +LEPT_DLL extern l_int32 pixRenderHashBoxArb ( PIX *pix, BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval ); +LEPT_DLL extern l_int32 pixRenderHashBoxBlend ( PIX *pix, BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval, l_float32 fract ); +LEPT_DLL extern l_int32 pixRenderHashBoxa ( PIX *pix, BOXA *boxa, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 op ); +LEPT_DLL extern l_int32 pixRenderHashBoxaArb ( PIX *pix, BOXA *boxa, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval ); +LEPT_DLL extern l_int32 pixRenderHashBoxaBlend ( PIX *pix, BOXA *boxa, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval, l_float32 fract ); LEPT_DLL extern l_int32 pixRenderPolyline ( PIX *pix, PTA *ptas, l_int32 width, l_int32 op, l_int32 closeflag ); LEPT_DLL extern l_int32 pixRenderPolylineArb ( PIX *pix, PTA *ptas, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_int32 closeflag ); LEPT_DLL extern l_int32 pixRenderPolylineBlend ( PIX *pix, PTA *ptas, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_float32 fract, l_int32 closeflag, l_int32 removedups ); LEPT_DLL extern PIX * pixRenderRandomCmapPtaa ( PIX *pix, PTAA *ptaa, l_int32 polyflag, l_int32 width, l_int32 closeflag ); +LEPT_DLL extern PIX * pixRenderPolygon ( PTA *ptas, l_int32 width, l_int32 *pxmin, l_int32 *pymin ); +LEPT_DLL extern PIX * pixFillPolygon ( PIX *pixs, PTA *pta, l_int32 xmin, l_int32 ymin ); LEPT_DLL extern PIX * pixRenderContours ( PIX *pixs, l_int32 startval, l_int32 incr, l_int32 outdepth ); LEPT_DLL extern PIX * fpixAutoRenderContours ( FPIX *fpix, l_int32 ncontours ); LEPT_DLL extern PIX * fpixRenderContours ( FPIX *fpixs, l_float32 incr, l_float32 proxim ); @@ -872,7 +915,6 @@ LEPT_DLL extern void thresholdTo4bppLow ( l_uint32 *datad, l_int32 h, l_int32 wp LEPT_DLL extern L_HEAP * lheapCreate ( l_int32 nalloc, l_int32 direction ); LEPT_DLL extern void lheapDestroy ( L_HEAP **plh, l_int32 freeflag ); LEPT_DLL extern l_int32 lheapAdd ( L_HEAP *lh, void *item ); -LEPT_DLL extern l_int32 lheapExtendArray ( L_HEAP *lh ); LEPT_DLL extern void * lheapRemove ( L_HEAP *lh ); LEPT_DLL extern l_int32 lheapGetCount ( L_HEAP *lh ); LEPT_DLL extern l_int32 lheapSwapUp ( L_HEAP *lh, l_int32 index ); @@ -891,7 +933,8 @@ LEPT_DLL extern l_int32 pixHaustest ( PIX *pix1, PIX *pix2, PIX *pix3, PIX *pix4 LEPT_DLL extern l_int32 pixRankHaustest ( PIX *pix1, PIX *pix2, PIX *pix3, PIX *pix4, l_float32 delx, l_float32 dely, l_int32 maxdiffw, l_int32 maxdiffh, l_int32 area1, l_int32 area3, l_float32 rank, l_int32 *tab8 ); LEPT_DLL extern l_int32 jbClassifyCorrelation ( JBCLASSER *classer, BOXA *boxa, PIXA *pixas ); LEPT_DLL extern l_int32 jbGetComponents ( PIX *pixs, l_int32 components, l_int32 maxwidth, l_int32 maxheight, BOXA **pboxad, PIXA **ppixad ); -LEPT_DLL extern PIX * pixWordMaskByDilation ( PIX *pixs, l_int32 maxsize, l_int32 *psize ); +LEPT_DLL extern l_int32 pixWordMaskByDilation ( PIX *pixs, l_int32 maxdil, PIX **ppixm, l_int32 *psize ); +LEPT_DLL extern l_int32 pixWordBoxesByDilation ( PIX *pixs, l_int32 maxdil, l_int32 minwidth, l_int32 minheight, l_int32 maxwidth, l_int32 maxheight, BOXA **pboxa, l_int32 *psize ); LEPT_DLL extern PIXA * jbAccumulateComposites ( PIXAA *pixaa, NUMA **pna, PTA **pptat ); LEPT_DLL extern PIXA * jbTemplatesFromComposites ( PIXA *pixac, NUMA *na ); LEPT_DLL extern JBCLASSER * jbClasserCreate ( l_int32 method, l_int32 components ); @@ -903,17 +946,21 @@ LEPT_DLL extern JBDATA * jbDataRead ( const char *rootname ); LEPT_DLL extern PIXA * jbDataRender ( JBDATA *data, l_int32 debugflag ); LEPT_DLL extern l_int32 jbGetULCorners ( JBCLASSER *classer, PIX *pixs, BOXA *boxa ); LEPT_DLL extern l_int32 jbGetLLCorners ( JBCLASSER *classer ); +LEPT_DLL extern l_int32 readHeaderJp2k ( const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pspp ); +LEPT_DLL extern l_int32 freadHeaderJp2k ( FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pspp ); +LEPT_DLL extern l_int32 sreadHeaderJp2k ( const l_uint8 *data, size_t size, l_int32 *pw, l_int32 *ph, l_int32 *pspp ); LEPT_DLL extern PIX * pixReadJpeg ( const char *filename, l_int32 cmflag, l_int32 reduction, l_int32 *pnwarn ); LEPT_DLL extern PIX * pixReadStreamJpeg ( FILE *fp, l_int32 cmflag, l_int32 reduction, l_int32 *pnwarn, l_int32 hint ); LEPT_DLL extern l_int32 readHeaderJpeg ( const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk ); LEPT_DLL extern l_int32 freadHeaderJpeg ( FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk ); LEPT_DLL extern l_int32 fgetJpegResolution ( FILE *fp, l_int32 *pxres, l_int32 *pyres ); +LEPT_DLL extern l_int32 fgetJpegComment ( FILE *fp, l_uint8 **pcomment ); LEPT_DLL extern l_int32 pixWriteJpeg ( const char *filename, PIX *pix, l_int32 quality, l_int32 progressive ); LEPT_DLL extern l_int32 pixWriteStreamJpeg ( FILE *fp, PIX *pix, l_int32 quality, l_int32 progressive ); LEPT_DLL extern PIX * pixReadMemJpeg ( const l_uint8 *cdata, size_t size, l_int32 cmflag, l_int32 reduction, l_int32 *pnwarn, l_int32 hint ); LEPT_DLL extern l_int32 readHeaderMemJpeg ( const l_uint8 *cdata, size_t size, l_int32 *pw, l_int32 *ph, l_int32 *pspp, l_int32 *pycck, l_int32 *pcmyk ); LEPT_DLL extern l_int32 pixWriteMemJpeg ( l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 quality, l_int32 progressive ); -LEPT_DLL extern void l_jpegSetNoChromaSampling ( l_int32 flag ); +LEPT_DLL extern l_int32 pixSetChromaSampling ( PIX *pix, l_int32 sampling ); LEPT_DLL extern l_int32 extractJpegDataFromFile ( const char *filein, l_uint8 **pdata, size_t *pnbytes, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp ); LEPT_DLL extern l_int32 extractJpegDataFromArray ( const void *data, size_t nbytes, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp ); LEPT_DLL extern L_KERNEL * kernelCreate ( l_int32 height, l_int32 width ); @@ -992,7 +1039,7 @@ LEPT_DLL extern PIX * pixIntersectionOfMorphOps ( PIX *pixs, SELA *sela, l_int32 LEPT_DLL extern PIX * pixSelectiveConnCompFill ( PIX *pixs, l_int32 connectivity, l_int32 minw, l_int32 minh ); LEPT_DLL extern l_int32 pixRemoveMatchedPattern ( PIX *pixs, PIX *pixp, PIX *pixe, l_int32 x0, l_int32 y0, l_int32 dsize ); LEPT_DLL extern PIX * pixDisplayMatchedPattern ( PIX *pixs, PIX *pixp, PIX *pixe, l_int32 x0, l_int32 y0, l_uint32 color, l_float32 scale, l_int32 nlevels ); -LEPT_DLL extern PIX * pixSeedfillMorph ( PIX *pixs, PIX *pixm, l_int32 connectivity ); +LEPT_DLL extern PIX * pixSeedfillMorph ( PIX *pixs, PIX *pixm, l_int32 maxiters, l_int32 connectivity ); LEPT_DLL extern NUMA * pixRunHistogramMorph ( PIX *pixs, l_int32 runtype, l_int32 direction, l_int32 maxsize ); LEPT_DLL extern PIX * pixTophat ( PIX *pixs, l_int32 hsize, l_int32 vsize, l_int32 type ); LEPT_DLL extern PIX * pixHDome ( PIX *pixs, l_int32 height, l_int32 connectivity ); @@ -1028,7 +1075,6 @@ LEPT_DLL extern NUMA * numaCopy ( NUMA *na ); LEPT_DLL extern NUMA * numaClone ( NUMA *na ); LEPT_DLL extern l_int32 numaEmpty ( NUMA *na ); LEPT_DLL extern l_int32 numaAddNumber ( NUMA *na, l_float32 val ); -LEPT_DLL extern l_int32 numaExtendArray ( NUMA *na ); LEPT_DLL extern l_int32 numaInsertNumber ( NUMA *na, l_int32 index, l_float32 val ); LEPT_DLL extern l_int32 numaRemoveNumber ( NUMA *na, l_int32 index ); LEPT_DLL extern l_int32 numaReplaceNumber ( NUMA *na, l_int32 index, l_float32 val ); @@ -1042,14 +1088,17 @@ LEPT_DLL extern l_int32 * numaGetIArray ( NUMA *na ); LEPT_DLL extern l_float32 * numaGetFArray ( NUMA *na, l_int32 copyflag ); LEPT_DLL extern l_int32 numaGetRefcount ( NUMA *na ); LEPT_DLL extern l_int32 numaChangeRefcount ( NUMA *na, l_int32 delta ); -LEPT_DLL extern l_int32 numaGetXParameters ( NUMA *na, l_float32 *pstartx, l_float32 *pdelx ); -LEPT_DLL extern l_int32 numaSetXParameters ( NUMA *na, l_float32 startx, l_float32 delx ); -LEPT_DLL extern l_int32 numaCopyXParameters ( NUMA *nad, NUMA *nas ); +LEPT_DLL extern l_int32 numaGetParameters ( NUMA *na, l_float32 *pstartx, l_float32 *pdelx ); +LEPT_DLL extern l_int32 numaSetParameters ( NUMA *na, l_float32 startx, l_float32 delx ); +LEPT_DLL extern l_int32 numaCopyParameters ( NUMA *nad, NUMA *nas ); +LEPT_DLL extern SARRAY * numaConvertToSarray ( NUMA *na, l_int32 size1, l_int32 size2, l_int32 addzeros, l_int32 type ); LEPT_DLL extern NUMA * numaRead ( const char *filename ); LEPT_DLL extern NUMA * numaReadStream ( FILE *fp ); LEPT_DLL extern l_int32 numaWrite ( const char *filename, NUMA *na ); LEPT_DLL extern l_int32 numaWriteStream ( FILE *fp, NUMA *na ); LEPT_DLL extern NUMAA * numaaCreate ( l_int32 n ); +LEPT_DLL extern NUMAA * numaaCreateFull ( l_int32 ntop, l_int32 n ); +LEPT_DLL extern l_int32 numaaTruncate ( NUMAA *naa ); LEPT_DLL extern void numaaDestroy ( NUMAA **pnaa ); LEPT_DLL extern l_int32 numaaAddNuma ( NUMAA *naa, NUMA *na, l_int32 copyflag ); LEPT_DLL extern l_int32 numaaExtendArray ( NUMAA *naa ); @@ -1059,7 +1108,7 @@ LEPT_DLL extern l_int32 numaaGetNumberCount ( NUMAA *naa ); LEPT_DLL extern NUMA ** numaaGetPtrArray ( NUMAA *naa ); LEPT_DLL extern NUMA * numaaGetNuma ( NUMAA *naa, l_int32 index, l_int32 accessflag ); LEPT_DLL extern l_int32 numaaReplaceNuma ( NUMAA *naa, l_int32 index, NUMA *na ); -LEPT_DLL extern l_int32 numaaGetValue ( NUMAA *naa, l_int32 i, l_int32 j, l_float32 *pval ); +LEPT_DLL extern l_int32 numaaGetValue ( NUMAA *naa, l_int32 i, l_int32 j, l_float32 *pfval, l_int32 *pival ); LEPT_DLL extern l_int32 numaaAddNumber ( NUMAA *naa, l_int32 index, l_float32 val ); LEPT_DLL extern NUMAA * numaaRead ( const char *filename ); LEPT_DLL extern NUMAA * numaaReadStream ( FILE *fp ); @@ -1079,6 +1128,8 @@ LEPT_DLL extern l_int32 numaHashAdd ( NUMAHASH *nahash, l_uint32 key, l_float32 LEPT_DLL extern NUMA * numaArithOp ( NUMA *nad, NUMA *na1, NUMA *na2, l_int32 op ); LEPT_DLL extern NUMA * numaLogicalOp ( NUMA *nad, NUMA *na1, NUMA *na2, l_int32 op ); LEPT_DLL extern NUMA * numaInvert ( NUMA *nad, NUMA *nas ); +LEPT_DLL extern l_int32 numaSimilar ( NUMA *na1, NUMA *na2, l_float32 maxdiff, l_int32 *psimilar ); +LEPT_DLL extern l_int32 numaAddToNumber ( NUMA *na, l_int32 index, l_float32 val ); LEPT_DLL extern l_int32 numaGetMin ( NUMA *na, l_float32 *pminval, l_int32 *piminloc ); LEPT_DLL extern l_int32 numaGetMax ( NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc ); LEPT_DLL extern l_int32 numaGetSum ( NUMA *na, l_float32 *psum ); @@ -1098,6 +1149,7 @@ LEPT_DLL extern l_int32 numaGetCountRelativeToZero ( NUMA *na, l_int32 type, l_i LEPT_DLL extern NUMA * numaClipToInterval ( NUMA *nas, l_int32 first, l_int32 last ); LEPT_DLL extern NUMA * numaMakeThresholdIndicator ( NUMA *nas, l_float32 thresh, l_int32 type ); LEPT_DLL extern NUMA * numaUniformSampling ( NUMA *nas, l_int32 nsamp ); +LEPT_DLL extern NUMA * numaReverse ( NUMA *nad, NUMA *nas ); LEPT_DLL extern NUMA * numaLowPassIntervals ( NUMA *nas, l_float32 thresh, l_float32 maxn ); LEPT_DLL extern NUMA * numaThresholdEdges ( NUMA *nas, l_float32 thresh1, l_float32 thresh2, l_float32 maxn ); LEPT_DLL extern l_int32 numaGetSpanValues ( NUMA *na, l_int32 span, l_int32 *pstart, l_int32 *pend ); @@ -1109,6 +1161,10 @@ LEPT_DLL extern l_int32 numaInterpolateArbxInterval ( NUMA *nax, NUMA *nay, l_in LEPT_DLL extern l_int32 numaFitMax ( NUMA *na, l_float32 *pmaxval, NUMA *naloc, l_float32 *pmaxloc ); LEPT_DLL extern l_int32 numaDifferentiateInterval ( NUMA *nax, NUMA *nay, l_float32 x0, l_float32 x1, l_int32 npts, NUMA **pnadx, NUMA **pnady ); LEPT_DLL extern l_int32 numaIntegrateInterval ( NUMA *nax, NUMA *nay, l_float32 x0, l_float32 x1, l_int32 npts, l_float32 *psum ); +LEPT_DLL extern l_int32 numaSortGeneral ( NUMA *na, NUMA **pnasort, NUMA **pnaindex, NUMA **pnainvert, l_int32 sortorder, l_int32 sorttype ); +LEPT_DLL extern NUMA * numaSortAutoSelect ( NUMA *nas, l_int32 sortorder ); +LEPT_DLL extern NUMA * numaSortIndexAutoSelect ( NUMA *nas, l_int32 sortorder ); +LEPT_DLL extern l_int32 numaChooseSortType ( NUMA *nas ); LEPT_DLL extern NUMA * numaSort ( NUMA *naout, NUMA *nain, l_int32 sortorder ); LEPT_DLL extern NUMA * numaBinSort ( NUMA *nas, l_int32 sortorder ); LEPT_DLL extern NUMA * numaGetSortIndex ( NUMA *na, l_int32 sortorder ); @@ -1116,6 +1172,7 @@ LEPT_DLL extern NUMA * numaGetBinSortIndex ( NUMA *nas, l_int32 sortorder ); LEPT_DLL extern NUMA * numaSortByIndex ( NUMA *nas, NUMA *naindex ); LEPT_DLL extern l_int32 numaIsSorted ( NUMA *nas, l_int32 sortorder, l_int32 *psorted ); LEPT_DLL extern l_int32 numaSortPair ( NUMA *nax, NUMA *nay, l_int32 sortorder, NUMA **pnasx, NUMA **pnasy ); +LEPT_DLL extern NUMA * numaInvertMap ( NUMA *nas ); LEPT_DLL extern NUMA * numaPseudorandomSequence ( l_int32 size, l_int32 seed ); LEPT_DLL extern NUMA * numaRandomPermutation ( NUMA *nas, l_int32 seed ); LEPT_DLL extern l_int32 numaGetRankValue ( NUMA *na, l_float32 fract, NUMA *nasort, l_int32 usebins, l_float32 *pval ); @@ -1124,6 +1181,7 @@ LEPT_DLL extern l_int32 numaGetBinnedMedian ( NUMA *na, l_int32 *pval ); LEPT_DLL extern l_int32 numaGetMode ( NUMA *na, l_float32 *pval, l_int32 *pcount ); LEPT_DLL extern l_int32 numaGetMedianVariation ( NUMA *na, l_float32 *pmedval, l_float32 *pmedvar ); LEPT_DLL extern l_int32 numaJoin ( NUMA *nad, NUMA *nas, l_int32 istart, l_int32 iend ); +LEPT_DLL extern l_int32 numaaJoin ( NUMAA *naad, NUMAA *naas, l_int32 istart, l_int32 iend ); LEPT_DLL extern NUMA * numaaFlattenToNuma ( NUMAA *naa ); LEPT_DLL extern NUMA * numaErode ( NUMA *nas, l_int32 size ); LEPT_DLL extern NUMA * numaDilate ( NUMA *nas, l_int32 size ); @@ -1139,7 +1197,7 @@ LEPT_DLL extern NUMA * numaMakeHistogram ( NUMA *na, l_int32 maxbins, l_int32 *p LEPT_DLL extern NUMA * numaMakeHistogramAuto ( NUMA *na, l_int32 maxbins ); LEPT_DLL extern NUMA * numaMakeHistogramClipped ( NUMA *na, l_float32 binsize, l_float32 maxsize ); LEPT_DLL extern NUMA * numaRebinHistogram ( NUMA *nas, l_int32 newsize ); -LEPT_DLL extern NUMA * numaNormalizeHistogram ( NUMA *nas, l_float32 area ); +LEPT_DLL extern NUMA * numaNormalizeHistogram ( NUMA *nas, l_float32 tsum ); LEPT_DLL extern l_int32 numaGetStatsUsingHistogram ( NUMA *na, l_int32 maxbins, l_float32 *pmin, l_float32 *pmax, l_float32 *pmean, l_float32 *pvariance, l_float32 *pmedian, l_float32 rank, l_float32 *prval, NUMA **phisto ); LEPT_DLL extern l_int32 numaGetHistogramStats ( NUMA *nahisto, l_float32 startx, l_float32 deltax, l_float32 *pxmean, l_float32 *pxmedian, l_float32 *pxmode, l_float32 *pxvariance ); LEPT_DLL extern l_int32 numaGetHistogramStatsOnInterval ( NUMA *nahisto, l_float32 startx, l_float32 deltax, l_int32 ifirst, l_int32 ilast, l_float32 *pxmean, l_float32 *pxmedian, l_float32 *pxmode, l_float32 *pxvariance ); @@ -1149,6 +1207,7 @@ LEPT_DLL extern l_int32 numaHistogramGetValFromRank ( NUMA *na, l_float32 rank, LEPT_DLL extern l_int32 numaDiscretizeRankAndIntensity ( NUMA *na, l_int32 nbins, NUMA **pnarbin, NUMA **pnam, NUMA **pnar, NUMA **pnabb ); LEPT_DLL extern l_int32 numaGetRankBinValues ( NUMA *na, l_int32 nbins, NUMA **pnarbin, NUMA **pnam ); LEPT_DLL extern l_int32 numaSplitDistribution ( NUMA *na, l_float32 scorefract, l_int32 *psplitindex, l_float32 *pave1, l_float32 *pave2, l_float32 *pnum1, l_float32 *pnum2, NUMA **pnascore ); +LEPT_DLL extern l_int32 numaEarthMoverDistance ( NUMA *na1, NUMA *na2, l_float32 *pdist ); LEPT_DLL extern NUMA * numaFindPeaks ( NUMA *nas, l_int32 nmax, l_float32 fract1, l_float32 fract2 ); LEPT_DLL extern NUMA * numaFindExtrema ( NUMA *nas, l_float32 delta ); LEPT_DLL extern l_int32 numaCountReversals ( NUMA *nas, l_float32 minreversal, l_int32 *pnr, l_float32 *pnrpl ); @@ -1161,7 +1220,11 @@ LEPT_DLL extern l_int32 pixGetRegionsBinary ( PIX *pixs, PIX **ppixhm, PIX **ppi LEPT_DLL extern PIX * pixGenHalftoneMask ( PIX *pixs, PIX **ppixtext, l_int32 *phtfound, l_int32 debug ); LEPT_DLL extern PIX * pixGenTextlineMask ( PIX *pixs, PIX **ppixvws, l_int32 *ptlfound, l_int32 debug ); LEPT_DLL extern PIX * pixGenTextblockMask ( PIX *pixs, PIX *pixvws, l_int32 debug ); +LEPT_DLL extern BOX * pixFindPageForeground ( PIX *pixs, l_int32 threshold, l_int32 mindist, l_int32 erasedist, l_int32 pagenum, l_int32 showmorph, l_int32 display, const char *pdfdir ); +LEPT_DLL extern l_int32 pixSplitIntoCharacters ( PIX *pixs, l_int32 minw, l_int32 minh, BOXA **pboxa, PIXA **ppixa, PIX **ppixdebug ); +LEPT_DLL extern BOXA * pixSplitComponentWithProfile ( PIX *pixs, l_int32 delta, l_int32 mindel, PIX **ppixdebug ); LEPT_DLL extern l_int32 pixSetSelectCmap ( PIX *pixs, BOX *box, l_int32 sindex, l_int32 rval, l_int32 gval, l_int32 bval ); +LEPT_DLL extern l_int32 pixColorGrayRegionsCmap ( PIX *pixs, BOXA *boxa, l_int32 type, l_int32 rval, l_int32 gval, l_int32 bval ); LEPT_DLL extern l_int32 pixColorGrayCmap ( PIX *pixs, BOX *box, l_int32 type, l_int32 rval, l_int32 gval, l_int32 bval ); LEPT_DLL extern l_int32 addColorizedGrayToCmap ( PIXCMAP *cmap, l_int32 type, l_int32 rval, l_int32 gval, l_int32 bval, NUMA **pna ); LEPT_DLL extern l_int32 pixSetSelectMaskedCmap ( PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 sindex, l_int32 rval, l_int32 gval, l_int32 bval ); @@ -1173,21 +1236,25 @@ LEPT_DLL extern l_int32 convertFilesToPdf ( const char *dirname, const char *sub LEPT_DLL extern l_int32 saConvertFilesToPdf ( SARRAY *sa, l_int32 res, l_float32 scalefactor, l_int32 type, l_int32 quality, const char *title, const char *fileout ); LEPT_DLL extern l_int32 saConvertFilesToPdfData ( SARRAY *sa, l_int32 res, l_float32 scalefactor, l_int32 type, l_int32 quality, const char *title, l_uint8 **pdata, size_t *pnbytes ); LEPT_DLL extern l_int32 selectDefaultPdfEncoding ( PIX *pix, l_int32 *ptype ); +LEPT_DLL extern l_int32 convertUnscaledFilesToPdf ( const char *dirname, const char *substr, const char *title, const char *fileout ); +LEPT_DLL extern l_int32 saConvertUnscaledFilesToPdf ( SARRAY *sa, const char *title, const char *fileout ); +LEPT_DLL extern l_int32 saConvertUnscaledFilesToPdfData ( SARRAY *sa, const char *title, l_uint8 **pdata, size_t *pnbytes ); +LEPT_DLL extern l_int32 convertUnscaledToPdfData ( const char *fname, const char *title, l_uint8 **pdata, size_t *pnbytes ); LEPT_DLL extern l_int32 pixaConvertToPdf ( PIXA *pixa, l_int32 res, l_float32 scalefactor, l_int32 type, l_int32 quality, const char *title, const char *fileout ); LEPT_DLL extern l_int32 pixaConvertToPdfData ( PIXA *pixa, l_int32 res, l_float32 scalefactor, l_int32 type, l_int32 quality, const char *title, l_uint8 **pdata, size_t *pnbytes ); -LEPT_DLL extern l_int32 convertToPdf ( const char *filein, l_int32 type, l_int32 quality, const char *fileout, l_int32 x, l_int32 y, l_int32 res, L_PDF_DATA **plpd, l_int32 position, const char *title ); -LEPT_DLL extern l_int32 convertImageDataToPdf ( l_uint8 *imdata, size_t size, l_int32 type, l_int32 quality, const char *fileout, l_int32 x, l_int32 y, l_int32 res, L_PDF_DATA **plpd, l_int32 position, const char *title ); -LEPT_DLL extern l_int32 convertToPdfData ( const char *filein, l_int32 type, l_int32 quality, l_uint8 **pdata, size_t *pnbytes, l_int32 x, l_int32 y, l_int32 res, L_PDF_DATA **plpd, l_int32 position, const char *title ); -LEPT_DLL extern l_int32 convertImageDataToPdfData ( l_uint8 *imdata, size_t size, l_int32 type, l_int32 quality, l_uint8 **pdata, size_t *pnbytes, l_int32 x, l_int32 y, l_int32 res, L_PDF_DATA **plpd, l_int32 position, const char *title ); -LEPT_DLL extern l_int32 pixConvertToPdf ( PIX *pix, l_int32 type, l_int32 quality, const char *fileout, l_int32 x, l_int32 y, l_int32 res, L_PDF_DATA **plpd, l_int32 position, const char *title ); -LEPT_DLL extern l_int32 pixConvertToPdfData ( PIX *pix, l_int32 type, l_int32 quality, l_uint8 **pdata, size_t *pnbytes, l_int32 x, l_int32 y, l_int32 res, L_PDF_DATA **plpd, l_int32 position, const char *title ); +LEPT_DLL extern l_int32 convertToPdf ( const char *filein, l_int32 type, l_int32 quality, const char *fileout, l_int32 x, l_int32 y, l_int32 res, const char *title, L_PDF_DATA **plpd, l_int32 position ); +LEPT_DLL extern l_int32 convertImageDataToPdf ( l_uint8 *imdata, size_t size, l_int32 type, l_int32 quality, const char *fileout, l_int32 x, l_int32 y, l_int32 res, const char *title, L_PDF_DATA **plpd, l_int32 position ); +LEPT_DLL extern l_int32 convertToPdfData ( const char *filein, l_int32 type, l_int32 quality, l_uint8 **pdata, size_t *pnbytes, l_int32 x, l_int32 y, l_int32 res, const char *title, L_PDF_DATA **plpd, l_int32 position ); +LEPT_DLL extern l_int32 convertImageDataToPdfData ( l_uint8 *imdata, size_t size, l_int32 type, l_int32 quality, l_uint8 **pdata, size_t *pnbytes, l_int32 x, l_int32 y, l_int32 res, const char *title, L_PDF_DATA **plpd, l_int32 position ); +LEPT_DLL extern l_int32 pixConvertToPdf ( PIX *pix, l_int32 type, l_int32 quality, const char *fileout, l_int32 x, l_int32 y, l_int32 res, const char *title, L_PDF_DATA **plpd, l_int32 position ); +LEPT_DLL extern l_int32 pixConvertToPdfData ( PIX *pix, l_int32 type, l_int32 quality, l_uint8 **pdata, size_t *pnbytes, l_int32 x, l_int32 y, l_int32 res, const char *title, L_PDF_DATA **plpd, l_int32 position ); LEPT_DLL extern l_int32 pixWriteStreamPdf ( FILE *fp, PIX *pix, l_int32 res, const char *title ); LEPT_DLL extern l_int32 convertSegmentedFilesToPdf ( const char *dirname, const char *substr, l_int32 res, l_int32 type, l_int32 thresh, BOXAA *baa, l_int32 quality, l_float32 scalefactor, const char *title, const char *fileout ); LEPT_DLL extern BOXAA * convertNumberedMasksToBoxaa ( const char *dirname, const char *substr, l_int32 numpre, l_int32 numpost ); -LEPT_DLL extern l_int32 convertToPdfSegmented ( const char *filein, l_int32 res, l_int32 type, l_int32 thresh, BOXA *boxa, l_int32 quality, l_float32 scalefactor, const char *fileout ); -LEPT_DLL extern l_int32 pixConvertToPdfSegmented ( PIX *pixs, l_int32 res, l_int32 type, l_int32 thresh, BOXA *boxa, l_int32 quality, l_float32 scalefactor, const char *fileout, const char *title ); -LEPT_DLL extern l_int32 convertToPdfDataSegmented ( const char *filein, l_int32 res, l_int32 type, l_int32 thresh, BOXA *boxa, l_int32 quality, l_float32 scalefactor, l_uint8 **pdata, size_t *pnbytes ); -LEPT_DLL extern l_int32 pixConvertToPdfDataSegmented ( PIX *pixs, l_int32 res, l_int32 type, l_int32 thresh, BOXA *boxa, l_int32 quality, l_float32 scalefactor, l_uint8 **pdata, size_t *pnbytes, const char *title ); +LEPT_DLL extern l_int32 convertToPdfSegmented ( const char *filein, l_int32 res, l_int32 type, l_int32 thresh, BOXA *boxa, l_int32 quality, l_float32 scalefactor, const char *title, const char *fileout ); +LEPT_DLL extern l_int32 pixConvertToPdfSegmented ( PIX *pixs, l_int32 res, l_int32 type, l_int32 thresh, BOXA *boxa, l_int32 quality, l_float32 scalefactor, const char *title, const char *fileout ); +LEPT_DLL extern l_int32 convertToPdfDataSegmented ( const char *filein, l_int32 res, l_int32 type, l_int32 thresh, BOXA *boxa, l_int32 quality, l_float32 scalefactor, const char *title, l_uint8 **pdata, size_t *pnbytes ); +LEPT_DLL extern l_int32 pixConvertToPdfDataSegmented ( PIX *pixs, l_int32 res, l_int32 type, l_int32 thresh, BOXA *boxa, l_int32 quality, l_float32 scalefactor, const char *title, l_uint8 **pdata, size_t *pnbytes ); LEPT_DLL extern l_int32 concatenatePdf ( const char *dirname, const char *substr, const char *fileout ); LEPT_DLL extern l_int32 saConcatenatePdf ( SARRAY *sa, const char *fileout ); LEPT_DLL extern l_int32 ptraConcatenatePdf ( L_PTRA *pa, const char *fileout ); @@ -1196,7 +1263,7 @@ LEPT_DLL extern l_int32 saConcatenatePdfToData ( SARRAY *sa, l_uint8 **pdata, si LEPT_DLL extern l_int32 ptraConcatenatePdfToData ( L_PTRA *pa_data, SARRAY *sa, l_uint8 **pdata, size_t *pnbytes ); LEPT_DLL extern void l_pdfSetG4ImageMask ( l_int32 flag ); LEPT_DLL extern void l_pdfSetDateAndVersion ( l_int32 flag ); -LEPT_DLL extern void setPixMemoryManager ( void * ( allocator ( size_t ) ), void ( deallocator ( void * ) ) ); +LEPT_DLL extern void setPixMemoryManager ( void * ( ( *allocator ) ( size_t ) ), void ( ( *deallocator ) ( void * ) ) ); LEPT_DLL extern PIX * pixCreate ( l_int32 width, l_int32 height, l_int32 depth ); LEPT_DLL extern PIX * pixCreateNoInit ( l_int32 width, l_int32 height, l_int32 depth ); LEPT_DLL extern PIX * pixCreateTemplate ( PIX *pixs ); @@ -1219,6 +1286,9 @@ LEPT_DLL extern l_int32 pixSetDepth ( PIX *pix, l_int32 depth ); LEPT_DLL extern l_int32 pixGetDimensions ( PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd ); LEPT_DLL extern l_int32 pixSetDimensions ( PIX *pix, l_int32 w, l_int32 h, l_int32 d ); LEPT_DLL extern l_int32 pixCopyDimensions ( PIX *pixd, PIX *pixs ); +LEPT_DLL extern l_int32 pixGetSpp ( PIX *pix ); +LEPT_DLL extern l_int32 pixSetSpp ( PIX *pix, l_int32 spp ); +LEPT_DLL extern l_int32 pixCopySpp ( PIX *pixd, PIX *pixs ); LEPT_DLL extern l_int32 pixGetWpl ( PIX *pix ); LEPT_DLL extern l_int32 pixSetWpl ( PIX *pix, l_int32 wpl ); LEPT_DLL extern l_int32 pixGetRefcount ( PIX *pix ); @@ -1255,10 +1325,13 @@ LEPT_DLL extern l_int32 pixGetRandomPixel ( PIX *pix, l_uint32 *pval, l_int32 *p LEPT_DLL extern l_int32 pixClearPixel ( PIX *pix, l_int32 x, l_int32 y ); LEPT_DLL extern l_int32 pixFlipPixel ( PIX *pix, l_int32 x, l_int32 y ); LEPT_DLL extern void setPixelLow ( l_uint32 *line, l_int32 x, l_int32 depth, l_uint32 val ); +LEPT_DLL extern l_int32 pixGetBlackOrWhiteVal ( PIX *pixs, l_int32 op, l_uint32 *pval ); LEPT_DLL extern l_int32 pixClearAll ( PIX *pix ); LEPT_DLL extern l_int32 pixSetAll ( PIX *pix ); +LEPT_DLL extern l_int32 pixSetAllGray ( PIX *pix, l_int32 grayval ); LEPT_DLL extern l_int32 pixSetAllArbitrary ( PIX *pix, l_uint32 val ); LEPT_DLL extern l_int32 pixSetBlackOrWhite ( PIX *pixs, l_int32 op ); +LEPT_DLL extern l_int32 pixSetComponentArbitrary ( PIX *pix, l_int32 comp, l_int32 val ); LEPT_DLL extern l_int32 pixClearInRect ( PIX *pix, BOX *box ); LEPT_DLL extern l_int32 pixSetInRect ( PIX *pix, BOX *box ); LEPT_DLL extern l_int32 pixSetInRectArbitrary ( PIX *pix, BOX *box, l_uint32 val ); @@ -1271,19 +1344,26 @@ LEPT_DLL extern l_int32 pixSetBorderRingVal ( PIX *pixs, l_int32 dist, l_uint32 LEPT_DLL extern l_int32 pixSetMirroredBorder ( PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot ); LEPT_DLL extern PIX * pixCopyBorder ( PIX *pixd, PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot ); LEPT_DLL extern PIX * pixAddBorder ( PIX *pixs, l_int32 npix, l_uint32 val ); -LEPT_DLL extern PIX * pixAddBlackBorder ( PIX *pixs, l_int32 npix ); +LEPT_DLL extern PIX * pixAddBlackOrWhiteBorder ( PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_int32 op ); LEPT_DLL extern PIX * pixAddBorderGeneral ( PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val ); LEPT_DLL extern PIX * pixRemoveBorder ( PIX *pixs, l_int32 npix ); LEPT_DLL extern PIX * pixRemoveBorderGeneral ( PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot ); +LEPT_DLL extern PIX * pixRemoveBorderToSize ( PIX *pixs, l_int32 wd, l_int32 hd ); LEPT_DLL extern PIX * pixAddMirroredBorder ( PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot ); LEPT_DLL extern PIX * pixAddRepeatedBorder ( PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot ); LEPT_DLL extern PIX * pixAddMixedBorder ( PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot ); +LEPT_DLL extern PIX * pixAddContinuedBorder ( PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot ); +LEPT_DLL extern l_int32 pixShiftAndTransferAlpha ( PIX *pixd, PIX *pixs, l_float32 shiftx, l_float32 shifty ); +LEPT_DLL extern PIX * pixDisplayLayersRGBA ( PIX *pixs, l_uint32 val, l_int32 maxw ); LEPT_DLL extern PIX * pixCreateRGBImage ( PIX *pixr, PIX *pixg, PIX *pixb ); -LEPT_DLL extern PIX * pixGetRGBComponent ( PIX *pixs, l_int32 color ); -LEPT_DLL extern l_int32 pixSetRGBComponent ( PIX *pixd, PIX *pixs, l_int32 color ); -LEPT_DLL extern PIX * pixGetRGBComponentCmap ( PIX *pixs, l_int32 color ); +LEPT_DLL extern PIX * pixGetRGBComponent ( PIX *pixs, l_int32 comp ); +LEPT_DLL extern l_int32 pixSetRGBComponent ( PIX *pixd, PIX *pixs, l_int32 comp ); +LEPT_DLL extern PIX * pixGetRGBComponentCmap ( PIX *pixs, l_int32 comp ); +LEPT_DLL extern l_int32 pixCopyRGBComponent ( PIX *pixd, PIX *pixs, l_int32 comp ); LEPT_DLL extern l_int32 composeRGBPixel ( l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel ); +LEPT_DLL extern l_int32 composeRGBAPixel ( l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel ); LEPT_DLL extern void extractRGBValues ( l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval ); +LEPT_DLL extern void extractRGBAValues ( l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval, l_int32 *paval ); LEPT_DLL extern l_int32 extractMinMaxComponent ( l_uint32 pixel, l_int32 type ); LEPT_DLL extern l_int32 pixGetRGBLine ( PIX *pixs, l_int32 row, l_uint8 *bufr, l_uint8 *bufg, l_uint8 *bufb ); LEPT_DLL extern PIX * pixEndianByteSwapNew ( PIX *pixs ); @@ -1292,6 +1372,7 @@ LEPT_DLL extern l_int32 lineEndianByteSwap ( l_uint32 *datad, l_uint32 *datas, l LEPT_DLL extern PIX * pixEndianTwoByteSwapNew ( PIX *pixs ); LEPT_DLL extern l_int32 pixEndianTwoByteSwap ( PIX *pixs ); LEPT_DLL extern l_int32 pixGetRasterData ( PIX *pixs, l_uint8 **pdata, size_t *pnbytes ); +LEPT_DLL extern l_int32 pixAlphaIsOpaque ( PIX *pix, l_int32 *popaque ); LEPT_DLL extern l_uint8 ** pixSetupByteProcessing ( PIX *pix, l_int32 *pw, l_int32 *ph ); LEPT_DLL extern l_int32 pixCleanupByteProcessing ( PIX *pix, l_uint8 **lineptrs ); LEPT_DLL extern void l_setAlphaMaskBorder ( l_float32 val1, l_float32 val2 ); @@ -1302,7 +1383,7 @@ LEPT_DLL extern l_int32 pixCombineMaskedGeneral ( PIX *pixd, PIX *pixs, PIX *pix LEPT_DLL extern l_int32 pixPaintThroughMask ( PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val ); LEPT_DLL extern l_int32 pixPaintSelfThroughMask ( PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_int32 tilesize, l_int32 searchdir ); LEPT_DLL extern PIX * pixMakeMaskFromLUT ( PIX *pixs, l_int32 *tab ); -LEPT_DLL extern PIX * pixSetUnderTransparency ( PIX *pixs, l_uint32 val, l_int32 debugflag ); +LEPT_DLL extern PIX * pixSetUnderTransparency ( PIX *pixs, l_uint32 val, l_int32 debug ); LEPT_DLL extern PIX * pixInvert ( PIX *pixd, PIX *pixs ); LEPT_DLL extern PIX * pixOr ( PIX *pixd, PIX *pixs1, PIX *pixs2 ); LEPT_DLL extern PIX * pixAnd ( PIX *pixd, PIX *pixs1, PIX *pixs2 ); @@ -1310,18 +1391,28 @@ LEPT_DLL extern PIX * pixXor ( PIX *pixd, PIX *pixs1, PIX *pixs2 ); LEPT_DLL extern PIX * pixSubtract ( PIX *pixd, PIX *pixs1, PIX *pixs2 ); LEPT_DLL extern l_int32 pixZero ( PIX *pix, l_int32 *pempty ); LEPT_DLL extern l_int32 pixForegroundFraction ( PIX *pix, l_float32 *pfract ); -LEPT_DLL extern l_int32 pixCountPixels ( PIX *pix, l_int32 *pcount, l_int32 *tab8 ); LEPT_DLL extern NUMA * pixaCountPixels ( PIXA *pixa ); -LEPT_DLL extern l_int32 pixCountPixelsInRow ( PIX *pix, l_int32 row, l_int32 *pcount, l_int32 *tab8 ); +LEPT_DLL extern l_int32 pixCountPixels ( PIX *pix, l_int32 *pcount, l_int32 *tab8 ); +LEPT_DLL extern NUMA * pixCountByRow ( PIX *pix, BOX *box ); +LEPT_DLL extern NUMA * pixCountByColumn ( PIX *pix, BOX *box ); LEPT_DLL extern NUMA * pixCountPixelsByRow ( PIX *pix, l_int32 *tab8 ); LEPT_DLL extern NUMA * pixCountPixelsByColumn ( PIX *pix ); -LEPT_DLL extern NUMA * pixSumPixelsByRow ( PIX *pix, l_int32 *tab8 ); -LEPT_DLL extern NUMA * pixSumPixelsByColumn ( PIX *pix ); +LEPT_DLL extern l_int32 pixCountPixelsInRow ( PIX *pix, l_int32 row, l_int32 *pcount, l_int32 *tab8 ); +LEPT_DLL extern NUMA * pixGetMomentByColumn ( PIX *pix, l_int32 order ); LEPT_DLL extern l_int32 pixThresholdPixelSum ( PIX *pix, l_int32 thresh, l_int32 *pabove, l_int32 *tab8 ); LEPT_DLL extern l_int32 * makePixelSumTab8 ( void ); LEPT_DLL extern l_int32 * makePixelCentroidTab8 ( void ); +LEPT_DLL extern NUMA * pixAverageByRow ( PIX *pix, BOX *box, l_int32 type ); +LEPT_DLL extern NUMA * pixAverageByColumn ( PIX *pix, BOX *box, l_int32 type ); +LEPT_DLL extern l_int32 pixAverageInRect ( PIX *pix, BOX *box, l_float32 *pave ); +LEPT_DLL extern NUMA * pixVarianceByRow ( PIX *pix, BOX *box ); +LEPT_DLL extern NUMA * pixVarianceByColumn ( PIX *pix, BOX *box ); +LEPT_DLL extern l_int32 pixVarianceInRect ( PIX *pix, BOX *box, l_float32 *prootvar ); +LEPT_DLL extern NUMA * pixAbsDiffByRow ( PIX *pix, BOX *box ); +LEPT_DLL extern NUMA * pixAbsDiffByColumn ( PIX *pix, BOX *box ); +LEPT_DLL extern l_int32 pixAbsDiffInRect ( PIX *pix, BOX *box, l_int32 dir, l_float32 *pabsdiff ); +LEPT_DLL extern l_int32 pixAbsDiffOnLine ( PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_float32 *pabsdiff ); LEPT_DLL extern l_int32 pixCountArbInRect ( PIX *pixs, BOX *box, l_int32 val, l_int32 factor, l_int32 *pcount ); -LEPT_DLL extern l_int32 pixSumPixelValues ( PIX *pix, BOX *box, l_float64 *psum ); LEPT_DLL extern PIX * pixMirroredTiling ( PIX *pixs, l_int32 w, l_int32 h ); LEPT_DLL extern NUMA * pixGetGrayHistogram ( PIX *pixs, l_int32 factor ); LEPT_DLL extern NUMA * pixGetGrayHistogramMasked ( PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor ); @@ -1339,8 +1430,8 @@ LEPT_DLL extern l_int32 pixGetAverageMaskedRGB ( PIX *pixs, PIX *pixm, l_int32 x LEPT_DLL extern l_int32 pixGetAverageMasked ( PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, l_int32 type, l_float32 *pval ); LEPT_DLL extern l_int32 pixGetAverageTiledRGB ( PIX *pixs, l_int32 sx, l_int32 sy, l_int32 type, PIX **ppixr, PIX **ppixg, PIX **ppixb ); LEPT_DLL extern PIX * pixGetAverageTiled ( PIX *pixs, l_int32 sx, l_int32 sy, l_int32 type ); -LEPT_DLL extern l_int32 pixRowStats ( PIX *pixs, NUMA **pnamean, NUMA **pnamedian, NUMA **pnamode, NUMA **pnamodecount, NUMA **pnavar, NUMA **pnarootvar ); -LEPT_DLL extern l_int32 pixColumnStats ( PIX *pixs, NUMA **pnamean, NUMA **pnamedian, NUMA **pnamode, NUMA **pnamodecount, NUMA **pnavar, NUMA **pnarootvar ); +LEPT_DLL extern l_int32 pixRowStats ( PIX *pixs, BOX *box, NUMA **pnamean, NUMA **pnamedian, NUMA **pnamode, NUMA **pnamodecount, NUMA **pnavar, NUMA **pnarootvar ); +LEPT_DLL extern l_int32 pixColumnStats ( PIX *pixs, BOX *box, NUMA **pnamean, NUMA **pnamedian, NUMA **pnamode, NUMA **pnamodecount, NUMA **pnavar, NUMA **pnarootvar ); LEPT_DLL extern l_int32 pixGetComponentRange ( PIX *pixs, l_int32 factor, l_int32 color, l_int32 *pminval, l_int32 *pmaxval ); LEPT_DLL extern l_int32 pixGetExtremeValue ( PIX *pixs, l_int32 factor, l_int32 type, l_int32 *prval, l_int32 *pgval, l_int32 *pbval, l_int32 *pgrayval ); LEPT_DLL extern l_int32 pixGetMaxValueInRect ( PIX *pixs, BOX *box, l_uint32 *pmaxval, l_int32 *pxmax, l_int32 *pymax ); @@ -1356,21 +1447,28 @@ LEPT_DLL extern l_int32 pixSetPixelColumn ( PIX *pix, l_int32 col, l_float32 *co LEPT_DLL extern l_int32 pixThresholdForFgBg ( PIX *pixs, l_int32 factor, l_int32 thresh, l_int32 *pfgval, l_int32 *pbgval ); LEPT_DLL extern l_int32 pixSplitDistributionFgBg ( PIX *pixs, l_float32 scorefract, l_int32 factor, l_int32 *pthresh, l_int32 *pfgval, l_int32 *pbgval, l_int32 debugflag ); LEPT_DLL extern l_int32 pixaFindDimensions ( PIXA *pixa, NUMA **pnaw, NUMA **pnah ); -LEPT_DLL extern NUMA * pixaFindAreaPerimRatio ( PIXA *pixa ); LEPT_DLL extern l_int32 pixFindAreaPerimRatio ( PIX *pixs, l_int32 *tab, l_float32 *pfract ); +LEPT_DLL extern NUMA * pixaFindPerimToAreaRatio ( PIXA *pixa ); +LEPT_DLL extern l_int32 pixFindPerimToAreaRatio ( PIX *pixs, l_int32 *tab, l_float32 *pfract ); LEPT_DLL extern NUMA * pixaFindPerimSizeRatio ( PIXA *pixa ); LEPT_DLL extern l_int32 pixFindPerimSizeRatio ( PIX *pixs, l_int32 *tab, l_float32 *pratio ); LEPT_DLL extern NUMA * pixaFindAreaFraction ( PIXA *pixa ); LEPT_DLL extern l_int32 pixFindAreaFraction ( PIX *pixs, l_int32 *tab, l_float32 *pfract ); +LEPT_DLL extern NUMA * pixaFindAreaFractionMasked ( PIXA *pixa, PIX *pixm, l_int32 debug ); +LEPT_DLL extern l_int32 pixFindAreaFractionMasked ( PIX *pixs, BOX *box, PIX *pixm, l_int32 *tab, l_float32 *pfract ); LEPT_DLL extern NUMA * pixaFindWidthHeightRatio ( PIXA *pixa ); LEPT_DLL extern NUMA * pixaFindWidthHeightProduct ( PIXA *pixa ); LEPT_DLL extern l_int32 pixFindOverlapFraction ( PIX *pixs1, PIX *pixs2, l_int32 x2, l_int32 y2, l_int32 *tab, l_float32 *pratio, l_int32 *pnoverlap ); LEPT_DLL extern BOXA * pixFindRectangleComps ( PIX *pixs, l_int32 dist, l_int32 minw, l_int32 minh ); LEPT_DLL extern l_int32 pixConformsToRectangle ( PIX *pixs, BOX *box, l_int32 dist, l_int32 *pconforms ); +LEPT_DLL extern PIXA * pixClipRectangles ( PIX *pixs, BOXA *boxa ); LEPT_DLL extern PIX * pixClipRectangle ( PIX *pixs, BOX *box, BOX **pboxc ); LEPT_DLL extern PIX * pixClipMasked ( PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_uint32 outval ); +LEPT_DLL extern l_int32 pixCropToMatch ( PIX *pixs1, PIX *pixs2, PIX **ppixd1, PIX **ppixd2 ); +LEPT_DLL extern PIX * pixCropToSize ( PIX *pixs, l_int32 w, l_int32 h ); LEPT_DLL extern PIX * pixResizeToMatch ( PIX *pixs, PIX *pixt, l_int32 w, l_int32 h ); LEPT_DLL extern l_int32 pixClipToForeground ( PIX *pixs, PIX **ppixd, BOX **pbox ); +LEPT_DLL extern l_int32 pixTestClipToForeground ( PIX *pixs, l_int32 *pcanclip ); LEPT_DLL extern l_int32 pixClipBoxToForeground ( PIX *pixs, BOX *boxs, PIX **ppixd, BOX **pboxd ); LEPT_DLL extern l_int32 pixScanForForeground ( PIX *pixs, BOX *box, l_int32 scanflag, l_int32 *ploc ); LEPT_DLL extern l_int32 pixClipBoxToEdges ( PIX *pixs, BOX *boxs, l_int32 lowthresh, l_int32 highthresh, l_int32 maxwidth, l_int32 factor, PIX **ppixd, BOX **pboxd ); @@ -1379,6 +1477,8 @@ LEPT_DLL extern NUMA * pixExtractOnLine ( PIX *pixs, l_int32 x1, l_int32 y1, l_i LEPT_DLL extern l_float32 pixAverageOnLine ( PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 factor ); LEPT_DLL extern NUMA * pixAverageIntensityProfile ( PIX *pixs, l_float32 fract, l_int32 dir, l_int32 first, l_int32 last, l_int32 factor1, l_int32 factor2 ); LEPT_DLL extern NUMA * pixReversalProfile ( PIX *pixs, l_float32 fract, l_int32 dir, l_int32 first, l_int32 last, l_int32 minreversal, l_int32 factor1, l_int32 factor2 ); +LEPT_DLL extern l_int32 pixWindowedVarianceOnLine ( PIX *pixs, l_int32 dir, l_int32 loc, l_int32 c1, l_int32 c2, l_int32 size, NUMA **pnad ); +LEPT_DLL extern l_int32 pixMinMaxNearLine ( PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 dist, l_int32 direction, NUMA **pnamin, NUMA **pnamax, l_float32 *pminave, l_float32 *pmaxave ); LEPT_DLL extern PIX * pixRankRowTransform ( PIX *pixs ); LEPT_DLL extern PIX * pixRankColumnTransform ( PIX *pixs ); LEPT_DLL extern PIXA * pixaCreate ( l_int32 n ); @@ -1388,9 +1488,8 @@ LEPT_DLL extern PIXA * pixaSplitPix ( PIX *pixs, l_int32 nx, l_int32 ny, l_int32 LEPT_DLL extern void pixaDestroy ( PIXA **ppixa ); LEPT_DLL extern PIXA * pixaCopy ( PIXA *pixa, l_int32 copyflag ); LEPT_DLL extern l_int32 pixaAddPix ( PIXA *pixa, PIX *pix, l_int32 copyflag ); -LEPT_DLL extern l_int32 pixaExtendArray ( PIXA *pixa ); -LEPT_DLL extern l_int32 pixaExtendArrayToSize ( PIXA *pixa, l_int32 size ); LEPT_DLL extern l_int32 pixaAddBox ( PIXA *pixa, BOX *box, l_int32 copyflag ); +LEPT_DLL extern l_int32 pixaExtendArrayToSize ( PIXA *pixa, l_int32 size ); LEPT_DLL extern l_int32 pixaGetCount ( PIXA *pixa ); LEPT_DLL extern l_int32 pixaChangeRefcount ( PIXA *pixa, l_int32 delta ); LEPT_DLL extern PIX * pixaGetPix ( PIXA *pixa, l_int32 index, l_int32 accesstype ); @@ -1399,33 +1498,48 @@ LEPT_DLL extern BOXA * pixaGetBoxa ( PIXA *pixa, l_int32 accesstype ); LEPT_DLL extern l_int32 pixaGetBoxaCount ( PIXA *pixa ); LEPT_DLL extern BOX * pixaGetBox ( PIXA *pixa, l_int32 index, l_int32 accesstype ); LEPT_DLL extern l_int32 pixaGetBoxGeometry ( PIXA *pixa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph ); +LEPT_DLL extern l_int32 pixaSetBoxa ( PIXA *pixa, BOXA *boxa, l_int32 accesstype ); LEPT_DLL extern PIX ** pixaGetPixArray ( PIXA *pixa ); +LEPT_DLL extern l_int32 pixaVerifyDepth ( PIXA *pixa, l_int32 *pmaxdepth ); +LEPT_DLL extern l_int32 pixaIsFull ( PIXA *pixa, l_int32 *pfullpa, l_int32 *pfullba ); +LEPT_DLL extern l_int32 pixaCountText ( PIXA *pixa, l_int32 *pntext ); +LEPT_DLL extern void *** pixaGetLinePtrs ( PIXA *pixa, l_int32 *psize ); LEPT_DLL extern l_int32 pixaReplacePix ( PIXA *pixa, l_int32 index, PIX *pix, BOX *box ); LEPT_DLL extern l_int32 pixaInsertPix ( PIXA *pixa, l_int32 index, PIX *pixs, BOX *box ); LEPT_DLL extern l_int32 pixaRemovePix ( PIXA *pixa, l_int32 index ); +LEPT_DLL extern l_int32 pixaRemovePixAndSave ( PIXA *pixa, l_int32 index, PIX **ppix, BOX **pbox ); LEPT_DLL extern l_int32 pixaInitFull ( PIXA *pixa, PIX *pix, BOX *box ); LEPT_DLL extern l_int32 pixaClear ( PIXA *pixa ); LEPT_DLL extern l_int32 pixaJoin ( PIXA *pixad, PIXA *pixas, l_int32 istart, l_int32 iend ); +LEPT_DLL extern l_int32 pixaaJoin ( PIXAA *paad, PIXAA *paas, l_int32 istart, l_int32 iend ); LEPT_DLL extern PIXAA * pixaaCreate ( l_int32 n ); LEPT_DLL extern PIXAA * pixaaCreateFromPixa ( PIXA *pixa, l_int32 n, l_int32 type, l_int32 copyflag ); -LEPT_DLL extern void pixaaDestroy ( PIXAA **ppixaa ); -LEPT_DLL extern l_int32 pixaaAddPixa ( PIXAA *pixaa, PIXA *pixa, l_int32 copyflag ); -LEPT_DLL extern l_int32 pixaaExtendArray ( PIXAA *pixaa ); -LEPT_DLL extern l_int32 pixaaAddBox ( PIXAA *pixaa, BOX *box, l_int32 copyflag ); -LEPT_DLL extern l_int32 pixaaGetCount ( PIXAA *pixaa ); -LEPT_DLL extern PIXA * pixaaGetPixa ( PIXAA *pixaa, l_int32 index, l_int32 accesstype ); -LEPT_DLL extern BOXA * pixaaGetBoxa ( PIXAA *pixaa, l_int32 accesstype ); -LEPT_DLL extern PIX * pixaaGetPix ( PIXAA *paa, l_int32 ipixa, l_int32 ipix, l_int32 accessflag ); +LEPT_DLL extern void pixaaDestroy ( PIXAA **ppaa ); +LEPT_DLL extern l_int32 pixaaAddPixa ( PIXAA *paa, PIXA *pixa, l_int32 copyflag ); +LEPT_DLL extern l_int32 pixaaExtendArray ( PIXAA *paa ); +LEPT_DLL extern l_int32 pixaaAddPix ( PIXAA *paa, l_int32 index, PIX *pix, BOX *box, l_int32 copyflag ); +LEPT_DLL extern l_int32 pixaaAddBox ( PIXAA *paa, BOX *box, l_int32 copyflag ); +LEPT_DLL extern l_int32 pixaaGetCount ( PIXAA *paa, NUMA **pna ); +LEPT_DLL extern PIXA * pixaaGetPixa ( PIXAA *paa, l_int32 index, l_int32 accesstype ); +LEPT_DLL extern BOXA * pixaaGetBoxa ( PIXAA *paa, l_int32 accesstype ); +LEPT_DLL extern PIX * pixaaGetPix ( PIXAA *paa, l_int32 index, l_int32 ipix, l_int32 accessflag ); +LEPT_DLL extern l_int32 pixaaVerifyDepth ( PIXAA *paa, l_int32 *pmaxdepth ); +LEPT_DLL extern l_int32 pixaaIsFull ( PIXAA *paa, l_int32 *pfull ); +LEPT_DLL extern l_int32 pixaaInitFull ( PIXAA *paa, PIXA *pixa ); +LEPT_DLL extern l_int32 pixaaReplacePixa ( PIXAA *paa, l_int32 index, PIXA *pixa ); +LEPT_DLL extern l_int32 pixaaClear ( PIXAA *paa ); +LEPT_DLL extern l_int32 pixaaTruncate ( PIXAA *paa ); LEPT_DLL extern PIXA * pixaRead ( const char *filename ); LEPT_DLL extern PIXA * pixaReadStream ( FILE *fp ); LEPT_DLL extern l_int32 pixaWrite ( const char *filename, PIXA *pixa ); LEPT_DLL extern l_int32 pixaWriteStream ( FILE *fp, PIXA *pixa ); +LEPT_DLL extern PIXAA * pixaaReadFromFiles ( const char *dirname, const char *substr, l_int32 first, l_int32 nfiles ); LEPT_DLL extern PIXAA * pixaaRead ( const char *filename ); LEPT_DLL extern PIXAA * pixaaReadStream ( FILE *fp ); -LEPT_DLL extern l_int32 pixaaWrite ( const char *filename, PIXAA *pixaa ); -LEPT_DLL extern l_int32 pixaaWriteStream ( FILE *fp, PIXAA *pixaa ); +LEPT_DLL extern l_int32 pixaaWrite ( const char *filename, PIXAA *paa ); +LEPT_DLL extern l_int32 pixaaWriteStream ( FILE *fp, PIXAA *paa ); LEPT_DLL extern PIXACC * pixaccCreate ( l_int32 w, l_int32 h, l_int32 negflag ); -LEPT_DLL extern PIXACC * pixaccCreateWithPix ( PIX *pix, l_int32 negflag ); +LEPT_DLL extern PIXACC * pixaccCreateFromPix ( PIX *pix, l_int32 negflag ); LEPT_DLL extern void pixaccDestroy ( PIXACC **ppixacc ); LEPT_DLL extern PIX * pixaccFinal ( PIXACC *pixacc, l_int32 outdepth ); LEPT_DLL extern PIX * pixaccGetPix ( PIXACC *pixacc ); @@ -1436,8 +1550,11 @@ LEPT_DLL extern l_int32 pixaccMultConst ( PIXACC *pixacc, l_float32 factor ); LEPT_DLL extern l_int32 pixaccMultConstAccumulate ( PIXACC *pixacc, PIX *pix, l_float32 factor ); LEPT_DLL extern PIX * pixSelectBySize ( PIX *pixs, l_int32 width, l_int32 height, l_int32 connectivity, l_int32 type, l_int32 relation, l_int32 *pchanged ); LEPT_DLL extern PIXA * pixaSelectBySize ( PIXA *pixas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged ); -LEPT_DLL extern PIX * pixSelectByAreaPerimRatio ( PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged ); -LEPT_DLL extern PIXA * pixaSelectByAreaPerimRatio ( PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged ); +LEPT_DLL extern NUMA * pixaMakeSizeIndicator ( PIXA *pixa, l_int32 width, l_int32 height, l_int32 type, l_int32 relation ); +LEPT_DLL extern PIX * pixSelectByPerimToAreaRatio ( PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged ); +LEPT_DLL extern PIXA * pixaSelectByPerimToAreaRatio ( PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged ); +LEPT_DLL extern PIX * pixSelectByPerimSizeRatio ( PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged ); +LEPT_DLL extern PIXA * pixaSelectByPerimSizeRatio ( PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged ); LEPT_DLL extern PIX * pixSelectByAreaFraction ( PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged ); LEPT_DLL extern PIXA * pixaSelectByAreaFraction ( PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged ); LEPT_DLL extern PIX * pixSelectByWidthHeightRatio ( PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged ); @@ -1450,24 +1567,40 @@ LEPT_DLL extern PIXA * pixaSort ( PIXA *pixas, l_int32 sorttype, l_int32 sortord LEPT_DLL extern PIXA * pixaBinSort ( PIXA *pixas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex, l_int32 copyflag ); LEPT_DLL extern PIXA * pixaSortByIndex ( PIXA *pixas, NUMA *naindex, l_int32 copyflag ); LEPT_DLL extern PIXAA * pixaSort2dByIndex ( PIXA *pixas, NUMAA *naa, l_int32 copyflag ); +LEPT_DLL extern PIXA * pixaSelectRange ( PIXA *pixas, l_int32 first, l_int32 last, l_int32 copyflag ); +LEPT_DLL extern PIXAA * pixaaSelectRange ( PIXAA *paas, l_int32 first, l_int32 last, l_int32 copyflag ); +LEPT_DLL extern PIXAA * pixaaScaleToSize ( PIXAA *paas, l_int32 wd, l_int32 hd ); +LEPT_DLL extern PIXAA * pixaaScaleToSizeVar ( PIXAA *paas, NUMA *nawd, NUMA *nahd ); +LEPT_DLL extern PIXA * pixaScaleToSize ( PIXA *pixas, l_int32 wd, l_int32 hd ); LEPT_DLL extern PIXA * pixaAddBorderGeneral ( PIXA *pixad, PIXA *pixas, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val ); -LEPT_DLL extern PIXA * pixaaFlattenToPixa ( PIXAA *pixaa, NUMA **pnaindex, l_int32 copyflag ); +LEPT_DLL extern PIXA * pixaaFlattenToPixa ( PIXAA *paa, NUMA **pnaindex, l_int32 copyflag ); +LEPT_DLL extern l_int32 pixaaSizeRange ( PIXAA *paa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh ); LEPT_DLL extern l_int32 pixaSizeRange ( PIXA *pixa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh ); LEPT_DLL extern PIXA * pixaClipToPix ( PIXA *pixas, PIX *pixs ); +LEPT_DLL extern l_int32 pixaGetRenderingDepth ( PIXA *pixa, l_int32 *pdepth ); +LEPT_DLL extern l_int32 pixaHasColor ( PIXA *pixa, l_int32 *phascolor ); LEPT_DLL extern l_int32 pixaAnyColormaps ( PIXA *pixa, l_int32 *phascmap ); LEPT_DLL extern l_int32 pixaGetDepthInfo ( PIXA *pixa, l_int32 *pmaxdepth, l_int32 *psame ); +LEPT_DLL extern PIXA * pixaConvertToSameDepth ( PIXA *pixas ); LEPT_DLL extern l_int32 pixaEqual ( PIXA *pixa1, PIXA *pixa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame ); LEPT_DLL extern PIX * pixaDisplay ( PIXA *pixa, l_int32 w, l_int32 h ); LEPT_DLL extern PIX * pixaDisplayOnColor ( PIXA *pixa, l_int32 w, l_int32 h, l_uint32 bgcolor ); LEPT_DLL extern PIX * pixaDisplayRandomCmap ( PIXA *pixa, l_int32 w, l_int32 h ); -LEPT_DLL extern PIX * pixaDisplayOnLattice ( PIXA *pixa, l_int32 xspace, l_int32 yspace ); +LEPT_DLL extern PIX * pixaDisplayLinearly ( PIXA *pixas, l_int32 direction, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border, BOXA **pboxa ); +LEPT_DLL extern PIX * pixaDisplayOnLattice ( PIXA *pixa, l_int32 cellw, l_int32 cellh, l_int32 *pncols, BOXA **pboxa ); LEPT_DLL extern PIX * pixaDisplayUnsplit ( PIXA *pixa, l_int32 nx, l_int32 ny, l_int32 borderwidth, l_uint32 bordercolor ); LEPT_DLL extern PIX * pixaDisplayTiled ( PIXA *pixa, l_int32 maxwidth, l_int32 background, l_int32 spacing ); LEPT_DLL extern PIX * pixaDisplayTiledInRows ( PIXA *pixa, l_int32 outdepth, l_int32 maxwidth, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border ); LEPT_DLL extern PIX * pixaDisplayTiledAndScaled ( PIXA *pixa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border ); -LEPT_DLL extern PIX * pixaaDisplay ( PIXAA *pixaa, l_int32 w, l_int32 h ); -LEPT_DLL extern PIX * pixaaDisplayByPixa ( PIXAA *pixaa, l_int32 xspace, l_int32 yspace, l_int32 maxw ); -LEPT_DLL extern PIXA * pixaaDisplayTiledAndScaled ( PIXAA *pixaa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border ); +LEPT_DLL extern PIX * pixaaDisplay ( PIXAA *paa, l_int32 w, l_int32 h ); +LEPT_DLL extern PIX * pixaaDisplayByPixa ( PIXAA *paa, l_int32 xspace, l_int32 yspace, l_int32 maxw ); +LEPT_DLL extern PIXA * pixaaDisplayTiledAndScaled ( PIXAA *paa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border ); +LEPT_DLL extern PIXA * pixaConvertTo1 ( PIXA *pixas, l_int32 thresh ); +LEPT_DLL extern PIXA * pixaConvertTo8 ( PIXA *pixas, l_int32 cmapflag ); +LEPT_DLL extern PIXA * pixaConvertTo8Color ( PIXA *pixas, l_int32 dither ); +LEPT_DLL extern PIXA * pixaConvertTo32 ( PIXA *pixas ); +LEPT_DLL extern l_int32 convertToNUpFiles ( const char *dir, const char *substr, l_int32 nx, l_int32 ny, l_int32 tw, l_int32 spacing, l_int32 border, const char *fontdir, const char *outdir ); +LEPT_DLL extern PIXA * convertToNUpPixa ( const char *dir, const char *substr, l_int32 nx, l_int32 ny, l_int32 tw, l_int32 spacing, l_int32 border, const char *fontdir ); LEPT_DLL extern l_int32 pmsCreate ( size_t minsize, size_t smallest, NUMA *numalloc, const char *logfile ); LEPT_DLL extern void pmsDestroy ( ); LEPT_DLL extern void * pmsCustomAlloc ( size_t nbytes ); @@ -1487,6 +1620,7 @@ LEPT_DLL extern PIX * pixFinalAccumulateThreshold ( PIX *pixs, l_uint32 offset, LEPT_DLL extern l_int32 pixAccumulate ( PIX *pixd, PIX *pixs, l_int32 op ); LEPT_DLL extern l_int32 pixMultConstAccumulate ( PIX *pixs, l_float32 factor, l_uint32 offset ); LEPT_DLL extern PIX * pixAbsDifference ( PIX *pixs1, PIX *pixs2 ); +LEPT_DLL extern PIX * pixAddRGB ( PIX *pixs1, PIX *pixs2 ); LEPT_DLL extern PIX * pixMinOrMax ( PIX *pixd, PIX *pixs1, PIX *pixs2, l_int32 type ); LEPT_DLL extern PIX * pixMaxDynamicRange ( PIX *pixs, l_int32 type ); LEPT_DLL extern l_float32 * makeLogBase2Tab ( void ); @@ -1499,14 +1633,13 @@ LEPT_DLL extern l_int32 pixcompGetDimensions ( PIXC *pixc, l_int32 *pw, l_int32 LEPT_DLL extern l_int32 pixcompDetermineFormat ( l_int32 comptype, l_int32 d, l_int32 cmapflag, l_int32 *pformat ); LEPT_DLL extern PIX * pixCreateFromPixcomp ( PIXC *pixc ); LEPT_DLL extern PIXAC * pixacompCreate ( l_int32 n ); -LEPT_DLL extern PIXAC * pixacompCreateInitialized ( l_int32 n, l_int32 offset, PIX *pix, l_int32 comptype ); +LEPT_DLL extern PIXAC * pixacompCreateWithInit ( l_int32 n, l_int32 offset, PIX *pix, l_int32 comptype ); LEPT_DLL extern PIXAC * pixacompCreateFromPixa ( PIXA *pixa, l_int32 comptype, l_int32 accesstype ); LEPT_DLL extern PIXAC * pixacompCreateFromFiles ( const char *dirname, const char *substr, l_int32 comptype ); LEPT_DLL extern PIXAC * pixacompCreateFromSA ( SARRAY *sa, l_int32 comptype ); LEPT_DLL extern void pixacompDestroy ( PIXAC **ppixac ); LEPT_DLL extern l_int32 pixacompAddPix ( PIXAC *pixac, PIX *pix, l_int32 comptype ); LEPT_DLL extern l_int32 pixacompAddPixcomp ( PIXAC *pixac, PIXC *pixc ); -LEPT_DLL extern l_int32 pixacompExtendArray ( PIXAC *pixac ); LEPT_DLL extern l_int32 pixacompReplacePix ( PIXAC *pixac, l_int32 index, PIX *pix, l_int32 comptype ); LEPT_DLL extern l_int32 pixacompReplacePixcomp ( PIXAC *pixac, l_int32 index, PIXC *pixc ); LEPT_DLL extern l_int32 pixacompAddBox ( PIXAC *pixac, BOX *box, l_int32 copyflag ); @@ -1531,6 +1664,7 @@ LEPT_DLL extern l_int32 pixacompWriteStreamInfo ( FILE *fp, PIXAC *pixac, const LEPT_DLL extern l_int32 pixcompWriteStreamInfo ( FILE *fp, PIXC *pixc, const char *text ); LEPT_DLL extern PIX * pixacompDisplayTiledAndScaled ( PIXAC *pixac, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border ); LEPT_DLL extern PIX * pixThreshold8 ( PIX *pixs, l_int32 d, l_int32 nlevels, l_int32 cmapflag ); +LEPT_DLL extern PIX * pixRemoveColormapGeneral ( PIX *pixs, l_int32 type, l_int32 ifnocmap ); LEPT_DLL extern PIX * pixRemoveColormap ( PIX *pixs, l_int32 type ); LEPT_DLL extern l_int32 pixAddGrayColormap8 ( PIX *pixs ); LEPT_DLL extern PIX * pixAddMinimalGrayColormap8 ( PIX *pixs ); @@ -1538,12 +1672,13 @@ LEPT_DLL extern PIX * pixConvertRGBToLuminance ( PIX *pixs ); LEPT_DLL extern PIX * pixConvertRGBToGray ( PIX *pixs, l_float32 rwt, l_float32 gwt, l_float32 bwt ); LEPT_DLL extern PIX * pixConvertRGBToGrayFast ( PIX *pixs ); LEPT_DLL extern PIX * pixConvertRGBToGrayMinMax ( PIX *pixs, l_int32 type ); +LEPT_DLL extern PIX * pixConvertRGBToGraySatBoost ( PIX *pixs, l_int32 refval ); LEPT_DLL extern PIX * pixConvertGrayToColormap ( PIX *pixs ); LEPT_DLL extern PIX * pixConvertGrayToColormap8 ( PIX *pixs, l_int32 mindepth ); LEPT_DLL extern PIX * pixColorizeGray ( PIX *pixs, l_uint32 color, l_int32 cmapflag ); LEPT_DLL extern PIX * pixConvertRGBToColormap ( PIX *pixs, l_int32 ditherflag ); LEPT_DLL extern l_int32 pixQuantizeIfFewColors ( PIX *pixs, l_int32 maxcolors, l_int32 mingraycolors, l_int32 octlevel, PIX **ppixd ); -LEPT_DLL extern PIX * pixConvert16To8 ( PIX *pixs, l_int32 whichbyte ); +LEPT_DLL extern PIX * pixConvert16To8 ( PIX *pixs, l_int32 type ); LEPT_DLL extern PIX * pixConvertGrayToFalseColor ( PIX *pixs, l_float32 gamma ); LEPT_DLL extern PIX * pixUnpackBinary ( PIX *pixs, l_int32 depth, l_int32 invert ); LEPT_DLL extern PIX * pixConvert1To16 ( PIX *pixd, PIX *pixs, l_uint16 val0, l_uint16 val1 ); @@ -1560,6 +1695,7 @@ LEPT_DLL extern PIX * pixConvertTo1 ( PIX *pixs, l_int32 threshold ); LEPT_DLL extern PIX * pixConvertTo1BySampling ( PIX *pixs, l_int32 factor, l_int32 threshold ); LEPT_DLL extern PIX * pixConvertTo8 ( PIX *pixs, l_int32 cmapflag ); LEPT_DLL extern PIX * pixConvertTo8BySampling ( PIX *pixs, l_int32 factor, l_int32 cmapflag ); +LEPT_DLL extern PIX * pixConvertTo8Color ( PIX *pixs, l_int32 dither ); LEPT_DLL extern PIX * pixConvertTo16 ( PIX *pixs ); LEPT_DLL extern PIX * pixConvertTo32 ( PIX *pixs ); LEPT_DLL extern PIX * pixConvertTo32BySampling ( PIX *pixs, l_int32 factor ); @@ -1567,11 +1703,15 @@ LEPT_DLL extern PIX * pixConvert8To32 ( PIX *pixs ); LEPT_DLL extern PIX * pixConvertTo8Or32 ( PIX *pixs, l_int32 copyflag, l_int32 warnflag ); LEPT_DLL extern PIX * pixConvert24To32 ( PIX *pixs ); LEPT_DLL extern PIX * pixConvert32To24 ( PIX *pixs ); +LEPT_DLL extern PIX * pixRemoveAlpha ( PIX *pixs ); LEPT_DLL extern PIX * pixConvertLossless ( PIX *pixs, l_int32 d ); LEPT_DLL extern PIX * pixConvertForPSWrap ( PIX *pixs ); LEPT_DLL extern PIX * pixConvertToSubpixelRGB ( PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order ); LEPT_DLL extern PIX * pixConvertGrayToSubpixelRGB ( PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order ); LEPT_DLL extern PIX * pixConvertColorToSubpixelRGB ( PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order ); +LEPT_DLL extern PIX * pixConnCompTransform ( PIX *pixs, l_int32 connect, l_int32 depth ); +LEPT_DLL extern PIX * pixConnCompAreaTransform ( PIX *pixs, l_int32 connect ); +LEPT_DLL extern PIX * pixLocToColorTransform ( PIX *pixs ); LEPT_DLL extern PIXTILING * pixTilingCreate ( PIX *pixs, l_int32 nx, l_int32 ny, l_int32 w, l_int32 h, l_int32 xoverlap, l_int32 yoverlap ); LEPT_DLL extern void pixTilingDestroy ( PIXTILING **ppt ); LEPT_DLL extern l_int32 pixTilingGetCount ( PIXTILING *pt, l_int32 *pnx, l_int32 *pny ); @@ -1580,27 +1720,23 @@ LEPT_DLL extern PIX * pixTilingGetTile ( PIXTILING *pt, l_int32 i, l_int32 j ); LEPT_DLL extern l_int32 pixTilingNoStripOnPaint ( PIXTILING *pt ); LEPT_DLL extern l_int32 pixTilingPaintTile ( PIX *pixd, l_int32 i, l_int32 j, PIX *pixs, PIXTILING *pt ); LEPT_DLL extern PIX * pixReadStreamPng ( FILE *fp ); -LEPT_DLL extern l_int32 readHeaderPng ( const char *filename, l_int32 *pwidth, l_int32 *pheight, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap ); -LEPT_DLL extern l_int32 freadHeaderPng ( FILE *fp, l_int32 *pwidth, l_int32 *pheight, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap ); -LEPT_DLL extern l_int32 sreadHeaderPng ( const l_uint8 *data, l_int32 *pwidth, l_int32 *pheight, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap ); +LEPT_DLL extern l_int32 readHeaderPng ( const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap ); +LEPT_DLL extern l_int32 freadHeaderPng ( FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap ); +LEPT_DLL extern l_int32 sreadHeaderPng ( const l_uint8 *data, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap ); LEPT_DLL extern l_int32 fgetPngResolution ( FILE *fp, l_int32 *pxres, l_int32 *pyres ); LEPT_DLL extern l_int32 pixWritePng ( const char *filename, PIX *pix, l_float32 gamma ); LEPT_DLL extern l_int32 pixWriteStreamPng ( FILE *fp, PIX *pix, l_float32 gamma ); -LEPT_DLL extern PIX * pixReadRGBAPng ( const char *filename ); -LEPT_DLL extern l_int32 pixWriteRGBAPng ( const char *filename, PIX *pix ); -LEPT_DLL extern void l_pngSetStrip16To8 ( l_int32 flag ); -LEPT_DLL extern void l_pngSetStripAlpha ( l_int32 flag ); -LEPT_DLL extern void l_pngSetWriteAlpha ( l_int32 flag ); -LEPT_DLL extern void l_pngSetZlibCompression ( l_int32 val ); +LEPT_DLL extern l_int32 pixSetZlibCompression ( PIX *pix, l_int32 compval ); +LEPT_DLL extern void l_pngSetReadStrip16To8 ( l_int32 flag ); LEPT_DLL extern PIX * pixReadMemPng ( const l_uint8 *cdata, size_t size ); LEPT_DLL extern l_int32 pixWriteMemPng ( l_uint8 **pdata, size_t *psize, PIX *pix, l_float32 gamma ); LEPT_DLL extern PIX * pixReadStreamPnm ( FILE *fp ); -LEPT_DLL extern l_int32 readHeaderPnm ( const char *filename, PIX **ppix, l_int32 *pwidth, l_int32 *pheight, l_int32 *pdepth, l_int32 *ptype, l_int32 *pbps, l_int32 *pspp ); -LEPT_DLL extern l_int32 freadHeaderPnm ( FILE *fp, PIX **ppix, l_int32 *pwidth, l_int32 *pheight, l_int32 *pdepth, l_int32 *ptype, l_int32 *pbps, l_int32 *pspp ); +LEPT_DLL extern l_int32 readHeaderPnm ( const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pd, l_int32 *ptype, l_int32 *pbps, l_int32 *pspp ); +LEPT_DLL extern l_int32 freadHeaderPnm ( FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pd, l_int32 *ptype, l_int32 *pbps, l_int32 *pspp ); LEPT_DLL extern l_int32 pixWriteStreamPnm ( FILE *fp, PIX *pix ); LEPT_DLL extern l_int32 pixWriteStreamAsciiPnm ( FILE *fp, PIX *pix ); LEPT_DLL extern PIX * pixReadMemPnm ( const l_uint8 *cdata, size_t size ); -LEPT_DLL extern l_int32 sreadHeaderPnm ( const l_uint8 *cdata, size_t size, l_int32 *pwidth, l_int32 *pheight, l_int32 *pdepth, l_int32 *ptype, l_int32 *pbps, l_int32 *pspp ); +LEPT_DLL extern l_int32 sreadHeaderPnm ( const l_uint8 *cdata, size_t size, l_int32 *pw, l_int32 *ph, l_int32 *pd, l_int32 *ptype, l_int32 *pbps, l_int32 *pspp ); LEPT_DLL extern l_int32 pixWriteMemPnm ( l_uint8 **pdata, size_t *psize, PIX *pix ); LEPT_DLL extern PIX * pixProjectiveSampledPta ( PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor ); LEPT_DLL extern PIX * pixProjectiveSampled ( PIX *pixs, l_float32 *vc, l_int32 incolor ); @@ -1611,7 +1747,6 @@ LEPT_DLL extern PIX * pixProjectiveColor ( PIX *pixs, l_float32 *vc, l_uint32 co LEPT_DLL extern PIX * pixProjectivePtaGray ( PIX *pixs, PTA *ptad, PTA *ptas, l_uint8 grayval ); LEPT_DLL extern PIX * pixProjectiveGray ( PIX *pixs, l_float32 *vc, l_uint8 grayval ); LEPT_DLL extern PIX * pixProjectivePtaWithAlpha ( PIX *pixs, PTA *ptad, PTA *ptas, PIX *pixg, l_float32 fract, l_int32 border ); -LEPT_DLL extern PIX * pixProjectivePtaGammaXform ( PIX *pixs, l_float32 gamma, PTA *ptad, PTA *ptas, l_float32 fract, l_int32 border ); LEPT_DLL extern l_int32 getProjectiveXformCoeffs ( PTA *ptas, PTA *ptad, l_float32 **pvc ); LEPT_DLL extern l_int32 projectiveXformSampledPt ( l_float32 *vc, l_int32 x, l_int32 y, l_int32 *pxp, l_int32 *pyp ); LEPT_DLL extern l_int32 projectiveXformPt ( l_float32 *vc, l_int32 x, l_int32 y, l_float32 *pxp, l_float32 *pyp ); @@ -1634,23 +1769,25 @@ LEPT_DLL extern void convertByteToHexAscii ( l_uint8 byteval, char *pnib1, char LEPT_DLL extern l_int32 convertJpegToPSEmbed ( const char *filein, const char *fileout ); LEPT_DLL extern l_int32 convertJpegToPS ( const char *filein, const char *fileout, const char *operation, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 endpage ); LEPT_DLL extern l_int32 convertJpegToPSString ( const char *filein, char **poutstr, l_int32 *pnbytes, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 endpage ); -LEPT_DLL extern char * generateJpegPS ( const char *filein, L_COMPRESSED_DATA *cid, l_float32 xpt, l_float32 ypt, l_float32 wpt, l_float32 hpt, l_int32 pageno, l_int32 endpage ); -LEPT_DLL extern L_COMPRESSED_DATA * pixGenerateJpegData ( PIX *pixs, l_int32 ascii85flag, l_int32 quality ); -LEPT_DLL extern L_COMPRESSED_DATA * l_generateJpegData ( const char *fname, l_int32 ascii85flag ); -LEPT_DLL extern void compressed_dataDestroy ( L_COMPRESSED_DATA **pcid ); +LEPT_DLL extern char * generateJpegPS ( const char *filein, L_COMP_DATA *cid, l_float32 xpt, l_float32 ypt, l_float32 wpt, l_float32 hpt, l_int32 pageno, l_int32 endpage ); +LEPT_DLL extern L_COMP_DATA * pixGenerateJpegData ( PIX *pixs, l_int32 ascii85flag, l_int32 quality ); +LEPT_DLL extern L_COMP_DATA * l_generateJpegData ( const char *fname, l_int32 ascii85flag ); +LEPT_DLL extern void l_compdataDestroy ( L_COMP_DATA **pcid ); LEPT_DLL extern l_int32 convertG4ToPSEmbed ( const char *filein, const char *fileout ); LEPT_DLL extern l_int32 convertG4ToPS ( const char *filein, const char *fileout, const char *operation, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 maskflag, l_int32 endpage ); LEPT_DLL extern l_int32 convertG4ToPSString ( const char *filein, char **poutstr, l_int32 *pnbytes, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 maskflag, l_int32 endpage ); -LEPT_DLL extern char * generateG4PS ( const char *filein, L_COMPRESSED_DATA *cid, l_float32 xpt, l_float32 ypt, l_float32 wpt, l_float32 hpt, l_int32 maskflag, l_int32 pageno, l_int32 endpage ); -LEPT_DLL extern L_COMPRESSED_DATA * pixGenerateG4Data ( PIX *pixs, l_int32 ascii85flag ); -LEPT_DLL extern L_COMPRESSED_DATA * l_generateG4Data ( const char *fname, l_int32 ascii85flag ); +LEPT_DLL extern char * generateG4PS ( const char *filein, L_COMP_DATA *cid, l_float32 xpt, l_float32 ypt, l_float32 wpt, l_float32 hpt, l_int32 maskflag, l_int32 pageno, l_int32 endpage ); +LEPT_DLL extern L_COMP_DATA * pixGenerateG4Data ( PIX *pixs, l_int32 ascii85flag ); +LEPT_DLL extern L_COMP_DATA * l_generateG4Data ( const char *fname, l_int32 ascii85flag ); LEPT_DLL extern l_int32 convertTiffMultipageToPS ( const char *filein, const char *fileout, const char *tempfile, l_float32 fillfract ); LEPT_DLL extern l_int32 convertFlateToPSEmbed ( const char *filein, const char *fileout ); LEPT_DLL extern l_int32 convertFlateToPS ( const char *filein, const char *fileout, const char *operation, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 endpage ); LEPT_DLL extern l_int32 convertFlateToPSString ( const char *filein, char **poutstr, l_int32 *pnbytes, l_int32 x, l_int32 y, l_int32 res, l_float32 scale, l_int32 pageno, l_int32 endpage ); -LEPT_DLL extern char * generateFlatePS ( const char *filein, L_COMPRESSED_DATA *cid, l_float32 xpt, l_float32 ypt, l_float32 wpt, l_float32 hpt, l_int32 pageno, l_int32 endpage ); -LEPT_DLL extern L_COMPRESSED_DATA * l_generateFlateData ( const char *fname, l_int32 ascii85flag ); -LEPT_DLL extern L_COMPRESSED_DATA * pixGenerateFlateData ( PIX *pixs, l_int32 ascii85flag ); +LEPT_DLL extern char * generateFlatePS ( const char *filein, L_COMP_DATA *cid, l_float32 xpt, l_float32 ypt, l_float32 wpt, l_float32 hpt, l_int32 pageno, l_int32 endpage ); +LEPT_DLL extern L_COMP_DATA * l_generateFlateData ( const char *fname, l_int32 ascii85flag ); +LEPT_DLL extern L_COMP_DATA * pixGenerateFlateData ( PIX *pixs, l_int32 ascii85flag ); +LEPT_DLL extern l_int32 l_generateCIData ( const char *fname, l_int32 type, l_int32 quality, l_int32 ascii85, L_COMP_DATA **pcid ); +LEPT_DLL extern l_int32 pixGenerateCIData ( PIX *pixs, l_int32 type, l_int32 quality, l_int32 ascii85, L_COMP_DATA **pcid ); LEPT_DLL extern l_int32 pixWriteMemPS ( l_uint8 **pdata, size_t *psize, PIX *pix, BOX *box, l_int32 res, l_float32 scale ); LEPT_DLL extern l_int32 getResLetterPage ( l_int32 w, l_int32 h, l_float32 fillfract ); LEPT_DLL extern l_int32 getResA4Page ( l_int32 w, l_int32 h, l_float32 fillfract ); @@ -1665,7 +1802,8 @@ LEPT_DLL extern PTA * ptaCopyRange ( PTA *ptas, l_int32 istart, l_int32 iend ); LEPT_DLL extern PTA * ptaClone ( PTA *pta ); LEPT_DLL extern l_int32 ptaEmpty ( PTA *pta ); LEPT_DLL extern l_int32 ptaAddPt ( PTA *pta, l_float32 x, l_float32 y ); -LEPT_DLL extern l_int32 ptaExtendArrays ( PTA *pta ); +LEPT_DLL extern l_int32 ptaInsertPt ( PTA *pta, l_int32 index, l_int32 x, l_int32 y ); +LEPT_DLL extern l_int32 ptaRemovePt ( PTA *pta, l_int32 index ); LEPT_DLL extern l_int32 ptaGetRefcount ( PTA *pta ); LEPT_DLL extern l_int32 ptaChangeRefcount ( PTA *pta, l_int32 delta ); LEPT_DLL extern l_int32 ptaGetCount ( PTA *pta ); @@ -1680,16 +1818,20 @@ LEPT_DLL extern l_int32 ptaWriteStream ( FILE *fp, PTA *pta, l_int32 type ); LEPT_DLL extern PTAA * ptaaCreate ( l_int32 n ); LEPT_DLL extern void ptaaDestroy ( PTAA **pptaa ); LEPT_DLL extern l_int32 ptaaAddPta ( PTAA *ptaa, PTA *pta, l_int32 copyflag ); -LEPT_DLL extern l_int32 ptaaExtendArray ( PTAA *ptaa ); LEPT_DLL extern l_int32 ptaaGetCount ( PTAA *ptaa ); LEPT_DLL extern PTA * ptaaGetPta ( PTAA *ptaa, l_int32 index, l_int32 accessflag ); LEPT_DLL extern l_int32 ptaaGetPt ( PTAA *ptaa, l_int32 ipta, l_int32 jpt, l_float32 *px, l_float32 *py ); +LEPT_DLL extern l_int32 ptaaInitFull ( PTAA *ptaa, PTA *pta ); +LEPT_DLL extern l_int32 ptaaReplacePta ( PTAA *ptaa, l_int32 index, PTA *pta ); +LEPT_DLL extern l_int32 ptaaAddPt ( PTAA *ptaa, l_int32 ipta, l_float32 x, l_float32 y ); +LEPT_DLL extern l_int32 ptaaTruncate ( PTAA *ptaa ); LEPT_DLL extern PTAA * ptaaRead ( const char *filename ); LEPT_DLL extern PTAA * ptaaReadStream ( FILE *fp ); LEPT_DLL extern l_int32 ptaaWrite ( const char *filename, PTAA *ptaa, l_int32 type ); LEPT_DLL extern l_int32 ptaaWriteStream ( FILE *fp, PTAA *ptaa, l_int32 type ); LEPT_DLL extern PTA * ptaSubsample ( PTA *ptas, l_int32 subfactor ); LEPT_DLL extern l_int32 ptaJoin ( PTA *ptad, PTA *ptas, l_int32 istart, l_int32 iend ); +LEPT_DLL extern l_int32 ptaaJoin ( PTAA *ptaad, PTAA *ptaas, l_int32 istart, l_int32 iend ); LEPT_DLL extern PTA * ptaReverse ( PTA *ptas, l_int32 type ); LEPT_DLL extern PTA * ptaTranspose ( PTA *ptas ); LEPT_DLL extern PTA * ptaCyclicPerm ( PTA *ptas, l_int32 xs, l_int32 ys ); @@ -1705,6 +1847,8 @@ LEPT_DLL extern PTA * pixFindCornerPixels ( PIX *pixs ); LEPT_DLL extern l_int32 ptaContainsPt ( PTA *pta, l_int32 x, l_int32 y ); LEPT_DLL extern l_int32 ptaTestIntersection ( PTA *pta1, PTA *pta2 ); LEPT_DLL extern PTA * ptaTransform ( PTA *ptas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley ); +LEPT_DLL extern l_int32 ptaPtInsidePolygon ( PTA *pta, l_float32 x, l_float32 y, l_int32 *pinside ); +LEPT_DLL extern l_float32 l_angleBetweenVectors ( l_float32 x1, l_float32 y1, l_float32 x2, l_float32 y2 ); LEPT_DLL extern l_int32 ptaGetLinearLSF ( PTA *pta, l_float32 *pa, l_float32 *pb, NUMA **pnafit ); LEPT_DLL extern l_int32 ptaGetQuadraticLSF ( PTA *pta, l_float32 *pa, l_float32 *pb, l_float32 *pc, NUMA **pnafit ); LEPT_DLL extern l_int32 ptaGetCubicLSF ( PTA *pta, l_float32 *pa, l_float32 *pb, l_float32 *pc, l_float32 *pd, NUMA **pnafit ); @@ -1723,14 +1867,12 @@ LEPT_DLL extern PTAA * ptaaGetBoundaryPixels ( PIX *pixs, l_int32 type, l_int32 LEPT_DLL extern PIX * pixDisplayPta ( PIX *pixd, PIX *pixs, PTA *pta ); LEPT_DLL extern PIX * pixDisplayPtaaPattern ( PIX *pixd, PIX *pixs, PTAA *ptaa, PIX *pixp, l_int32 cx, l_int32 cy ); LEPT_DLL extern PIX * pixDisplayPtaPattern ( PIX *pixd, PIX *pixs, PTA *pta, PIX *pixp, l_int32 cx, l_int32 cy, l_uint32 color ); -LEPT_DLL extern PTA * ptaReplicatePattern ( PTA *ptas, PIX *pixp, l_int32 cx, l_int32 cy, l_int32 w, l_int32 h ); +LEPT_DLL extern PTA * ptaReplicatePattern ( PTA *ptas, PIX *pixp, PTA *ptap, l_int32 cx, l_int32 cy, l_int32 w, l_int32 h ); LEPT_DLL extern PIX * pixDisplayPtaa ( PIX *pixs, PTAA *ptaa ); LEPT_DLL extern L_PTRA * ptraCreate ( l_int32 n ); LEPT_DLL extern void ptraDestroy ( L_PTRA **ppa, l_int32 freeflag, l_int32 warnflag ); LEPT_DLL extern l_int32 ptraAdd ( L_PTRA *pa, void *item ); -LEPT_DLL extern l_int32 ptraExtendArray ( L_PTRA *pa ); LEPT_DLL extern l_int32 ptraInsert ( L_PTRA *pa, l_int32 index, void *item, l_int32 shiftflag ); -LEPT_DLL extern void * ptraGetHandle ( L_PTRA *pa, l_int32 index ); LEPT_DLL extern void * ptraRemove ( L_PTRA *pa, l_int32 index, l_int32 flag ); LEPT_DLL extern void * ptraRemoveLast ( L_PTRA *pa ); LEPT_DLL extern void * ptraReplace ( L_PTRA *pa, l_int32 index, void *item, l_int32 freeflag ); @@ -1759,7 +1901,6 @@ LEPT_DLL extern PIX * fpixaDisplayQuadtree ( FPIXA *fpixa, l_int32 factor ); LEPT_DLL extern L_QUEUE * lqueueCreate ( l_int32 nalloc ); LEPT_DLL extern void lqueueDestroy ( L_QUEUE **plq, l_int32 freeflag ); LEPT_DLL extern l_int32 lqueueAdd ( L_QUEUE *lq, void *item ); -LEPT_DLL extern l_int32 lqueueExtendArray ( L_QUEUE *lq ); LEPT_DLL extern void * lqueueRemove ( L_QUEUE *lq ); LEPT_DLL extern l_int32 lqueueGetCount ( L_QUEUE *lq ); LEPT_DLL extern l_int32 lqueuePrint ( FILE *fp, L_QUEUE *lq ); @@ -1793,9 +1934,90 @@ LEPT_DLL extern l_int32 fileFormatIsTiff ( FILE *fp ); LEPT_DLL extern PIX * pixReadMem ( const l_uint8 *data, size_t size ); LEPT_DLL extern l_int32 pixReadHeaderMem ( const l_uint8 *data, size_t size, l_int32 *pformat, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *piscmap ); LEPT_DLL extern l_int32 ioFormatTest ( const char *filename ); +LEPT_DLL extern L_RECOGA * recogaCreateFromRecog ( L_RECOG *recog ); +LEPT_DLL extern L_RECOGA * recogaCreateFromPixaa ( PIXAA *paa, l_int32 scalew, l_int32 scaleh, l_int32 templ_type, l_int32 threshold, l_int32 maxyshift, const char *fontdir ); +LEPT_DLL extern L_RECOGA * recogaCreate ( l_int32 n ); +LEPT_DLL extern void recogaDestroy ( L_RECOGA **precoga ); +LEPT_DLL extern l_int32 recogaAddRecog ( L_RECOGA *recoga, L_RECOG *recog ); +LEPT_DLL extern l_int32 recogReplaceInRecoga ( L_RECOG **precog1, L_RECOG *recog2 ); +LEPT_DLL extern L_RECOG * recogaGetRecog ( L_RECOGA *recoga, l_int32 index ); +LEPT_DLL extern l_int32 recogaGetCount ( L_RECOGA *recoga ); +LEPT_DLL extern l_int32 recogGetCount ( L_RECOG *recog ); +LEPT_DLL extern l_int32 recogGetIndex ( L_RECOG *recog, l_int32 *pindex ); +LEPT_DLL extern L_RECOGA * recogGetParent ( L_RECOG *recog ); +LEPT_DLL extern l_int32 recogSetBootflag ( L_RECOG *recog ); +LEPT_DLL extern L_RECOG * recogCreateFromRecog ( L_RECOG *recs, l_int32 scalew, l_int32 scaleh, l_int32 templ_type, l_int32 threshold, l_int32 maxyshift, const char *fontdir ); +LEPT_DLL extern L_RECOG * recogCreateFromPixa ( PIXA *pixa, l_int32 scalew, l_int32 scaleh, l_int32 templ_type, l_int32 threshold, l_int32 maxyshift, const char *fontdir ); +LEPT_DLL extern L_RECOG * recogCreate ( l_int32 scalew, l_int32 scaleh, l_int32 templ_type, l_int32 threshold, l_int32 maxyshift, const char *fontdir ); +LEPT_DLL extern void recogDestroy ( L_RECOG **precog ); +LEPT_DLL extern l_int32 recogAppend ( L_RECOG *recog1, L_RECOG *recog2 ); +LEPT_DLL extern l_int32 recogGetClassIndex ( L_RECOG *recog, l_int32 val, char *text, l_int32 *pindex ); +LEPT_DLL extern l_int32 recogStringToIndex ( L_RECOG *recog, char *text, l_int32 *pindex ); +LEPT_DLL extern l_int32 recogGetClassString ( L_RECOG *recog, l_int32 index, char **pcharstr ); +LEPT_DLL extern l_int32 l_convertCharstrToInt ( const char *str, l_int32 *pval ); +LEPT_DLL extern L_RECOGA * recogaRead ( const char *filename ); +LEPT_DLL extern L_RECOGA * recogaReadStream ( FILE *fp ); +LEPT_DLL extern l_int32 recogaWrite ( const char *filename, L_RECOGA *recoga ); +LEPT_DLL extern l_int32 recogaWriteStream ( FILE *fp, L_RECOGA *recoga, const char *filename ); +LEPT_DLL extern l_int32 recogaWritePixaa ( const char *filename, L_RECOGA *recoga ); +LEPT_DLL extern L_RECOG * recogRead ( const char *filename ); +LEPT_DLL extern L_RECOG * recogReadStream ( FILE *fp ); +LEPT_DLL extern l_int32 recogWrite ( const char *filename, L_RECOG *recog ); +LEPT_DLL extern l_int32 recogWriteStream ( FILE *fp, L_RECOG *recog, const char *filename ); +LEPT_DLL extern l_int32 recogWritePixa ( const char *filename, L_RECOG *recog ); +LEPT_DLL extern l_int32 recogDecode ( L_RECOG *recog, PIX *pixs, l_int32 nlevels, PIX **ppixdb ); +LEPT_DLL extern l_int32 recogMakeDecodingArrays ( L_RECOG *recog, PIX *pixs, l_int32 debug ); +LEPT_DLL extern l_int32 recogRunViterbi ( L_RECOG *recog, PIX **ppixdb ); +LEPT_DLL extern l_int32 recogCreateDid ( L_RECOG *recog, PIX *pixs ); +LEPT_DLL extern l_int32 recogDestroyDid ( L_RECOG *recog ); +LEPT_DLL extern l_int32 recogDidExists ( L_RECOG *recog ); +LEPT_DLL extern L_RDID * recogGetDid ( L_RECOG *recog ); +LEPT_DLL extern l_int32 recogSetChannelParams ( L_RECOG *recog, l_int32 nlevels ); +LEPT_DLL extern l_int32 recogaIdentifyMultiple ( L_RECOGA *recoga, PIX *pixs, l_int32 nitems, l_int32 minw, l_int32 minh, BOXA **pboxa, PIXA **ppixa, PIX **ppixdb, l_int32 debugsplit ); +LEPT_DLL extern l_int32 recogSplitIntoCharacters ( L_RECOG *recog, PIX *pixs, l_int32 minw, l_int32 minh, BOXA **pboxa, PIXA **ppixa, NUMA **pnaid, l_int32 debug ); +LEPT_DLL extern l_int32 recogCorrelationBestRow ( L_RECOG *recog, PIX *pixs, BOXA **pboxa, NUMA **pnascore, NUMA **pnaindex, SARRAY **psachar, l_int32 debug ); +LEPT_DLL extern l_int32 recogCorrelationBestChar ( L_RECOG *recog, PIX *pixs, BOX **pbox, l_float32 *pscore, l_int32 *pindex, char **pcharstr, PIX **ppixdb ); +LEPT_DLL extern l_int32 recogaIdentifyPixa ( L_RECOGA *recoga, PIXA *pixa, NUMA *naid, PIX **ppixdb ); +LEPT_DLL extern l_int32 recogIdentifyPixa ( L_RECOG *recog, PIXA *pixa, NUMA *naid, PIX **ppixdb ); +LEPT_DLL extern l_int32 recogIdentifyPix ( L_RECOG *recog, PIX *pixs, PIX **ppixdb ); +LEPT_DLL extern l_int32 recogSkipIdentify ( L_RECOG *recog ); +LEPT_DLL extern void rchaDestroy ( L_RCHA **prcha ); +LEPT_DLL extern void rchDestroy ( L_RCH **prch ); +LEPT_DLL extern l_int32 rchaExtract ( L_RCHA *rcha, NUMA **pnaindex, NUMA **pnascore, SARRAY **psatext, NUMA **pnasample, NUMA **pnaxloc, NUMA **pnayloc, NUMA **pnawidth ); +LEPT_DLL extern l_int32 rchExtract ( L_RCH *rch, l_int32 *pindex, l_float32 *pscore, char **ptext, l_int32 *psample, l_int32 *pxloc, l_int32 *pyloc, l_int32 *pwidth ); +LEPT_DLL extern PIX * recogProcessToIdentify ( L_RECOG *recog, PIX *pixs, l_int32 pad ); +LEPT_DLL extern PIX * recogPreSplittingFilter ( L_RECOG *recog, PIX *pixs, l_float32 maxasp, l_float32 minaf, l_float32 maxaf, l_int32 debug ); +LEPT_DLL extern l_int32 recogSplittingFilter ( L_RECOG *recog, PIX *pixs, l_float32 maxasp, l_float32 minaf, l_float32 maxaf, l_int32 *premove, l_int32 debug ); +LEPT_DLL extern SARRAY * recogaExtractNumbers ( L_RECOGA *recoga, BOXA *boxas, l_float32 scorethresh, l_int32 spacethresh, BOXAA **pbaa, NUMAA **pnaa ); +LEPT_DLL extern l_int32 recogSetTemplateType ( L_RECOG *recog, l_int32 templ_type ); +LEPT_DLL extern l_int32 recogSetScaling ( L_RECOG *recog, l_int32 scalew, l_int32 scaleh ); +LEPT_DLL extern l_int32 recogTrainLabelled ( L_RECOG *recog, PIX *pixs, BOX *box, char *text, l_int32 multflag, l_int32 debug ); +LEPT_DLL extern l_int32 recogProcessMultLabelled ( L_RECOG *recog, PIX *pixs, BOX *box, char *text, PIXA **ppixa, l_int32 debug ); +LEPT_DLL extern l_int32 recogProcessSingleLabelled ( L_RECOG *recog, PIX *pixs, BOX *box, char *text, PIXA **ppixa ); +LEPT_DLL extern l_int32 recogAddSamples ( L_RECOG *recog, PIXA *pixa, l_int32 classindex, l_int32 debug ); +LEPT_DLL extern PIX * recogScaleCharacter ( L_RECOG *recog, PIX *pixs ); +LEPT_DLL extern l_int32 recogAverageSamples ( L_RECOG *recog, l_int32 debug ); +LEPT_DLL extern l_int32 pixaAccumulateSamples ( PIXA *pixa, PTA *pta, PIX **ppixd, l_float32 *px, l_float32 *py ); +LEPT_DLL extern l_int32 recogTrainingFinished ( L_RECOG *recog, l_int32 debug ); +LEPT_DLL extern l_int32 recogRemoveOutliers ( L_RECOG *recog, l_float32 targetscore, l_float32 minfract, l_int32 debug ); +LEPT_DLL extern l_int32 recogaTrainingDone ( L_RECOGA *recoga, l_int32 *pdone ); +LEPT_DLL extern l_int32 recogaFinishAveraging ( L_RECOGA *recoga ); +LEPT_DLL extern l_int32 recogTrainUnlabelled ( L_RECOG *recog, L_RECOG *recogboot, PIX *pixs, BOX *box, l_int32 singlechar, l_float32 minscore, l_int32 debug ); +LEPT_DLL extern l_int32 recogPadTrainingSet ( L_RECOG **precog, l_int32 debug ); +LEPT_DLL extern l_int32 recogBestCorrelForPadding ( L_RECOG *recog, L_RECOGA *recoga, NUMA **pnaset, NUMA **pnaindex, NUMA **pnascore, NUMA **pnasum, PIXA **ppixadb ); +LEPT_DLL extern l_int32 recogCorrelAverages ( L_RECOG *recog1, L_RECOG *recog2, NUMA **pnaindex, NUMA **pnascore, PIXA **ppixadb ); +LEPT_DLL extern l_int32 recogSetPadParams ( L_RECOG *recog, const char *bootdir, const char *bootpattern, const char *bootpath, l_int32 type, l_int32 min_nopad, l_int32 max_afterpad ); +LEPT_DLL extern l_int32 recogaShowContent ( FILE *fp, L_RECOGA *recoga, l_int32 display ); +LEPT_DLL extern l_int32 recogShowContent ( FILE *fp, L_RECOG *recog, l_int32 display ); +LEPT_DLL extern l_int32 recogDebugAverages ( L_RECOG *recog, l_int32 debug ); +LEPT_DLL extern l_int32 recogShowAverageTemplates ( L_RECOG *recog ); +LEPT_DLL extern l_int32 recogShowMatchesInRange ( L_RECOG *recog, PIXA *pixa, l_float32 minscore, l_float32 maxscore, l_int32 display ); +LEPT_DLL extern PIX * recogShowMatch ( L_RECOG *recog, PIX *pix1, PIX *pix2, BOX *box, l_int32 index, l_float32 score ); +LEPT_DLL extern l_int32 recogMakeBmf ( L_RECOG *recog, const char *fontdir, l_int32 size ); LEPT_DLL extern l_int32 regTestSetup ( l_int32 argc, char **argv, L_REGPARAMS **prp ); LEPT_DLL extern l_int32 regTestCleanup ( L_REGPARAMS *rp ); LEPT_DLL extern l_int32 regTestCompareValues ( L_REGPARAMS *rp, l_float32 val1, l_float32 val2, l_float32 delta ); +LEPT_DLL extern l_int32 regTestCompareStrings ( L_REGPARAMS *rp, l_uint8 *string1, size_t bytes1, l_uint8 *string2, size_t bytes2 ); LEPT_DLL extern l_int32 regTestComparePix ( L_REGPARAMS *rp, PIX *pix1, PIX *pix2 ); LEPT_DLL extern l_int32 regTestCompareSimilarPix ( L_REGPARAMS *rp, PIX *pix1, PIX *pix2, l_int32 mindiff, l_float32 maxfract, l_int32 printstats ); LEPT_DLL extern l_int32 regTestCheckFile ( L_REGPARAMS *rp, const char *localname ); @@ -1817,7 +2039,6 @@ LEPT_DLL extern PIX * pixEmbedForRotation ( PIX *pixs, l_float32 angle, l_int32 LEPT_DLL extern PIX * pixRotateBySampling ( PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor ); LEPT_DLL extern PIX * pixRotateBinaryNice ( PIX *pixs, l_float32 angle, l_int32 incolor ); LEPT_DLL extern PIX * pixRotateWithAlpha ( PIX *pixs, l_float32 angle, PIX *pixg, l_float32 fract ); -LEPT_DLL extern PIX * pixRotateGammaXform ( PIX *pixs, l_float32 gamma, l_float32 angle, l_float32 fract ); LEPT_DLL extern PIX * pixRotateAM ( PIX *pixs, l_float32 angle, l_int32 incolor ); LEPT_DLL extern PIX * pixRotateAMColor ( PIX *pixs, l_float32 angle, l_uint32 colorval ); LEPT_DLL extern PIX * pixRotateAMGray ( PIX *pixs, l_float32 angle, l_uint8 grayval ); @@ -1847,6 +2068,7 @@ LEPT_DLL extern PIX * pixRotate3Shear ( PIX *pixs, l_int32 xcen, l_int32 ycen, l LEPT_DLL extern l_int32 pixRotateShearIP ( PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor ); LEPT_DLL extern PIX * pixRotateShearCenter ( PIX *pixs, l_float32 angle, l_int32 incolor ); LEPT_DLL extern l_int32 pixRotateShearCenterIP ( PIX *pixs, l_float32 angle, l_int32 incolor ); +LEPT_DLL extern PIX * pixStrokeWidthTransform ( PIX *pixs, l_int32 color, l_int32 depth, l_int32 nangles ); LEPT_DLL extern PIX * pixRunlengthTransform ( PIX *pixs, l_int32 color, l_int32 direction, l_int32 depth ); LEPT_DLL extern l_int32 pixFindHorizontalRuns ( PIX *pix, l_int32 y, l_int32 *xstart, l_int32 *xend, l_int32 *pn ); LEPT_DLL extern l_int32 pixFindVerticalRuns ( PIX *pix, l_int32 x, l_int32 *ystart, l_int32 *yend, l_int32 *pn ); @@ -1860,7 +2082,6 @@ LEPT_DLL extern void sarrayDestroy ( SARRAY **psa ); LEPT_DLL extern SARRAY * sarrayCopy ( SARRAY *sa ); LEPT_DLL extern SARRAY * sarrayClone ( SARRAY *sa ); LEPT_DLL extern l_int32 sarrayAddString ( SARRAY *sa, char *string, l_int32 copyflag ); -LEPT_DLL extern l_int32 sarrayExtendArray ( SARRAY *sa ); LEPT_DLL extern char * sarrayRemoveString ( SARRAY *sa, l_int32 index ); LEPT_DLL extern l_int32 sarrayReplaceString ( SARRAY *sa, l_int32 index, char *newstr, l_int32 copyflag ); LEPT_DLL extern l_int32 sarrayClear ( SARRAY *sa ); @@ -1880,6 +2101,7 @@ LEPT_DLL extern SARRAY * sarraySelectBySubstring ( SARRAY *sain, const char *sub LEPT_DLL extern SARRAY * sarraySelectByRange ( SARRAY *sain, l_int32 first, l_int32 last ); LEPT_DLL extern l_int32 sarrayParseRange ( SARRAY *sa, l_int32 start, l_int32 *pactualstart, l_int32 *pend, l_int32 *pnewstart, const char *substr, l_int32 loc ); LEPT_DLL extern SARRAY * sarraySort ( SARRAY *saout, SARRAY *sain, l_int32 sortorder ); +LEPT_DLL extern SARRAY * sarraySortByIndex ( SARRAY *sain, NUMA *naindex ); LEPT_DLL extern l_int32 stringCompareLexical ( const char *str1, const char *str2 ); LEPT_DLL extern SARRAY * sarrayRead ( const char *filename ); LEPT_DLL extern SARRAY * sarrayReadStream ( FILE *fp ); @@ -1887,7 +2109,7 @@ LEPT_DLL extern l_int32 sarrayWrite ( const char *filename, SARRAY *sa ); LEPT_DLL extern l_int32 sarrayWriteStream ( FILE *fp, SARRAY *sa ); LEPT_DLL extern l_int32 sarrayAppend ( const char *filename, SARRAY *sa ); LEPT_DLL extern SARRAY * getNumberedPathnamesInDirectory ( const char *dirname, const char *substr, l_int32 numpre, l_int32 numpost, l_int32 maxnum ); -LEPT_DLL extern SARRAY * getSortedPathnamesInDirectory ( const char *dirname, const char *substr, l_int32 firstpage, l_int32 npages ); +LEPT_DLL extern SARRAY * getSortedPathnamesInDirectory ( const char *dirname, const char *substr, l_int32 first, l_int32 nfiles ); LEPT_DLL extern SARRAY * convertSortedToNumberedPathnames ( SARRAY *sa, l_int32 numpre, l_int32 numpost, l_int32 maxnum ); LEPT_DLL extern SARRAY * getFilenamesInDirectory ( const char *dirname ); LEPT_DLL extern PIX * pixScale ( PIX *pixs, l_float32 scalex, l_float32 scaley ); @@ -1901,6 +2123,7 @@ LEPT_DLL extern PIX * pixScaleGrayLI ( PIX *pixs, l_float32 scalex, l_float32 sc LEPT_DLL extern PIX * pixScaleGray2xLI ( PIX *pixs ); LEPT_DLL extern PIX * pixScaleGray4xLI ( PIX *pixs ); LEPT_DLL extern PIX * pixScaleBySampling ( PIX *pixs, l_float32 scalex, l_float32 scaley ); +LEPT_DLL extern PIX * pixScaleBySamplingToSize ( PIX *pixs, l_int32 wd, l_int32 hd ); LEPT_DLL extern PIX * pixScaleByIntSubsampling ( PIX *pixs, l_int32 factor ); LEPT_DLL extern PIX * pixScaleRGBToGrayFast ( PIX *pixs, l_int32 factor, l_int32 color ); LEPT_DLL extern PIX * pixScaleRGBToBinaryFast ( PIX *pixs, l_int32 factor, l_int32 thresh ); @@ -1929,8 +2152,8 @@ LEPT_DLL extern PIX * pixScaleGrayMinMax ( PIX *pixs, l_int32 xfact, l_int32 yfa LEPT_DLL extern PIX * pixScaleGrayMinMax2 ( PIX *pixs, l_int32 type ); LEPT_DLL extern PIX * pixScaleGrayRankCascade ( PIX *pixs, l_int32 level1, l_int32 level2, l_int32 level3, l_int32 level4 ); LEPT_DLL extern PIX * pixScaleGrayRank2 ( PIX *pixs, l_int32 rank ); +LEPT_DLL extern l_int32 pixScaleAndTransferAlpha ( PIX *pixd, PIX *pixs, l_float32 scalex, l_float32 scaley ); LEPT_DLL extern PIX * pixScaleWithAlpha ( PIX *pixs, l_float32 scalex, l_float32 scaley, PIX *pixg, l_float32 fract ); -LEPT_DLL extern PIX * pixScaleGammaXform ( PIX *pixs, l_float32 gamma, l_float32 scalex, l_float32 scaley, l_float32 fract ); LEPT_DLL extern void scaleColorLILow ( l_uint32 *datad, l_int32 wd, l_int32 hd, l_int32 wpld, l_uint32 *datas, l_int32 ws, l_int32 hs, l_int32 wpls ); LEPT_DLL extern void scaleGrayLILow ( l_uint32 *datad, l_int32 wd, l_int32 hd, l_int32 wpld, l_uint32 *datas, l_int32 ws, l_int32 hs, l_int32 wpls ); LEPT_DLL extern void scaleColor2xLILow ( l_uint32 *datad, l_int32 wpld, l_uint32 *datas, l_int32 ws, l_int32 hs, l_int32 wpls ); @@ -1967,6 +2190,7 @@ LEPT_DLL extern PIX * pixHolesByFilling ( PIX *pixs, l_int32 connectivity ); LEPT_DLL extern PIX * pixFillClosedBorders ( PIX *pixs, l_int32 connectivity ); LEPT_DLL extern PIX * pixExtractBorderConnComps ( PIX *pixs, l_int32 connectivity ); LEPT_DLL extern PIX * pixRemoveBorderConnComps ( PIX *pixs, l_int32 connectivity ); +LEPT_DLL extern PIX * pixFillBgFromBorder ( PIX *pixs, l_int32 connectivity ); LEPT_DLL extern PIX * pixFillHolesToBoundingRect ( PIX *pixs, l_int32 minsize, l_float32 maxhfract, l_float32 minfgfract ); LEPT_DLL extern l_int32 pixSeedfillGray ( PIX *pixs, PIX *pixm, l_int32 connectivity ); LEPT_DLL extern l_int32 pixSeedfillGrayInv ( PIX *pixs, PIX *pixm, l_int32 connectivity ); @@ -1978,7 +2202,7 @@ LEPT_DLL extern PIX * pixSeedspread ( PIX *pixs, l_int32 connectivity ); LEPT_DLL extern l_int32 pixLocalExtrema ( PIX *pixs, l_int32 maxmin, l_int32 minmax, PIX **ppixmin, PIX **ppixmax ); LEPT_DLL extern l_int32 pixSelectedLocalExtrema ( PIX *pixs, l_int32 mindist, PIX **ppixmin, PIX **ppixmax ); LEPT_DLL extern PIX * pixFindEqualValues ( PIX *pixs1, PIX *pixs2 ); -LEPT_DLL extern PTA * pixSelectMinInConnComp ( PIX *pixs, PIX *pixm, NUMA **pnav ); +LEPT_DLL extern l_int32 pixSelectMinInConnComp ( PIX *pixs, PIX *pixm, PTA **ppta, NUMA **pnav ); LEPT_DLL extern PIX * pixRemoveSeededComponents ( PIX *pixd, PIX *pixs, PIX *pixm, l_int32 connectivity, l_int32 bordersize ); LEPT_DLL extern void seedfillBinaryLow ( l_uint32 *datas, l_int32 hs, l_int32 wpls, l_uint32 *datam, l_int32 hm, l_int32 wplm, l_int32 connectivity ); LEPT_DLL extern void seedfillGrayLow ( l_uint32 *datas, l_int32 w, l_int32 h, l_int32 wpls, l_uint32 *datam, l_int32 wplm, l_int32 connectivity ); @@ -1996,7 +2220,6 @@ LEPT_DLL extern SEL * selCreateBrick ( l_int32 h, l_int32 w, l_int32 cy, l_int32 LEPT_DLL extern SEL * selCreateComb ( l_int32 factor1, l_int32 factor2, l_int32 direction ); LEPT_DLL extern l_int32 ** create2dIntArray ( l_int32 sy, l_int32 sx ); LEPT_DLL extern l_int32 selaAddSel ( SELA *sela, SEL *sel, const char *selname, l_int32 copyflag ); -LEPT_DLL extern l_int32 selaExtendArray ( SELA *sela ); LEPT_DLL extern l_int32 selaGetCount ( SELA *sela ); LEPT_DLL extern SEL * selaGetSel ( SELA *sela, l_int32 i ); LEPT_DLL extern char * selGetName ( SEL *sel ); @@ -2044,16 +2267,16 @@ LEPT_DLL extern NUMA * pixGetRunsOnLine ( PIX *pixs, l_int32 x1, l_int32 y1, l_i LEPT_DLL extern PTA * pixSubsampleBoundaryPixels ( PIX *pixs, l_int32 skip ); LEPT_DLL extern l_int32 adjacentOnPixelInRaster ( PIX *pixs, l_int32 x, l_int32 y, l_int32 *pxa, l_int32 *pya ); LEPT_DLL extern PIX * pixDisplayHitMissSel ( PIX *pixs, SEL *sel, l_int32 scalefactor, l_uint32 hitcolor, l_uint32 misscolor ); -LEPT_DLL extern PIX * pixHShear ( PIX *pixd, PIX *pixs, l_int32 liney, l_float32 radang, l_int32 incolor ); -LEPT_DLL extern PIX * pixVShear ( PIX *pixd, PIX *pixs, l_int32 linex, l_float32 radang, l_int32 incolor ); +LEPT_DLL extern PIX * pixHShear ( PIX *pixd, PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor ); +LEPT_DLL extern PIX * pixVShear ( PIX *pixd, PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor ); LEPT_DLL extern PIX * pixHShearCorner ( PIX *pixd, PIX *pixs, l_float32 radang, l_int32 incolor ); LEPT_DLL extern PIX * pixVShearCorner ( PIX *pixd, PIX *pixs, l_float32 radang, l_int32 incolor ); LEPT_DLL extern PIX * pixHShearCenter ( PIX *pixd, PIX *pixs, l_float32 radang, l_int32 incolor ); LEPT_DLL extern PIX * pixVShearCenter ( PIX *pixd, PIX *pixs, l_float32 radang, l_int32 incolor ); -LEPT_DLL extern l_int32 pixHShearIP ( PIX *pixs, l_int32 liney, l_float32 radang, l_int32 incolor ); -LEPT_DLL extern l_int32 pixVShearIP ( PIX *pixs, l_int32 linex, l_float32 radang, l_int32 incolor ); -LEPT_DLL extern PIX * pixHShearLI ( PIX *pixs, l_int32 liney, l_float32 radang, l_int32 incolor ); -LEPT_DLL extern PIX * pixVShearLI ( PIX *pixs, l_int32 linex, l_float32 radang, l_int32 incolor ); +LEPT_DLL extern l_int32 pixHShearIP ( PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor ); +LEPT_DLL extern l_int32 pixVShearIP ( PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor ); +LEPT_DLL extern PIX * pixHShearLI ( PIX *pixs, l_int32 yloc, l_float32 radang, l_int32 incolor ); +LEPT_DLL extern PIX * pixVShearLI ( PIX *pixs, l_int32 xloc, l_float32 radang, l_int32 incolor ); LEPT_DLL extern PIX * pixDeskew ( PIX *pixs, l_int32 redsearch ); LEPT_DLL extern PIX * pixFindSkewAndDeskew ( PIX *pixs, l_int32 redsearch, l_float32 *pangle, l_float32 *pconf ); LEPT_DLL extern PIX * pixDeskewGeneral ( PIX *pixs, l_int32 redsweep, l_float32 sweeprange, l_float32 sweepdelta, l_int32 redsearch, l_int32 thresh, l_float32 *pangle, l_float32 *pconf ); @@ -2078,7 +2301,6 @@ LEPT_DLL extern L_STACK * lstackCreate ( l_int32 nalloc ); LEPT_DLL extern void lstackDestroy ( L_STACK **plstack, l_int32 freeflag ); LEPT_DLL extern l_int32 lstackAdd ( L_STACK *lstack, void *item ); LEPT_DLL extern void * lstackRemove ( L_STACK *lstack ); -LEPT_DLL extern l_int32 lstackExtendArray ( L_STACK *lstack ); LEPT_DLL extern l_int32 lstackGetCount ( L_STACK *lstack ); LEPT_DLL extern l_int32 lstackPrint ( FILE *fp, L_STACK *lstack ); LEPT_DLL extern l_int32 * sudokuReadFile ( const char *filename ); @@ -2090,8 +2312,11 @@ LEPT_DLL extern l_int32 sudokuTestUniqueness ( l_int32 *array, l_int32 *punique LEPT_DLL extern L_SUDOKU * sudokuGenerate ( l_int32 *array, l_int32 seed, l_int32 minelems, l_int32 maxtries ); LEPT_DLL extern l_int32 sudokuOutput ( L_SUDOKU *sud, l_int32 arraytype ); LEPT_DLL extern PIX * pixAddSingleTextblock ( PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow ); +LEPT_DLL extern PIX * pixAddSingleTextline ( PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location ); LEPT_DLL extern l_int32 pixSetTextblock ( PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 x0, l_int32 y0, l_int32 wtext, l_int32 firstindent, l_int32 *poverflow ); LEPT_DLL extern l_int32 pixSetTextline ( PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 x0, l_int32 y0, l_int32 *pwidth, l_int32 *poverflow ); +LEPT_DLL extern PIXA * pixaAddTextNumber ( PIXA *pixas, L_BMF *bmf, NUMA *na, l_uint32 val, l_int32 location ); +LEPT_DLL extern PIXA * pixaAddTextline ( PIXA *pixas, L_BMF *bmf, SARRAY *sa, l_uint32 val, l_int32 location ); LEPT_DLL extern SARRAY * bmfGetLineStrings ( L_BMF *bmf, const char *textstr, l_int32 maxw, l_int32 firstindent, l_int32 *ph ); LEPT_DLL extern NUMA * bmfGetWordWidths ( L_BMF *bmf, const char *textstr, SARRAY *sa ); LEPT_DLL extern l_int32 bmfGetStringWidth ( L_BMF *bmf, const char *textstr, l_int32 *pw ); @@ -2115,25 +2340,10 @@ LEPT_DLL extern l_int32 extractG4DataFromFile ( const char *filein, l_uint8 **pd LEPT_DLL extern PIX * pixReadMemTiff ( const l_uint8 *cdata, size_t size, l_int32 n ); LEPT_DLL extern l_int32 pixWriteMemTiff ( l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 comptype ); LEPT_DLL extern l_int32 pixWriteMemTiffCustom ( l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 comptype, NUMA *natags, SARRAY *savals, SARRAY *satypes, NUMA *nasizes ); +LEPT_DLL extern l_int32 setMsgSeverity ( l_int32 newsev ); LEPT_DLL extern l_int32 returnErrorInt ( const char *msg, const char *procname, l_int32 ival ); LEPT_DLL extern l_float32 returnErrorFloat ( const char *msg, const char *procname, l_float32 fval ); LEPT_DLL extern void * returnErrorPtr ( const char *msg, const char *procname, void *pval ); -LEPT_DLL extern void l_error ( const char *msg, const char *procname ); -LEPT_DLL extern void l_errorString ( const char *msg, const char *procname, const char *str ); -LEPT_DLL extern void l_errorInt ( const char *msg, const char *procname, l_int32 ival ); -LEPT_DLL extern void l_errorFloat ( const char *msg, const char *procname, l_float32 fval ); -LEPT_DLL extern void l_warning ( const char *msg, const char *procname ); -LEPT_DLL extern void l_warningString ( const char *msg, const char *procname, const char *str ); -LEPT_DLL extern void l_warningInt ( const char *msg, const char *procname, l_int32 ival ); -LEPT_DLL extern void l_warningInt2 ( const char *msg, const char *procname, l_int32 ival1, l_int32 ival2 ); -LEPT_DLL extern void l_warningFloat ( const char *msg, const char *procname, l_float32 fval ); -LEPT_DLL extern void l_warningFloat2 ( const char *msg, const char *procname, l_float32 fval1, l_float32 fval2 ); -LEPT_DLL extern void l_info ( const char *msg, const char *procname ); -LEPT_DLL extern void l_infoString ( const char *msg, const char *procname, const char *str ); -LEPT_DLL extern void l_infoInt ( const char *msg, const char *procname, l_int32 ival ); -LEPT_DLL extern void l_infoInt2 ( const char *msg, const char *procname, l_int32 ival1, l_int32 ival2 ); -LEPT_DLL extern void l_infoFloat ( const char *msg, const char *procname, l_float32 fval ); -LEPT_DLL extern void l_infoFloat2 ( const char *msg, const char *procname, l_float32 fval1, l_float32 fval2 ); LEPT_DLL extern char * stringNew ( const char *src ); LEPT_DLL extern l_int32 stringCopy ( char *dest, const char *src, l_int32 n ); LEPT_DLL extern l_int32 stringReplace ( char **pdest, const char *src ); @@ -2180,10 +2390,14 @@ LEPT_DLL extern l_int32 splitPathAtDirectory ( const char *pathname, char **pdir LEPT_DLL extern l_int32 splitPathAtExtension ( const char *pathname, char **pbasename, char **pextension ); LEPT_DLL extern char * pathJoin ( const char *dir, const char *fname ); LEPT_DLL extern char * genPathname ( const char *dir, const char *fname ); +LEPT_DLL extern l_int32 makeTempDirname ( char *result, size_t nbytes, const char *subdir ); LEPT_DLL extern char * genTempFilename ( const char *dir, const char *tail, l_int32 usetime, l_int32 usepid ); LEPT_DLL extern l_int32 extractNumberFromFilename ( const char *fname, l_int32 numpre, l_int32 numpost ); +LEPT_DLL extern l_int32 fileCorruptByDeletion ( const char *filein, l_float32 loc, l_float32 size, const char *fileout ); LEPT_DLL extern l_int32 genRandomIntegerInRange ( l_int32 range, l_int32 seed, l_int32 *pval ); LEPT_DLL extern l_int32 lept_roundftoi ( l_float32 fval ); +LEPT_DLL extern l_uint32 convertBinaryToGrayCode ( l_uint32 val ); +LEPT_DLL extern l_uint32 convertGrayCodeToBinary ( l_uint32 val ); LEPT_DLL extern char * getLeptonicaVersion ( ); LEPT_DLL extern void startTimer ( void ); LEPT_DLL extern l_float32 stopTimer ( void ); @@ -2191,8 +2405,6 @@ LEPT_DLL extern L_TIMER startTimerNested ( void ); LEPT_DLL extern l_float32 stopTimerNested ( L_TIMER rusage_start ); LEPT_DLL extern void l_getCurrentTime ( l_int32 *sec, l_int32 *usec ); LEPT_DLL extern char * l_getFormattedDate ( ); -LEPT_DLL extern l_uint8 * arrayRead ( const char *fname, l_int32 *pnbytes ); -LEPT_DLL extern l_uint8 * arrayReadStream ( FILE *fp, l_int32 *pnbytes ); LEPT_DLL extern l_int32 pixHtmlViewer ( const char *dirin, const char *dirout, const char *rootname, l_int32 thumbwidth, l_int32 viewwidth, l_int32 copyorig ); LEPT_DLL extern PIX * pixSimpleCaptcha ( PIX *pixs, l_int32 border, l_int32 nterms, l_uint32 seed, l_uint32 color, l_int32 cmapflag ); LEPT_DLL extern PIX * pixRandomHarmonicWarp ( PIX *pixs, l_float32 xmag, l_float32 ymag, l_float32 xfreq, l_float32 yfreq, l_int32 nx, l_int32 ny, l_uint32 seed, l_int32 grayval ); @@ -2211,9 +2423,11 @@ LEPT_DLL extern l_int32 wshedBasins ( L_WSHED *wshed, PIXA **ppixa, NUMA **pnale LEPT_DLL extern PIX * wshedRenderFill ( L_WSHED *wshed ); LEPT_DLL extern PIX * wshedRenderColors ( L_WSHED *wshed ); LEPT_DLL extern PIX * pixReadStreamWebP ( FILE *fp ); -LEPT_DLL extern l_int32 readHeaderWebP ( const char *filename, l_int32 *pwidth, l_int32 *pheight ); -LEPT_DLL extern l_int32 pixWriteWebP ( const char *filename, PIX *pixs, l_int32 quality ); -LEPT_DLL extern l_int32 pixWriteStreamWebP ( FILE *fp, PIX *pixs, l_int32 quality ); +LEPT_DLL extern PIX * pixReadMemWebP ( const l_uint8 *filedata, size_t filesize ); +LEPT_DLL extern l_int32 readHeaderWebP ( const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pspp ); +LEPT_DLL extern l_int32 pixWriteWebP ( const char *filename, PIX *pixs, l_int32 quality, l_int32 lossless ); +LEPT_DLL extern l_int32 pixWriteStreamWebP ( FILE *fp, PIX *pixs, l_int32 quality, l_int32 lossless ); +LEPT_DLL extern l_int32 pixWriteMemWebP ( l_uint8 **pencdata, size_t *pencsize, PIX *pixs, l_int32 quality, l_int32 lossless ); LEPT_DLL extern l_int32 pixaWriteFiles ( const char *rootname, PIXA *pixa, l_int32 format ); LEPT_DLL extern l_int32 pixWrite ( const char *filename, PIX *pix, l_int32 format ); LEPT_DLL extern l_int32 pixWriteStream ( FILE *fp, PIX *pix, l_int32 format ); @@ -2228,8 +2442,8 @@ LEPT_DLL extern l_int32 pixDisplayWithTitle ( PIX *pixs, l_int32 x, l_int32 y, c LEPT_DLL extern l_int32 pixDisplayMultiple ( const char *filepattern ); LEPT_DLL extern l_int32 pixDisplayWrite ( PIX *pixs, l_int32 reduction ); LEPT_DLL extern l_int32 pixDisplayWriteFormat ( PIX *pixs, l_int32 reduction, l_int32 format ); -LEPT_DLL extern l_int32 pixSaveTiled ( PIX *pixs, PIXA *pixa, l_int32 reduction, l_int32 newrow, l_int32 space, l_int32 dp ); -LEPT_DLL extern l_int32 pixSaveTiledOutline ( PIX *pixs, PIXA *pixa, l_int32 reduction, l_int32 newrow, l_int32 space, l_int32 linewidth, l_int32 dp ); +LEPT_DLL extern l_int32 pixSaveTiled ( PIX *pixs, PIXA *pixa, l_float32 scalefactor, l_int32 newrow, l_int32 space, l_int32 dp ); +LEPT_DLL extern l_int32 pixSaveTiledOutline ( PIX *pixs, PIXA *pixa, l_float32 scalefactor, l_int32 newrow, l_int32 space, l_int32 linewidth, l_int32 dp ); LEPT_DLL extern l_int32 pixSaveTiledWithText ( PIX *pixs, PIXA *pixa, l_int32 outwidth, l_int32 newrow, l_int32 space, l_int32 linewidth, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location ); LEPT_DLL extern void l_chooseDisplayProg ( l_int32 selection ); LEPT_DLL extern l_uint8 * zlibCompress ( l_uint8 *datain, size_t nin, size_t *pnout ); diff --git a/TesseractOCR/include/leptonica/alltypes.h b/TesseractOCR/include/leptonica/alltypes.h old mode 100755 new mode 100644 index feb03be0..2ebb04c7 --- a/TesseractOCR/include/leptonica/alltypes.h +++ b/TesseractOCR/include/leptonica/alltypes.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -30,31 +30,34 @@ /* Standard */ #include #include +#include /* General and configuration defs */ #include "environ.h" - /* Imaging */ + /* Generic and non-image-specific containers */ #include "array.h" -#include "arrayaccess.h" #include "bbuffer.h" +#include "heap.h" +#include "list.h" +#include "ptra.h" +#include "queue.h" +#include "stack.h" + + /* Imaging */ +#include "arrayaccess.h" #include "bmf.h" #include "ccbord.h" #include "dewarp.h" #include "gplot.h" -#include "heap.h" #include "imageio.h" #include "jbclass.h" -#include "list.h" #include "morph.h" #include "pix.h" -#include "ptra.h" -#include "queue.h" +#include "recog.h" #include "regutils.h" #include "sudoku.h" -#include "stack.h" #include "watershed.h" #endif /* LEPTONICA_ALLTYPES_H */ - diff --git a/TesseractOCR/include/leptonica/array.h b/TesseractOCR/include/leptonica/array.h old mode 100755 new mode 100644 index 33e3da0f..8fdcbb35 --- a/TesseractOCR/include/leptonica/array.h +++ b/TesseractOCR/include/leptonica/array.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -40,10 +40,12 @@ * * Contains definitions for: * Numa interpolation flags + * Numa and FPix border flags + * Numa data type conversion to string */ -/*------------------------------------------------------------------------* +/*------------------------------------------------------------------------* * Array Structs * *------------------------------------------------------------------------*/ @@ -142,10 +144,9 @@ struct L_Bytea typedef struct L_Bytea L_BYTEA; -/*------------------------------------------------------------------------* +/*------------------------------------------------------------------------* * Array flags * *------------------------------------------------------------------------*/ - /* Flags for interpolation in Numa */ enum { L_LINEAR_INTERP = 1, /* linear */ @@ -159,5 +160,11 @@ enum { L_MIRRORED_BORDER = 3 /* mirrored */ }; + /* Flags for data type converted from Numa */ +enum { + L_INTEGER_VALUE = 1, /* convert to integer */ + L_FLOAT_VALUE = 2 /* convert to float */ +}; + #endif /* LEPTONICA_ARRAY_H */ diff --git a/TesseractOCR/include/leptonica/arrayaccess.h b/TesseractOCR/include/leptonica/arrayaccess.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/leptonica/bbuffer.h b/TesseractOCR/include/leptonica/bbuffer.h old mode 100755 new mode 100644 index 3d308eb8..204cfddb --- a/TesseractOCR/include/leptonica/bbuffer.h +++ b/TesseractOCR/include/leptonica/bbuffer.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR diff --git a/TesseractOCR/include/leptonica/bilateral.h b/TesseractOCR/include/leptonica/bilateral.h new file mode 100644 index 00000000..520799db --- /dev/null +++ b/TesseractOCR/include/leptonica/bilateral.h @@ -0,0 +1,130 @@ +/*====================================================================* + - Copyright (C) 2001 Leptonica. All rights reserved. + - + - 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY + - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *====================================================================*/ + +#ifndef LEPTONICA_BILATERAL_H +#define LEPTONICA_BILATERAL_H + +/* + * Contains the following struct + * struct L_Bilateral + * + * + * For a tutorial introduction to bilateral filters, which apply a + * gaussian blur to smooth parts of the image while preserving edges, see + * http://people.csail.mit.edu/sparis/bf_course/slides/03_definition_bf.pdf + * + * We give an implementation of a bilateral filtering algorithm given in: + * "Real-Time O(1) Bilateral Filtering," by Yang, Tan and Ahuja, CVPR 2009 + * which is at: + * http://vision.ai.uiuc.edu/~qyang6/publications/cvpr-09-qingxiong-yang.pdf + * This is based on an earlier algorithm by Sylvain Paris and Frédo Durand: + * http://people.csail.mit.edu/sparis/publi/2006/eccv/ + * Paris_06_Fast_Approximation.pdf + * + * The kernel of the filter is a product of a spatial gaussian and a + * monotonically decreasing function of the difference in intensity + * between the source pixel and the neighboring pixel. The intensity + * part of the filter gives higher influence for pixels with intensities + * that are near to the source pixel, and the spatial part of the + * filter gives higher weight to pixels that are near the source pixel. + * This combination smooths in relatively uniform regions, while + * maintaining edges. + * + * The advantage of the appoach of Yang et al is that it is separable, + * so the computation time is linear in the gaussian filter size. + * Furthermore, it is possible to do much of the computation as a reduced + * scale, which gives a good approximation to the full resolution version + * but greatly speeds it up. + * + * The bilateral filtered value at x is: + * + * sum[y in N(x)]: spatial(|y - x|) * range(|I(x) - I(y)|) * I(y) + * I'(x) = -------------------------------------------------------------- + * sum[y in N(x)]: spatial(|y - x|) * range(|I(x) - I(y)|) + * + * where I() is the input image, I'() is the filtered image, N(x) is the + * set of pixels around x in the filter support, and spatial() and range() + * are gaussian functions: + * spatial(x) = exp(-x^2 / (2 * s_s^2)) + * range(x) = exp(-x^2 / (2 * s_r^2)) + * and s_s and s_r and the standard deviations of the two gaussians. + * + * Yang et al use a separable approximation to this, by defining a set + * of related but separable functions J(k,x), that we call Principal + * Bilateral Components (PBC): + * + * sum[y in N(x)]: spatial(|y - x|) * range(|k - I(y)|) * I(y) + * J(k,x) = ----------------------------------------------------------- + * sum[y in N(x)]: spatial(|y - x|) * range(|k - I(y)|) + * + * which are computed quickly for a set of n values k[p], p = 0 ... n-1. + * Then each output pixel is found using a linear interpolation: + * + * I'(x) = (1 - q) * J(k[p],x) + q * J(k[p+1],x) + * + * where J(k[p],x) and J(k[p+1],x) are PBC for which + * k[p] <= I(x) and k[p+1] >= I(x), and + * q = (I(x) - k[p]) / (k[p+1] - k[p]). + * + * We can also subsample I(x), create subsampled versions of J(k,x), + * which are then interpolated between for I'(x). + * + * We generate 'pixsc', by optionally downscaling the input image + * (using area mapping by the factor 'reduction'), and then adding + * a mirrored border to avoid boundary cases. This is then used + * to compute 'ncomps' PBCs. + * + * The 'spatial_stdev' is also downscaled by 'reduction'. The size + * of the 'spatial' array is 4 * (reduced 'spatial_stdev') + 1. + * The size of the 'range' array is 256. + */ + + +/*------------------------------------------------------------------------* + * Bilateral filter * + *------------------------------------------------------------------------*/ +struct L_Bilateral +{ + struct Pix *pixs; /* clone of source pix */ + struct Pix *pixsc; /* downscaled pix with mirrored border */ + l_int32 reduction; /* 1, 2 or 4x for intermediates */ + l_float32 spatial_stdev; /* stdev of spatial gaussian */ + l_float32 range_stdev; /* stdev of range gaussian */ + l_float32 *spatial; /* 1D gaussian spatial kernel */ + l_float32 *range; /* one-sided gaussian range kernel */ + l_int32 minval; /* min value in 8 bpp pix */ + l_int32 maxval; /* max value in 8 bpp pix */ + l_int32 ncomps; /* number of intermediate results */ + l_int32 *nc; /* set of k values (size ncomps) */ + l_int32 *kindex; /* mapping from intensity to lower k */ + l_float32 *kfract; /* mapping from intensity to fract k */ + struct Pixa *pixac; /* intermediate result images (PBC) */ + l_uint32 ***lineset; /* lineptrs for pixac */ +}; +typedef struct L_Bilateral L_BILATERAL; + + +#endif /* LEPTONICA_BILATERAL_H */ diff --git a/TesseractOCR/include/leptonica/bmf.h b/TesseractOCR/include/leptonica/bmf.h old mode 100755 new mode 100644 index 007534c3..25d40f25 --- a/TesseractOCR/include/leptonica/bmf.h +++ b/TesseractOCR/include/leptonica/bmf.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -27,7 +27,7 @@ #ifndef LEPTONICA_BMF_H #define LEPTONICA_BMF_H -/* +/* * bmf.h * * Simple data structure to hold bitmap fonts and related data diff --git a/TesseractOCR/include/leptonica/bmp.h b/TesseractOCR/include/leptonica/bmp.h old mode 100755 new mode 100644 index c50b7b4f..212dce5e --- a/TesseractOCR/include/leptonica/bmp.h +++ b/TesseractOCR/include/leptonica/bmp.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR diff --git a/TesseractOCR/include/leptonica/ccbord.h b/TesseractOCR/include/leptonica/ccbord.h old mode 100755 new mode 100644 index 9c976aa2..47ec57ac --- a/TesseractOCR/include/leptonica/ccbord.h +++ b/TesseractOCR/include/leptonica/ccbord.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR diff --git a/TesseractOCR/include/leptonica/config_auto.h b/TesseractOCR/include/leptonica/config_auto.h new file mode 100644 index 00000000..675e4b40 --- /dev/null +++ b/TesseractOCR/include/leptonica/config_auto.h @@ -0,0 +1,102 @@ +/* config_auto.h. Generated from config.h.in by configure. */ +/* config/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `fmemopen' function. */ +/* #undef HAVE_FMEMOPEN */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have giflib. */ +/* #undef HAVE_LIBGIF */ + +/* Define to 1 if you have jpeg. */ +/* #undef HAVE_LIBJPEG */ + +/* Define to 1 if you have libpng. */ +/* #undef HAVE_LIBPNG */ + +/* Define to 1 if you have libtiff. */ +/* #undef HAVE_LIBTIFF */ + +/* Define to 1 if you have libwebp. */ +/* #undef HAVE_LIBWEBP */ + +/* Define to 1 if you have zlib. */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "leptonica" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "leptonica" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "leptonica 1.70" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "leptonica" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.70" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.70" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/TesseractOCR/include/leptonica/dewarp.h b/TesseractOCR/include/leptonica/dewarp.h old mode 100755 new mode 100644 index d83a8c9e..79792664 --- a/TesseractOCR/include/leptonica/dewarp.h +++ b/TesseractOCR/include/leptonica/dewarp.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -48,28 +48,31 @@ * However, at rendering time, a page can have one of two different * types of models. * (1) A valid model is an actual model that meets the rendering - * requirements, including whether a full model (horizontal - * and vertical disparity) is required, and limits on model - * curvatures. See dewarpaTestForValidModel() for details. - * Valid models are identified by dewarpaInsertRefModels(), which - * sets the 'valid' field. Only valid models are used for rendering. + * constraints, which are limits on model curvature parameters. + * See dewarpaTestForValidModel() for details. + * Valid models are identified by dewarpaInsertRefModels(), + * which sets the 'vvalid' and 'hvalid' fields. Only valid + * models are used for rendering. * (2) A reference model is used by a page that doesn't have * a valid model, but has a nearby valid model of the same - * parity (even/odd page) that it can use. The range to search - * for a valid model is given by the 'maxdist' field. - * A page may have neither a valid nor a reference model, in - * which case rendering simply copies the input image. - * By default, only the vertical disparity is required for - * an actual model ('fullmodel' = 0). The 'maxdist' parameter is - * input when the dewarpa is created. The other rendering parameters - * have default values given in dewarp.c. All parameters used by - * rendering can be set (or reset) using accessors. + * parity (even/odd page) that it can use. The range in pages + * to search for a valid model is given by the 'maxdist' field. + * + * If a valid vertical disparity model (VDM) is not available, + * just use the input image. Otherwise, assuming the VDM is available: + * (a) with useboth == 0, we use only the VDM. + * (b) with useboth == 1, we require using the VDM and, if a valid + * horizontal disparity model (HDM) is available, we also use it. + * + * The 'maxdist' parameter is input when the dewarpa is created. + * The other rendering parameters have default values given in dewarp.c. + * All parameters used by rendering can be set (or reset) using accessors. * - * After dewarping, use of the vertical disparity will cause all - * points on each altered curve to have a y-value equal to the - * minimum. Use of horizontal disparity will cause the left - * and right edges of the textlines to be vertically aligned if - * they had been typeset flush-left and flush-right, respectively. + * After dewarping, use of the VDM will cause all points on each + * altered curve to have a y-value equal to the minimum. Use of + * the HDA will cause the left and right edges of the textlines + * to be vertically aligned if they had been typeset flush-left + * and flush-right, respectively. * * The sampled disparity arrays are expanded to full resolution, * using linear interpolation, and this is further expanded @@ -88,63 +91,70 @@ * In most situations, the serialized version is ephemeral -- it is * not needed after being used. No functions will be provided to * convert between different versions. */ -#define DEWARP_VERSION_NUMBER 2 +#define DEWARP_VERSION_NUMBER 3 struct L_Dewarpa { - l_int32 nalloc; /* size of dewarp ptr array */ - l_int32 maxpage; /* maximum page number in array */ - struct L_Dewarp **dewarp; /* array of ptrs to page dewarp */ - struct Numa *namodels; /* list of page numbers for pages */ - /* with page models */ - struct Numa *napages; /* list of page numbers with either */ - /* page models or ref page models */ - l_int32 redfactor; /* reduction factor of input: 1 or 2 */ - l_int32 sampling; /* disparity arrays sampling factor */ - l_int32 minlines; /* min number of long lines required */ - l_int32 maxdist; /* max distance for getting ref pages */ - l_int32 min_medcurv; /* minimum median abs line curvature, */ - /* in micro-units */ - l_int32 max_medcurv; /* maximum median abs line curvature, */ - /* in micro-units */ - l_int32 max_leftcurv; /* maximum left edge line curvature, */ - /* in micro-units */ - l_int32 max_rightcurv; /* maximum right edge line curvature, */ - /* in micro-units */ - l_int32 fullmodel; /* both disparity arrays required */ - l_int32 modelsready; /* invalid models have been removed */ - /* and refs built against valid set */ + l_int32 nalloc; /* size of dewarp ptr array */ + l_int32 maxpage; /* maximum page number in array */ + struct L_Dewarp **dewarp; /* array of ptrs to page dewarp */ + struct L_Dewarp **dewarpcache; /* array of ptrs to cached dewarps */ + struct Numa *namodels; /* list of page numbers for pages */ + /* with page models */ + struct Numa *napages; /* list of page numbers with either */ + /* page models or ref page models */ + l_int32 redfactor; /* reduction factor of input: 1 or 2 */ + l_int32 sampling; /* disparity arrays sampling factor */ + l_int32 minlines; /* min number of long lines required */ + l_int32 maxdist; /* max distance for getting ref pages */ + l_int32 max_linecurv; /* maximum abs line curvature, */ + /* in micro-units */ + l_int32 min_diff_linecurv; /* minimum abs diff line curvature */ + /* in micro-units */ + l_int32 max_diff_linecurv; /* maximum abs diff line curvature */ + /* in micro-units */ + l_int32 max_edgecurv; /* maximum abs left or right edge */ + /* curvature, in micro-units */ + l_int32 max_diff_edgecurv; /* maximum abs diff left-right */ + /* edge curvature, in micro-units */ + l_int32 useboth; /* use both disparity arrays if */ + /* available; just vertical otherwise */ + l_int32 modelsready; /* invalid models have been removed */ + /* and refs built against valid set */ }; typedef struct L_Dewarpa L_DEWARPA; struct L_Dewarp { - struct Pix *pixs; /* source pix, 1 bpp */ - struct Pix *pixd; /* dewarped pix; 1, 8 or 32 bpp */ - struct FPix *sampvdispar; /* sampled vert disparity array */ - struct FPix *samphdispar; /* sampled horiz disparity array */ - struct FPix *fullvdispar; /* full vert disparity array */ - struct FPix *fullhdispar; /* full horiz disparity array */ - struct Numa *naflats; /* sorted flat location of each line */ - struct Numa *nacurves; /* sorted curvature of each line */ - l_int32 w; /* width of source image */ - l_int32 h; /* height of source image */ - l_int32 pageno; /* page number; important for reuse */ - l_int32 sampling; /* sampling factor of disparity arrays */ - l_int32 redfactor; /* reduction factor of pixs: 1 or 2 */ - l_int32 minlines; /* min number of long lines required */ - l_int32 nlines; /* number of long lines found */ - l_int32 medcurv; /* median abs curvature in micro-units */ - l_int32 leftcurv; /* left edge curvature in micro-units */ - l_int32 rightcurv; /* right edge curvature in micro-units */ - l_int32 nx; /* number of sampling pts in x direction */ - l_int32 ny; /* number of sampling pts in y direction */ - l_int32 hasref; /* 0 if normal; 1 if has a refpage */ - l_int32 refpage; /* page with disparity model to use here */ - l_int32 success; /* sets to 1 if model build succeeds */ - l_int32 valid; /* sets to 1 if model is valid */ - l_int32 debug; /* sets to 1 if debug output requested */ + struct L_Dewarpa *dewa; /* ptr to parent (not owned) */ + struct Pix *pixs; /* source pix, 1 bpp */ + struct FPix *sampvdispar; /* sampled vert disparity array */ + struct FPix *samphdispar; /* sampled horiz disparity array */ + struct FPix *fullvdispar; /* full vert disparity array */ + struct FPix *fullhdispar; /* full horiz disparity array */ + struct Numa *namidys; /* sorted y val of midpoint each line */ + struct Numa *nacurves; /* sorted curvature of each line */ + l_int32 w; /* width of source image */ + l_int32 h; /* height of source image */ + l_int32 pageno; /* page number; important for reuse */ + l_int32 sampling; /* sampling factor of disparity arrays */ + l_int32 redfactor; /* reduction factor of pixs: 1 or 2 */ + l_int32 minlines; /* min number of long lines required */ + l_int32 nlines; /* number of long lines found */ + l_int32 mincurv; /* min line curvature in micro-units */ + l_int32 maxcurv; /* max line curvature in micro-units */ + l_int32 leftcurv; /* left edge curvature in micro-units */ + l_int32 rightcurv; /* right edge curvature in micro-units */ + l_int32 nx; /* number of sampling pts in x-dir */ + l_int32 ny; /* number of sampling pts in y-dir */ + l_int32 hasref; /* 0 if normal; 1 if has a refpage */ + l_int32 refpage; /* page with disparity model to use */ + l_int32 vsuccess; /* sets to 1 if vert disparity builds */ + l_int32 hsuccess; /* sets to 1 if horiz disparity builds */ + l_int32 vvalid; /* sets to 1 if valid vert disparity */ + l_int32 hvalid; /* sets to 1 if valid horiz disparity */ + l_int32 debug; /* sets to 1 if debug output requested */ }; typedef struct L_Dewarp L_DEWARP; diff --git a/TesseractOCR/include/leptonica/endianness.h b/TesseractOCR/include/leptonica/endianness.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/leptonica/environ.h b/TesseractOCR/include/leptonica/environ.h old mode 100755 new mode 100644 index da2cbd99..c2ff9f69 --- a/TesseractOCR/include/leptonica/environ.h +++ b/TesseractOCR/include/leptonica/environ.h @@ -41,6 +41,7 @@ /* MS VC++ does not provide stdint.h, so define the missing types here */ + #ifndef _MSC_VER #include @@ -65,24 +66,18 @@ typedef unsigned int uintptr_t; #endif /* _MSC_VER */ /* Windows specifics */ - #ifdef _WIN32 - -/* DLL EXPORTS and IMPORTS: - * Important: LEPTONLIB_* is deprected. It is retained here only for - * compatibility with tesseract 3.00. In your project files, use - * LIBLEPT_EXPORTS and LIBLEPT_IMPORTS */ -#if defined(LIBLEPT_EXPORTS) || defined(LEPTONLIB_EXPORTS) -#define LEPT_DLL __declspec(dllexport) -#elif defined(LIBLEPT_IMPORTS) || defined(LEPTONLIB_IMPORTS) -#define LEPT_DLL __declspec(dllimport) -#else -#define LEPT_DLL -#endif - -#else /* non-WINDOWS-SPECIFICS */ -#include -#define LEPT_DLL + /* DLL EXPORTS and IMPORTS */ + #if defined(LIBLEPT_EXPORTS) + #define LEPT_DLL __declspec(dllexport) + #elif defined(LIBLEPT_IMPORTS) + #define LEPT_DLL __declspec(dllimport) + #else + #define LEPT_DLL + #endif +#else /* non-Windows specifics */ + #include + #define LEPT_DLL #endif /* _WIN32 */ typedef intptr_t l_intptr_t; @@ -94,7 +89,7 @@ typedef void *L_TIMER; * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!* * USER CONFIGURABLE * * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!* - * Environ variables with I/O libraries * + * Environment variables with I/O libraries * * Manual Configuration Only: NOT AUTO_CONF * *--------------------------------------------------------------------*/ /* @@ -133,13 +128,14 @@ typedef void *L_TIMER; * Environ variables for uncompressed formatted image I/O * *--------------------------------------------------------------------*/ /* - * Leptonica supplies image I/O for pnm, bmp, ps, and pdf. + * Leptonica supplies image I/O for bmp, pnm, jp2k, pdf and ps. * Setting any of these to 0 causes non-functioning stubs to be linked. */ #define USE_BMPIO 1 #define USE_PNMIO 1 -#define USE_PSIO 1 +#define USE_JP2KIO 1 #define USE_PDFIO 1 +#define USE_PSIO 1 /*--------------------------------------------------------------------* @@ -153,6 +149,13 @@ typedef int l_int32; typedef unsigned int l_uint32; typedef float l_float32; typedef double l_float64; +#ifdef COMPILER_MSVC +typedef __int64 l_int64; +typedef unsigned __int64 l_uint64; +#else +typedef long long l_int64; +typedef unsigned long long l_uint64; +#endif /* COMPILER_MSVC */ /*------------------------------------------------------------------------* @@ -192,7 +195,7 @@ typedef double l_float64; /*--------------------------------------------------------------------* - * Environ variables used within compiler invocation * + * Environment variables for endian dependence * *--------------------------------------------------------------------*/ /* * To control conditional compilation, one of two variables @@ -206,7 +209,7 @@ typedef double l_float64; /*------------------------------------------------------------------------* - * Simple search state variables * + * Simple search state variables * *------------------------------------------------------------------------*/ enum { L_NOT_FOUND = 0, @@ -216,10 +219,10 @@ enum { /*------------------------------------------------------------------------* * Standard memory allocation * - * - * These specify the memory management functions that are used - * on all heap data except for Pix. Memory management for Pix - * also defaults to malloc and free. See pix1.c for details. + * * + * These specify the memory management functions that are used * + * on all heap data except for Pix. Memory management for Pix * + * also defaults to malloc and free. See pix1.c for details. * *------------------------------------------------------------------------*/ #define MALLOC(blocksize) malloc(blocksize) #define CALLOC(numelem, elemsize) calloc(numelem, elemsize) @@ -228,55 +231,197 @@ enum { /*------------------------------------------------------------------------* - * Control printing of error, warning, and info messages * + * Control printing of error, warning, and info messages * + * * + * To omit all messages to stderr, simply define NO_CONSOLE_IO on the * + * command line. For finer grained control, we have a mechanism * + * based on the message severity level. The following assumes that * + * NO_CONSOLE_IO is not defined. * + * * + * Messages are printed if the message severity is greater than or equal * + * to the current severity threshold. The current severity threshold * + * is the greater of the compile-time severity, which is the minimum * + * severity that can be reported, and the run-time severity, which is * + * the severity threshold at the moment. * * * - * (Use -DNO_CONSOLE_IO on compiler line to prevent text output) * + * The compile-time threshold determines which messages are compiled * + * into the library for potential printing. Messages below the * + * compile-time threshold are omitted and can never be printed. The * + * default compile-time threshold is L_SEVERITY_INFO, but this may be * + * overridden by defining MINIMUM_SEVERITY to the desired enumeration * + * identifier on the compiler command line. Defining NO_CONSOLE_IO on * + * the command line is the same as setting MINIMUM_SEVERITY to * + * L_SEVERITY_NONE. * + * * + * The run-time threshold determines which messages are printed during * + * library execution. It defaults to the compile-time threshold but * + * may be changed either statically by defining DEFAULT_SEVERITY to * + * the desired enumeration identifier on the compiler command line, or * + * dynamically by calling setMsgSeverity() to specify a new threshold. * + * The run-time threshold may also be set from the value of the * + * environment variable LEPT_MSG_SEVERITY by calling setMsgSeverity() * + * and specifying L_SEVERITY_EXTERNAL. * + * * + * In effect, the compile-time threshold setting says, "Generate code * + * to permit messages of equal or greater severity than this to be * + * printed, if desired," whereas the run-time threshold setting says, * + * "Print messages that have an equal or greater severity than this." * *------------------------------------------------------------------------*/ +enum { + L_SEVERITY_EXTERNAL = 0, /* Get the severity from the environment */ + L_SEVERITY_ALL = 1, /* Lowest severity: print all messages */ + L_SEVERITY_DEBUG = 2, /* Print debugging and higher messages */ + L_SEVERITY_INFO = 3, /* Print informational and higher messages */ + L_SEVERITY_WARNING = 4, /* Print warning and higher messages */ + L_SEVERITY_ERROR = 5, /* Print error and higher messages */ + L_SEVERITY_NONE = 6 /* Highest severity: print no messages */ +}; + +/* No message less than the compile-time threshold will ever be + * reported, regardless of the current run-time threshold. This allows + * selection of the set of messages to include in the library. For + * example, setting the threshold to L_SEVERITY_WARNING eliminates all + * informational messages from the library. With that setting, both + * warning and error messages would be printed unless setMsgSeverity() + * was called, or DEFAULT_SEVERITY was redefined, to set the run-time + * severity to L_SEVERITY_ERROR. In that case, only error messages + * would be printed. + * + * This mechanism makes the library smaller and faster, by eliminating + * undesired message reporting and the associated run-time overhead for + * message threshold checking, because code for messages whose severity + * is lower than MINIMUM_SEVERITY won't be generated. + * + * A production library might typically permit WARNING and higher + * messages to be generated, and a development library might permit + * DEBUG and higher. The actual messages printed (as opposed to + * generated) would depend on the current run-time severity threshold. + */ + #ifdef NO_CONSOLE_IO + #undef MINIMUM_SEVERITY + #undef DEFAULT_SEVERITY -#define PROCNAME(name) -#define ERROR_PTR(a,b,c) ((void *)(c)) -#define ERROR_INT(a,b,c) ((l_int32)(c)) -#define ERROR_FLOAT(a,b,c) ((l_float32)(c)) -#define L_ERROR(a,b) -#define L_ERROR_STRING(a,b,c) -#define L_ERROR_INT(a,b,c) -#define L_ERROR_FLOAT(a,b,c) -#define L_WARNING(a,b) -#define L_WARNING_STRING(a,b,c) -#define L_WARNING_INT(a,b,c) -#define L_WARNING_INT2(a,b,c,d) -#define L_WARNING_FLOAT(a,b,c) -#define L_WARNING_FLOAT2(a,b,c,d) -#define L_INFO(a,b) -#define L_INFO_STRING(a,b,c) -#define L_INFO_INT(a,b,c) -#define L_INFO_INT2(a,b,c,d) -#define L_INFO_FLOAT(a,b,c) -#define L_INFO_FLOAT2(a,b,c,d) + #define MINIMUM_SEVERITY L_SEVERITY_NONE + #define DEFAULT_SEVERITY L_SEVERITY_NONE #else + #ifndef MINIMUM_SEVERITY + #define MINIMUM_SEVERITY L_SEVERITY_INFO /* Compile-time default */ + #endif + + #ifndef DEFAULT_SEVERITY + #define DEFAULT_SEVERITY MINIMUM_SEVERITY /* Run-time default */ + #endif +#endif -#define PROCNAME(name) static const char procName[] = name -#define ERROR_PTR(a,b,c) returnErrorPtr((a),(b),(c)) -#define ERROR_INT(a,b,c) returnErrorInt((a),(b),(c)) -#define ERROR_FLOAT(a,b,c) returnErrorFloat((a),(b),(c)) -#define L_ERROR(a,b) l_error((a),(b)) -#define L_ERROR_STRING(a,b,c) l_errorString((a),(b),(c)) -#define L_ERROR_INT(a,b,c) l_errorInt((a),(b),(c)) -#define L_ERROR_FLOAT(a,b,c) l_errorFloat((a),(b),(c)) -#define L_WARNING(a,b) l_warning((a),(b)) -#define L_WARNING_STRING(a,b,c) l_warningString((a),(b),(c)) -#define L_WARNING_INT(a,b,c) l_warningInt((a),(b),(c)) -#define L_WARNING_INT2(a,b,c,d) l_warningInt2((a),(b),(c),(d)) -#define L_WARNING_FLOAT(a,b,c) l_warningFloat((a),(b),(c)) -#define L_WARNING_FLOAT2(a,b,c,d) l_warningFloat2((a),(b),(c),(d)) -#define L_INFO(a,b) l_info((a),(b)) -#define L_INFO_STRING(a,b,c) l_infoString((a),(b),(c)) -#define L_INFO_INT(a,b,c) l_infoInt((a),(b),(c)) -#define L_INFO_INT2(a,b,c,d) l_infoInt2((a),(b),(c),(d)) -#define L_INFO_FLOAT(a,b,c) l_infoFloat((a),(b),(c)) -#define L_INFO_FLOAT2(a,b,c,d) l_infoFloat2((a),(b),(c),(d)) + +/* The run-time message severity threshold is defined in utils.c. */ +LEPT_DLL extern l_int32 LeptMsgSeverity; + +/* + * Usage + * ===== + * Messages are of two types. + * + * (1) The messages + * ERROR_INT(a,b,c) : returns l_int32 + * ERROR_FLOAT(a,b,c) : returns l_float32 + * ERROR_PTR(a,b,c) : returns void* + * are used to return from functions and take a fixed set of parameters: + * a : + * b : procName + * c : + * where procName is the name of the local variable naming the function. + * + * (2) The purely informational L_* messages + * L_ERROR(a,...) + * L_WARNING(a,...) + * L_INFO(a,...) + * do not take a return value, but they take at least two parameters: + * a : with optional format conversions + * v1 : procName (this must be included as the first vararg) + * v2, ... : optional varargs to match format converters in the message + * + * To return an error from a function that returns void, use: + * L_ERROR(, procName, [...]) + * return; + * + * Implementation details + * ====================== + * Messages are defined with the IF_SEV macro. The first parameter is + * the message severity, the second is the function to call if the + * message is to be printed, and the third is the return value if the + * message is to be suppressed. For example, we might have an + * informational message defined as: + * + * IF_SEV(L_SEVERITY_INFO, fprintf(.......), 0) + * + * The macro expands into a conditional. Because the first comparison + * is between two constants, an optimizing compiler will remove either + * the comparison (if it's true) or the entire macro expansion (if it + * is false). This means that there is no run-time overhead for + * messages whose severity falls below the minimum specified at compile + * time, and for others the overhead is one (not two) comparisons. + * + * The L_nnn() macros below do not return a value, but because the + * conditional operator requires one for the false condition, we + * specify a void expression. + */ + +#ifdef NO_CONSOLE_IO + + #define PROCNAME(name) + #define ERROR_INT(a,b,c) ((l_int32)(c)) + #define ERROR_FLOAT(a,b,c) ((l_float32)(c)) + #define ERROR_PTR(a,b,c) ((void *)(c)) + #define L_ERROR(a,...) + #define L_WARNING(a,...) + #define L_INFO(a,...) + +#else + + #define PROCNAME(name) static const char procName[] = name + #define IF_SEV(l,t,f) \ + ((l) >= MINIMUM_SEVERITY && (l) >= LeptMsgSeverity ? (t) : (f)) + + #define ERROR_INT(a,b,c) \ + IF_SEV(L_SEVERITY_ERROR, returnErrorInt((a),(b),(c)), (l_int32)(c)) + #define ERROR_FLOAT(a,b,c) \ + IF_SEV(L_SEVERITY_ERROR, returnErrorFloat((a),(b),(c)), (l_float32)(c)) + #define ERROR_PTR(a,b,c) \ + IF_SEV(L_SEVERITY_ERROR, returnErrorPtr((a),(b),(c)), (void *)(c)) + + #define L_ERROR(a,...) \ + IF_SEV(L_SEVERITY_ERROR, \ + (void)fprintf(stderr, "Error in %s: " a, __VA_ARGS__), \ + (void)0) + #define L_WARNING(a,...) \ + IF_SEV(L_SEVERITY_WARNING, \ + (void)fprintf(stderr, "Warning in %s: " a, __VA_ARGS__), \ + (void)0) + #define L_INFO(a,...) \ + IF_SEV(L_SEVERITY_INFO, \ + (void)fprintf(stderr, "Info in %s: " a, __VA_ARGS__), \ + (void)0) + +#if 0 /* Alternative method for controlling L_* message output */ + #define L_ERROR(a,...) \ + { if (L_SEVERITY_ERROR >= MINIMUM_SEVERITY && \ + L_SEVERITY_ERROR >= LeptMsgSeverity) \ + fprintf(stderr, "Error in %s: " a, __VA_ARGS__) \ + } + #define L_WARNING(a,...) \ + { if (L_SEVERITY_WARNING >= MINIMUM_SEVERITY && \ + L_SEVERITY_WARNING >= LeptMsgSeverity) \ + fprintf(stderr, "Warning in %s: " a, __VA_ARGS__) \ + } + #define L_INFO(a,...) \ + { if (L_SEVERITY_INFO >= MINIMUM_SEVERITY && \ + L_SEVERITY_INFO >= LeptMsgSeverity) \ + fprintf(stderr, "Info in %s: " a, __VA_ARGS__) \ + } +#endif #endif /* NO_CONSOLE_IO */ diff --git a/TesseractOCR/include/leptonica/freetype.h b/TesseractOCR/include/leptonica/freetype.h old mode 100755 new mode 100644 index 17fa11a4..6969d411 --- a/TesseractOCR/include/leptonica/freetype.h +++ b/TesseractOCR/include/leptonica/freetype.h @@ -1,16 +1,27 @@ /*====================================================================* - - Copyright (C) 2008 Leptonica. All rights reserved. - - This software is distributed in the hope that it will be - - useful, but with NO WARRANTY OF ANY KIND. - - No author or distributor accepts responsibility to anyone for the - - consequences of using this software, or for whether it serves any - - particular purpose or works at all, unless he or she says so in - - writing. Everyone is granted permission to copy, modify and - - redistribute this source code, for commercial or non-commercial - - purposes, with the following restrictions: (1) the origin of this - - source code must not be misrepresented; (2) modified versions must - - be plainly marked as such; and (3) this notice may not be removed - - or altered from any source or modified source distribution. + - Copyright (C) 2001 Leptonica. All rights reserved. + - + - 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY + - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *====================================================================*/ #ifndef LEPTONICA_FREETYPE_H diff --git a/TesseractOCR/include/leptonica/gplot.h b/TesseractOCR/include/leptonica/gplot.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/leptonica/heap.h b/TesseractOCR/include/leptonica/heap.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/leptonica/imageio.h b/TesseractOCR/include/leptonica/imageio.h old mode 100755 new mode 100644 index e3926725..4e0332c7 --- a/TesseractOCR/include/leptonica/imageio.h +++ b/TesseractOCR/include/leptonica/imageio.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -28,7 +28,7 @@ #define LEPTONICA_IMAGEIO_H /* ------------------ Image file format types -------------- */ -/* +/* * The IFF_DEFAULT flag is used to write the file out in the * same (input) file format that the pix was read from. If the pix * was not read from file, the input format field will be @@ -83,7 +83,8 @@ enum { enum { L_JPEG_ENCODE = 1, /* use dct encoding: 8 and 32 bpp, no cmap */ L_G4_ENCODE = 2, /* use ccitt g4 fax encoding: 1 bpp */ - L_FLATE_ENCODE = 3 /* use flate encoding: any depth, cmap ok */ + L_FLATE_ENCODE = 3, /* use flate encoding: any depth, cmap ok */ + L_JP2K_ENCODE = 4 /* use jp2k encoding: 8 and 32 bpp, no cmap */ }; @@ -116,7 +117,7 @@ struct L_Compressed_Data size_t nbytes; /* number of uncompressed raster bytes */ l_int32 res; /* resolution (ppi) */ }; -typedef struct L_Compressed_Data L_COMPRESSED_DATA; +typedef struct L_Compressed_Data L_COMP_DATA; /* ------------------------ Pdf multi-image flags ------------------------ */ diff --git a/TesseractOCR/include/leptonica/jbclass.h b/TesseractOCR/include/leptonica/jbclass.h old mode 100755 new mode 100644 index 0a22ab33..0c28c869 --- a/TesseractOCR/include/leptonica/jbclass.h +++ b/TesseractOCR/include/leptonica/jbclass.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR diff --git a/TesseractOCR/include/leptonica/leptwin.h b/TesseractOCR/include/leptonica/leptwin.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/leptonica/list.h b/TesseractOCR/include/leptonica/list.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/leptonica/morph.h b/TesseractOCR/include/leptonica/morph.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/leptonica/pix.h b/TesseractOCR/include/leptonica/pix.h old mode 100755 new mode 100644 index 332453eb..0c599da8 --- a/TesseractOCR/include/leptonica/pix.h +++ b/TesseractOCR/include/leptonica/pix.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -30,7 +30,23 @@ /* * pix.h * - * Contains the following structures: + * Valid image types in leptonica: + * Pix: 1 bpp, with and without colormap + * Pix: 2 bpp, with and without colormap + * Pix: 4 bpp, with and without colormap + * Pix: 8 bpp, with and without colormap + * Pix: 16 bpp (1 spp) + * Pix: 32 bpp (rgb, 3 spp) + * Pix: 32 bpp (rgba, 4 spp) + * FPix: 32 bpp float + * DPix: 64 bpp double + * Notes: + * (1) The only valid Pix image type with alpha is rgba. + * In particular, the alpha component is not used in + * cmapped images. + * (2) PixComp can hold any Pix with IFF_PNG encoding. + * + * This file defines most of the image-related structs used in leptonica: * struct Pix * struct PixColormap * struct RGBA_Quad @@ -49,7 +65,7 @@ * struct PixComp * struct PixaComp * - * Contains definitions for: + * This file has definitions for: * Colors for RGB * Perceptual color weights * Colormap conversion flags @@ -60,10 +76,13 @@ * Graphics pixel setting flags * Size filtering flags * Color component selection flags + * 16-bit conversion flags * Rotation and shear flags * Affine transform order flags * Grayscale filling flags * Flags for setting to white or black + * Flags for getting white or black pixel value + * Flags for 8 and 16 bit pixel sums * Dithering flags * Distance flags * Statistical measures @@ -73,6 +92,7 @@ * Line orientation flags * Scan direction flags * Box size adjustment flags + * Handling overlapping bounding boxes in boxa * Horizontal warp * Pixel selection for resampling * Thinning flags @@ -85,17 +105,21 @@ * Region flags (inclusion, exclusion) * Flags for adding text to a pix * Flags for selecting display program + * Flags in the 'special' pix field for non-default operations */ /*-------------------------------------------------------------------------* * Basic Pix * *-------------------------------------------------------------------------*/ + /* The 'special' field is by default 0, but it can hold integers + * that direct non-default actions, e.g., in png and jpeg I/O. */ struct Pix { l_uint32 w; /* width in pixels */ l_uint32 h; /* height in pixels */ - l_uint32 d; /* depth in bits */ + l_uint32 d; /* depth in bits (bpp) */ + l_uint32 spp; /* number of samples per pixel */ l_uint32 wpl; /* 32-bit words/line */ l_uint32 refcount; /* reference count (1 if no clones) */ l_int32 xres; /* image res (ppi) in x direction */ @@ -103,6 +127,7 @@ struct Pix l_int32 yres; /* image res (ppi) in y direction */ /* (use 0 if unknown) */ l_int32 informat; /* input file format, IFF_* */ + l_int32 special; /* special instructions for I/O, etc */ char *text; /* text string associated with pix */ struct PixColormap *colormap; /* colormap (may be null) */ l_uint32 *data; /* the image data */ @@ -129,7 +154,7 @@ struct RGBA_Quad l_uint8 blue; l_uint8 green; l_uint8 red; - l_uint8 reserved; + l_uint8 alpha; }; typedef struct RGBA_Quad RGBA_QUAD; @@ -142,14 +167,14 @@ typedef struct RGBA_Quad RGBA_QUAD; * (1) These are the byte indices for colors in 32 bpp images. * They are used through the GET/SET_DATA_BYTE accessors. * The 4th byte, typically known as the "alpha channel" and used - * for blending, is not explicitly used in leptonica. - * (2) If you redefine these values, functions that have the shifts - * hardcoded (instead of using the constants below) will break. - * These functions are labelled with "***" next to their names - * at the top of the files in which they are defined. - * Advice: Do not change these values! - * (3) The shifts to extract the red, green and blue components - * from a 32 bit pixel are defined in terms of these colors. + * for blending, is used to a small extent in leptonica. + * (2) Do not change these values! If you redefine them, functions + * that have the shifts hardcoded for efficiency and conciseness + * (instead of using the constants below) will break. These + * functions are labelled with "***" next to their names at + * the top of the files in which they are defined. + * (3) The shifts to extract the red, green, blue and alpha components + * from a 32 bit pixel are defined here. */ enum { COLOR_RED = 0, @@ -190,7 +215,8 @@ enum { REMOVE_CMAP_TO_BINARY = 0, REMOVE_CMAP_TO_GRAYSCALE = 1, REMOVE_CMAP_TO_FULL_COLOR = 2, - REMOVE_CMAP_BASED_ON_SRC = 3 + REMOVE_CMAP_WITH_ALPHA = 3, + REMOVE_CMAP_BASED_ON_SRC = 4 }; @@ -292,12 +318,13 @@ enum { * This MSB to LSB ordering allows left and right shift * operations on 32 bit words to move the pixels properly. * - * (4) For 24-bit color images, use 32 bpp data, leaving - * the fourth byte unused. Within each 4 byte pixel, the + * (4) We use 32 bit pixels for both RGB and RGBA color images. + * The A (alpha) byte is ignored in most leptonica functions + * operating on color images. Within each 4 byte pixel, the * colors are ordered from MSB to LSB, as follows: * * | MSB | 2nd MSB | 3rd MSB | LSB | - * red green blue unused + * red green blue alpha * 0 1 2 3 (big-endian) * 3 2 1 0 (little-endian) * @@ -308,24 +335,28 @@ enum { * red: byte 0 (MSB) * green: byte 1 (2nd MSB) * blue: byte 2 (3rd MSB) + * alpha: byte 3 (LSB) * - * This specific color assignment is made in this file, + * The specific color assignment is made in this file, * through the definitions of COLOR_RED, etc. Then the R, G - * and B sample values can be retrieved using + * B and A sample values can be retrieved using * redval = GET_DATA_BYTE(&pixel, COLOR_RED); * greenval = GET_DATA_BYTE(&pixel, COLOR_GREEN); * blueval = GET_DATA_BYTE(&pixel, COLOR_BLUE); + * alphaval = GET_DATA_BYTE(&pixel, L_ALPHA_CHANNEL); * and they can be set with * SET_DATA_BYTE(&pixel, COLOR_RED, redval); * SET_DATA_BYTE(&pixel, COLOR_GREEN, greenval); * SET_DATA_BYTE(&pixel, COLOR_BLUE, blueval); + * SET_DATA_BYTE(&pixel, L_ALPHA_CHANNEL, alphaval); * - * For extra speed we extract the R, G and B colors directly + * For extra speed we extract these components directly * by shifting and masking, explicitly using the values in - * L_RED_SHIFT, L_GREEN_SHIFT and L_BLUE_SHIFT: + * L_RED_SHIFT, etc.: * (pixel32 >> L_RED_SHIFT) & 0xff; (red) * (pixel32 >> L_GREEN_SHIFT) & 0xff; (green) * (pixel32 >> L_BLUE_SHIFT) & 0xff; (blue) + * (pixel32 >> L_ALPHA_SHIFT) & 0xff; (alpha) * All these operations work properly on both big- and little-endians. * * For a few situations, these color shift values are hard-coded. @@ -618,21 +649,28 @@ static const l_int32 L_NOCOPY = 0; /* copyflag value in sarrayGetString() */ /*--------------------------------------------------------------------------* * Sort flags * *--------------------------------------------------------------------------*/ +enum { + L_SHELL_SORT = 1, /* use shell sort */ + L_BIN_SORT = 2 /* use bin sort */ +}; + enum { L_SORT_INCREASING = 1, /* sort in increasing order */ L_SORT_DECREASING = 2 /* sort in decreasing order */ }; enum { - L_SORT_BY_X = 3, /* sort box or c.c. by horiz location */ - L_SORT_BY_Y = 4, /* sort box or c.c. by vert location */ - L_SORT_BY_WIDTH = 5, /* sort box or c.c. by width */ - L_SORT_BY_HEIGHT = 6, /* sort box or c.c. by height */ - L_SORT_BY_MIN_DIMENSION = 7, /* sort box or c.c. by min dimension */ - L_SORT_BY_MAX_DIMENSION = 8, /* sort box or c.c. by max dimension */ - L_SORT_BY_PERIMETER = 9, /* sort box or c.c. by perimeter */ - L_SORT_BY_AREA = 10, /* sort box or c.c. by area */ - L_SORT_BY_ASPECT_RATIO = 11 /* sort box or c.c. by width/height ratio */ + L_SORT_BY_X = 1, /* sort box or c.c. by left edge location */ + L_SORT_BY_Y = 2, /* sort box or c.c. by top edge location */ + L_SORT_BY_RIGHT = 3, /* sort box or c.c. by right edge location */ + L_SORT_BY_BOT = 4, /* sort box or c.c. by bot edge location */ + L_SORT_BY_WIDTH = 5, /* sort box or c.c. by width */ + L_SORT_BY_HEIGHT = 6, /* sort box or c.c. by height */ + L_SORT_BY_MIN_DIMENSION = 7, /* sort box or c.c. by min dimension */ + L_SORT_BY_MAX_DIMENSION = 8, /* sort box or c.c. by max dimension */ + L_SORT_BY_PERIMETER = 9, /* sort box or c.c. by perimeter */ + L_SORT_BY_AREA = 10, /* sort box or c.c. by area */ + L_SORT_BY_ASPECT_RATIO = 11 /* sort box or c.c. by width/height ratio */ }; @@ -694,6 +732,16 @@ enum { }; +/*-------------------------------------------------------------------------* + * 16-bit conversion flags * + *-------------------------------------------------------------------------*/ +enum { + L_LS_BYTE = 0, /* use LSB */ + L_MS_BYTE = 1, /* use MSB */ + L_CLIP_TO_255 = 2 /* use max(val, 255) */ +}; + + /*-------------------------------------------------------------------------* * Rotate and shear flags * *-------------------------------------------------------------------------*/ @@ -745,6 +793,24 @@ enum { }; +/*-------------------------------------------------------------------------* + * Flags for getting white or black value * + *-------------------------------------------------------------------------*/ +enum { + L_GET_WHITE_VAL = 1, /* get white pixel value */ + L_GET_BLACK_VAL = 2 /* get black pixel value */ +}; + + +/*-------------------------------------------------------------------------* + * Flags for 8 bit and 16 bit pixel sums * + *-------------------------------------------------------------------------*/ +enum { + L_WHITE_IS_MAX = 1, /* white pixels are 0xff or 0xffff; black are 0 */ + L_BLACK_IS_MAX = 2 /* black pixels are 0xff or 0xffff; white are 0 */ +}; + + /*-------------------------------------------------------------------------* * Dither parameters * * If within this grayscale distance from black or white, * @@ -831,23 +897,45 @@ enum { L_FROM_LEFT = 0, /* scan from left */ L_FROM_RIGHT = 1, /* scan from right */ L_FROM_TOP = 2, /* scan from top */ - L_FROM_BOTTOM = 3 /* scan from bottom */ + L_FROM_BOT = 3, /* scan from bottom */ + L_SCAN_NEGATIVE = 4, /* scan in negative direction */ + L_SCAN_POSITIVE = 5, /* scan in positive direction */ + L_SCAN_BOTH = 6 /* scan in both directions */ }; /*-------------------------------------------------------------------------* - * Box size adjustment flags * + * Box size adjustment and location flags * *-------------------------------------------------------------------------*/ enum { - L_ADJUST_LEFT = 0, /* adjust left edge */ - L_ADJUST_RIGHT = 1, /* adjust right edge */ - L_ADJUST_LEFT_AND_RIGHT = 2, /* adjust both left and right edges */ - L_ADJUST_TOP = 3, /* adjust top edge */ - L_ADJUST_BOT = 4, /* adjust bottom edge */ - L_ADJUST_TOP_AND_BOT = 5 /* adjust both top and bottom edges */ + L_ADJUST_SKIP = 0, /* do not adjust */ + L_ADJUST_LEFT = 1, /* adjust left edge */ + L_ADJUST_RIGHT = 2, /* adjust right edge */ + L_ADJUST_LEFT_AND_RIGHT = 3, /* adjust both left and right edges */ + L_ADJUST_TOP = 4, /* adjust top edge */ + L_ADJUST_BOT = 5, /* adjust bottom edge */ + L_ADJUST_TOP_AND_BOT = 6, /* adjust both top and bottom edges */ + L_ADJUST_CHOOSE_MIN = 7, /* choose the min median value */ + L_ADJUST_CHOOSE_MAX = 8, /* choose the max median value */ + L_SET_LEFT = 9, /* set left side to a given value */ + L_SET_RIGHT = 10, /* set right side to a given value */ + L_SET_TOP = 11, /* set top side to a given value */ + L_SET_BOT = 12, /* set bottom side to a given value */ + L_GET_LEFT = 13, /* get left side location */ + L_GET_RIGHT = 14, /* get right side location */ + L_GET_TOP = 15, /* get top side location */ + L_GET_BOT = 16 /* get bottom side location */ }; +/*-------------------------------------------------------------------------* + * Handling overlapping bounding boxes in boxa * + *-------------------------------------------------------------------------*/ +enum { + L_COMBINE = 1, /* resize to bounding region; remove smaller */ + L_REMOVE_SMALL = 2 /* only remove smaller */ +}; + /*-------------------------------------------------------------------------* * Horizontal warp * *-------------------------------------------------------------------------*/ @@ -952,9 +1040,13 @@ enum { *-------------------------------------------------------------------------*/ enum { L_ADD_ABOVE = 1, /* Add text above the image */ - L_ADD_AT_TOP = 2, /* Add text over the top of the image */ - L_ADD_AT_BOTTOM = 3, /* Add text over the bottom of the image */ - L_ADD_BELOW = 4 /* Add text below the image */ + L_ADD_BELOW = 2, /* Add text below the image */ + L_ADD_LEFT = 3, /* Add text to the left of the image */ + L_ADD_RIGHT = 4, /* Add text to the right of the image */ + L_ADD_AT_TOP = 5, /* Add text over the top of the image */ + L_ADD_AT_BOT = 6, /* Add text over the bottom of the image */ + L_ADD_AT_LEFT = 7, /* Add text over left side of the image */ + L_ADD_AT_RIGHT = 8 /* Add text over right side of the image */ }; @@ -962,10 +1054,20 @@ enum { * Flags for selecting display program * *-------------------------------------------------------------------------*/ enum { - L_DISPLAY_WITH_XV = 1, /* Use xv with pixDisplay() */ + L_DISPLAY_WITH_XZGV = 1, /* Use xzgv with pixDisplay() */ L_DISPLAY_WITH_XLI = 2, /* Use xli with pixDisplay() */ - L_DISPLAY_WITH_XZGV = 3, /* Use xzgv with pixDisplay() */ - L_DISPLAY_WITH_IV = 4 /* Use irfvanview with pixDisplay() */ + L_DISPLAY_WITH_XV = 3, /* Use xv with pixDisplay() */ + L_DISPLAY_WITH_IV = 4, /* Use irfvanview (win) with pixDisplay() */ + L_DISPLAY_WITH_OPEN = 5 /* Use open (apple) with pixDisplay() */ +}; + +/*-------------------------------------------------------------------------* + * Flag(s) used in the 'special' pix field for non-default operations * + * - 0 is default * + * - 10-19 are reserved for zlib compression in png write * + *-------------------------------------------------------------------------*/ +enum { + L_NO_CHROMA_SAMPLING_JPEG = 1 /* Write full resolution chroma */ }; #endif /* LEPTONICA_PIX_H */ diff --git a/TesseractOCR/include/leptonica/ptra.h b/TesseractOCR/include/leptonica/ptra.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/leptonica/queue.h b/TesseractOCR/include/leptonica/queue.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/leptonica/readbarcode.h b/TesseractOCR/include/leptonica/readbarcode.h old mode 100755 new mode 100644 index 44ae29c1..4cfb9d53 --- a/TesseractOCR/include/leptonica/readbarcode.h +++ b/TesseractOCR/include/leptonica/readbarcode.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR diff --git a/TesseractOCR/include/leptonica/recog.h b/TesseractOCR/include/leptonica/recog.h new file mode 100644 index 00000000..6a449d24 --- /dev/null +++ b/TesseractOCR/include/leptonica/recog.h @@ -0,0 +1,258 @@ +/*====================================================================* + - Copyright (C) 2001 Leptonica. All rights reserved. + - + - 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY + - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *====================================================================*/ + +#ifndef LEPTONICA_RECOG_H +#define LEPTONICA_RECOG_H + +/* + * recog.h + * + * A simple utility for training and recognizing individual + * machine-printed text characters. In an application, one can + * envision using a number of these, one for each trained set. + * + * In training mode, a set of labelled bitmaps is presented, either + * one at a time, or in a directory, or in a pixa. If in a directory, + * or a pixa, the labelling text string must be embedded in the + * text field of the image file. + * + * Any number of recognizers (L_Recog) can be trained and then used + * together in an array (L_Recoga). All these trained structures + * can be serialized to file and read back. The serialized version + * holds all the bitmaps used for training, plus, for arbitrary + * character sets, the UTF8 representation and the lookup table + * mapping from the character representation to index. + * + * There are three levels of "sets" here: + * + * (1) Example set: the examples representing a character that + * were printed in the same way, so that they can be combined + * without scaling to form an "average" template for the character. + * In the recognition phase, we use either this aligned average, + * or the individual bitmaps. All examples in the set are given + * the same character label. Example: the letter 'a' in the + * predominant font in a book. + * + * (2) Character set (represented by L_Recog, a single recognizer): + * The set of different characters, each of which is described + * by (1). Each element of the set has a different character + * label. Example: the digits '0' through '9' that are used for + * page numbering in a book. + * + * (3) Recognizer set (represented by L_Recoga, an array of recogs): + * A set of recognizers, each of which is described by (2). + * In general, we do not want to combine the character sets + * with the same labels within different recognizer sets, + * because the bitmaps can differ in font type, style or size. + * Example 1: the letter 'a' can be printed in two very different + * ways (either with a large loop or with a smaller loop in + * the lower half); both share the same label but need to be + * distinguished so that they are not mixed when averaging. + * Example 2: a recognizer trained for a book may be missing + * some characters, so we need to supplement it with another + * "generic" or "bootstrap" recognizer that has the additional + * characters from a variety of sources. Bootstrap recognizers + * must be run in a mode where all characters are scaled. + * + * In the recognition process, for each component in an input image, + * each recognizer (L_Recog) records the best match (highest + * correlation score). If there is more than one recognizer, these + * results are aggregated to find the best match for each character + * for all the recognizers, and this is stored in L_Recoga. + */ + +#define RECOG_VERSION_NUMBER 1 + +struct L_Recoga { + l_int32 n; /* number of recogs */ + l_int32 nalloc; /* number of recog ptrs allocated */ + struct L_Recog **recog; /* recog ptr array */ + struct L_Rcha *rcha; /* stores the array of best chars */ +}; +typedef struct L_Recoga L_RECOGA; + + +struct L_Recog { + l_int32 scalew; /* scale all examples to this width; */ + /* use 0 prevent horizontal scaling */ + l_int32 scaleh; /* scale all examples to this height; */ + /* use 0 prevent vertical scaling */ + l_int32 templ_type; /* template type: either an average of */ + /* examples (L_USE_AVERAGE) or the set */ + /* of all examples (L_USE_ALL) */ + l_int32 maxarraysize; /* initialize container arrays to this */ + l_int32 setsize; /* size of character set */ + l_int32 threshold; /* for binarizing if depth > 1 */ + l_int32 maxyshift; /* vertical jiggle on nominal centroid */ + /* alignment; typically 0 or 1 */ + l_float32 asperity_fr; /* +- allowed fractional asperity ratio */ + l_int32 charset_type; /* one of L_ARABIC_NUMERALS, etc. */ + l_int32 charset_size; /* expected number of classes in charset */ + char *bootdir; /* dir with bootstrap pixa charsets */ + char *bootpattern; /* file pattern for bootstrap pixa charsets */ + char *bootpath; /* path for single bootstrap pixa charset */ + l_int32 min_nopad; /* min number of samples without padding */ + l_int32 max_afterpad; /* max number of samples after padding */ + l_int32 samplenum; /* keep track of number of training samples */ + l_int32 minwidth_u; /* min width of averaged unscaled templates */ + l_int32 maxwidth_u; /* max width of averaged unscaled templates */ + l_int32 minheight_u; /* min height of averaged unscaled templates */ + l_int32 maxheight_u; /* max height of averaged unscaled templates */ + l_int32 minwidth; /* min width of averaged scaled templates */ + l_int32 maxwidth; /* max width of averaged scaled templates */ + l_int32 ave_done; /* set to 1 when averaged bitmaps are made */ + l_int32 train_done; /* set to 1 when training is complete or */ + /* identification has started */ + l_int32 min_splitw; /* min component width kept in splitting */ + l_int32 min_splith; /* min component height kept in splitting */ + l_int32 max_splith; /* max component height kept in splitting */ + struct Sarray *sa_text; /* text array for arbitrary char set */ + struct L_Dna *dna_tochar; /* index-to-char lut for arbitrary char set */ + l_int32 *centtab; /* table for finding centroids */ + l_int32 *sumtab; /* table for finding pixel sums */ + char *fname; /* serialized filename (if read) */ + struct Pixaa *pixaa_u; /* all unscaled bitmaps for each class */ + struct Pixa *pixa_u; /* averaged unscaled bitmaps for each class */ + struct Ptaa *ptaa_u; /* centroids of all unscaled bitmaps */ + struct Pta *pta_u; /* centroids of unscaled averaged bitmaps */ + struct Numaa *naasum_u; /* area of all unscaled bitmap examples */ + struct Numa *nasum_u; /* area of unscaled averaged bitmaps */ + struct Pixaa *pixaa; /* all bitmap examples for each class */ + struct Pixa *pixa; /* averaged bitmaps for each class */ + struct Ptaa *ptaa; /* centroids of all bitmap examples */ + struct Pta *pta; /* centroids of averaged bitmaps */ + struct Numaa *naasum; /* area of all bitmap examples */ + struct Numa *nasum; /* area of averaged bitmaps */ + struct Pixa *pixa_tr; /* input training images */ + struct Pixa *pixadb_ave; /* unscaled and scaled averaged bitmaps */ + struct Pixa *pixa_id; /* input images for identifying */ + struct Pix *pixdb_ave; /* debug: best match of input against ave. */ + struct Pix *pixdb_range; /* debug: best matches within range */ + struct Pixa *pixadb_boot; /* debug: bootstrap training results */ + struct Pixa *pixadb_split; /* debug: splitting results */ + char *fontdir; /* directory for bitmapped fonts */ + struct L_Bmf *bmf; /* bmf fonts */ + l_int32 bmf_size; /* font size of bmf; default is 6 pt */ + struct L_Rdid *did; /* temp data used for image decoding */ + struct L_Rch *rch; /* temp data used for holding best char */ + struct L_Rcha *rcha; /* temp data used for array of best chars */ + l_int32 bootrecog; /* 1 if using bootstrap samples; else 0 */ + l_int32 index; /* recog index in recoga; -1 if no parent */ + struct L_Recoga *parent; /* ptr to parent array; can be null */ + +}; +typedef struct L_Recog L_RECOG; + +/* + * Data returned from correlation matching on a single character + */ +struct L_Rch { + l_int32 index; /* index of best template */ + l_float32 score; /* correlation score of best template */ + char *text; /* character string of best template */ + l_int32 sample; /* index of best sample (within the best */ + /* template class, if all samples are used) */ + l_int32 xloc; /* x-location of template (delx + shiftx) */ + l_int32 yloc; /* y-location of template (dely + shifty) */ + l_int32 width; /* width of best template */ +}; +typedef struct L_Rch L_RCH; + +/* + * Data returned from correlation matching on an array of characters + */ +struct L_Rcha { + struct Numa *naindex; /* indices of best templates */ + struct Numa *nascore; /* correlation scores of best templates */ + struct Sarray *satext; /* character strings of best templates */ + struct Numa *nasample; /* indices of best samples */ + struct Numa *naxloc; /* x-locations of templates (delx + shiftx) */ + struct Numa *nayloc; /* y-locations of templates (dely + shifty) */ + struct Numa *nawidth; /* widths of best templates */ +}; +typedef struct L_Rcha L_RCHA; + +/* + * Data used for decoding a line of characters. + */ +struct L_Rdid { + struct Pix *pixs; /* clone of pix to be decoded */ + l_int32 **counta; /* count array for each averaged template */ + l_int32 **delya; /* best y-shift array per averaged template */ + l_int32 narray; /* number of averaged templates */ + l_int32 size; /* size of count array (width of pixs) */ + l_int32 *setwidth; /* setwidths for each template */ + struct Numa *nasum; /* pixel count in pixs by column */ + struct Numa *namoment; /* first moment of pixels in pixs by column */ + l_int32 fullarrays; /* 1 if full arrays are made; 0 otherwise */ + l_float32 *beta; /* channel coeffs for template fg term */ + l_float32 *gamma; /* channel coeffs for bit-and term */ + l_float32 *trellisscore; /* score on trellis */ + l_int32 *trellistempl; /* template on trellis (for backtrack) */ + struct Numa *natempl; /* indices of best path templates */ + struct Numa *naxloc; /* x locations of best path templates */ + struct Numa *nadely; /* y locations of best path templates */ + struct Numa *nawidth; /* widths of best path templates */ + struct Numa *nascore; /* correlation scores: best path templates */ + struct Numa *natempl_r; /* indices of best rescored templates */ + struct Numa *naxloc_r; /* x locations of best rescoredtemplates */ + struct Numa *nadely_r; /* y locations of best rescoredtemplates */ + struct Numa *nawidth_r; /* widths of best rescoredtemplates */ + struct Numa *nascore_r; /* correlation scores: rescored templates */ +}; +typedef struct L_Rdid L_RDID; + + +/*-------------------------------------------------------------------------* + * Flags for selecting processing * + *-------------------------------------------------------------------------*/ +enum { + L_SELECT_UNSCALED = 0, /* select the unscaled bitmaps */ + L_SELECT_SCALED = 1, /* select the scaled bitmaps */ + L_SELECT_BOTH = 2 /* select both unscaled and scaled */ +}; + +/*-------------------------------------------------------------------------* + * Flags for determining what to test against * + *-------------------------------------------------------------------------*/ +enum { + L_USE_AVERAGE = 0, /* form template from class average */ + L_USE_ALL = 1 /* match against all elements of each class */ +}; + +/*-------------------------------------------------------------------------* + * Flags for describing limited character sets * + *-------------------------------------------------------------------------*/ +enum { + L_UNKNOWN = 0, /* character set type is not specified */ + L_ARABIC_NUMERALS = 1, /* 10 digits */ + L_LC_ROMAN_NUMERALS = 2, /* 7 lower-case letters (i,v,x,l,c,d,m) */ + L_UC_ROMAN_NUMERALS = 3, /* 7 upper-case letters (I,V,X,L,C,D,M) */ + L_LC_ALPHA = 4, /* 26 lower-case letters */ + L_UC_ALPHA = 5 /* 26 upper-case letters */ +}; + +#endif /* LEPTONICA_RECOG_H */ diff --git a/TesseractOCR/include/leptonica/regutils.h b/TesseractOCR/include/leptonica/regutils.h old mode 100755 new mode 100644 index 9d1e74ed..c278a020 --- a/TesseractOCR/include/leptonica/regutils.h +++ b/TesseractOCR/include/leptonica/regutils.h @@ -33,14 +33,14 @@ * Contains this regression test parameter packaging struct * struct L_RegParams * - * * The regression test utility allows you to write regression tests - * that compare results with existing "golden files". + * that compare results with existing "golden files" and with + * compiled in data. * - * Such regression tests can be called in three ways. + * Regression tests can be called in three ways. * For example, for distance_reg: * - * Case 1: distance_reg generate + * Case 1: distance_reg [generate] * This generates golden files in /tmp for the reg test. * * Case 2: distance_reg compare @@ -49,16 +49,19 @@ * as well as the details of any parts of the test that failed. * It writes to a temporary file stream (fp) * - * Case 3: distance_reg [display] + * Case 3: distance_reg display * This runs the test but makes no comparison of the output * against the set of golden files. In addition, this displays * images and plots that are specified in the test under * control of the display variable. Display is enabled only * for this case. Using 'display' on the command line is optional. * - * Regression tests follow the pattern given below. In an actual - * case, comparisons of pix and of files can occur in any order. - * We give a specific order here for clarity. + * Regression tests follow the pattern given below. Tests are + * automatically numbered sequentially, and it is convenient to + * comment each with a number to keep track (for comparison tests + * and for debugging). In an actual case, comparisons of pix and + * of files can occur in any order. We give a specific order here + * for clarity. * * L_REGPARAMS *rp; // holds data required by the test functions * @@ -68,21 +71,21 @@ * * // Test pairs of generated pix for identity. This compares * // two pix; no golden file is generated. - * regTestComparePix(rp, pix1, pix2); + * regTestComparePix(rp, pix1, pix2); // 0 * * // Test pairs of generated pix for similarity. This compares * // two pix; no golden file is generated. The last arg determines * // if stats are to be written to stderr. - * regTestCompareSimilarPix(rp, pix1, pix2, 15, 0.001, 0); + * regTestCompareSimilarPix(rp, pix1, pix2, 15, 0.001, 0); // 1 * * // Generation of outputs and testing for identity * // These files can be anything, of course. - * regTestCheckFile(rp, ); - * regTestCheckFile(rp, ); + * regTestCheckFile(rp, ); // 2 + * regTestCheckFile(rp, ); // 3 * * // Test pairs of output golden files for identity. Here we - * // are comparing golden files 4 and 5. - * regTestCompareFiles(rp, 4, 5); + * // are comparing golden files 2 and 3. + * regTestCompareFiles(rp, 2, 3); // 4 * * // "Write and check". This writes a pix using a canonical * // formulation for the local filename and either: @@ -93,8 +96,8 @@ * // Then check against the golden file. The internal @index * // is incremented; it is embedded in the local filename and, * // if generating, in the golden file as well. - * regTestWritePixAndCheck(rp, pix1, IFF_PNG); - * regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); + * regTestWritePixAndCheck(rp, pix1, IFF_PNG); // 5 + * regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); // 6 * * // Display if reg test was called in 'display' mode * pixDisplayWithTitle(pix1, 100, 100, NULL, rp->display); @@ -103,7 +106,6 @@ * regTestCleanup(rp); */ - /*-------------------------------------------------------------------------* * Regression test parameter packer * *-------------------------------------------------------------------------*/ diff --git a/TesseractOCR/include/leptonica/stack.h b/TesseractOCR/include/leptonica/stack.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/leptonica/sudoku.h b/TesseractOCR/include/leptonica/sudoku.h old mode 100755 new mode 100644 index cd9f80ef..8cacf9d9 --- a/TesseractOCR/include/leptonica/sudoku.h +++ b/TesseractOCR/include/leptonica/sudoku.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR diff --git a/TesseractOCR/include/leptonica/watershed.h b/TesseractOCR/include/leptonica/watershed.h old mode 100755 new mode 100644 index 5350479b..91ca355b --- a/TesseractOCR/include/leptonica/watershed.h +++ b/TesseractOCR/include/leptonica/watershed.h @@ -10,7 +10,7 @@ - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - + - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -27,14 +27,14 @@ #ifndef LEPTONICA_WATERSHED_H #define LEPTONICA_WATERSHED_H -/* +/* * watershed.h * * Simple data structure to hold watershed data. * All data here is owned by the L_WShed and must be freed. */ -struct L_WShed +struct L_WShed { struct Pix *pixs; /* clone of input 8 bpp pixs */ struct Pix *pixm; /* clone of input 1 bpp seed (marker) pixm */ diff --git a/TesseractOCR/include/tesseract/adaptive.h b/TesseractOCR/include/tesseract/adaptive.h new file mode 100644 index 00000000..c67670f6 --- /dev/null +++ b/TesseractOCR/include/tesseract/adaptive.h @@ -0,0 +1,141 @@ +/****************************************************************************** + ** Filename: adaptive.h + ** Purpose: Interface to adaptive matcher. + ** Author: Dan Johnson + ** History: Fri Mar 8 10:00:49 1991, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef ADAPTIVE_H +#define ADAPTIVE_H + +/*---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------*/ +#include "oldlist.h" +#include "intproto.h" +#include + +typedef struct +{ + uinT16 ProtoId; + uinT16 dummy; + PROTO_STRUCT Proto; +} + + +TEMP_PROTO_STRUCT; +typedef TEMP_PROTO_STRUCT *TEMP_PROTO; + +typedef struct +{ + uinT8 NumTimesSeen; + uinT8 ProtoVectorSize; + PROTO_ID MaxProtoId; + LIST ContextsSeen; + BIT_VECTOR Protos; + int FontinfoId; // font information inferred from pre-trained templates +} TEMP_CONFIG_STRUCT; +typedef TEMP_CONFIG_STRUCT *TEMP_CONFIG; + +typedef struct +{ + UNICHAR_ID *Ambigs; + int FontinfoId; // font information inferred from pre-trained templates +} PERM_CONFIG_STRUCT; +typedef PERM_CONFIG_STRUCT *PERM_CONFIG; + +typedef union +{ + TEMP_CONFIG Temp; + PERM_CONFIG Perm; +} ADAPTED_CONFIG; + +typedef struct +{ + uinT8 NumPermConfigs; + uinT8 MaxNumTimesSeen; // maximum number of times any TEMP_CONFIG was seen + uinT8 dummy[2]; // (cut at matcher_min_examples_for_prototyping) + BIT_VECTOR PermProtos; + BIT_VECTOR PermConfigs; + LIST TempProtos; + ADAPTED_CONFIG Config[MAX_NUM_CONFIGS]; +} ADAPT_CLASS_STRUCT; +typedef ADAPT_CLASS_STRUCT *ADAPT_CLASS; + +typedef struct +{ + INT_TEMPLATES Templates; + int NumNonEmptyClasses; + uinT8 NumPermClasses; + uinT8 dummy[3]; + ADAPT_CLASS Class[MAX_NUM_CLASSES]; +} ADAPT_TEMPLATES_STRUCT; +typedef ADAPT_TEMPLATES_STRUCT *ADAPT_TEMPLATES; + +/*---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------*/ +#define NumNonEmptyClassesIn(Template) ((Template)->NumNonEmptyClasses) + +#define IsEmptyAdaptedClass(Class) ((Class)->NumPermConfigs == 0 && \ +(Class)->TempProtos == NIL_LIST) + +#define ConfigIsPermanent(Class,ConfigId) \ +(test_bit ((Class)->PermConfigs, ConfigId)) + +#define MakeConfigPermanent(Class,ConfigId) \ +(SET_BIT ((Class)->PermConfigs, ConfigId)) + +#define MakeProtoPermanent(Class,ProtoId) \ +(SET_BIT ((Class)->PermProtos, ProtoId)) + +#define TempConfigFor(Class,ConfigId) \ +((Class)->Config[ConfigId].Temp) + +#define PermConfigFor(Class,ConfigId) \ +((Class)->Config[ConfigId].Perm) + +#define IncreaseConfidence(TempConfig) \ +((TempConfig)->NumTimesSeen++) + +void AddAdaptedClass(ADAPT_TEMPLATES Templates, + ADAPT_CLASS Class, + CLASS_ID ClassId); + +void FreeTempProto(void *arg); + +void FreeTempConfig(TEMP_CONFIG Config); + +ADAPT_CLASS NewAdaptedClass(); + +void free_adapted_class(ADAPT_CLASS adapt_class); + +void free_adapted_templates(ADAPT_TEMPLATES templates); + +TEMP_CONFIG NewTempConfig(int MaxProtoId, int FontinfoId); + +TEMP_PROTO NewTempProto(); + +ADAPT_CLASS ReadAdaptedClass(FILE *File); + +PERM_CONFIG ReadPermConfig(FILE *File); + +TEMP_CONFIG ReadTempConfig(FILE *File); + +void WriteAdaptedClass(FILE *File, ADAPT_CLASS Class, int NumConfigs); + +void WritePermConfig(FILE *File, PERM_CONFIG Config); + +void WriteTempConfig(FILE *File, TEMP_CONFIG Config); + +#endif diff --git a/TesseractOCR/include/tesseract/alignedblob.h b/TesseractOCR/include/tesseract/alignedblob.h new file mode 100644 index 00000000..cbc727a1 --- /dev/null +++ b/TesseractOCR/include/tesseract/alignedblob.h @@ -0,0 +1,145 @@ +/////////////////////////////////////////////////////////////////////// +// File: alignedblob.h +// Description: A class to find vertically aligned blobs in a BBGrid, +// and a struct to hold control parameters. +// Author: Ray Smith +// Created: Fri Mar 21 15:03:01 PST 2008 +// +// (C) Copyright 2008, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_ALIGNEDBLOB_H__ +#define TESSERACT_TEXTORD_ALIGNEDBLOB_H__ + +#include "bbgrid.h" +#include "blobbox.h" +#include "strngs.h" +#include "tabvector.h" + +extern INT_VAR_H(textord_debug_bugs, 0, + "Turn on output related to bugs in tab finding"); +extern INT_VAR_H(textord_debug_tabfind, 2, "Debug tab finding"); +extern BOOL_VAR_H(textord_debug_images, false, + "Use greyed image background for debug"); +extern BOOL_VAR_H(textord_debug_printable, false, + "Make debug windows printable"); + +namespace tesseract { + +// Simple structure to hold the search parameters for AlignedBlob. +// The members are mostly derived from constants, which are +// conditioned on the alignment parameter. +// For finding vertical lines, a different set of constants are +// used, conditioned on the different constructor. +struct AlignedBlobParams { + // Constructor to set the parameters for finding aligned and ragged tabs. + // Vertical_x and vertical_y are the current estimates of the true vertical + // direction (up) in the image. Height is the height of the starter blob. + // v_gap_multiple is the multiple of height that will be used as a limit + // on vertical gap before giving up and calling the line ended. + // resolution is the original image resolution, and align0 indicates the + // type of tab stop to be found. + AlignedBlobParams(int vertical_x, int vertical_y, int height, + int v_gap_multiple, int min_gutter_width, int resolution, + TabAlignment alignment0); + // Constructor to set the parameters for finding vertical lines. + // Vertical_x and vertical_y are the current estimates of the true vertical + // direction (up) in the image. Width is the width of the starter blob. + AlignedBlobParams(int vertical_x, int vertical_y, int width); + + // Fit the vertical vector into an ICOORD, which is 16 bit. + void set_vertical(int vertical_x, int vertical_y); + + double gutter_fraction; // Multiple of height used for min_gutter. + bool right_tab; // We are looking at right edges. + bool ragged; // We are looking for a ragged (vs aligned) edge. + TabAlignment alignment; // The type we are trying to produce. + TabType confirmed_type; // Type to flag blobs if accepted. + int max_v_gap; // Max vertical gap to be tolerated. + int min_gutter; // Minimum gutter between columns. + // Tolerances allowed on horizontal alignment of aligned edges. + int l_align_tolerance; // Left edges. + int r_align_tolerance; // Right edges. + // Conditions for accepting a line. + int min_points; // Minimum number of points to be OK. + int min_length; // Min length of completed line. + + ICOORD vertical; // Current estimate of logical vertical. +}; + +// The AlignedBlob class contains code to find vertically aligned blobs. +// This is factored out into a separate class, so it can be used by both +// vertical line finding (LineFind) and tabstop finding (TabFind). +class AlignedBlob : public BlobGrid { + public: + AlignedBlob(int gridsize, const ICOORD& bleft, const ICOORD& tright); + virtual ~AlignedBlob(); + + // Return true if the given coordinates are within the test rectangle + // and the debug level is at least the given detail level. + static bool WithinTestRegion(int detail_level, int x, int y); + + // Display the tab codes of the BLOBNBOXes in this grid. + ScrollView* DisplayTabs(const char* window_name, ScrollView* tab_win); + + // Finds a vector corresponding to a set of vertically aligned blob edges + // running through the given box. The type of vector returned and the + // search parameters are determined by the AlignedBlobParams. + // vertical_x and y are updated with an estimate of the real + // vertical direction. (skew finding.) + // Returns NULL if no decent vector can be found. + TabVector* FindVerticalAlignment(AlignedBlobParams align_params, + BLOBNBOX* bbox, + int* vertical_x, int* vertical_y); + + // Increment the serial number counter and set the string to use + // for a filename if textord_debug_images is true. + static void IncrementDebugPix(); + + // Return the string to use for a filename if textord_debug_images is true. + // Use IncrementDebugPix first to set the filename, and each time is + // to be incremented. + static const STRING& textord_debug_pix() { + return textord_debug_pix_; + } + + private: + // Find a set of blobs that are aligned in the given vertical + // direction with the given blob. Returns a list of aligned + // blobs and the number in the list. + // For other parameters see FindAlignedBlob below. + int AlignTabs(const AlignedBlobParams& params, + bool top_to_bottom, BLOBNBOX* bbox, + BLOBNBOX_CLIST* good_points, int* end_y); + + // Search vertically for a blob that is aligned with the input bbox. + // The search parameters are determined by AlignedBlobParams. + // top_to_bottom tells whether to search down or up. + // The return value is NULL if nothing was found in the search box + // or if a blob was found in the gutter. On a NULL return, end_y + // is set to the edge of the search box or the leading edge of the + // gutter blob if one was found. + BLOBNBOX* FindAlignedBlob(const AlignedBlobParams& p, + bool top_to_bottom, BLOBNBOX* bbox, + int x_start, int* end_y); + + // Name of image file to use if textord_debug_images is true. + static STRING textord_debug_pix_; + // Index to image file to use if textord_debug_images is true. + static int debug_pix_index_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_ALIGNEDBLOB_H__ + diff --git a/TesseractOCR/include/tesseract/altlist.h b/TesseractOCR/include/tesseract/altlist.h new file mode 100644 index 00000000..3aebf313 --- /dev/null +++ b/TesseractOCR/include/tesseract/altlist.h @@ -0,0 +1,61 @@ +/********************************************************************** + * File: alt_list.h + * Description: Class to abstarct a list of alternate results + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The AltList class is the base class for the list of alternate recognition +// results. Each alternate has a cost an an optional tag associated with it + +#ifndef ALT_LIST_H +#define ALT_LIST_H + +#include +#include "cube_utils.h" + +namespace tesseract { +class AltList { + public: + explicit AltList(int max_alt); + virtual ~AltList(); + // sort the list of alternates based + virtual void Sort() = 0; + // return the best possible cost and index of corresponding alternate + int BestCost (int *best_alt) const; + // return the count of alternates + inline int AltCount() const { return alt_cnt_; } + // returns the cost (-ve log prob) of an alternate + inline int AltCost(int alt_idx) const { return alt_cost_[alt_idx]; } + // returns the prob of an alternate + inline double AltProb(int alt_idx) const { + return CubeUtils::Cost2Prob(AltCost(alt_idx)); + } + // returns the alternate tag + inline void *AltTag(int alt_idx) const { return alt_tag_[alt_idx]; } + + protected: + // max number of alternates the list can hold + int max_alt_; + // actual alternate count + int alt_cnt_; + // array of alternate costs + int *alt_cost_; + // array of alternate tags + void **alt_tag_; +}; +} + +#endif // ALT_LIST_H diff --git a/TesseractOCR/include/tesseract/ambigs.h b/TesseractOCR/include/tesseract/ambigs.h old mode 100755 new mode 100644 index a72e7516..b278f9f3 --- a/TesseractOCR/include/tesseract/ambigs.h +++ b/TesseractOCR/include/tesseract/ambigs.h @@ -123,7 +123,10 @@ class AmbigSpec : public ELIST_LINK { *reinterpret_cast(spec1); const AmbigSpec *s2 = *reinterpret_cast(spec2); - return UnicharIdArrayUtils::compare(s1->wrong_ngram, s2->wrong_ngram); + int result = UnicharIdArrayUtils::compare(s1->wrong_ngram, s2->wrong_ngram); + if (result != 0) return result; + return UnicharIdArrayUtils::compare(s1->correct_fragments, + s2->correct_fragments); } UNICHAR_ID wrong_ngram[MAX_AMBIG_SIZE + 1]; @@ -150,6 +153,13 @@ class UnicharAmbigs { const UnicharAmbigsVector &dang_ambigs() const { return dang_ambigs_; } const UnicharAmbigsVector &replace_ambigs() const { return replace_ambigs_; } + // Initializes the ambigs by adding a NULL pointer to each table. + void InitUnicharAmbigs(const UNICHARSET& unicharset, + bool use_ambigs_for_adaption); + + // Loads the universal ambigs that are useful for any language. + void LoadUniversal(const UNICHARSET& encoder_set, UNICHARSET* unicharset); + // Fills in two ambiguity tables (replaceable and dangerous) with information // read from the ambigs file. An ambiguity table is an array of lists. // The array is indexed by a class id. Each entry in the table provides @@ -160,7 +170,10 @@ class UnicharAmbigs { // one_to_one_definite_ambigs_. This vector is also indexed by the class id // of the wrong part of the ambiguity and each entry contains a vector of // unichar ids that are ambiguous to it. - void LoadUnicharAmbigs(FILE *ambigs_file, inT64 end_offset, int debug_level, + // encoder_set is used to encode the ambiguity strings, undisturbed by new + // unichar_ids that may be created by adding the ambigs. + void LoadUnicharAmbigs(const UNICHARSET& encoder_set, + TFile *ambigs_file, int debug_level, bool use_ambigs_for_adaption, UNICHARSET *unicharset); // Returns definite 1-1 ambigs for the given unichar id. @@ -191,17 +204,18 @@ class UnicharAmbigs { } private: - bool ParseAmbiguityLine(int line_num, int version, int debug_level, const UNICHARSET &unicharset, char *buffer, - int *TestAmbigPartSize, UNICHAR_ID *TestUnicharIds, - int *ReplacementAmbigPartSize, - char *ReplacementString, int *type); - void InsertIntoTable(UnicharAmbigsVector &table, - int TestAmbigPartSize, UNICHAR_ID *TestUnicharIds, - int ReplacementAmbigPartSize, - const char *ReplacementString, int type, + int *test_ambig_part_size, + UNICHAR_ID *test_unichar_ids, + int *replacement_ambig_part_size, + char *replacement_string, int *type); + bool InsertIntoTable(UnicharAmbigsVector &table, + int test_ambig_part_size, UNICHAR_ID *test_unichar_ids, + int replacement_ambig_part_size, + const char *replacement_string, int type, AmbigSpec *ambig_spec, UNICHARSET *unicharset); + UnicharAmbigsVector dang_ambigs_; UnicharAmbigsVector replace_ambigs_; GenericVector one_to_one_definite_ambigs_; diff --git a/TesseractOCR/include/tesseract/apitypes.h b/TesseractOCR/include/tesseract/apitypes.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/associate.h b/TesseractOCR/include/tesseract/associate.h new file mode 100644 index 00000000..977193b2 --- /dev/null +++ b/TesseractOCR/include/tesseract/associate.h @@ -0,0 +1,125 @@ +/////////////////////////////////////////////////////////////////////// +// File: associate.h +// Description: Structs, classes, typedefs useful for the segmentation +// search. Functions for scoring segmentation paths according +// to their character widths, gap widths and seam cuts. +// Author: Daria Antonova +// Created: Mon Mar 8 11:26:43 PDT 2010 +// +// (C) Copyright 2010, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef ASSOCIATE_H +#define ASSOCIATE_H + +#include "blobs.h" +#include "elst.h" +#include "ratngs.h" +#include "seam.h" +#include "split.h" + +class WERD_RES; + +namespace tesseract { + +// Statisitcs about character widths, gaps and seams. +struct AssociateStats { + AssociateStats() { Clear(); } + + void Clear() { + shape_cost = 0.0f; + bad_shape = false; + full_wh_ratio = 0.0f; + full_wh_ratio_total = 0.0f; + full_wh_ratio_var = 0.0f; + bad_fixed_pitch_right_gap = false; + bad_fixed_pitch_wh_ratio = false; + gap_sum = 0; + } + + void Print() { + tprintf("AssociateStats: w(%g %d) s(%g %d)\n", shape_cost, bad_shape); + } + + float shape_cost; // cost of blob shape + bool bad_shape; // true if the shape of the blob is unacceptable + float full_wh_ratio; // width-to-hight ratio + gap on the right + float full_wh_ratio_total; // sum of width-to-hight ratios + // on the path terminating at this blob + float full_wh_ratio_var; // variance of full_wh_ratios on the path + bool bad_fixed_pitch_right_gap; // true if there is no gap before + // the blob on the right + bool bad_fixed_pitch_wh_ratio; // true if the blobs has width-to-hight + // ratio > kMaxFixedPitchCharAspectRatio + int gap_sum; // sum of gaps within the blob +}; + +// Utility functions for scoring segmentation paths according to their +// character widths, gap widths, seam characteristics. +class AssociateUtils { + public: + static const float kMaxFixedPitchCharAspectRatio; + static const float kMinGap; + + // Returns outline length of the given blob is computed as: + // rating_cert_scale * rating / certainty + // Since from Wordrec::SegSearch() in segsearch.cpp + // rating_cert_scale = -1.0 * getDict().certainty_scale / rating_scale + // And from Classify::ConvertMatchesToChoices() in adaptmatch.cpp + // Rating = Certainty = next.rating + // Rating *= rating_scale * Results->BlobLength + // Certainty *= -(getDict().certainty_scale) + static inline float ComputeOutlineLength(float rating_cert_scale, + const BLOB_CHOICE &b) { + return rating_cert_scale * b.rating() / b.certainty(); + } + static inline float ComputeRating(float rating_cert_scale, + float cert, int width) { + return static_cast(width) * cert / rating_cert_scale; + } + + // Computes character widths, gaps and seams stats given the + // AssociateStats of the path so far, col, row of the blob that + // is being added to the path, and WERD_RES containing information + // about character widths, gaps and seams. + // Fills associate_cost with the combined shape, gap and seam cost + // of adding a unichar from (col, row) to the path (note that since + // this function could be used to compute the prioritization for + // pain points, (col, row) entry might not be classified yet; thus + // information in the (col, row) entry of the ratings matrix is not used). + // + // Note: the function assumes that word_res, stats and + // associate_cost pointers are not NULL. + static void ComputeStats(int col, int row, + const AssociateStats *parent_stats, + int parent_path_length, + bool fixed_pitch, + float max_char_wh_ratio, + WERD_RES *word_res, + bool debug, + AssociateStats *stats); + + // Returns the width cost for fixed-pitch text. + static float FixedPitchWidthCost(float norm_width, float right_gap, + bool end_pos, float max_char_wh_ratio); + + // Returns the gap cost for fixed-pitch text (penalizes vertically + // overlapping components). + static inline float FixedPitchGapCost(float norm_gap, bool end_pos) { + return (norm_gap < 0.05 && !end_pos) ? 5.0f : 0.0f; + } +}; + +} // namespace tesseract + +#endif diff --git a/TesseractOCR/include/tesseract/baseapi.h b/TesseractOCR/include/tesseract/baseapi.h old mode 100755 new mode 100644 index a52c41de..40e77632 --- a/TesseractOCR/include/tesseract/baseapi.h +++ b/TesseractOCR/include/tesseract/baseapi.h @@ -37,12 +37,10 @@ template class GenericVector; class PAGE_RES; class PAGE_RES_IT; class ParagraphModel; -class BlamerBundle; +struct BlamerBundle; class BLOCK_LIST; class DENORM; -class IMAGE; class MATRIX; -class PBLOB; class ROW; class STRING; class WERD; @@ -54,16 +52,10 @@ class ETEXT_DESC; struct OSResults; class TBOX; class UNICHARSET; +class WERD_CHOICE_LIST; -// From oldlist.h -// TODO(antonova): remove when oldlist is deprecated. -struct list_rec; -typedef list_rec *LIST; - -#define MAX_NUM_INT_FEATURES 512 struct INT_FEATURE_STRUCT; typedef INT_FEATURE_STRUCT *INT_FEATURE; -typedef INT_FEATURE_STRUCT INT_FEATURE_ARRAY[MAX_NUM_INT_FEATURES]; struct TBLOB; namespace tesseract { @@ -72,8 +64,11 @@ class CubeRecoContext; class Dawg; class Dict; class EquationDetect; +class PageIterator; class LTRResultIterator; +class ResultIterator; class MutableIterator; +class TessResultRenderer; class Tesseract; class Trie; class Wordrec; @@ -85,11 +80,14 @@ typedef double (Dict::*ProbabilityInContextFunc)(const char* lang, int context_bytes, const char* character, int character_bytes); +typedef float (Dict::*ParamsModelClassifyFunc)( + const char *lang, void *path); typedef void (Wordrec::*FillLatticeFunc)(const MATRIX &ratings, - const LIST &best_choices, + const WERD_CHOICE_LIST &best_choices, const UNICHARSET &unicharset, BlamerBundle *blamer_bundle); -typedef TessCallback3 TruthCallback; +typedef TessCallback4 + TruthCallback; /** * Base class for all tesseract APIs. @@ -110,10 +108,37 @@ class TESS_API TessBaseAPI { static const char* Version(); /** - * Set the name of the input file. Needed only for training and - * reading a UNLV zone file. + * If compiled with OpenCL AND an available OpenCL + * device is deemed faster than serial code, then + * "device" is populated with the cl_device_id + * and returns sizeof(cl_device_id) + * otherwise *device=NULL and returns 0. + */ + static size_t getOpenCLDevice(void **device); + + /** + * Writes the thresholded image to stderr as a PBM file on receipt of a + * SIGSEGV, SIGFPE, or SIGBUS signal. (Linux/Unix only). + */ + static void CatchSignals(); + + /** + * Set the name of the input file. Needed for training and + * reading a UNLV zone file, and for searchable PDF output. */ void SetInputName(const char* name); + /** + * These functions are required for searchable PDF output. + * We need our hands on the input file so that we can include + * it in the PDF without transcoding. If that is not possible, + * we need the original image. Finally, resolution metadata + * is stored in the PDF so we need that as well. + */ + const char* GetInputName(); + void SetInputImage(Pix *pix); + Pix* GetInputImage(); + int GetSourceYResolution(); + const char* GetDatapath(); /** Set the name of the bonus output files. Needed only for debugging. */ void SetOutputName(const char* name); @@ -127,8 +152,6 @@ class TESS_API TessBaseAPI { * Or SetVariable("classify_bln_numeric_mode", "1"); to set numeric-only mode. * SetVariable may be used before Init, but settings will revert to * defaults on End(). - * TODO(rays) Add a command-line option to dump the parameters to stdout - * and add a pointer to it in the FAQ * * Note: Must be called after Init(). Only works for non-init variables * (init variables should be passed to Init()). @@ -370,10 +393,21 @@ class TESS_API TessBaseAPI { * Get the textlines as a leptonica-style * Boxa, Pixa pair, in reading order. * Can be called before or after Recognize. - * If blockids is not NULL, the block-id of each line is also returned - * as an array of one element per line. delete [] after use. - */ - Boxa* GetTextlines(Pixa** pixa, int** blockids); + * If raw_image is true, then extract from the original image instead of the + * thresholded image and pad by raw_padding pixels. + * If blockids is not NULL, the block-id of each line is also returned as an + * array of one element per line. delete [] after use. + * If paraids is not NULL, the paragraph-id of each line within its block is + * also returned as an array of one element per line. delete [] after use. + */ + Boxa* GetTextlines(const bool raw_image, const int raw_padding, + Pixa** pixa, int** blockids, int** paraids); + /* + Helper method to extract from the thresholded image. (most common usage) + */ + Boxa* GetTextlines(Pixa** pixa, int** blockids) { + return GetTextlines(false, 0, pixa, blockids, NULL); + } /** * Get textlines and strips of image regions as a leptonica-style Boxa, Pixa @@ -408,11 +442,23 @@ class TESS_API TessBaseAPI { * Can be called before or after Recognize. * If blockids is not NULL, the block-id of each component is also returned * as an array of one element per component. delete [] after use. + * If blockids is not NULL, the paragraph-id of each component with its block + * is also returned as an array of one element per component. delete [] after + * use. + * If raw_image is true, then portions of the original image are extracted + * instead of the thresholded image and padded with raw_padding. * If text_only is true, then only text components are returned. */ - Boxa* GetComponentImages(PageIteratorLevel level, - bool text_only, - Pixa** pixa, int** blockids); + Boxa* GetComponentImages(const PageIteratorLevel level, + const bool text_only, const bool raw_image, + const int raw_padding, + Pixa** pixa, int** blockids, int** paraids); + // Helper function to get binary images with no padding (most common usage). + Boxa* GetComponentImages(const PageIteratorLevel level, + const bool text_only, + Pixa** pixa, int** blockids) { + return GetComponentImages(level, text_only, false, 0, pixa, blockids, NULL); + } /** * Returns the scale factor of the thresholded image that would be returned by @@ -478,6 +524,10 @@ class TESS_API TessBaseAPI { const char* retry_config, int timeout_millisec, STRING* text_out); + bool ProcessPages(const char* filename, + const char* retry_config, int timeout_millisec, + TessResultRenderer* renderer); + /** * Recognizes a single page for ProcessPages, appending the text to text_out. * The pix is the image processed - filename and page_index are metadata @@ -493,6 +543,10 @@ class TESS_API TessBaseAPI { const char* retry_config, int timeout_millisec, STRING* text_out); + bool ProcessPage(Pix* pix, int page_index, const char* filename, + const char* retry_config, int timeout_millisec, + TessResultRenderer* renderer); + /** * Get a reading-order iterator to the results of LayoutAnalysis and/or * Recognize. The returned iterator must be deleted after use. @@ -525,6 +579,7 @@ class TESS_API TessBaseAPI { * page_number is 0-based but will appear in the output as 1-based. */ char* GetHOCRText(int page_number); + /** * The recognized text is returned as a char* which is coded in the same * format as a box file used in training. Returned string must be freed with @@ -577,6 +632,15 @@ class TESS_API TessBaseAPI { */ void End(); + /** + * Clear any library-level memory caches. + * There are a variety of expensive-to-load constant data structures (mostly + * language dictionaries) that are cached globally -- surviving the Init() + * and End() of individual TessBaseAPI's. This function allows the clearing + * of these caches. + **/ + static void ClearPersistentCache(); + /** * Check whether a word is valid according to Tesseract's language model * @return 0 if the word is invalid, non-zero if valid. @@ -605,9 +669,8 @@ class TESS_API TessBaseAPI { bool DetectOS(OSResults*); /** This method returns the features associated with the input image. */ - void GetFeaturesForBlob(TBLOB* blob, const DENORM& denorm, - INT_FEATURE_ARRAY int_features, - int* num_features, int* FeatureOutlineIndex); + void GetFeaturesForBlob(TBLOB* blob, INT_FEATURE_STRUCT* int_features, + int* num_features, int* feature_outline_index); /** * This method returns the row to which a box of specified dimensions would @@ -620,7 +683,7 @@ class TESS_API TessBaseAPI { * Method to run adaptive classifier on a blob. * It returns at max num_max_matches results. */ - void RunAdaptiveClassifier(TBLOB* blob, const DENORM& denorm, + void RunAdaptiveClassifier(TBLOB* blob, int num_max_matches, int* unichar_ids, float* ratings, @@ -647,13 +710,12 @@ class TESS_API TessBaseAPI { * for normalization. The denorm is an optional parameter in which the * normalization-antidote is returned. */ - static void NormalizeTBLOB(TBLOB *tblob, ROW *row, - bool numeric_mode, DENORM *denorm); + static void NormalizeTBLOB(TBLOB *tblob, ROW *row, bool numeric_mode); Tesseract* const tesseract() const { return tesseract_; } - + OcrEngineMode const oem() const { return last_oem_requested_; } @@ -701,7 +763,7 @@ class TESS_API TessBaseAPI { TESS_LOCAL int FindLines(); /** Delete the pageres and block list ready for a new page. */ - TESS_LOCAL void ClearResults(); + void ClearResults(); /** * Return an LTR Result Iterator -- used only for training, as we really want @@ -734,7 +796,8 @@ class TESS_API TessBaseAPI { /** Recognize text doing one pass only, using settings for a given pass. */ TESS_LOCAL PAGE_RES* RecognitionPass1(BLOCK_LIST* block_list); - TESS_LOCAL PAGE_RES* RecognitionPass2(BLOCK_LIST* block_list, PAGE_RES* pass1_result); + TESS_LOCAL PAGE_RES* RecognitionPass2(BLOCK_LIST* block_list, + PAGE_RES* pass1_result); //// paragraphs.cpp //////////////////////////////////////////////////// TESS_LOCAL void DetectParagraphs(bool after_text_recognition); @@ -757,6 +820,7 @@ class TESS_API TessBaseAPI { }; /* @} */ + protected: Tesseract* tesseract_; ///< The underlying data object. Tesseract* osd_tesseract_; ///< For orientation & script detection. @@ -766,6 +830,7 @@ class TESS_API TessBaseAPI { BLOCK_LIST* block_list_; ///< The page layout. PAGE_RES* page_res_; ///< The page-level data. STRING* input_file_; ///< Name used by training code. + Pix* input_image_; ///< Image used for searchable PDF STRING* output_file_; ///< Name used by debug code. STRING* datapath_; ///< Current location of tessdata. STRING* language_; ///< Last initialized language. @@ -786,6 +851,17 @@ class TESS_API TessBaseAPI { int image_height_; /* @} */ + private: + /** + * DEPRECATED + * Returns new renderer instance based on how tesseract was configured to + * render results using old API. This should be removed along with those + * attributes so that the renderer is just passed in rather than the + * old methods taking output strings. + * + * Caller must destroy result. + */ + TessResultRenderer* NewRenderer(); }; } // namespace tesseract. diff --git a/TesseractOCR/include/tesseract/basedir.h b/TesseractOCR/include/tesseract/basedir.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/baselinedetect.h b/TesseractOCR/include/tesseract/baselinedetect.h new file mode 100644 index 00000000..7a47931f --- /dev/null +++ b/TesseractOCR/include/tesseract/baselinedetect.h @@ -0,0 +1,284 @@ +/////////////////////////////////////////////////////////////////////// +// File: baselinedetect.h +// Description: Initial Baseline Determination. +// Copyright 2012 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +// Created: Mon Apr 30 10:03:19 PDT 2012 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_BASELINEDETECT_H_ +#define TESSERACT_TEXTORD_BASELINEDETECT_H_ + +#include "detlinefit.h" +#include "genericvector.h" +#include "points.h" +#include "rect.h" +#include "strngs.h" + +class BLOBNBOX_LIST; +class TO_BLOCK; +class TO_BLOCK_LIST; +class TO_ROW; +struct Pix; + +namespace tesseract { + +class Textord; + +// Class to compute and hold baseline data for a TO_ROW. +class BaselineRow { + public: + BaselineRow(double line_size, TO_ROW* to_row); + + const TBOX& bounding_box() const { + return bounding_box_; + } + // Sets the TO_ROW with the output straight line. + void SetupOldLineParameters(TO_ROW* row) const; + + // Outputs diagnostic information. + void Print() const; + + // Returns the skew angle (in radians) of the current baseline in [-pi,pi]. + double BaselineAngle() const; + // Computes and returns the linespacing at the middle of the overlap + // between this and other. + double SpaceBetween(const BaselineRow& other) const; + // Computes and returns the displacement of the center of the line + // perpendicular to the given direction. + double PerpDisp(const FCOORD& direction) const; + // Computes the y coordinate at the given x using the straight baseline + // defined by baseline1_ and baseline2_. + double StraightYAtX(double x) const; + + // Fits a straight baseline to the points. Returns true if it had enough + // points to be reasonably sure of the fitted baseline. + // If use_box_bottoms is false, baselines positions are formed by + // considering the outlines of the blobs. + bool FitBaseline(bool use_box_bottoms); + // Modifies an existing result of FitBaseline to be parallel to the given + // vector if that produces a better result. + void AdjustBaselineToParallel(int debug, const FCOORD& direction); + // Modifies the baseline to snap to the textline grid if the existing + // result is not good enough. + double AdjustBaselineToGrid(int debug, const FCOORD& direction, + double line_spacing, double line_offset); + + private: + // Sets up displacement_modes_ with the top few modes of the perpendicular + // distance of each blob from the given direction vector, after rounding. + void SetupBlobDisplacements(const FCOORD& direction); + + // Fits a line in the given direction to blobs that are close to the given + // target_offset perpendicular displacement from the direction. The fit + // error is allowed to be cheat_allowance worse than the existing fit, and + // will still be used. + // If cheat_allowance > 0, the new fit will be good and replace the current + // fit if it has better fit (with cheat) OR its error is below + // max_baseline_error_ and the old fit is marked bad. + // Otherwise the new fit will only replace the old if it is really better, + // or the old fit is marked bad and the new fit has sufficient points, as + // well as being within the max_baseline_error_. + void FitConstrainedIfBetter(int debug, const FCOORD& direction, + double cheat_allowance, + double target_offset); + // Returns the perpendicular distance of the point from the straight + // baseline. + double PerpDistanceFromBaseline(const FCOORD& pt) const; + // Computes the bounding box of the row. + void ComputeBoundingBox(); + + // The blobs of the row to which this BaselineRow adds extra information + // during baseline fitting. Note that blobs_ could easily come from either + // a TO_ROW or a ColPartition. + BLOBNBOX_LIST* blobs_; + // Bounding box of all the blobs. + TBOX bounding_box_; + // Fitter used to fit lines to the blobs. + DetLineFit fitter_; + // 2 points on the straight baseline. + FCOORD baseline_pt1_; + FCOORD baseline_pt2_; + // Set of modes of displacements. They indicate preferable baseline positions. + GenericVector displacement_modes_; + // Quantization factor used for displacement_modes_. + double disp_quant_factor_; + // Half the acceptance range of blob displacements for computing the + // error during a constrained fit. + double fit_halfrange_; + // Max baseline error before a line is regarded as fitting badly. + double max_baseline_error_; + // The error of fit of the baseline. + double baseline_error_; + // True if this row seems to have a good baseline. + bool good_baseline_; +}; + +// Class to compute and hold baseline data for a TO_BLOCK. +class BaselineBlock { + public: + BaselineBlock(int debug_level, bool non_text, TO_BLOCK* block); + + TO_BLOCK* block() const { + return block_; + } + double skew_angle() const { + return skew_angle_; + } + + // Computes and returns the absolute error of the given perp_disp from the + // given linespacing model. + static double SpacingModelError(double perp_disp, double line_spacing, + double line_offset); + + // Fits straight line baselines and computes the skew angle from the + // median angle. Returns true if a good angle is found. + // If use_box_bottoms is false, baseline positions are formed by + // considering the outlines of the blobs. + bool FitBaselinesAndFindSkew(bool use_box_bottoms); + + // Refits the baseline to a constrained angle, using the stored block + // skew if good enough, otherwise the supplied default skew. + void ParallelizeBaselines(double default_block_skew); + + // Sets the parameters in TO_BLOCK that are needed by subsequent processes. + void SetupBlockParameters() const; + + // Processing that is required before fitting baseline splines, but requires + // linear baselines in order to be successful: + // Removes noise if required + // Separates out underlines + // Pre-associates blob fragments. + // TODO(rays/joeliu) This entire section of code is inherited from the past + // and could be improved/eliminated. + // page_tr is used to size a debug window. + void PrepareForSplineFitting(ICOORD page_tr, bool remove_noise); + + // Fits splines to the textlines, or creates fake QSPLINES from the straight + // baselines that are already on the TO_ROWs. + // As a side-effect, computes the xheights of the rows and the block. + // Although x-height estimation is conceptually separate, it is part of + // detecting perspective distortion and therefore baseline fitting. + void FitBaselineSplines(bool enable_splines, bool show_final_rows, + Textord* textord); + + // Draws the (straight) baselines and final blobs colored according to + // what was discarded as noise and what is associated with each row. + void DrawFinalRows(const ICOORD& page_tr); + + // Render the generated spline baselines for this block on pix_in. + void DrawPixSpline(Pix* pix_in); + + private: + // Top-level line-spacing calculation. Computes an estimate of the line- + // spacing, using the current baselines in the TO_ROWS of the block, and + // then refines it by fitting a regression line to the baseline positions + // as a function of their integer index. + // Returns true if it seems that the model is a reasonable fit to the + // observations. + bool ComputeLineSpacing(); + + // Computes the deskewed vertical position of each baseline in the block and + // stores them in the given vector. + void ComputeBaselinePositions(const FCOORD& direction, + GenericVector* positions); + + // Computes an estimate of the line spacing of the block from the median + // of the spacings between adjacent overlapping textlines. + void EstimateLineSpacing(); + + // Refines the line spacing of the block by fitting a regression + // line to the deskewed y-position of each baseline as a function of its + // estimated line index, allowing for a small error in the initial linespacing + // and choosing the best available model. + void RefineLineSpacing(const GenericVector& positions); + + // Given an initial estimate of line spacing (m_in) and the positions of each + // baseline, computes the line spacing of the block more accurately in m_out, + // and the corresponding intercept in c_out, and the number of spacings seen + // in index_delta. Returns the error of fit to the line spacing model. + double FitLineSpacingModel(const GenericVector& positions, + double m_in, double* m_out, double* c_out, + int* index_delta); + + + // The block to which this class adds extra information used during baseline + // calculation. + TO_BLOCK* block_; + // The rows in the block that we will be working with. + PointerVector rows_; + // Amount of debugging output to provide. + int debug_level_; + // True if the block is non-text (graphic). + bool non_text_block_; + // True if the block has at least one good enough baseline to compute the + // skew angle and therefore skew_angle_ is valid. + bool good_skew_angle_; + // Angle of skew in radians using the conventional anticlockwise from x-axis. + double skew_angle_; + // Current best estimate line spacing in pixels perpendicular to skew_angle_. + double line_spacing_; + // Offset for baseline positions, in pixels. Each baseline is at + // line_spacing_ * n + line_offset_ for integer n, which represents + // [textline] line number in a line numbering system that has line 0 on or + // at least near the x-axis. Not equal to the actual line number of a line + // within a block as most blocks are not near the x-axis. + double line_offset_; + // The error of the line spacing model. + double model_error_; +}; + +class BaselineDetect { + public: + BaselineDetect(int debug_level, const FCOORD& page_skew, + TO_BLOCK_LIST* blocks); + + ~BaselineDetect(); + + // Finds the initial baselines for each TO_ROW in each TO_BLOCK, gathers + // block-wise and page-wise data to smooth small blocks/rows, and applies + // smoothing based on block/page-level skew and block-level linespacing. + void ComputeStraightBaselines(bool use_box_bottoms); + + // Computes the baseline splines for each TO_ROW in each TO_BLOCK and + // other associated side-effects, including pre-associating blobs, computing + // x-heights and displaying debug information. + // NOTE that ComputeStraightBaselines must have been called first as this + // sets up data in the TO_ROWs upon which this function depends. + void ComputeBaselineSplinesAndXheights(const ICOORD& page_tr, + bool enable_splines, + bool remove_noise, + bool show_final_rows, + Textord* textord); + + // Set up the image and filename, so that a debug image with the detected + // baseline rendered will be saved. + void SetDebugImage(Pix* pixIn, const STRING& output_path); + + private: + // Average (median) skew of the blocks on the page among those that have + // a good angle of their own. + FCOORD page_skew_; + // Amount of debug output to produce. + int debug_level_; + // The blocks that we are working with. + PointerVector blocks_; + + Pix* pix_debug_; + STRING debug_file_prefix_; +}; + +} // namespace tesseract + +#endif // TESSERACT_TEXTORD_BASELINEDETECT_H_ diff --git a/TesseractOCR/include/tesseract/bbgrid.h b/TesseractOCR/include/tesseract/bbgrid.h new file mode 100644 index 00000000..f780f9ae --- /dev/null +++ b/TesseractOCR/include/tesseract/bbgrid.h @@ -0,0 +1,961 @@ +/////////////////////////////////////////////////////////////////////// +// File: bbgrid.h +// Description: Class to hold BLOBNBOXs in a grid for fast access +// to neighbours. +// Author: Ray Smith +// Created: Wed Jun 06 17:22:01 PDT 2007 +// +// (C) Copyright 2007, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_BBGRID_H__ +#define TESSERACT_TEXTORD_BBGRID_H__ + +#include "clst.h" +#include "coutln.h" +#include "hashfn.h" +#include "rect.h" +#include "scrollview.h" + +#include "allheaders.h" + +class BLOCK; + +namespace tesseract { + +// Helper function to return a scaled Pix with one pixel per grid cell, +// set (black) where the given outline enters the corresponding grid cell, +// and clear where the outline does not touch the grid cell. +// Also returns the grid coords of the bottom-left of the Pix, in *left +// and *bottom, which corresponds to (0, 0) on the Pix. +// Note that the Pix is used upside-down, with (0, 0) being the bottom-left. +Pix* TraceOutlineOnReducedPix(C_OUTLINE* outline, int gridsize, + ICOORD bleft, int* left, int* bottom); +// As TraceOutlineOnReducedPix above, but on a BLOCK instead of a C_OUTLINE. +Pix* TraceBlockOnReducedPix(BLOCK* block, int gridsize, + ICOORD bleft, int* left, int* bottom); + +template class GridSearch; + +// The GridBase class is the base class for BBGrid and IntGrid. +// It holds the geometry and scale of the grid. +class GridBase { + public: + GridBase(); + GridBase(int gridsize, const ICOORD& bleft, const ICOORD& tright); + virtual ~GridBase(); + + // (Re)Initialize the grid. The gridsize is the size in pixels of each cell, + // and bleft, tright are the bounding box of everything to go in it. + void Init(int gridsize, const ICOORD& bleft, const ICOORD& tright); + + // Simple accessors. + int gridsize() const { + return gridsize_; + } + int gridwidth() const { + return gridwidth_; + } + int gridheight() const { + return gridheight_; + } + const ICOORD& bleft() const { + return bleft_; + } + const ICOORD& tright() const { + return tright_; + } + // Compute the given grid coordinates from image coords. + void GridCoords(int x, int y, int* grid_x, int* grid_y) const; + + // Clip the given grid coordinates to fit within the grid. + void ClipGridCoords(int* x, int* y) const; + + protected: + // TODO(rays) Make these private and migrate to the accessors in subclasses. + int gridsize_; // Pixel size of each grid cell. + int gridwidth_; // Size of the grid in cells. + int gridheight_; + int gridbuckets_; // Total cells in grid. + ICOORD bleft_; // Pixel coords of bottom-left of grid. + ICOORD tright_; // Pixel coords of top-right of grid. + + private: +}; + +// The IntGrid maintains a single int for each cell in a grid. +class IntGrid : public GridBase { + public: + IntGrid(); + IntGrid(int gridsize, const ICOORD& bleft, const ICOORD& tright); + virtual ~IntGrid(); + + // (Re)Initialize the grid. The gridsize is the size in pixels of each cell, + // and bleft, tright are the bounding box of everything to go in it. + void Init(int gridsize, const ICOORD& bleft, const ICOORD& tright); + + // Clear all the ints in the grid to zero. + void Clear(); + + // Rotate the grid by rotation, keeping cell contents. + // rotation must be a multiple of 90 degrees. + // NOTE: due to partial cells, cell coverage in the rotated grid will be + // inexact. This is why there is no Rotate for the generic BBGrid. + void Rotate(const FCOORD& rotation); + + // Returns a new IntGrid containing values equal to the sum of all the + // neighbouring cells. The returned grid must be deleted after use. + IntGrid* NeighbourhoodSum() const; + + int GridCellValue(int grid_x, int grid_y) const { + ClipGridCoords(&grid_x, &grid_y); + return grid_[grid_y * gridwidth_ + grid_x]; + } + void SetGridCell(int grid_x, int grid_y, int value) { + ASSERT_HOST(grid_x >= 0 && grid_x < gridwidth()); + ASSERT_HOST(grid_y >= 0 && grid_y < gridheight()); + grid_[grid_y * gridwidth_ + grid_x] = value; + } + // Returns true if more than half the area of the rect is covered by grid + // cells that are over the theshold. + bool RectMostlyOverThreshold(const TBOX& rect, int threshold) const; + + // Returns true if any cell value in the given rectangle is zero. + bool AnyZeroInRect(const TBOX& rect) const; + + // Returns a full-resolution binary pix in which each cell over the given + // threshold is filled as a black square. pixDestroy after use. + Pix* ThresholdToPix(int threshold) const; + + private: + int* grid_; // 2-d array of ints. +}; + +// The BBGrid class holds C_LISTs of template classes BBC (bounding box class) +// in a grid for fast neighbour access. +// The BBC class must have a member const TBOX& bounding_box() const. +// The BBC class must have been CLISTIZEH'ed elsewhere to make the +// list class BBC_CLIST and the iterator BBC_C_IT. +// Use of C_LISTs enables BBCs to exist in multiple cells simultaneously. +// As a consequence, ownership of BBCs is assumed to be elsewhere and +// persistent for at least the life of the BBGrid, or at least until Clear is +// called which removes all references to inserted objects without actually +// deleting them. +// Most uses derive a class from a specific instantiation of BBGrid, +// thereby making most of the ugly template notation go away. +// The friend class GridSearch, with the same template arguments, is +// used to search a grid efficiently in one of several search patterns. +template class BBGrid + : public GridBase { + friend class GridSearch; + public: + BBGrid(); + BBGrid(int gridsize, const ICOORD& bleft, const ICOORD& tright); + virtual ~BBGrid(); + + // (Re)Initialize the grid. The gridsize is the size in pixels of each cell, + // and bleft, tright are the bounding box of everything to go in it. + void Init(int gridsize, const ICOORD& bleft, const ICOORD& tright); + + // Empty all the lists but leave the grid itself intact. + void Clear(); + // Deallocate the data in the lists but otherwise leave the lists and the grid + // intact. + void ClearGridData(void (*free_method)(BBC*)); + + // Insert a bbox into the appropriate place in the grid. + // If h_spread, then all cells covered horizontally by the box are + // used, otherwise, just the bottom-left. Similarly for v_spread. + // WARNING: InsertBBox may invalidate an active GridSearch. Call + // RepositionIterator() on any GridSearches that are active on this grid. + void InsertBBox(bool h_spread, bool v_spread, BBC* bbox); + + // Using a pix from TraceOutlineOnReducedPix or TraceBlockOnReducedPix, in + // which each pixel corresponds to a grid cell, insert a bbox into every + // place in the grid where the corresponding pixel is 1. The Pix is handled + // upside-down to match the Tesseract coordinate system. (As created by + // TraceOutlineOnReducedPix or TraceBlockOnReducedPix.) + // (0, 0) in the pix corresponds to (left, bottom) in the + // grid (in grid coords), and the pix works up the grid from there. + // WARNING: InsertPixPtBBox may invalidate an active GridSearch. Call + // RepositionIterator() on any GridSearches that are active on this grid. + void InsertPixPtBBox(int left, int bottom, Pix* pix, BBC* bbox); + + // Remove the bbox from the grid. + // WARNING: Any GridSearch operating on this grid could be invalidated! + // If a GridSearch is operating, call GridSearch::RemoveBBox() instead. + void RemoveBBox(BBC* bbox); + + // Returns true if the given rectangle has no overlapping elements. + bool RectangleEmpty(const TBOX& rect); + + // Returns an IntGrid showing the number of elements in each cell. + // Returned IntGrid must be deleted after use. + IntGrid* CountCellElements(); + + // Make a window of an appropriate size to display things in the grid. + ScrollView* MakeWindow(int x, int y, const char* window_name); + + // Display the bounding boxes of the BLOBNBOXes in this grid. + // Use of this function requires an additional member of the BBC class: + // ScrollView::Color BBC::BoxColor() const. + void DisplayBoxes(ScrollView* window); + + // ASSERT_HOST that every cell contains no more than one copy of each entry. + void AssertNoDuplicates(); + + // Handle a click event in a display window. + virtual void HandleClick(int x, int y); + + protected: + BBC_CLIST* grid_; // 2-d array of CLISTS of BBC elements. + + private: +}; + +// Hash functor for generic pointers. +template struct PtrHash { + size_t operator()(const T* ptr) const { + return reinterpret_cast(ptr) / sizeof(T); + } +}; + + +// The GridSearch class enables neighbourhood searching on a BBGrid. +template class GridSearch { + public: + GridSearch(BBGrid* grid) + : grid_(grid), unique_mode_(false), + previous_return_(NULL), next_return_(NULL) { + } + + // Get the grid x, y coords of the most recently returned BBC. + int GridX() const { + return x_; + } + int GridY() const { + return y_; + } + + // Sets the search mode to return a box only once. + // Efficiency warning: Implementation currently uses a squared-order + // search in the number of returned elements. Use only where a small + // number of elements are spread over a wide area, eg ColPartitions. + void SetUniqueMode(bool mode) { + unique_mode_ = mode; + } + // TODO(rays) Replace calls to ReturnedSeedElement with SetUniqueMode. + // It only works if the search includes the bottom-left corner. + // Apart from full search, all other searches return a box several + // times if the box is inserted with h_spread or v_spread. + // This method will return true for only one occurrence of each box + // that was inserted with both h_spread and v_spread as true. + // It will usually return false for boxes that were not inserted with + // both h_spread=true and v_spread=true + bool ReturnedSeedElement() const { + TBOX box = previous_return_->bounding_box(); + int x_center = (box.left()+box.right())/2; + int y_center = (box.top()+box.bottom())/2; + int grid_x, grid_y; + grid_->GridCoords(x_center, y_center, &grid_x, &grid_y); + return (x_ == grid_x) && (y_ == grid_y); + } + + // Various searching iterations... Note that these iterations + // all share data members, so you can't run more than one iteration + // in parallel in a single GridSearch instance, but multiple instances + // can search the same BBGrid in parallel. + // Note that all the searches can return blobs that may not exactly + // match the search conditions, since they return everything in the + // covered grid cells. It is up to the caller to check for + // appropriateness. + // TODO(rays) NextRectSearch only returns valid elements. Make the other + // searches test before return also and remove the tests from code + // that uses GridSearch. + + // Start a new full search. Will iterate all stored blobs, from the top. + // If the blobs have been inserted using InsertBBox, (not InsertPixPtBBox) + // then the full search guarantees to return each blob in the grid once. + // Other searches may return a blob more than once if they have been + // inserted using h_spread or v_spread. + void StartFullSearch(); + // Return the next bbox in the search or NULL if done. + BBC* NextFullSearch(); + + // Start a new radius search. Will search in a spiral upto a + // given maximum radius in grid cells from the given center in pixels. + void StartRadSearch(int x, int y, int max_radius); + // Return the next bbox in the radius search or NULL if the + // maximum radius has been reached. + BBC* NextRadSearch(); + + // Start a new left or right-looking search. Will search to the side + // for a box that vertically overlaps the given vertical line segment. + // CAVEAT: This search returns all blobs from the cells to the side + // of the start, and somewhat below, since there is no guarantee + // that there may not be a taller object in a lower cell. The + // blobs returned will include all those that vertically overlap and + // are no more than twice as high, but may also include some that do + // not overlap and some that are more than twice as high. + void StartSideSearch(int x, int ymin, int ymax); + // Return the next bbox in the side search or NULL if the + // edge has been reached. Searches left to right or right to left + // according to the flag. + BBC* NextSideSearch(bool right_to_left); + + // Start a vertical-looking search. Will search up or down + // for a box that horizontally overlaps the given line segment. + void StartVerticalSearch(int xmin, int xmax, int y); + // Return the next bbox in the vertical search or NULL if the + // edge has been reached. Searches top to bottom or bottom to top + // according to the flag. + BBC* NextVerticalSearch(bool top_to_bottom); + + // Start a rectangular search. Will search for a box that overlaps the + // given rectangle. + void StartRectSearch(const TBOX& rect); + // Return the next bbox in the rectangular search or NULL if complete. + BBC* NextRectSearch(); + + // Remove the last returned BBC. Will not invalidate this. May invalidate + // any other concurrent GridSearch on the same grid. If any others are + // in use, call RepositionIterator on those, to continue without harm. + void RemoveBBox(); + void RepositionIterator(); + + private: + // Factored out helper to start a search. + void CommonStart(int x, int y); + // Factored out helper to complete a next search. + BBC* CommonNext(); + // Factored out final return when search is exhausted. + BBC* CommonEnd(); + // Factored out function to set the iterator to the current x_, y_ + // grid coords and mark the cycle pt. + void SetIterator(); + + private: + // The grid we are searching. + BBGrid* grid_; + // For executing a search. The different search algorithms use these in + // different ways, but most use x_origin_ and y_origin_ as the start position. + int x_origin_; + int y_origin_; + int max_radius_; + int radius_; + int rad_index_; + int rad_dir_; + TBOX rect_; + int x_; // The current location in grid coords, of the current search. + int y_; + bool unique_mode_; + BBC* previous_return_; // Previous return from Next*. + BBC* next_return_; // Current value of it_.data() used for repositioning. + // An iterator over the list at (x_, y_) in the grid_. + BBC_C_IT it_; + // Set of unique returned elements used when unique_mode_ is true. + unordered_set > returns_; +}; + +// Sort function to sort a BBC by bounding_box().left(). +template +int SortByBoxLeft(const void* void1, const void* void2) { + // The void*s are actually doubly indirected, so get rid of one level. + const BBC* p1 = *reinterpret_cast(void1); + const BBC* p2 = *reinterpret_cast(void2); + int result = p1->bounding_box().left() - p2->bounding_box().left(); + if (result != 0) + return result; + result = p1->bounding_box().right() - p2->bounding_box().right(); + if (result != 0) + return result; + result = p1->bounding_box().bottom() - p2->bounding_box().bottom(); + if (result != 0) + return result; + return p1->bounding_box().top() - p2->bounding_box().top(); +} + +// Sort function to sort a BBC by bounding_box().right() in right-to-left order. +template +int SortRightToLeft(const void* void1, const void* void2) { + // The void*s are actually doubly indirected, so get rid of one level. + const BBC* p1 = *reinterpret_cast(void1); + const BBC* p2 = *reinterpret_cast(void2); + int result = p2->bounding_box().right() - p1->bounding_box().right(); + if (result != 0) + return result; + result = p2->bounding_box().left() - p1->bounding_box().left(); + if (result != 0) + return result; + result = p1->bounding_box().bottom() - p2->bounding_box().bottom(); + if (result != 0) + return result; + return p1->bounding_box().top() - p2->bounding_box().top(); +} + +// Sort function to sort a BBC by bounding_box().bottom(). +template +int SortByBoxBottom(const void* void1, const void* void2) { + // The void*s are actually doubly indirected, so get rid of one level. + const BBC* p1 = *reinterpret_cast(void1); + const BBC* p2 = *reinterpret_cast(void2); + int result = p1->bounding_box().bottom() - p2->bounding_box().bottom(); + if (result != 0) + return result; + result = p1->bounding_box().top() - p2->bounding_box().top(); + if (result != 0) + return result; + result = p1->bounding_box().left() - p2->bounding_box().left(); + if (result != 0) + return result; + return p1->bounding_box().right() - p2->bounding_box().right(); +} + +/////////////////////////////////////////////////////////////////////// +// BBGrid IMPLEMENTATION. +/////////////////////////////////////////////////////////////////////// +template +BBGrid::BBGrid() : grid_(NULL) { +} + +template +BBGrid::BBGrid( + int gridsize, const ICOORD& bleft, const ICOORD& tright) + : grid_(NULL) { + Init(gridsize, bleft, tright); +} + +template +BBGrid::~BBGrid() { + if (grid_ != NULL) + delete [] grid_; +} + +// (Re)Initialize the grid. The gridsize is the size in pixels of each cell, +// and bleft, tright are the bounding box of everything to go in it. +template +void BBGrid::Init(int gridsize, + const ICOORD& bleft, + const ICOORD& tright) { + GridBase::Init(gridsize, bleft, tright); + if (grid_ != NULL) + delete [] grid_; + grid_ = new BBC_CLIST[gridbuckets_]; +} + +// Clear all lists, but leave the array of lists present. +template +void BBGrid::Clear() { + for (int i = 0; i < gridbuckets_; ++i) { + grid_[i].shallow_clear(); + } +} + +// Deallocate the data in the lists but otherwise leave the lists and the grid +// intact. +template +void BBGrid::ClearGridData( + void (*free_method)(BBC*)) { + if (grid_ == NULL) return; + GridSearch search(this); + search.StartFullSearch(); + BBC* bb; + BBC_CLIST bb_list; + BBC_C_IT it(&bb_list); + while ((bb = search.NextFullSearch()) != NULL) { + it.add_after_then_move(bb); + } + for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { + free_method(it.data()); + } +} + +// Insert a bbox into the appropriate place in the grid. +// If h_spread, then all cells covered horizontally by the box are +// used, otherwise, just the bottom-left. Similarly for v_spread. +// WARNING: InsertBBox may invalidate an active GridSearch. Call +// RepositionIterator() on any GridSearches that are active on this grid. +template +void BBGrid::InsertBBox(bool h_spread, bool v_spread, + BBC* bbox) { + TBOX box = bbox->bounding_box(); + int start_x, start_y, end_x, end_y; + GridCoords(box.left(), box.bottom(), &start_x, &start_y); + GridCoords(box.right(), box.top(), &end_x, &end_y); + if (!h_spread) + end_x = start_x; + if (!v_spread) + end_y = start_y; + int grid_index = start_y * gridwidth_; + for (int y = start_y; y <= end_y; ++y, grid_index += gridwidth_) { + for (int x = start_x; x <= end_x; ++x) { + grid_[grid_index + x].add_sorted(SortByBoxLeft, true, bbox); + } + } +} + +// Using a pix from TraceOutlineOnReducedPix or TraceBlockOnReducedPix, in +// which each pixel corresponds to a grid cell, insert a bbox into every +// place in the grid where the corresponding pixel is 1. The Pix is handled +// upside-down to match the Tesseract coordinate system. (As created by +// TraceOutlineOnReducedPix or TraceBlockOnReducedPix.) +// (0, 0) in the pix corresponds to (left, bottom) in the +// grid (in grid coords), and the pix works up the grid from there. +// WARNING: InsertPixPtBBox may invalidate an active GridSearch. Call +// RepositionIterator() on any GridSearches that are active on this grid. +template +void BBGrid::InsertPixPtBBox(int left, int bottom, + Pix* pix, BBC* bbox) { + int width = pixGetWidth(pix); + int height = pixGetHeight(pix); + for (int y = 0; y < height; ++y) { + l_uint32* data = pixGetData(pix) + y * pixGetWpl(pix); + for (int x = 0; x < width; ++x) { + if (GET_DATA_BIT(data, x)) { + grid_[(bottom + y) * gridwidth_ + x + left]. + add_sorted(SortByBoxLeft, true, bbox); + } + } + } +} + +// Remove the bbox from the grid. +// WARNING: Any GridSearch operating on this grid could be invalidated! +// If a GridSearch is operating, call GridSearch::RemoveBBox() instead. +template +void BBGrid::RemoveBBox(BBC* bbox) { + TBOX box = bbox->bounding_box(); + int start_x, start_y, end_x, end_y; + GridCoords(box.left(), box.bottom(), &start_x, &start_y); + GridCoords(box.right(), box.top(), &end_x, &end_y); + int grid_index = start_y * gridwidth_; + for (int y = start_y; y <= end_y; ++y, grid_index += gridwidth_) { + for (int x = start_x; x <= end_x; ++x) { + BBC_C_IT it(&grid_[grid_index + x]); + for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { + if (it.data() == bbox) + it.extract(); + } + } + } +} + +// Returns true if the given rectangle has no overlapping elements. +template +bool BBGrid::RectangleEmpty(const TBOX& rect) { + GridSearch rsearch(this); + rsearch.StartRectSearch(rect); + return rsearch.NextRectSearch() == NULL; +} + +// Returns an IntGrid showing the number of elements in each cell. +// Returned IntGrid must be deleted after use. +template +IntGrid* BBGrid::CountCellElements() { + IntGrid* intgrid = new IntGrid(gridsize(), bleft(), tright()); + for (int y = 0; y < gridheight(); ++y) { + for (int x = 0; x < gridwidth(); ++x) { + int cell_count = grid_[y * gridwidth() + x].length(); + intgrid->SetGridCell(x, y, cell_count); + } + } + return intgrid; +} + + +template class TabEventHandler : public SVEventHandler { + public: + explicit TabEventHandler(G* grid) : grid_(grid) { + } + void Notify(const SVEvent* sv_event) { + if (sv_event->type == SVET_CLICK) { + grid_->HandleClick(sv_event->x, sv_event->y); + } + } + private: + G* grid_; +}; + +// Make a window of an appropriate size to display things in the grid. +// Position the window at the given x,y. +template +ScrollView* BBGrid::MakeWindow( + int x, int y, const char* window_name) { + ScrollView* tab_win = NULL; +#ifndef GRAPHICS_DISABLED + tab_win = new ScrollView(window_name, x, y, + tright_.x() - bleft_.x(), + tright_.y() - bleft_.y(), + tright_.x() - bleft_.x(), + tright_.y() - bleft_.y(), + true); + TabEventHandler >* handler = + new TabEventHandler >(this); + tab_win->AddEventHandler(handler); + tab_win->Pen(ScrollView::GREY); + tab_win->Rectangle(0, 0, tright_.x() - bleft_.x(), tright_.y() - bleft_.y()); +#endif + return tab_win; +} + +// Create a window at (x,y) and display the bounding boxes of the +// BLOBNBOXes in this grid. +// Use of this function requires an additional member of the BBC class: +// ScrollView::Color BBC::BoxColor() const. +template +void BBGrid::DisplayBoxes(ScrollView* tab_win) { +#ifndef GRAPHICS_DISABLED + tab_win->Pen(ScrollView::BLUE); + tab_win->Brush(ScrollView::NONE); + + // For every bbox in the grid, display it. + GridSearch gsearch(this); + gsearch.StartFullSearch(); + BBC* bbox; + while ((bbox = gsearch.NextFullSearch()) != NULL) { + TBOX box = bbox->bounding_box(); + int left_x = box.left(); + int right_x = box.right(); + int top_y = box.top(); + int bottom_y = box.bottom(); + ScrollView::Color box_color = bbox->BoxColor(); + tab_win->Pen(box_color); + tab_win->Rectangle(left_x, bottom_y, right_x, top_y); + } + tab_win->Update(); +#endif +} + +// ASSERT_HOST that every cell contains no more than one copy of each entry. +template +void BBGrid::AssertNoDuplicates() { + // Process all grid cells. + for (int i = gridwidth_ * gridheight_ - 1; i >= 0; --i) { + // Iterate over all elements excent the last. + for (BBC_C_IT it(&grid_[i]); !it.at_last(); it.forward()) { + BBC* ptr = it.data(); + BBC_C_IT it2(it); + // None of the rest of the elements in the list should equal ptr. + for (it2.forward(); !it2.at_first(); it2.forward()) { + ASSERT_HOST(it2.data() != ptr); + } + } + } +} + +// Handle a click event in a display window. +template +void BBGrid::HandleClick(int x, int y) { + tprintf("Click at (%d, %d)\n", x, y); +} + +/////////////////////////////////////////////////////////////////////// +// GridSearch IMPLEMENTATION. +/////////////////////////////////////////////////////////////////////// + +// Start a new full search. Will iterate all stored blobs. +template +void GridSearch::StartFullSearch() { + // Full search uses x_ and y_ as the current grid + // cell being searched. + CommonStart(grid_->bleft_.x(), grid_->tright_.y()); +} + +// Return the next bbox in the search or NULL if done. +// The other searches will return a box that overlaps the grid cell +// thereby duplicating boxes, but NextFullSearch only returns each box once. +template +BBC* GridSearch::NextFullSearch() { + int x; + int y; + do { + while (it_.cycled_list()) { + ++x_; + if (x_ >= grid_->gridwidth_) { + --y_; + if (y_ < 0) + return CommonEnd(); + x_ = 0; + } + SetIterator(); + } + CommonNext(); + TBOX box = previous_return_->bounding_box(); + grid_->GridCoords(box.left(), box.bottom(), &x, &y); + } while (x != x_ || y != y_); + return previous_return_; +} + +// Start a new radius search. +template +void GridSearch::StartRadSearch(int x, int y, + int max_radius) { + // Rad search uses x_origin_ and y_origin_ as the center of the circle. + // The radius_ is the radius of the (diamond-shaped) circle and + // rad_index/rad_dir_ combine to determine the position around it. + max_radius_ = max_radius; + radius_ = 0; + rad_index_ = 0; + rad_dir_ = 3; + CommonStart(x, y); +} + +// Return the next bbox in the radius search or NULL if the +// maximum radius has been reached. +template +BBC* GridSearch::NextRadSearch() { + do { + while (it_.cycled_list()) { + ++rad_index_; + if (rad_index_ >= radius_) { + ++rad_dir_; + rad_index_ = 0; + if (rad_dir_ >= 4) { + ++radius_; + if (radius_ > max_radius_) + return CommonEnd(); + rad_dir_ = 0; + } + } + ICOORD offset = C_OUTLINE::chain_step(rad_dir_); + offset *= radius_ - rad_index_; + offset += C_OUTLINE::chain_step(rad_dir_ + 1) * rad_index_; + x_ = x_origin_ + offset.x(); + y_ = y_origin_ + offset.y(); + if (x_ >= 0 && x_ < grid_->gridwidth_ && + y_ >= 0 && y_ < grid_->gridheight_) + SetIterator(); + } + CommonNext(); + } while (unique_mode_ && returns_.find(previous_return_) != returns_.end()); + if (unique_mode_) + returns_.insert(previous_return_); + return previous_return_; +} + +// Start a new left or right-looking search. Will search to the side +// for a box that vertically overlaps the given vertical line segment. +template +void GridSearch::StartSideSearch(int x, + int ymin, int ymax) { + // Right search records the x in x_origin_, the ymax in y_origin_ + // and the size of the vertical strip to search in radius_. + // To guarantee finding overlapping objects of upto twice the + // given size, double the height. + radius_ = ((ymax - ymin) * 2 + grid_->gridsize_ - 1) / grid_->gridsize_; + rad_index_ = 0; + CommonStart(x, ymax); +} + +// Return the next bbox in the side search or NULL if the +// edge has been reached. Searches left to right or right to left +// according to the flag. +template +BBC* GridSearch::NextSideSearch(bool right_to_left) { + do { + while (it_.cycled_list()) { + ++rad_index_; + if (rad_index_ > radius_) { + if (right_to_left) + --x_; + else + ++x_; + rad_index_ = 0; + if (x_ < 0 || x_ >= grid_->gridwidth_) + return CommonEnd(); + } + y_ = y_origin_ - rad_index_; + if (y_ >= 0 && y_ < grid_->gridheight_) + SetIterator(); + } + CommonNext(); + } while (unique_mode_ && returns_.find(previous_return_) != returns_.end()); + if (unique_mode_) + returns_.insert(previous_return_); + return previous_return_; +} + +// Start a vertical-looking search. Will search up or down +// for a box that horizontally overlaps the given line segment. +template +void GridSearch::StartVerticalSearch(int xmin, + int xmax, + int y) { + // Right search records the xmin in x_origin_, the y in y_origin_ + // and the size of the horizontal strip to search in radius_. + radius_ = (xmax - xmin + grid_->gridsize_ - 1) / grid_->gridsize_; + rad_index_ = 0; + CommonStart(xmin, y); +} + +// Return the next bbox in the vertical search or NULL if the +// edge has been reached. Searches top to bottom or bottom to top +// according to the flag. +template +BBC* GridSearch::NextVerticalSearch( + bool top_to_bottom) { + do { + while (it_.cycled_list()) { + ++rad_index_; + if (rad_index_ > radius_) { + if (top_to_bottom) + --y_; + else + ++y_; + rad_index_ = 0; + if (y_ < 0 || y_ >= grid_->gridheight_) + return CommonEnd(); + } + x_ = x_origin_ + rad_index_; + if (x_ >= 0 && x_ < grid_->gridwidth_) + SetIterator(); + } + CommonNext(); + } while (unique_mode_ && returns_.find(previous_return_) != returns_.end()); + if (unique_mode_) + returns_.insert(previous_return_); + return previous_return_; +} + +// Start a rectangular search. Will search for a box that overlaps the +// given rectangle. +template +void GridSearch::StartRectSearch(const TBOX& rect) { + // Rect search records the xmin in x_origin_, the ymin in y_origin_ + // and the xmax in max_radius_. + // The search proceeds left to right, top to bottom. + rect_ = rect; + CommonStart(rect.left(), rect.top()); + grid_->GridCoords(rect.right(), rect.bottom(), // - rect.height(), + &max_radius_, &y_origin_); +} + +// Return the next bbox in the rectangular search or NULL if complete. +template +BBC* GridSearch::NextRectSearch() { + do { + while (it_.cycled_list()) { + ++x_; + if (x_ > max_radius_) { + --y_; + x_ = x_origin_; + if (y_ < y_origin_) + return CommonEnd(); + } + SetIterator(); + } + CommonNext(); + } while (!rect_.overlap(previous_return_->bounding_box()) || + (unique_mode_ && returns_.find(previous_return_) != returns_.end())); + if (unique_mode_) + returns_.insert(previous_return_); + return previous_return_; +} + +// Remove the last returned BBC. Will not invalidate this. May invalidate +// any other concurrent GridSearch on the same grid. If any others are +// in use, call RepositionIterator on those, to continue without harm. +template +void GridSearch::RemoveBBox() { + if (previous_return_ != NULL) { + // Remove all instances of previous_return_ from the list, so the iterator + // remains valid after removal from the rest of the grid cells. + // if previous_return_ is not on the list, then it has been removed already. + BBC* prev_data = NULL; + BBC* new_previous_return = NULL; + it_.move_to_first(); + for (it_.mark_cycle_pt(); !it_.cycled_list();) { + if (it_.data() == previous_return_) { + new_previous_return = prev_data; + it_.extract(); + it_.forward(); + next_return_ = it_.cycled_list() ? NULL : it_.data(); + } else { + prev_data = it_.data(); + it_.forward(); + } + } + grid_->RemoveBBox(previous_return_); + previous_return_ = new_previous_return; + RepositionIterator(); + } +} + +template +void GridSearch::RepositionIterator() { + // Something was deleted, so we have little choice but to clear the + // returns list. + returns_.clear(); + // Reset the iterator back to one past the previous return. + // If the previous_return_ is no longer in the list, then + // next_return_ serves as a backup. + it_.move_to_first(); + // Special case, the first element was removed and reposition + // iterator was called. In this case, the data is fine, but the + // cycle point is not. Detect it and return. + if (!it_.empty() && it_.data() == next_return_) { + it_.mark_cycle_pt(); + return; + } + for (it_.mark_cycle_pt(); !it_.cycled_list(); it_.forward()) { + if (it_.data() == previous_return_ || + it_.data_relative(1) == next_return_) { + CommonNext(); + return; + } + } + // We ran off the end of the list. Move to a new cell next time. + previous_return_ = NULL; + next_return_ = NULL; +} + +// Factored out helper to start a search. +template +void GridSearch::CommonStart(int x, int y) { + grid_->GridCoords(x, y, &x_origin_, &y_origin_); + x_ = x_origin_; + y_ = y_origin_; + SetIterator(); + previous_return_ = NULL; + next_return_ = it_.empty() ? NULL : it_.data(); + returns_.clear(); +} + +// Factored out helper to complete a next search. +template +BBC* GridSearch::CommonNext() { + previous_return_ = it_.data(); + it_.forward(); + next_return_ = it_.cycled_list() ? NULL : it_.data(); + return previous_return_; +} + +// Factored out final return when search is exhausted. +template +BBC* GridSearch::CommonEnd() { + previous_return_ = NULL; + next_return_ = NULL; + return NULL; +} + +// Factored out function to set the iterator to the current x_, y_ +// grid coords and mark the cycle pt. +template +void GridSearch::SetIterator() { + it_= &(grid_->grid_[y_ * grid_->gridwidth_ + x_]); + it_.mark_cycle_pt(); +} + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_BBGRID_H__ diff --git a/TesseractOCR/include/tesseract/beam_search.h b/TesseractOCR/include/tesseract/beam_search.h new file mode 100644 index 00000000..a39f5b13 --- /dev/null +++ b/TesseractOCR/include/tesseract/beam_search.h @@ -0,0 +1,126 @@ +/********************************************************************** + * File: beam_search.h + * Description: Declaration of Beam Word Search Algorithm Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The Beam Search class implements a Beam Search algorithm for the +// N-best paths through the lattice of a search object using a language model +// The search object is a segmented bitmap of a word image. The language model +// is a state machine that defines valid sequences of characters +// The cost of each path is the combined (product) probabilities of the +// characters along the path. The character probabilities are computed using +// the character classifier member of the RecoContext +// The BeamSearch class itself holds the state of the last search it performed +// using its "Search" method. Subsequent class to the Search method erase the +// states of previously done searches + +#ifndef BEAM_SEARCH_H +#define BEAM_SEARCH_H + +#include "search_column.h" +#include "word_altlist.h" +#include "search_object.h" +#include "lang_model.h" +#include "cube_utils.h" +#include "cube_reco_context.h" +#include "allheaders.h" + +namespace tesseract { + +class BeamSearch { + public: + explicit BeamSearch(CubeRecoContext *cntxt, bool word_mode = true); + ~BeamSearch(); + // Performs a beam seach in the specified search using the specified + // language model; returns an alternate list of possible words as a result. + WordAltList *Search(SearchObject *srch_obj, LangModel *lang_mod = NULL); + // Returns the best node in the last column of last performed search. + SearchNode *BestNode() const; + // Returns the string corresponding to the specified alt. + char_32 *Alt(int alt) const; + // Backtracks from the specified lattice node and returns the corresponding + // character-mapped segments, character count, char_32 result string, and + // character bounding boxes (if char_boxes is not NULL). If the segments + // cannot be constructed, returns NULL, and all result arguments + // will be NULL. + CharSamp **BackTrack(SearchObject *srch_obj, int node_index, + int *char_cnt, char_32 **str32, Boxa **char_boxes) const; + // Same as above, except it takes a pointer to a search node object + // instead of node index. + CharSamp **BackTrack(SearchObject *srch_obj, SearchNode *node, + int *char_cnt, char_32 **str32, Boxa **char_boxes) const; + // Returns the size cost of a specified string of a lattice + // path that ends at the specified lattice node. + int SizeCost(SearchObject *srch_obj, SearchNode *node, + char_32 **str32 = NULL) const; + // Returns the word unigram cost of the given string, possibly + // stripping out a single trailing punctuation character. + int WordUnigramCost(char_32 *str32, WordUnigrams* word_unigrams) const; + + // Supplementary functions needed for visualization + // Return column count of the lattice. + inline int ColCnt() const { return col_cnt_; } + // Returns the lattice column corresponding to the specified column index. + SearchColumn *Column(int col_idx) const; + // Return the index of the best node in the last column of the + // best-cost path before the alternates list is sorted. + inline int BestPresortedNodeIndex() const { + return best_presorted_node_idx_; + }; + + private: + // Maximum reasonable segmentation point count + static const int kMaxSegPointCnt = 128; + // Recognition context object; the context holds the character classifier + // and the tuning parameters object + CubeRecoContext *cntxt_; + // Count of segmentation pts + int seg_pt_cnt_; + // Lattice column count; currently redundant with respect to seg_pt_cnt_ + // but that might change in the future + int col_cnt_; + // Array of lattice columns + SearchColumn **col_; + // Run in word or phrase mode + bool word_mode_; + // Node index of best-cost node, before alternates are merged and sorted + int best_presorted_node_idx_; + // Cleans up beam search state + void Cleanup(); + // Creates a Word alternate list from the results in the lattice. + // This function computes a cost for each node in the final column + // of the lattice, which is a weighted average of several costs: + // size cost, character bigram cost, word unigram cost, and + // recognition cost from the beam search. The weights are the + // CubeTuningParams, which are learned together with the character + // classifiers. + WordAltList *CreateWordAltList(SearchObject *srch_obj); + // Creates a set of children nodes emerging from a parent node based on + // the character alternate list and the language model. + void CreateChildren(SearchColumn *out_col, LangModel *lang_mod, + SearchNode *parent_node, LangModEdge *lm_parent_edge, + CharAltList *char_alt_list, int extra_cost); + // Backtracks from the given lattice node and returns the corresponding + // char mapped segments, character count, and character bounding boxes (if + // char_boxes is not NULL). If the segments cannot be constructed, + // returns NULL, and all result arguments will be NULL. + CharSamp **SplitByNode(SearchObject *srch_obj, SearchNode *srch_node, + int* char_cnt, Boxa **char_boxes) const; +}; +} + +#endif // BEAM_SEARCH_H diff --git a/TesseractOCR/include/tesseract/bits16.h b/TesseractOCR/include/tesseract/bits16.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/bitvec.h b/TesseractOCR/include/tesseract/bitvec.h new file mode 100644 index 00000000..af84ad60 --- /dev/null +++ b/TesseractOCR/include/tesseract/bitvec.h @@ -0,0 +1,75 @@ +/****************************************************************************** + ** Filename: bitvec.h + ** Purpose: Routines for manipulating bit vectors + ** Author: Dan Johnson + ** History: Wed Mar 7 17:52:45 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef BITVEC_H +#define BITVEC_H + +#include "host.h" + +/*----------------------------------------------------------------------------- + Include Files and Type Defines +-----------------------------------------------------------------------------*/ +// TODO(rays) Rename BITSINLONG to BITSINuinT32, and use sizeof. +#define BITSINLONG 32 /**< no of bits in a long */ +typedef uinT32 *BIT_VECTOR; + +/*----------------------------------------------------------------------------- + Public Function Prototypes +-----------------------------------------------------------------------------*/ +#define zero_all_bits(array,length) \ +{\ + register int index; /*temporary index*/\ +\ +for (index=0;index +#include "boxword.h" +#include "genericvector.h" +#include "matrix.h" +#include "params_training_featdef.h" +#include "ratngs.h" +#include "strngs.h" +#include "tesscallback.h" + +static const inT16 kBlamerBoxTolerance = 5; + +// Enum for expressing the source of error. +// Note: Please update kIncorrectResultReasonNames when modifying this enum. +enum IncorrectResultReason { + // The text recorded in best choice == truth text + IRR_CORRECT, + // Either: Top choice is incorrect and is a dictionary word (language model + // is unlikely to help correct such errors, so blame the classifier). + // Or: the correct unichar was not included in shortlist produced by the + // classifier at all. + IRR_CLASSIFIER, + // Chopper have not found one or more splits that correspond to the correct + // character bounding boxes recorded in BlamerBundle::truth_word. + IRR_CHOPPER, + // Classifier did include correct unichars for each blob in the correct + // segmentation, however its rating could have been too bad to allow the + // language model to pull out the correct choice. On the other hand the + // strength of the language model might have been too weak to favor the + // correct answer, this we call this case a classifier-language model + // tradeoff error. + IRR_CLASS_LM_TRADEOFF, + // Page layout failed to produce the correct bounding box. Blame page layout + // if the truth was not found for the word, which implies that the bounding + // box of the word was incorrect (no truth word had a similar bounding box). + IRR_PAGE_LAYOUT, + // SegSearch heuristic prevented one or more blobs from the correct + // segmentation state to be classified (e.g. the blob was too wide). + IRR_SEGSEARCH_HEUR, + // The correct segmentaiton state was not explored because of poor SegSearch + // pain point prioritization. We blame SegSearch pain point prioritization + // if the best rating of a choice constructed from correct segmentation is + // better than that of the best choice (i.e. if we got to explore the correct + // segmentation state, language model would have picked the correct choice). + IRR_SEGSEARCH_PP, + // Same as IRR_CLASS_LM_TRADEOFF, but used when we only run chopper on a word, + // and thus use the old language model (permuters). + // TODO(antonova): integrate the new language mode with chopper + IRR_CLASS_OLD_LM_TRADEOFF, + // If there is an incorrect adaptive template match with a better score than + // a correct one (either pre-trained or adapted), mark this as adaption error. + IRR_ADAPTION, + // split_and_recog_word() failed to find a suitable split in truth. + IRR_NO_TRUTH_SPLIT, + // Truth is not available for this word (e.g. when words in corrected content + // file are turned into ~~~~ because an appropriate alignment was not found. + IRR_NO_TRUTH, + // The text recorded in best choice != truth text, but none of the above + // reasons are set. + IRR_UNKNOWN, + + IRR_NUM_REASONS +}; + +// Blamer-related information to determine the source of errors. +struct BlamerBundle { + static const char *IncorrectReasonName(IncorrectResultReason irr); + BlamerBundle() : truth_has_char_boxes_(false), + incorrect_result_reason_(IRR_CORRECT), + lattice_data_(NULL) { ClearResults(); } + BlamerBundle(const BlamerBundle &other) { + this->CopyTruth(other); + this->CopyResults(other); + } + ~BlamerBundle() { delete[] lattice_data_; } + + // Accessors. + STRING TruthString() const { + STRING truth_str; + for (int i = 0; i < truth_text_.length(); ++i) + truth_str += truth_text_[i]; + return truth_str; + } + IncorrectResultReason incorrect_result_reason() const { + return incorrect_result_reason_; + } + bool NoTruth() const { + return incorrect_result_reason_ == IRR_NO_TRUTH || + incorrect_result_reason_ == IRR_PAGE_LAYOUT; + } + bool HasDebugInfo() const { + return debug_.length() > 0 || misadaption_debug_.length() > 0; + } + const STRING& debug() const { + return debug_; + } + const STRING& misadaption_debug() const { + return misadaption_debug_; + } + void UpdateBestRating(float rating) { + if (rating < best_correctly_segmented_rating_) + best_correctly_segmented_rating_ = rating; + } + int correct_segmentation_length() const { + return correct_segmentation_cols_.length(); + } + // Returns true if the given ratings matrix col,row position is included + // in the correct segmentation path at the given index. + bool MatrixPositionCorrect(int index, const MATRIX_COORD& coord) { + return correct_segmentation_cols_[index] == coord.col && + correct_segmentation_rows_[index] == coord.row; + } + void set_best_choice_is_dict_and_top_choice(bool value) { + best_choice_is_dict_and_top_choice_ = value; + } + const char* lattice_data() const { + return lattice_data_; + } + int lattice_size() const { + return lattice_size_; // size of lattice_data in bytes + } + void set_lattice_data(const char* data, int size) { + lattice_size_ = size; + delete [] lattice_data_; + lattice_data_ = new char[lattice_size_]; + memcpy(lattice_data_, data, lattice_size_); + } + const tesseract::ParamsTrainingBundle& params_training_bundle() const { + return params_training_bundle_; + } + // Adds a new ParamsTrainingHypothesis to the current hypothesis list. + void AddHypothesis(const tesseract::ParamsTrainingHypothesis& hypo) { + params_training_bundle_.AddHypothesis(hypo); + } + + // Functions to setup the blamer. + // Whole word string, whole word bounding box. + void SetWordTruth(const UNICHARSET& unicharset, + const char* truth_str, const TBOX& word_box); + // Single "character" string, "character" bounding box. + // May be called multiple times to indicate the characters in a word. + void SetSymbolTruth(const UNICHARSET& unicharset, + const char* char_str, const TBOX& char_box); + // Marks that there is something wrong with the truth text, like it contains + // reject characters. + void SetRejectedTruth(); + + // Returns true if the provided word_choice is correct. + bool ChoiceIsCorrect(const WERD_CHOICE* word_choice) const; + + void ClearResults() { + norm_truth_word_.DeleteAllBoxes(); + norm_box_tolerance_ = 0; + if (!NoTruth()) incorrect_result_reason_ = IRR_CORRECT; + debug_ = ""; + segsearch_is_looking_for_blame_ = false; + best_correctly_segmented_rating_ = WERD_CHOICE::kBadRating; + correct_segmentation_cols_.clear(); + correct_segmentation_rows_.clear(); + best_choice_is_dict_and_top_choice_ = false; + delete[] lattice_data_; + lattice_data_ = NULL; + lattice_size_ = 0; + } + void CopyTruth(const BlamerBundle &other) { + truth_has_char_boxes_ = other.truth_has_char_boxes_; + truth_word_ = other.truth_word_; + truth_text_ = other.truth_text_; + incorrect_result_reason_ = + (other.NoTruth() ? other.incorrect_result_reason_ : IRR_CORRECT); + } + void CopyResults(const BlamerBundle &other) { + norm_truth_word_ = other.norm_truth_word_; + norm_box_tolerance_ = other.norm_box_tolerance_; + incorrect_result_reason_ = other.incorrect_result_reason_; + segsearch_is_looking_for_blame_ = other.segsearch_is_looking_for_blame_; + best_correctly_segmented_rating_ = other.best_correctly_segmented_rating_; + correct_segmentation_cols_ = other.correct_segmentation_cols_; + correct_segmentation_rows_ = other.correct_segmentation_rows_; + best_choice_is_dict_and_top_choice_ = + other.best_choice_is_dict_and_top_choice_; + if (other.lattice_data_ != NULL) { + lattice_data_ = new char[other.lattice_size_]; + memcpy(lattice_data_, other.lattice_data_, other.lattice_size_); + lattice_size_ = other.lattice_size_; + } else { + lattice_data_ = NULL; + } + } + const char *IncorrectReason() const; + + // Appends choice and truth details to the given debug string. + void FillDebugString(const STRING &msg, const WERD_CHOICE *choice, + STRING *debug); + + // Sets up the norm_truth_word from truth_word using the given DENORM. + void SetupNormTruthWord(const DENORM& denorm); + + // Splits *this into two pieces in bundle1 and bundle2 (preallocated, empty + // bundles) where the right edge/ of the left-hand word is word1_right, + // and the left edge of the right-hand word is word2_left. + void SplitBundle(int word1_right, int word2_left, bool debug, + BlamerBundle* bundle1, BlamerBundle* bundle2) const; + // "Joins" the blames from bundle1 and bundle2 into *this. + void JoinBlames(const BlamerBundle& bundle1, const BlamerBundle& bundle2, + bool debug); + + // If a blob with the same bounding box as one of the truth character + // bounding boxes is not classified as the corresponding truth character + // blames character classifier for incorrect answer. + void BlameClassifier(const UNICHARSET& unicharset, + const TBOX& blob_box, + const BLOB_CHOICE_LIST& choices, + bool debug); + + + // Checks whether chops were made at all the character bounding box + // boundaries in word->truth_word. If not - blames the chopper for an + // incorrect answer. + void SetChopperBlame(const WERD_RES* word, bool debug); + // Blames the classifier or the language model if, after running only the + // chopper, best_choice is incorrect and no blame has been yet set. + // Blames the classifier if best_choice is classifier's top choice and is a + // dictionary word (i.e. language model could not have helped). + // Otherwise, blames the language model (formerly permuter word adjustment). + void BlameClassifierOrLangModel( + const WERD_RES* word, + const UNICHARSET& unicharset, bool valid_permuter, bool debug); + // Sets up the correct_segmentation_* to mark the correct bounding boxes. + void SetupCorrectSegmentation(const TWERD* word, bool debug); + + // Returns true if a guided segmentation search is needed. + bool GuidedSegsearchNeeded(const WERD_CHOICE *best_choice) const; + // Setup ready to guide the segmentation search to the correct segmentation. + // The callback pp_cb is used to avoid a cyclic dependency. + // It calls into LMPainPoints::GenerateForBlamer by pre-binding the + // WERD_RES, and the LMPainPoints itself. + // pp_cb must be a permanent callback, and should be deleted by the caller. + void InitForSegSearch(const WERD_CHOICE *best_choice, + MATRIX* ratings, UNICHAR_ID wildcard_id, + bool debug, STRING *debug_str, + TessResultCallback2* pp_cb); + // Returns true if the guided segsearch is in progress. + bool GuidedSegsearchStillGoing() const; + // The segmentation search has ended. Sets the blame appropriately. + void FinishSegSearch(const WERD_CHOICE *best_choice, + bool debug, STRING *debug_str); + + // If the bundle is null or still does not indicate the correct result, + // fix it and use some backup reason for the blame. + static void LastChanceBlame(bool debug, WERD_RES* word); + + // Sets the misadaption debug if this word is incorrect, as this word is + // being adapted to. + void SetMisAdaptionDebug(const WERD_CHOICE *best_choice, bool debug); + + private: + void SetBlame(IncorrectResultReason irr, const STRING &msg, + const WERD_CHOICE *choice, bool debug) { + incorrect_result_reason_ = irr; + debug_ = IncorrectReason(); + debug_ += " to blame: "; + FillDebugString(msg, choice, &debug_); + if (debug) tprintf("SetBlame(): %s", debug_.string()); + } + + private: + // Set to true when bounding boxes for individual unichars are recorded. + bool truth_has_char_boxes_; + // The true_word (in the original image coordinate space) contains ground + // truth bounding boxes for this WERD_RES. + tesseract::BoxWord truth_word_; + // Same as above, but in normalized coordinates + // (filled in by WERD_RES::SetupForRecognition()). + tesseract::BoxWord norm_truth_word_; + // Tolerance for bounding box comparisons in normalized space. + int norm_box_tolerance_; + // Contains ground truth unichar for each of the bounding boxes in truth_word. + GenericVector truth_text_; + // The reason for incorrect OCR result. + IncorrectResultReason incorrect_result_reason_; + // Debug text associated with the blame. + STRING debug_; + // Misadaption debug information (filled in if this word was misadapted to). + STRING misadaption_debug_; + // Variables used by the segmentation search when looking for the blame. + // Set to true while segmentation search is continued after the usual + // termination condition in order to look for the blame. + bool segsearch_is_looking_for_blame_; + // Best rating for correctly segmented path + // (set and used by SegSearch when looking for blame). + float best_correctly_segmented_rating_; + // Vectors populated by SegSearch to indicate column and row indices that + // correspond to blobs with correct bounding boxes. + GenericVector correct_segmentation_cols_; + GenericVector correct_segmentation_rows_; + // Set to true if best choice is a dictionary word and + // classifier's top choice. + bool best_choice_is_dict_and_top_choice_; + // Serialized segmentation search lattice. + char *lattice_data_; + int lattice_size_; // size of lattice_data in bytes + // Information about hypotheses (paths) explored by the segmentation search. + tesseract::ParamsTrainingBundle params_training_bundle_; +}; + + +#endif // TESSERACT_CCSTRUCT_BLAMER_H_ diff --git a/TesseractOCR/include/tesseract/blckerr.h b/TesseractOCR/include/tesseract/blckerr.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/blkocc.h b/TesseractOCR/include/tesseract/blkocc.h new file mode 100644 index 00000000..7be79090 --- /dev/null +++ b/TesseractOCR/include/tesseract/blkocc.h @@ -0,0 +1,263 @@ +/****************************************************************************** + * + * File: blkocc.h (Formerly blockocc.h) + * Description: Block Occupancy routines + * Author: Chris Newton + * Created: Fri Nov 8 + * Modified: + * Language: C++ + * Package: N/A + * Status: Experimental (Do Not Distribute) + * + * (c) Copyright 1991, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + ******************************************************************************/ + +#ifndef BLKOCC_H +#define BLKOCC_H + +#include "params.h" +#include "elst.h" + +/*************************************************************************** +CLASS REGION_OCC + + The class REGION_OCC defines a section of outline which exists entirely + within a single region. The only data held is the min and max x limits of + the outline within the region. + + REGION_OCCs are held on lists, one list for each region. The lists are + built in sorted order of min x. Overlapping REGION_OCCs are not permitted on + a single list. An overlapping region to be added causes the existing region + to be extended. This extension may result in the following REGION_OCC on the + list overlapping the ammended one. In this case the ammended REGION_OCC is + further extended to include the range of the following one, so that the + following one can be deleted. + +****************************************************************************/ + +class REGION_OCC:public ELIST_LINK +{ + public: + float min_x; //Lowest x in region + float max_x; //Highest x in region + inT16 region_type; //Type of crossing + + REGION_OCC() { + }; //constructor used + //only in COPIER etc + REGION_OCC( //constructor + float min, + float max, + inT16 region) { + min_x = min; + max_x = max; + region_type = region; + } +}; + +ELISTIZEH (REGION_OCC) +#define RANGE_IN_BAND( band_max, band_min, range_max, range_min ) \ +( ((range_min) >= (band_min)) && ((range_max) < (band_max)) ) ? TRUE : FALSE +/************************************************************************ +Adapted from the following procedure so that it can be used in the bands +class in an include file... + +BOOL8 range_in_band[ + range within band? +inT16 band_max, +inT16 band_min, +inT16 range_max, +inT16 range_min] +{ + if ( (range_min >= band_min) && (range_max < band_max) ) + return TRUE; + else + return FALSE; +} +***********************************************************************/ +#define RANGE_OVERLAPS_BAND( band_max, band_min, range_max, range_min ) \ +( ((range_max) >= (band_min)) && ((range_min) < (band_max)) ) ? TRUE : FALSE +/************************************************************************ +Adapted from the following procedure so that it can be used in the bands +class in an include file... + +BOOL8 range_overlaps_band[ + range crosses band? +inT16 band_max, +inT16 band_min, +inT16 range_max, +inT16 range_min] +{ + if ( (range_max >= band_min) && (range_min < band_max) ) + return TRUE; + else + return FALSE; +} +***********************************************************************/ +/********************************************************************** + Bands + ----- + + BAND 4 +-------------------------------- + BAND 3 +-------------------------------- + + BAND 2 + +-------------------------------- + + BAND 1 + +Band 0 is the dot band + +Each band has an error margin above and below. An outline is not considered to +have significantly changed bands until it has moved out of the error margin. +*************************************************************************/ +class BAND +{ + public: + inT16 max_max; //upper max + inT16 max; //nominal max + inT16 min_max; //lower max + inT16 max_min; //upper min + inT16 min; //nominal min + inT16 min_min; //lower min + + BAND() { + } // constructor + + void set( // initialise a band + inT16 new_max_max, // upper max + inT16 new_max, // new nominal max + inT16 new_min_max, // new lower max + inT16 new_max_min, // new upper min + inT16 new_min, // new nominal min + inT16 new_min_min) { // new lower min + max_max = new_max_max; + max = new_max; + min_max = new_min_max; + max_min = new_max_min; + min = new_min; + min_min = new_min_min; + } + + BOOL8 in_minimal( //in minimal limits? + float y) { //y value + if ((y >= max_min) && (y < min_max)) + return TRUE; + else + return FALSE; + } + + BOOL8 in_nominal( //in nominal limits? + float y) { //y value + if ((y >= min) && (y < max)) + return TRUE; + else + return FALSE; + } + + BOOL8 in_maximal( //in maximal limits? + float y) { //y value + if ((y >= min_min) && (y < max_max)) + return TRUE; + else + return FALSE; + } + + //overlaps min limits? + BOOL8 range_overlaps_minimal(float y1, //one range limit + float y2) { //other range limit + if (y1 > y2) + return RANGE_OVERLAPS_BAND (min_max, max_min, y1, y2); + else + return RANGE_OVERLAPS_BAND (min_max, max_min, y2, y1); + } + + //overlaps nom limits? + BOOL8 range_overlaps_nominal(float y1, //one range limit + float y2) { //other range limit + if (y1 > y2) + return RANGE_OVERLAPS_BAND (max, min, y1, y2); + else + return RANGE_OVERLAPS_BAND (max, min, y2, y1); + } + + //overlaps max limits? + BOOL8 range_overlaps_maximal(float y1, //one range limit + float y2) { //other range limit + if (y1 > y2) + return RANGE_OVERLAPS_BAND (max_max, min_min, y1, y2); + else + return RANGE_OVERLAPS_BAND (max_max, min_min, y2, y1); + } + + BOOL8 range_in_minimal( //within min limits? + float y1, //one range limit + float y2) { //other range limit + if (y1 > y2) + return RANGE_IN_BAND (min_max, max_min, y1, y2); + else + return RANGE_IN_BAND (min_max, max_min, y2, y1); + } + + BOOL8 range_in_nominal( //within nom limits? + float y1, //one range limit + float y2) { //other range limit + if (y1 > y2) + return RANGE_IN_BAND (max, min, y1, y2); + else + return RANGE_IN_BAND (max, min, y2, y1); + } + + BOOL8 range_in_maximal( //within max limits? + float y1, //one range limit + float y2) { //other range limit + if (y1 > y2) + return RANGE_IN_BAND (max_max, min_min, y1, y2); + else + return RANGE_IN_BAND (max_max, min_min, y2, y1); + } +}; + +/* Standard positions */ + +#define MAX_NUM_BANDS 5 +#define UNDEFINED_BAND 99 +#define NO_LOWER_LIMIT -9999 +#define NO_UPPER_LIMIT 9999 + +#define DOT_BAND 0 + +/* Special occupancy code emitted for the 0 region at the end of a word */ + +#define END_OF_WERD_CODE 255 + +extern BOOL_VAR_H (blockocc_show_result, FALSE, "Show intermediate results"); +extern INT_VAR_H (blockocc_desc_height, 0, +"Descender height after normalisation"); +extern INT_VAR_H (blockocc_asc_height, 255, +"Ascender height after normalisation"); +extern INT_VAR_H (blockocc_band_count, 4, "Number of bands used"); +extern double_VAR_H (textord_underline_threshold, 0.9, +"Fraction of width occupied"); + +BOOL8 test_underline( //look for underlines + BOOL8 testing_on, //drawing blob + C_BLOB *blob, //blob to test + inT16 baseline, //coords of baseline + inT16 xheight //height of line + ); + +#endif diff --git a/TesseractOCR/include/tesseract/blobbox.h b/TesseractOCR/include/tesseract/blobbox.h old mode 100755 new mode 100644 index 6229365c..bd26e1be --- a/TesseractOCR/include/tesseract/blobbox.h +++ b/TesseractOCR/include/tesseract/blobbox.h @@ -204,6 +204,10 @@ class BLOBNBOX:public ELIST_LINK // given horizontal range. TBOX BoundsWithinLimits(int left, int right); + // Estimates and stores the baseline position based on the shape of the + // outline. + void EstimateBaselinePosition(); + // Simple accessors. const TBOX& bounding_box() const { return box; @@ -219,6 +223,7 @@ class BLOBNBOX:public ELIST_LINK box = cblob_ptr->bounding_box(); base_char_top_ = box.top(); base_char_bottom_ = box.bottom(); + baseline_y_ = box.bottom(); } const TBOX& reduced_box() const { return red_box; @@ -363,6 +368,9 @@ class BLOBNBOX:public ELIST_LINK int base_char_bottom() const { return base_char_bottom_; } + int baseline_position() const { + return baseline_y_; + } int line_crossings() const { return line_crossings_; } @@ -407,6 +415,10 @@ class BLOBNBOX:public ELIST_LINK static void CleanNeighbours(BLOBNBOX_LIST* blobs); // Helper to delete all the deletable blobs on the list. static void DeleteNoiseBlobs(BLOBNBOX_LIST* blobs); + // Helper to compute edge offsets for all the blobs on the list. + // See coutln.h for an explanation of edge offsets. + static void ComputeEdgeOffsets(Pix* thresholds, Pix* grey, + BLOBNBOX_LIST* blobs); #ifndef GRAPHICS_DISABLED // Helper to draw all the blobs on the list in the given body_colour, @@ -464,6 +476,7 @@ class BLOBNBOX:public ELIST_LINK owner_ = NULL; base_char_top_ = box.top(); base_char_bottom_ = box.bottom(); + baseline_y_ = box.bottom(); line_crossings_ = 0; base_char_blob_ = NULL; horz_possible_ = false; @@ -498,6 +511,7 @@ class BLOBNBOX:public ELIST_LINK inT16 right_crossing_rule_; // x-coord of nearest or crossing rule line inT16 base_char_top_; // y-coord of top/bottom of diacritic base, inT16 base_char_bottom_; // if it exists else top/bottom of this blob. + inT16 baseline_y_; // Estimate of baseline position. int line_crossings_; // Number of line intersections touched. BLOBNBOX* base_char_blob_; // The blob that was the base char. float horz_stroke_width_; // Median horizontal stroke width @@ -527,6 +541,7 @@ class TO_ROW: public ELIST2_LINK float bottom, float row_size); + void print() const; float max_y() const { //access function return y_max; } @@ -707,12 +722,12 @@ class TO_BLOCK:public ELIST_LINK TO_ROW_IT row_it = &row_list; TO_ROW *row; - for (row_it.mark_cycle_pt (); !row_it.cycled_list (); - row_it.forward ()) { - row = row_it.data (); - printf ("Row range (%g,%g), para_c=%g, blobcount=" INT32FORMAT - "\n", row->min_y (), row->max_y (), row->parallel_c (), - row->blob_list ()->length ()); + for (row_it.mark_cycle_pt(); !row_it.cycled_list(); + row_it.forward()) { + row = row_it.data(); + tprintf("Row range (%g,%g), para_c=%g, blobcount=" INT32FORMAT + "\n", row->min_y(), row->max_y(), row->parallel_c(), + row->blob_list()->length()); } } @@ -725,6 +740,15 @@ class TO_BLOCK:public ELIST_LINK // Deletes noise blobs from all lists where not owned by a ColPartition. void DeleteUnownedNoise(); + // Computes and stores the edge offsets on each blob for use in feature + // extraction, using greyscale if the supplied grey and thresholds pixes + // are 8-bit or otherwise (if NULL or not 8 bit) the original binary + // edge step outlines. + // Thresholds must either be the same size as grey or an integer down-scale + // of grey. + // See coutln.h for an explanation of edge offsets. + void ComputeEdgeOffsets(Pix* thresholds, Pix* grey); + #ifndef GRAPHICS_DISABLED // Draw the noise blobs from all lists in red. void plot_noise_blobs(ScrollView* to_win); diff --git a/TesseractOCR/include/tesseract/blobclass.h b/TesseractOCR/include/tesseract/blobclass.h new file mode 100644 index 00000000..95510a2f --- /dev/null +++ b/TesseractOCR/include/tesseract/blobclass.h @@ -0,0 +1,56 @@ +/****************************************************************************** + ** Filename: blobclass.h + ** Purpose: Interface to high level classification and training. + ** Author: Dan Johnson + ** History: 5/29/89, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef BLOBCLASS_H +#define BLOBCLASS_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "featdefs.h" +#include "oldlist.h" +#include "blobs.h" + +/*--------------------------------------------------------------------------- + Macros +----------------------------------------------------------------------------*/ +/* macros for controlling the display of recognized characters */ +#define EnableCharDisplay() (DisplayCharacters = TRUE) +#define DisableCharDisplay() (DisplayCharacters = FALSE) + +/* macros for controlling the display of the entire match list */ +#define EnableMatchDisplay() (DisplayMatchList = TRUE) +#define DisableMatchDisplay() (DisplayMatchList = FALSE) + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +void LearnBlob(const FEATURE_DEFS_STRUCT &FeatureDefs, const STRING& filename, + TBLOB * Blob, const DENORM& bl_denorm, const DENORM& cn_denorm, + const INT_FX_RESULT_STRUCT& fx_info, + const char* BlobText); + +void LearnBlob(const FEATURE_DEFS_STRUCT &FeatureDefs, FILE* File, TBLOB* Blob, + const DENORM& bl_denorm, const DENORM& cn_denorm, + const INT_FX_RESULT_STRUCT& fx_info, + const char* BlobText, const char* FontName); + +/**---------------------------------------------------------------------------- + Global Data Definitions and Declarations +----------------------------------------------------------------------------**/ +/*parameter used to turn on/off output of recognized chars to the screen */ +#endif diff --git a/TesseractOCR/include/tesseract/blobgrid.h b/TesseractOCR/include/tesseract/blobgrid.h new file mode 100644 index 00000000..dc52be15 --- /dev/null +++ b/TesseractOCR/include/tesseract/blobgrid.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////// +// File: blobgrid.h +// Description: BBGrid of BLOBNBOX with useful BLOBNBOX-specific methods. +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +// Created: Sat Jun 11 10:26:01 PST 2011 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + + +#ifndef TESSERACT_TEXTORD_BLOBGRID_H_ +#define TESSERACT_TEXTORD_BLOBGRID_H_ + +#include "bbgrid.h" +#include "blobbox.h" + +CLISTIZEH(BLOBNBOX) + +namespace tesseract { + +typedef GridSearch BlobGridSearch; + +class BlobGrid : public BBGrid { + public: + BlobGrid(int gridsize, const ICOORD& bleft, const ICOORD& tright); + virtual ~BlobGrid(); + + // Inserts all the blobs from the given list, with x and y spreading, + // without removing from the source list, so ownership remains with the + // source list. + void InsertBlobList(BLOBNBOX_LIST* blobs); +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_BLOBGRID_H_ diff --git a/TesseractOCR/include/tesseract/blobs.h b/TesseractOCR/include/tesseract/blobs.h old mode 100755 new mode 100644 index 60ee48a8..e39761b1 --- a/TesseractOCR/include/tesseract/blobs.h +++ b/TesseractOCR/include/tesseract/blobs.h @@ -30,12 +30,15 @@ I n c l u d e s ----------------------------------------------------------------------*/ #include "clst.h" +#include "normalis.h" +#include "publictypes.h" #include "rect.h" #include "vecfuncs.h" class BLOCK; class C_BLOB; -class DENORM; +class C_OUTLINE; +class LLSQ; class ROW; class WERD; @@ -44,12 +47,6 @@ class WERD; ----------------------------------------------------------------------*/ #define EDGEPTFLAGS 4 /*concavity,length etc. */ -typedef struct -{ /* Widths of pieces */ - int num_chars; - int widths[1]; -} WIDTH_RECORD; - struct TPOINT { TPOINT(): x(0), y(0) {} TPOINT(inT16 vx, inT16 vy) : x(vx), y(vy) {} @@ -70,7 +67,8 @@ struct TPOINT { typedef TPOINT VECTOR; // structure for coordinates. struct EDGEPT { - EDGEPT() : next(NULL), prev(NULL) { + EDGEPT() + : next(NULL), prev(NULL), src_outline(NULL), start_step(0), step_count(0) { memset(flags, 0, EDGEPTFLAGS * sizeof(flags[0])); } EDGEPT(const EDGEPT& src) : next(NULL), prev(NULL) { @@ -85,6 +83,9 @@ struct EDGEPT { pos = src.pos; vec = src.vec; memcpy(flags, src.flags, EDGEPTFLAGS * sizeof(flags[0])); + src_outline = src.src_outline; + start_step = src.start_step; + step_count = src.step_count; } // Accessors to hide or reveal a cut edge from feature extractors. void Hide() { @@ -96,6 +97,15 @@ struct EDGEPT { bool IsHidden() const { return flags[0] != 0; } + void MarkChop() { + flags[2] = true; + } + void UnmarkChop() { + flags[2] = false; + } + bool IsChopPt() const { + return flags[2] != 0; + } TPOINT pos; // position VECTOR vec; // vector to next point @@ -105,6 +115,10 @@ struct EDGEPT { char flags[EDGEPTFLAGS]; // concavity, length etc EDGEPT* next; // anticlockwise element EDGEPT* prev; // clockwise element + C_OUTLINE* src_outline; // Outline it came from. + // The following fields are not used if src_outline is NULL. + int start_step; // Location of pos in src_outline. + int step_count; // Number of steps used (may wrap around). }; // For use in chop and findseam to keep a list of which EDGEPTs were inserted. @@ -159,6 +173,11 @@ struct TESSLINE { ScrollView::Color child_color); #endif // GRAPHICS_DISABLED + // Returns the first outline point that has a different src_outline to its + // predecessor, or, if all the same, the lowest indexed point. + EDGEPT* FindBestStartPt() const; + + int BBArea() const { return (botright.x - topleft.x) * (topleft.y - botright.y); } @@ -172,8 +191,8 @@ struct TESSLINE { }; // Outline structure. struct TBLOB { - TBLOB() : outlines(NULL), next(NULL) {} - TBLOB(const TBLOB& src) : outlines(NULL), next(NULL) { + TBLOB() : outlines(NULL) {} + TBLOB(const TBLOB& src) : outlines(NULL) { CopyFrom(src); } ~TBLOB() { @@ -183,21 +202,34 @@ struct TBLOB { CopyFrom(src); return *this; } - // Factory to build a TBLOB from a C_BLOB with polygonal - // approximation along the way. - static TBLOB* PolygonalCopy(C_BLOB* src); + // Factory to build a TBLOB from a C_BLOB with polygonal approximation along + // the way. If allow_detailed_fx is true, the EDGEPTs in the returned TBLOB + // contain pointers to the input C_OUTLINEs that enable higher-resolution + // feature extraction that does not use the polygonal approximation. + static TBLOB* PolygonalCopy(bool allow_detailed_fx, C_BLOB* src); + // Factory builds a blob with no outlines, but copies the other member data. + static TBLOB* ShallowCopy(const TBLOB& src); // Normalizes the blob for classification only if needed. // (Normally this means a non-zero classify rotation.) - // If no Normalization is needed, then NULL is returned, and the denorm is - // unchanged. Otherwise a new TBLOB is returned and the denorm points to - // a new DENORM. In this case, both the TBLOB and DENORM must be deleted. - TBLOB* ClassifyNormalizeIfNeeded(const DENORM** denorm) const; + // If no Normalization is needed, then NULL is returned, and the input blob + // can be used directly. Otherwise a new TBLOB is returned which must be + // deleted after use. + TBLOB* ClassifyNormalizeIfNeeded() const; + // Copies the data and the outlines, but leaves next untouched. void CopyFrom(const TBLOB& src); // Deletes owned data. void Clear(); - // Normalize in-place using the DENORM. - void Normalize(const DENORM& denorm); + // Sets up the built-in DENORM and normalizes the blob in-place. + // For parameters see DENORM::SetupNormalization, plus the inverse flag for + // this blob and the Pix for the full image. + void Normalize(const BLOCK* block, + const FCOORD* rotation, + const DENORM* predecessor, + float x_origin, float y_origin, + float x_scale, float y_scale, + float final_xshift, float final_yshift, + bool inverse, Pix* pix); // Rotates by the given rotation in place. void Rotate(const FCOORD rotation); // Moves by the given vec in place. @@ -212,6 +244,10 @@ struct TBLOB { TBOX bounding_box() const; + const DENORM& denorm() const { + return denorm_; + } + #ifndef GRAPHICS_DISABLED void plot(ScrollView* window, ScrollView::Color color, ScrollView::Color child_color); @@ -224,15 +260,48 @@ struct TBLOB { return total_area; } + // Computes the center of mass and second moments for the old baseline and + // 2nd moment normalizations. Returns the outline length. + // The input denorm should be the normalizations that have been applied from + // the image to the current state of this TBLOB. + int ComputeMoments(FCOORD* center, FCOORD* second_moments) const; + // Computes the precise bounding box of the coords that are generated by + // GetEdgeCoords. This may be different from the bounding box of the polygon. + void GetPreciseBoundingBox(TBOX* precise_box) const; + // Adds edges to the given vectors. + // For all the edge steps in all the outlines, or polygonal approximation + // where there are no edge steps, collects the steps into x_coords/y_coords. + // x_coords is a collection of the x-coords of vertical edges for each + // y-coord starting at box.bottom(). + // y_coords is a collection of the y-coords of horizontal edges for each + // x-coord starting at box.left(). + // Eg x_coords[0] is a collection of the x-coords of edges at y=bottom. + // Eg x_coords[1] is a collection of the x-coords of edges at y=bottom + 1. + void GetEdgeCoords(const TBOX& box, + GenericVector >* x_coords, + GenericVector >* y_coords) const; + TESSLINE *outlines; // List of outlines in blob. - TBLOB *next; // Next blob in block. -}; // Blob structure. -int count_blobs(TBLOB *blobs); + private: // TODO(rays) Someday the data members will be private too. + // For all the edge steps in all the outlines, or polygonal approximation + // where there are no edge steps, collects the steps into the bounding_box, + // llsq and/or the x_coords/y_coords. Both are used in different kinds of + // normalization. + // For a description of x_coords, y_coords, see GetEdgeCoords above. + void CollectEdges(const TBOX& box, + TBOX* bounding_box, LLSQ* llsq, + GenericVector >* x_coords, + GenericVector >* y_coords) const; + + private: + // DENORM indicating the transformations that this blob has undergone so far. + DENORM denorm_; +}; // Blob structure. struct TWERD { - TWERD() : blobs(NULL), latin_script(false), next(NULL) {} - TWERD(const TWERD& src) : blobs(NULL), next(NULL) { + TWERD() : latin_script(false) {} + TWERD(const TWERD& src) { CopyFrom(src); } ~TWERD() { @@ -244,14 +313,14 @@ struct TWERD { } // Factory to build a TWERD from a (C_BLOB) WERD, with polygonal // approximation along the way. - static TWERD* PolygonalCopy(WERD* src); - // Setup for Baseline normalization, recording the normalization in the - // DENORM, but doesn't do any normalization. - void SetupBLNormalize(const BLOCK* block, const ROW* row, - float x_height, bool numeric_mode, - DENORM* denorm) const; - // Normalize in-place using the DENORM. - void Normalize(const DENORM& denorm); + static TWERD* PolygonalCopy(bool allow_detailed_fx, WERD* src); + // Baseline normalizes the blobs in-place, recording the normalization in the + // DENORMs in the blobs. + void BLNormalize(const BLOCK* block, const ROW* row, Pix* pix, bool inverse, + float x_height, bool numeric_mode, + tesseract::OcrEngineMode hint, + const TBOX* norm_box, + DENORM* word_denorm); // Copies the data and the blobs, but leaves next untouched. void CopyFrom(const TWERD& src); // Deletes owned data. @@ -261,7 +330,7 @@ struct TWERD { // Returns the number of blobs in the word. int NumBlobs() const { - return count_blobs(blobs); + return blobs.size(); } TBOX bounding_box() const; @@ -271,9 +340,8 @@ struct TWERD { void plot(ScrollView* window); - TBLOB* blobs; // blobs in word. + GenericVector blobs; // Blobs in word. bool latin_script; // This word is in a latin-based script. - TWERD* next; // next word. }; /*---------------------------------------------------------------------- @@ -296,9 +364,6 @@ if (w) memfree (w) // Returns the center of blob's bounding box in origin. void blob_origin(TBLOB *blob, TPOINT *origin); - /*blob to compute on */ -WIDTH_RECORD *blobs_widths(TBLOB *blobs); - bool divisible_blob(TBLOB *blob, bool italic_blob, TPOINT* location); void divide_blobs(TBLOB *blob, TBLOB *other_blob, bool italic_blob, diff --git a/TesseractOCR/include/tesseract/blread.h b/TesseractOCR/include/tesseract/blread.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/bmp_8.h b/TesseractOCR/include/tesseract/bmp_8.h new file mode 100644 index 00000000..7200d7da --- /dev/null +++ b/TesseractOCR/include/tesseract/bmp_8.h @@ -0,0 +1,122 @@ +/********************************************************************** + * File: bmp_8.h + * Description: Declaration of an 8-bit Bitmap class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef BMP8_H +#define BMP8_H + +// The Bmp8 class is an 8-bit bitmap that represents images of +// words, characters and segments throughout Cube +// It is meant to provide fast access to the bitmap bits and provide +// fast scaling, cropping, deslanting, connected components detection, +// loading and saving functionality + +#include +#include +#include "con_comp.h" +#include "cached_file.h" + +namespace tesseract { + +// Non-integral deslanting parameters. +static const float kMinDeslantAngle = -30.0f; +static const float kMaxDeslantAngle = 30.0f; +static const float kDeslantAngleDelta = 0.5f; + +class Bmp8 { + public: + Bmp8(unsigned short wid, unsigned short hgt); + ~Bmp8(); + // Clears the bitmap + bool Clear(); + // accessors to bitmap dimensions + inline unsigned short Width() const { return wid_; } + inline unsigned short Stride() const { return stride_; } + inline unsigned short Height() const { return hgt_; } + inline unsigned char *RawData() const { + return (line_buff_ == NULL ? NULL : line_buff_[0]); + } + // creates a scaled version of the specified bitmap + // Optionally, scaling can be isotropic (preserving aspect ratio) or not + bool ScaleFrom(Bmp8 *bmp, bool isotropic = true); + // Deslant the bitmap vertically + bool Deslant(); + // Deslant the bitmap horizontally + bool HorizontalDeslant(double *deslant_angle); + // Create a bitmap object from a file + static Bmp8 *FromCharDumpFile(CachedFile *fp); + static Bmp8 *FromCharDumpFile(FILE *fp); + // are two bitmaps identical + bool IsIdentical(Bmp8 *pBmp) const; + // Detect connected components + ConComp ** FindConComps(int *concomp_cnt, int min_size) const; + // compute the foreground ratio + float ForegroundRatio() const; + // returns the mean horizontal histogram entropy of the bitmap + float MeanHorizontalHistogramEntropy() const; + // returns the horizontal histogram of the bitmap + int *HorizontalHistogram() const; + + private: + // Compute a look up tan table that will be used for fast slant computation + static bool ComputeTanTable(); + // create a bitmap buffer (two flavors char & int) and init contents + unsigned char ** CreateBmpBuffer(unsigned char init_val = 0xff); + static unsigned int ** CreateBmpBuffer(int wid, int hgt, + unsigned char init_val = 0xff); + // Free a bitmap buffer + static void FreeBmpBuffer(unsigned char **buff); + static void FreeBmpBuffer(unsigned int **buff); + + // a static array that holds the tan lookup table + static float *tan_table_; + // bitmap 32-bit-aligned stride + unsigned short stride_; + // Bmp8 magic number used to validate saved bitmaps + static const unsigned int kMagicNumber = 0xdeadbeef; + + protected: + // bitmap dimensions + unsigned short wid_; + unsigned short hgt_; + // bitmap contents + unsigned char **line_buff_; + // deslanting parameters + static const int kConCompAllocChunk = 16; + static const int kDeslantAngleCount; + + // Load dimensions & contents of bitmap from file + bool LoadFromCharDumpFile(CachedFile *fp); + bool LoadFromCharDumpFile(FILE *fp); + // Load dimensions & contents of bitmap from raw data + bool LoadFromCharDumpFile(unsigned char **raw_data); + // Load contents of bitmap from raw data + bool LoadFromRawData(unsigned char *data); + // save bitmap to a file + bool SaveBmp2CharDumpFile(FILE *fp) const; + // checks if a row or a column are entirely blank + bool IsBlankColumn(int x) const; + bool IsBlankRow(int y) const; + // crop the bitmap returning new dimensions + void Crop(int *xst_src, int *yst_src, int *wid, int *hgt); + // copy part of the specified bitmap + void Copy(int x, int y, int wid, int hgt, Bmp8 *bmp_dest) const; +}; +} + +#endif // BMP8_H diff --git a/TesseractOCR/include/tesseract/boxchar.h b/TesseractOCR/include/tesseract/boxchar.h new file mode 100644 index 00000000..bcb102ce --- /dev/null +++ b/TesseractOCR/include/tesseract/boxchar.h @@ -0,0 +1,84 @@ +/********************************************************************** + * File: boxchar.h + * Description: Simple class to associate a Tesseract classification unit with + * its bounding box so that the boxes can be rotated as the image + * is rotated for degradation. Also includes routines to output + * the character-tagged boxes to a boxfile. + * Author: Ray Smith + * Created: Mon Nov 18 2013 + * + * (C) Copyright 2013, Google Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + **********************************************************************/ + +#ifndef TESSERACT_TRAINING_BOXCHAR_H_ +#define TESSERACT_TRAINING_BOXCHAR_H_ + +#include +#include + +#include "allheaders.h" // from Leptonica + +#ifdef USE_STD_NAMESPACE +using std::string; +using std::vector; +#endif + +struct Box; + +namespace tesseract { + +class BoxChar { + public: + BoxChar(const char* utf8_str, int len); + + ~BoxChar(); + + // Accessors. + const string& ch() const { return ch_; } + const Box* box() const { return box_; } + const int& page() const { return page_; } + + + // Set the box_ member. + void AddBox(int x, int y, int width, int height); + + void set_page(int page) { page_ = page; } + + string* mutable_ch() { return &ch_; } + Box* mutable_box() { return box_; } + + static void TranslateBoxes(int xshift, int yshift, + vector* boxes); + + // Rotate the vector of boxes between start and end by the given rotation. + // The rotation is in radians clockwise about the given center. + static void RotateBoxes(float rotation, + int xcenter, + int ycenter, + int start_box, + int end_box, + vector* boxes); + + // Create a tesseract box file from the vector of boxes. The image height + // is needed to convert to tesseract coordinates. + static void WriteTesseractBoxFile(const string& name, int height, + const vector& boxes); + + private: + string ch_; + Box* box_; + int page_; +}; +} // namespace tesseract + +#endif // TESSERACT_TRAINING_BOXCHAR_H_ diff --git a/TesseractOCR/include/tesseract/boxread.h b/TesseractOCR/include/tesseract/boxread.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/boxword.h b/TesseractOCR/include/tesseract/boxword.h old mode 100755 new mode 100644 index bab2d7ee..c8495b59 --- a/TesseractOCR/include/tesseract/boxword.h +++ b/TesseractOCR/include/tesseract/boxword.h @@ -22,10 +22,10 @@ #include "genericvector.h" #include "rect.h" +#include "unichar.h" class BLOCK; class DENORM; -class PBLOB_LIST; struct TWERD; class UNICHARSET; class WERD; @@ -34,14 +34,6 @@ class WERD_RES; namespace tesseract { -// ScriptPos tells whether a character is subscript, superscript or normal. -enum ScriptPos { - SP_NORMAL, - SP_SUBSCRIPT, - SP_SUPERSCRIPT, - SP_DROPCAP -}; - // Class to hold an array of bounding boxes for an output word and // the bounding box of the whole word. class BoxWord { @@ -54,19 +46,9 @@ class BoxWord { void CopyFrom(const BoxWord& src); - // Factory to build a BoxWord from a TWERD and the DENORM to switch - // back to original image coordinates. - // If the denorm is not NULL, then the output is denormalized and rotated - // back to the original image coordinates. - static BoxWord* CopyFromNormalized(const DENORM* denorm, - TWERD* tessword); - - // Sets up the script_pos_ member using the tessword to get the bln - // bounding boxes, the best_choice to get the unichars, and the unicharset - // to get the target positions. If small_caps is true, sub/super are not - // considered, but dropcaps are. - void SetScriptPositions(const UNICHARSET& unicharset, bool small_caps, - TWERD* tessword, WERD_CHOICE* best_choice); + // Factory to build a BoxWord from a TWERD using the DENORMs on each blob to + // switch back to original image coordinates. + static BoxWord* CopyFromNormalized(TWERD* tessword); // Clean up the bounding boxes from the polygonal approximation by // expanding slightly, then clipping to the blobs from the original_word @@ -102,11 +84,6 @@ class BoxWord { const TBOX& BlobBox(int index) const { return boxes_[index]; } - ScriptPos BlobPosition(int index) const { - if (index < 0 || index >= script_pos_.size()) - return SP_NORMAL; - return script_pos_[index]; - } private: void ComputeBoundingBox(); @@ -114,7 +91,6 @@ class BoxWord { TBOX bbox_; int length_; GenericVector boxes_; - GenericVector script_pos_; }; } // namespace tesseract. diff --git a/TesseractOCR/include/tesseract/cached_file.h b/TesseractOCR/include/tesseract/cached_file.h new file mode 100644 index 00000000..eb671970 --- /dev/null +++ b/TesseractOCR/include/tesseract/cached_file.h @@ -0,0 +1,69 @@ +/********************************************************************** + * File: cached_file.h + * Description: Declaration of a Cached File class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef CACHED_FILE_H +#define CACHED_FILE_H + +// The CachedFile class provides a large-cache read access to a file +// It is mainly designed for loading large word dump files + +#include +#include +#ifdef USE_STD_NAMESPACE +using std::string; +#endif + +namespace tesseract { +class CachedFile { + public: + explicit CachedFile(string file_name); + ~CachedFile(); + + // reads a specified number of bytes to the specified buffer and + // returns the actual number of bytes read + int Read(void *read_buff, int bytes); + // Returns the file size + long Size(); + // returns the current position in the file + long Tell(); + // End of file flag + bool eof(); + + private: + static const unsigned int kCacheSize = 0x8000000; + // file name + string file_name_; + // internal file buffer + unsigned char *buff_; + // file position + long file_pos_; + // file size + long file_size_; + // position of file within buffer + int buff_pos_; + // buffer size + int buff_size_; + // file handle + FILE *fp_; + // Opens the file + bool Open(); +}; +} + +#endif // CACHED_FILE_H diff --git a/TesseractOCR/include/tesseract/callcpp.h b/TesseractOCR/include/tesseract/callcpp.h new file mode 100644 index 00000000..2ddf0b08 --- /dev/null +++ b/TesseractOCR/include/tesseract/callcpp.h @@ -0,0 +1,116 @@ +/********************************************************************** + * File: callcpp.h + * Description: extern C interface calling C++ from C. + * Author: Ray Smith + * Created: Sun Feb 04 20:39:23 MST 1996 + * + * (C) Copyright 1996, Hewlett-Packard Co. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef CALLCPP_H +#define CALLCPP_H + +#ifndef __UNIX__ +#include +#endif +#include "host.h" +#include "params.h" +#include "unichar.h" + +class ScrollView; + +typedef enum { + Black, + White, + Red, + Yellow, + Green, + Cyan, + Blue, + Magenta, + Aquamarine, + Dark_SLATE_BLUE, + Light_BLUE, + Medium_BLUE, + Midnight_BLUE, + Navy_BLUE, + Sky_BLUE, + Slate_BLUE, + Steel_BLUE, + Coral, + Brown, + Sandy_BROWN, + Gold, + GoldENROD, + Dark_GREEN, + Dark_OLIVE_GREEN, + Forest_GREEN, + Lime_GREEN, + Pale_GREEN, + Yellow_GREEN, + Light_GREY, + Dark_SLATE_GREY, + Dim_GREY, + Grey, + Khaki, + Maroon, + Orange, + Orchid, + Pink, + Plum, + Indian_RED, + Orange_RED, + Violet_RED, + Salmon, + Tan, + Turqoise, + Dark_TURQUOISE, + Violet, + Wheat, + Green_YELLOW +} C_COL; /*starbase colours */ + +void cprintf ( //Trace printf +const char *format, ... //special message +); +ScrollView *c_create_window( /*create a window */ + const char *name, /*name/title of window */ + inT16 xpos, /*coords of window */ + inT16 ypos, /*coords of window */ + inT16 xsize, /*size of window */ + inT16 ysize, /*size of window */ + double xmin, /*scrolling limits */ + double xmax, /*to stop users */ + double ymin, /*getting lost in */ + double ymax /*empty space */ + ); +void c_line_color_index( /*set color */ + void *win, + C_COL index); +void c_move( /*move pen */ + void *win, + double x, + double y); +void c_draw( /*move pen */ + void *win, + double x, + double y); +void c_make_current( /*move pen */ + void *win); +void c_clear_window( /*move pen */ + void *win); +char window_wait(ScrollView* win); +void reverse32(void *ptr); +void reverse16(void *ptr); + +#endif diff --git a/TesseractOCR/include/tesseract/capi.h b/TesseractOCR/include/tesseract/capi.h old mode 100755 new mode 100644 index 4c8a95be..73f9994c --- a/TesseractOCR/include/tesseract/capi.h +++ b/TesseractOCR/include/tesseract/capi.h @@ -5,6 +5,7 @@ # include "baseapi.h" # include "pageiterator.h" # include "resultiterator.h" +# include "renderer.h" #else # include "platform.h" # include @@ -29,6 +30,12 @@ extern "C" { #endif #ifdef TESS_CAPI_INCLUDE_BASEAPI +typedef tesseract::TessResultRenderer TessResultRenderer; +typedef tesseract::TessTextRenderer TessTextRenderer; +typedef tesseract::TessHOcrRenderer TessHOcrRenderer; +typedef tesseract::TessPDFRenderer TessPDFRenderer; +typedef tesseract::TessUnlvRenderer TessUnlvRenderer; +typedef tesseract::TessBoxTextRenderer TessBoxTextRenderer; typedef tesseract::TessBaseAPI TessBaseAPI; typedef tesseract::PageIterator TessPageIterator; typedef tesseract::ResultIterator TessResultIterator; @@ -39,6 +46,7 @@ typedef tesseract::ImageThresholder TessImageThresholder; typedef tesseract::PageIteratorLevel TessPageIteratorLevel; typedef tesseract::DictFunc TessDictFunc; typedef tesseract::ProbabilityInContextFunc TessProbabilityInContextFunc; +// typedef tesseract::ParamsModelClassifyFunc TessParamsModelClassifyFunc; typedef tesseract::FillLatticeFunc TessFillLatticeFunc; typedef tesseract::Dawg TessDawg; typedef tesseract::TruthCallback TessTruthCallback; @@ -47,17 +55,21 @@ typedef tesseract::Orientation TessOrientation; typedef tesseract::WritingDirection TessWritingDirection; typedef tesseract::TextlineOrder TessTextlineOrder; typedef PolyBlockType TessPolyBlockType; -typedef Pix PIX; -typedef Boxa BOXA; -typedef Pixa PIXA; #else +typedef struct TessResultRenderer TessResultRenderer; +typedef struct TessTextRenderer TessTextRenderer; +typedef struct TessHOcrRenderer TessHOcrRenderer; +typedef struct TessPDFRenderer TessPDFRenderer; +typedef struct TessUnlvRenderer TessUnlvRenderer; +typedef struct TessBoxTextRenderer TessBoxTextRenderer; typedef struct TessBaseAPI TessBaseAPI; typedef struct TessPageIterator TessPageIterator; typedef struct TessResultIterator TessResultIterator; typedef struct TessMutableIterator TessMutableIterator; typedef enum TessOcrEngineMode { OEM_TESSERACT_ONLY, OEM_CUBE_ONLY, OEM_TESSERACT_CUBE_COMBINED, OEM_DEFAULT } TessOcrEngineMode; typedef enum TessPageSegMode { PSM_OSD_ONLY, PSM_AUTO_OSD, PSM_AUTO_ONLY, PSM_AUTO, PSM_SINGLE_COLUMN, PSM_SINGLE_BLOCK_VERT_TEXT, - PSM_SINGLE_BLOCK, PSM_SINGLE_LINE, PSM_SINGLE_WORD, PSM_CIRCLE_WORD, PSM_SINGLE_CHAR, PSM_COUNT } TessPageSegMode; + PSM_SINGLE_BLOCK, PSM_SINGLE_LINE, PSM_SINGLE_WORD, PSM_CIRCLE_WORD, PSM_SINGLE_CHAR, PSM_SPARSE_TEXT, + PSM_SPARSE_TEXT_OSD, PSM_COUNT } TessPageSegMode; typedef enum TessPageIteratorLevel { RIL_BLOCK, RIL_PARA, RIL_TEXTLINE, RIL_WORD, RIL_SYMBOL} TessPageIteratorLevel; typedef enum TessPolyBlockType { PT_UNKNOWN, PT_FLOWING_TEXT, PT_HEADING_TEXT, PT_PULLOUT_TEXT, PT_TABLE, PT_VERTICAL_TEXT, PT_CAPTION_TEXT, PT_FLOWING_IMAGE, PT_HEADING_IMAGE, PT_PULLOUT_IMAGE, PT_HORZ_LINE, PT_VERT_LINE, @@ -66,11 +78,12 @@ typedef enum TessOrientation { ORIENTATION_PAGE_UP, ORIENTATION_PAGE_RIGHT typedef enum TessWritingDirection { WRITING_DIRECTION_LEFT_TO_RIGHT, WRITING_DIRECTION_RIGHT_TO_LEFT, WRITING_DIRECTION_TOP_TO_BOTTOM } TessWritingDirection; typedef enum TessTextlineOrder { TEXTLINE_ORDER_LEFT_TO_RIGHT, TEXTLINE_ORDER_RIGHT_TO_LEFT, TEXTLINE_ORDER_TOP_TO_BOTTOM } TessTextlineOrder; typedef struct ETEXT_DESC ETEXT_DESC; -typedef struct Pix PIX; -typedef struct Boxa BOXA; -typedef struct Pixa PIXA; #endif +struct Pix; +struct Boxa; +struct Pixa; + /* General free functions */ TESS_API const char* @@ -82,13 +95,45 @@ TESS_API void TESS_CALL TessDeleteIntArray(int* arr); TESS_API void TESS_CALL TessDeleteBlockList(BLOCK_LIST* block_list); #endif +/* Renderer API */ +TESS_API TessResultRenderer* TESS_CALL TessTextRendererCreate(); +TESS_API TessResultRenderer* TESS_CALL TessHOcrRendererCreate(); +TESS_API TessResultRenderer* TESS_CALL TessPDFRendererCreate(const char* datadir); +TESS_API TessResultRenderer* TESS_CALL TessUnlvRendererCreate(); +TESS_API TessResultRenderer* TESS_CALL TessBoxTextRendererCreate(); + +TESS_API void TESS_CALL TessDeleteResultRenderer(TessResultRenderer* renderer); +TESS_API void TESS_CALL TessResultRendererInsert(TessResultRenderer* renderer, TessResultRenderer* next); +TESS_API TessResultRenderer* + TESS_CALL TessResultRendererNext(TessResultRenderer* renderer); +TESS_API BOOL TESS_CALL TessResultRendererBeginDocument(TessResultRenderer* renderer, const char* title); +TESS_API BOOL TESS_CALL TessResultRendererAddImage(TessResultRenderer* renderer, TessBaseAPI* api); +TESS_API BOOL TESS_CALL TessResultRendererAddError(TessResultRenderer* renderer, TessBaseAPI* api); +TESS_API BOOL TESS_CALL TessResultRendererEndDocument(TessResultRenderer* renderer); +TESS_API BOOL TESS_CALL TessResultRendererGetOutput(TessResultRenderer* renderer, const char** data, int* data_len); + +TESS_API const char* TESS_CALL TessResultRendererTypename(TessResultRenderer* renderer); +TESS_API const char* TESS_CALL TessResultRendererExtention(TessResultRenderer* renderer); +TESS_API const char* TESS_CALL TessResultRendererTitle(TessResultRenderer* renderer); +TESS_API int TESS_CALL TessResultRendererImageNum(TessResultRenderer* renderer); + /* Base API */ TESS_API TessBaseAPI* TESS_CALL TessBaseAPICreate(); TESS_API void TESS_CALL TessBaseAPIDelete(TessBaseAPI* handle); +TESS_API size_t TESS_CALL TessBaseAPIGetOpenCLDevice(TessBaseAPI* handle, void **device); + TESS_API void TESS_CALL TessBaseAPISetInputName( TessBaseAPI* handle, const char* name); +TESS_API const char* TESS_CALL TessBaseAPIGetInputName(TessBaseAPI* handle); + +TESS_API void TESS_CALL TessBaseAPISetInputImage(TessBaseAPI* handle, struct Pix* pix); +TESS_API struct Pix* TESS_CALL TessBaseAPIGetInputImage(TessBaseAPI* handle); + +TESS_API int TESS_CALL TessBaseAPIGetSourceYResolution(TessBaseAPI* handle); +TESS_API const char* TESS_CALL TessBaseAPIGetDatapath(TessBaseAPI* handle); + TESS_API void TESS_CALL TessBaseAPISetOutputName(TessBaseAPI* handle, const char* name); TESS_API BOOL TESS_CALL TessBaseAPISetVariable(TessBaseAPI* handle, const char* name, const char* value); @@ -117,6 +162,11 @@ TESS_API int TESS_CALL TessBaseAPIInit1(TessBaseAPI* handle, const char* datap TESS_API int TESS_CALL TessBaseAPIInit2(TessBaseAPI* handle, const char* datapath, const char* language, TessOcrEngineMode oem); TESS_API int TESS_CALL TessBaseAPIInit3(TessBaseAPI* handle, const char* datapath, const char* language); +TESS_API int TESS_CALL TessBaseAPIInit4(TessBaseAPI* handle, const char* datapath, const char* language, TessOcrEngineMode mode, + char** configs, int configs_size, + char** vars_vec, char** vars_values, size_t vars_vec_size, + BOOL set_only_non_debug_params); + TESS_API const char* TESS_CALL TessBaseAPIGetInitLanguagesAsString(const TessBaseAPI* handle); TESS_API char** @@ -142,7 +192,7 @@ TESS_API void TESS_CALL TessBaseAPIClearAdaptiveClassifier(TessBaseAPI* handle) TESS_API void TESS_CALL TessBaseAPISetImage(TessBaseAPI* handle, const unsigned char* imagedata, int width, int height, int bytes_per_pixel, int bytes_per_line); -TESS_API void TESS_CALL TessBaseAPISetImage2(TessBaseAPI* handle, const PIX* pix); +TESS_API void TESS_CALL TessBaseAPISetImage2(TessBaseAPI* handle, const struct Pix* pix); TESS_API void TESS_CALL TessBaseAPISetSourceResolution(TessBaseAPI* handle, int ppi); @@ -152,13 +202,28 @@ TESS_API void TESS_CALL TessBaseAPISetRectangle(TessBaseAPI* handle, int left, TESS_API void TESS_CALL TessBaseAPISetThresholder(TessBaseAPI* handle, TessImageThresholder* thresholder); #endif -TESS_API PIX* TESS_CALL TessBaseAPIGetThresholdedImage( TessBaseAPI* handle); -TESS_API BOXA* TESS_CALL TessBaseAPIGetRegions( TessBaseAPI* handle, PIXA** pixa); -TESS_API BOXA* TESS_CALL TessBaseAPIGetTextlines( TessBaseAPI* handle, PIXA** pixa, int** blockids); -TESS_API BOXA* TESS_CALL TessBaseAPIGetStrips( TessBaseAPI* handle, PIXA** pixa, int** blockids); -TESS_API BOXA* TESS_CALL TessBaseAPIGetWords( TessBaseAPI* handle, PIXA** pixa); -TESS_API BOXA* TESS_CALL TessBaseAPIGetConnectedComponents(TessBaseAPI* handle, PIXA** cc); -TESS_API BOXA* TESS_CALL TessBaseAPIGetComponentImages( TessBaseAPI* handle, TessPageIteratorLevel level, BOOL text_only, PIXA** pixa, int** blockids); +TESS_API struct Pix* + TESS_CALL TessBaseAPIGetThresholdedImage( TessBaseAPI* handle); +TESS_API struct Boxa* + TESS_CALL TessBaseAPIGetRegions( TessBaseAPI* handle, struct Pixa** pixa); +TESS_API struct Boxa* + TESS_CALL TessBaseAPIGetTextlines( TessBaseAPI* handle, struct Pixa** pixa, int** blockids); +TESS_API struct Boxa* + TESS_CALL TessBaseAPIGetTextlines1( TessBaseAPI* handle, const BOOL raw_image, const int raw_padding, + struct Pixa** pixa, int** blockids, int** paraids); +TESS_API struct Boxa* + TESS_CALL TessBaseAPIGetStrips( TessBaseAPI* handle, struct Pixa** pixa, int** blockids); +TESS_API struct Boxa* + TESS_CALL TessBaseAPIGetWords( TessBaseAPI* handle, struct Pixa** pixa); +TESS_API struct Boxa* + TESS_CALL TessBaseAPIGetConnectedComponents(TessBaseAPI* handle, struct Pixa** cc); +TESS_API struct Boxa* + TESS_CALL TessBaseAPIGetComponentImages( TessBaseAPI* handle, const TessPageIteratorLevel level, const BOOL text_only, + struct Pixa** pixa, int** blockids); +TESS_API struct Boxa* + TESS_CALL TessBaseAPIGetComponentImages1( TessBaseAPI* handle, const TessPageIteratorLevel level, const BOOL text_only, + const BOOL raw_image, const int raw_padding, + struct Pixa** pixa, int** blockids, int** paraids); TESS_API int TESS_CALL TessBaseAPIGetThresholdedImageScaleFactor(const TessBaseAPI* handle); @@ -171,8 +236,12 @@ TESS_API int TESS_CALL TessBaseAPIRecognize(TessBaseAPI* handle, ETEXT_DESC* m TESS_API int TESS_CALL TessBaseAPIRecognizeForChopTest(TessBaseAPI* handle, ETEXT_DESC* monitor); TESS_API char* TESS_CALL TessBaseAPIProcessPages(TessBaseAPI* handle, const char* filename, const char* retry_config, int timeout_millisec); -TESS_API char* TESS_CALL TessBaseAPIProcessPage(TessBaseAPI* handle, PIX* pix, int page_index, const char* filename, +TESS_API BOOL TessBaseAPIProcessPages1(TessBaseAPI* handle, const char* filename, const char* retry_config, + int timeout_millisec, TessResultRenderer* renderer); +TESS_API char* TESS_CALL TessBaseAPIProcessPage(TessBaseAPI* handle, struct Pix* pix, int page_index, const char* filename, const char* retry_config, int timeout_millisec); +TESS_API BOOL TessBaseAPIProcessPage1(TessBaseAPI* handle, struct Pix* pix, int page_index, const char* filename, + const char* retry_config, int timeout_millisec, TessResultRenderer* renderer); TESS_API TessResultIterator* TESS_CALL TessBaseAPIGetIterator(TessBaseAPI* handle); @@ -190,20 +259,22 @@ TESS_API BOOL TESS_CALL TessBaseAPIAdaptToWordStr(TessBaseAPI* handle, TessPage TESS_API void TESS_CALL TessBaseAPIClear(TessBaseAPI* handle); TESS_API void TESS_CALL TessBaseAPIEnd(TessBaseAPI* handle); -TESS_API int TESS_CALL TessBaseAPIIsValidWord(TessBaseAPI* handle, const char *word); +TESS_API int TESS_CALL TessBaseAPIIsValidWord(TessBaseAPI* handle, const char* word); TESS_API BOOL TESS_CALL TessBaseAPIGetTextDirection(TessBaseAPI* handle, int* out_offset, float* out_slope); #ifdef TESS_CAPI_INCLUDE_BASEAPI TESS_API void TESS_CALL TessBaseAPISetDictFunc(TessBaseAPI* handle, TessDictFunc f); +TESS_API void TESS_CALL TessBaseAPIClearPersistentCache(TessBaseAPI* handle); TESS_API void TESS_CALL TessBaseAPISetProbabilityInContextFunc(TessBaseAPI* handle, TessProbabilityInContextFunc f); + TESS_API void TESS_CALL TessBaseAPISetFillLatticeFunc(TessBaseAPI* handle, TessFillLatticeFunc f); TESS_API BOOL TESS_CALL TessBaseAPIDetectOS(TessBaseAPI* handle, OSResults* results); -TESS_API void TESS_CALL TessBaseAPIGetFeaturesForBlob(TessBaseAPI* handle, TBLOB* blob, const DENORM* denorm, INT_FEATURE_ARRAY int_features, +TESS_API void TESS_CALL TessBaseAPIGetFeaturesForBlob(TessBaseAPI* handle, TBLOB* blob, INT_FEATURE_STRUCT* int_features, int* num_features, int* FeatureOutlineIndex); TESS_API ROW* TESS_CALL TessFindRowForBox(BLOCK_LIST* blocks, int left, int top, int right, int bottom); -TESS_API void TESS_CALL TessBaseAPIRunAdaptiveClassifier(TessBaseAPI* handle, TBLOB* blob, const DENORM* denorm, int num_max_matches, +TESS_API void TESS_CALL TessBaseAPIRunAdaptiveClassifier(TessBaseAPI* handle, TBLOB* blob, int num_max_matches, int* unichar_ids, float* ratings, int* num_matches_returned); #endif @@ -219,12 +290,12 @@ TESS_API int TESS_CALL TessBaseAPINumDawgs(const TessBaseAPI* handle); #ifdef TESS_CAPI_INCLUDE_BASEAPI TESS_API ROW* TESS_CALL TessMakeTessOCRRow(float baseline, float xheight, float descender, float ascender); TESS_API TBLOB* - TESS_CALL TessMakeTBLOB(Pix *pix); -TESS_API void TESS_CALL TessNormalizeTBLOB(TBLOB *tblob, ROW *row, BOOL numeric_mode, DENORM *denorm); + TESS_CALL TessMakeTBLOB(Pix* pix); +TESS_API void TESS_CALL TessNormalizeTBLOB(TBLOB* tblob, ROW* row, BOOL numeric_mode); TESS_API TessOcrEngineMode TESS_CALL TessBaseAPIOem(const TessBaseAPI* handle); -TESS_API void TESS_CALL TessBaseAPIInitTruthCallback(TessBaseAPI* handle, TessTruthCallback *cb); +TESS_API void TESS_CALL TessBaseAPIInitTruthCallback(TessBaseAPI* handle, TessTruthCallback* cb); TESS_API TessCubeRecoContext* TESS_CALL TessBaseAPIGetCubeRecoContext(const TessBaseAPI* handle); @@ -255,16 +326,18 @@ TESS_API BOOL TESS_CALL TessPageIteratorBoundingBox(const TessPageIterator* han TESS_API TessPolyBlockType TESS_CALL TessPageIteratorBlockType(const TessPageIterator* handle); -TESS_API PIX* TESS_CALL TessPageIteratorGetBinaryImage(const TessPageIterator* handle, TessPageIteratorLevel level); -TESS_API PIX* TESS_CALL TessPageIteratorGetImage(const TessPageIterator* handle, TessPageIteratorLevel level, int padding, +TESS_API struct Pix* + TESS_CALL TessPageIteratorGetBinaryImage(const TessPageIterator* handle, TessPageIteratorLevel level); +TESS_API struct Pix* + TESS_CALL TessPageIteratorGetImage(const TessPageIterator* handle, TessPageIteratorLevel level, int padding, int* left, int* top); TESS_API BOOL TESS_CALL TessPageIteratorBaseline(const TessPageIterator* handle, TessPageIteratorLevel level, int* x1, int* y1, int* x2, int* y2); -TESS_API void TESS_CALL TessPageIteratorOrientation(TessPageIterator* handle, TessOrientation *orientation, - TessWritingDirection *writing_direction, TessTextlineOrder *textline_order, - float *deskew_angle); +TESS_API void TESS_CALL TessPageIteratorOrientation(TessPageIterator* handle, TessOrientation* orientation, + TessWritingDirection* writing_direction, TessTextlineOrder* textline_order, + float* deskew_angle); /* Result iterator */ diff --git a/TesseractOCR/include/tesseract/ccnontextdetect.h b/TesseractOCR/include/tesseract/ccnontextdetect.h new file mode 100644 index 00000000..6489547f --- /dev/null +++ b/TesseractOCR/include/tesseract/ccnontextdetect.h @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////// +// File: ccnontextdetect.h +// Description: Connected-Component-based non-text detection. +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +// Created: Sat Jun 11 09:52:01 PST 2011 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_CCPHOTODETECT_H_ +#define TESSERACT_TEXTORD_CCPHOTODETECT_H_ + +#include "blobgrid.h" +#include "scrollview.h" + +namespace tesseract { + +// The CCNonTextDetect class contains grid-based operations on blobs to create +// a full-resolution image mask analogous yet complementary to +// pixGenHalftoneMask as it is better at line-drawings, graphs and charts. +class CCNonTextDetect : public BlobGrid { + public: + CCNonTextDetect(int gridsize, const ICOORD& bleft, const ICOORD& tright); + virtual ~CCNonTextDetect(); + + // Creates and returns a Pix with the same resolution as the original + // in which 1 (black) pixels represent likely non text (photo, line drawing) + // areas of the page, deleting from the blob_block the blobs that were + // determined to be non-text. + // The photo_map (binary image mask) is used to bias the decision towards + // non-text, rather than supplying a definite decision. + // The blob_block is the usual result of connected component analysis, + // holding the detected blobs. + // The returned Pix should be PixDestroyed after use. + Pix* ComputeNonTextMask(bool debug, Pix* photo_map, TO_BLOCK* blob_block); + + private: + // Computes and returns the noise_density IntGrid, at the same gridsize as + // this by summing the number of small elements in a 3x3 neighbourhood of + // each grid cell. good_grid is filled with blobs that are considered most + // likely good text, and this is filled with small and medium blobs that are + // more likely non-text. + // The photo_map is used to bias the decision towards non-text, rather than + // supplying definite decision. + IntGrid* ComputeNoiseDensity(bool debug, Pix* photo_map, BlobGrid* good_grid); + + // Tests each blob in the list to see if it is certain non-text using 2 + // conditions: + // 1. blob overlaps a cell with high value in noise_density_ (previously set + // by ComputeNoiseDensity). + // OR 2. The blob overlaps more than max_blob_overlaps in *this grid. This + // condition is disabled with max_blob_overlaps == -1. + // If it does, the blob is declared non-text, and is used to mark up the + // nontext_mask. Such blobs are fully deleted, and non-noise blobs have their + // neighbours reset, as they may now point to deleted data. + // WARNING: The blobs list blobs may be in the *this grid, but they are + // not removed. If any deleted blobs might be in *this, then this must be + // Clear()ed immediately after MarkAndDeleteNonTextBlobs is called. + // If the win is not NULL, deleted blobs are drawn on it in red, and kept + void MarkAndDeleteNonTextBlobs(BLOBNBOX_LIST* blobs, + int max_blob_overlaps, + ScrollView* win, ScrollView::Color ok_color, + Pix* nontext_mask); + // Returns true if the given blob overlaps more than max_overlaps blobs + // in the current grid. + bool BlobOverlapsTooMuch(BLOBNBOX* blob, int max_overlaps); + + // Max entry in noise_density_ before the cell is declared noisy. + int max_noise_count_; + // Completed noise density map, which we keep around to use for secondary + // noise detection. + IntGrid* noise_density_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_CCPHOTODETECT_H_ diff --git a/TesseractOCR/include/tesseract/ccstruct.h b/TesseractOCR/include/tesseract/ccstruct.h old mode 100755 new mode 100644 index 9564c39f..3f92122d --- a/TesseractOCR/include/tesseract/ccstruct.h +++ b/TesseractOCR/include/tesseract/ccstruct.h @@ -20,7 +20,6 @@ #define TESSERACT_CCSTRUCT_CCSTRUCT_H__ #include "cutil.h" -#include "image.h" namespace tesseract { class CCStruct : public CUtil { @@ -36,9 +35,6 @@ class CCStruct : public CUtil { static const double kAscenderFraction; // = 0.25; // Derived value giving the x-height as a fraction of cap-height. static const double kXHeightCapRatio; // = XHeight/(XHeight + Ascender). - - protected: - Image image_; }; class Tesseract; diff --git a/TesseractOCR/include/tesseract/ccutil.h b/TesseractOCR/include/tesseract/ccutil.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/char_altlist.h b/TesseractOCR/include/tesseract/char_altlist.h new file mode 100644 index 00000000..ef3a083a --- /dev/null +++ b/TesseractOCR/include/tesseract/char_altlist.h @@ -0,0 +1,70 @@ +/********************************************************************** + * File: char_altlist.h + * Description: Declaration of a Character Alternate List Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef CHAR_ALT_LIST_H +#define CHAR_ALT_LIST_H + +// The CharAltList class holds the list of class alternates returned from +// a character classifier. Each alternate represents a class ID. +// It inherits from the AltList class. +// The CharAltList owns a CharSet object that maps a class-id to a string. + +#include "altlist.h" +#include "char_set.h" + +namespace tesseract { +class CharAltList : public AltList { + public: + CharAltList(const CharSet *char_set, int max_alt = kMaxCharAlt); + ~CharAltList(); + + // Sort the alternate list based on cost + void Sort(); + // insert a new alternate with the specified class-id, cost and tag + bool Insert(int class_id, int cost, void *tag = NULL); + // returns the cost of a specific class ID + inline int ClassCost(int class_id) const { + if (class_id_cost_ == NULL || + class_id < 0 || + class_id >= char_set_->ClassCount()) { + return WORST_COST; + } + return class_id_cost_[class_id]; + } + // returns the alternate class-id corresponding to an alternate index + inline int Alt(int alt_idx) const { return class_id_alt_[alt_idx]; } + // set the cost of a certain alternate + void SetAltCost(int alt_idx, int cost) { + alt_cost_[alt_idx] = cost; + class_id_cost_[class_id_alt_[alt_idx]] = cost; + } + + private: + // character set object. Passed at construction time + const CharSet *char_set_; + // array of alternate class-ids + int *class_id_alt_; + // array of alternate costs + int *class_id_cost_; + // default max count of alternates + static const int kMaxCharAlt = 256; +}; +} + +#endif // CHAR_ALT_LIST_H diff --git a/TesseractOCR/include/tesseract/char_bigrams.h b/TesseractOCR/include/tesseract/char_bigrams.h new file mode 100644 index 00000000..5d819311 --- /dev/null +++ b/TesseractOCR/include/tesseract/char_bigrams.h @@ -0,0 +1,89 @@ +/********************************************************************** + * File: char_bigrams.h + * Description: Declaration of a Character Bigrams Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CharBigram class represents the interface to the character bigram +// table used by Cube +// A CharBigram object can be constructed from the Char Bigrams file +// Given a sequence of characters, the "Cost" method returns the Char Bigram +// cost of the string according to the table + +#ifndef CHAR_BIGRAMS_H +#define CHAR_BIGRAMS_H + +#include +#include "char_set.h" + +namespace tesseract { + +// structure representing a single bigram value +struct Bigram { + int cnt; + int cost; +}; + +// structure representing the char bigram array of characters +// following a specific character +struct CharBigram { + int total_cnt; + char_32 max_char; + Bigram *bigram; +}; + +// structure representing the whole bigram table +struct CharBigramTable { + int total_cnt; + int worst_cost; + char_32 max_char; + CharBigram *char_bigram; +}; + +class CharBigrams { + public: + CharBigrams(); + ~CharBigrams(); + // Construct the CharBigrams class from a file + static CharBigrams *Create(const string &data_file_path, + const string &lang); + // Top-level function to return the mean character bigram cost of a + // sequence of characters. If char_set is not NULL, use + // tesseract functions to return a case-invariant cost. + // This avoids unnecessarily penalizing all-one-case words or + // capitalized words (first-letter upper-case and remaining letters + // lower-case). + int Cost(const char_32 *str, CharSet *char_set) const; + + protected: + // Returns the character bigram cost of two characters. + int PairCost(char_32 ch1, char_32 ch2) const; + // Returns the mean character bigram cost of a sequence of + // characters. Adds a space at the beginning and end to account for + // cost of starting and ending characters. + int MeanCostWithSpaces(const char_32 *char_32_ptr) const; + + private: + // Only words this length or greater qualify for case-invariant character + // bigram cost. + static const int kMinLengthCaseInvariant = 4; + + + CharBigramTable bigram_table_; +}; +} + +#endif // CHAR_BIGRAMS_H diff --git a/TesseractOCR/include/tesseract/char_samp.h b/TesseractOCR/include/tesseract/char_samp.h new file mode 100644 index 00000000..700a11d0 --- /dev/null +++ b/TesseractOCR/include/tesseract/char_samp.h @@ -0,0 +1,166 @@ +/********************************************************************** + * File: char_samp.h + * Description: Declaration of a Character Bitmap Sample Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CharSamp inherits the Bmp8 class that represents images of +// words, characters and segments throughout Cube +// CharSamp adds more data members to hold the physical location of the image +// in a page, page number in a book if available. +// It also holds the label (GT) of the image that might correspond to a single +// character or a word +// It also provides methods for segmenting, scaling and cropping of the sample + +#ifndef CHAR_SAMP_H +#define CHAR_SAMP_H + +#include +#include +#include +#include "bmp_8.h" +#include "string_32.h" + +namespace tesseract { + +class CharSamp : public Bmp8 { + public: + CharSamp(); + CharSamp(int wid, int hgt); + CharSamp(int left, int top, int wid, int hgt); + ~CharSamp(); + // accessor methods + unsigned short Left() const { return left_; } + unsigned short Right() const { return left_ + wid_; } + unsigned short Top() const { return top_; } + unsigned short Bottom() const { return top_ + hgt_; } + unsigned short Page() const { return page_; } + unsigned short NormTop() const { return norm_top_; } + unsigned short NormBottom() const { return norm_bottom_; } + unsigned short NormAspectRatio() const { return norm_aspect_ratio_; } + unsigned short FirstChar() const { return first_char_; } + unsigned short LastChar() const { return last_char_; } + char_32 Label() const { + if (label32_ == NULL || LabelLen() != 1) { + return 0; + } + return label32_[0]; + } + char_32 * StrLabel() const { return label32_; } + string stringLabel() const; + + void SetLeft(unsigned short left) { left_ = left; } + void SetTop(unsigned short top) { top_ = top; } + void SetPage(unsigned short page) { page_ = page; } + void SetLabel(char_32 label) { + if (label32_ != NULL) { + delete []label32_; + } + label32_ = new char_32[2]; + if (label32_ != NULL) { + label32_[0] = label; + label32_[1] = 0; + } + } + void SetLabel(const char_32 *label32) { + if (label32_ != NULL) { + delete []label32_; + label32_ = NULL; + } + if (label32 != NULL) { + // remove any byte order markes if any + if (label32[0] == 0xfeff) { + label32++; + } + int len = LabelLen(label32); + label32_ = new char_32[len + 1]; + if (label32_ != NULL) { + memcpy(label32_, label32, len * sizeof(*label32)); + label32_[len] = 0; + } + } + } + void SetLabel(string str); + void SetNormTop(unsigned short norm_top) { norm_top_ = norm_top; } + void SetNormBottom(unsigned short norm_bottom) { + norm_bottom_ = norm_bottom; + } + void SetNormAspectRatio(unsigned short norm_aspect_ratio) { + norm_aspect_ratio_ = norm_aspect_ratio; + } + void SetFirstChar(unsigned short first_char) { + first_char_ = first_char; + } + void SetLastChar(unsigned short last_char) { + last_char_ = last_char; + } + + // Saves the charsamp to a dump file + bool Save2CharDumpFile(FILE *fp) const; + // Crops the underlying image and returns a new CharSamp with the + // same character information but new dimensions. Warning: does not + // necessarily set the normalized top and bottom correctly since + // those depend on its location within the word (or CubeSearchObject). + CharSamp *Crop(); + // Computes the connected components of the char sample + ConComp **Segment(int *seg_cnt, bool right_2_left, int max_hist_wnd, + int min_con_comp_size) const; + // returns a copy of the charsamp that is scaled to the + // specified width and height + CharSamp *Scale(int wid, int hgt, bool isotropic = true); + // returns a Clone of the charsample + CharSamp *Clone() const; + // computes the features corresponding to the char sample + bool ComputeFeatures(int conv_grid_size, float *features); + // Load a Char Samp from a dump file + static CharSamp *FromCharDumpFile(CachedFile *fp); + static CharSamp *FromCharDumpFile(FILE *fp); + static CharSamp *FromCharDumpFile(unsigned char **raw_data); + static CharSamp *FromRawData(int left, int top, int wid, int hgt, + unsigned char *data); + static CharSamp *FromConComps(ConComp **concomp_array, + int strt_concomp, int seg_flags_size, + int *seg_flags, bool *left_most, + bool *right_most, int word_hgt); + static int AuxFeatureCnt() { return (5); } + // Return the length of the label string + int LabelLen() const { return LabelLen(label32_); } + static int LabelLen(const char_32 *label32) { + if (label32 == NULL) { + return 0; + } + int len = 0; + while (label32[++len] != 0); + return len; + } + private: + char_32 * label32_; + unsigned short page_; + unsigned short left_; + unsigned short top_; + // top of sample normalized to a word height of 255 + unsigned short norm_top_; + // bottom of sample normalized to a word height of 255 + unsigned short norm_bottom_; + // 255 * ratio of character width to (width + height) + unsigned short norm_aspect_ratio_; + unsigned short first_char_; + unsigned short last_char_; +}; + +} + +#endif // CHAR_SAMP_H diff --git a/TesseractOCR/include/tesseract/char_samp_enum.h b/TesseractOCR/include/tesseract/char_samp_enum.h new file mode 100644 index 00000000..93768e0f --- /dev/null +++ b/TesseractOCR/include/tesseract/char_samp_enum.h @@ -0,0 +1,38 @@ +/********************************************************************** + * File: char_samp_enum.h + * Description: Declaration of a Character Sample Enumerator Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CharSampEnum class provides the base class for CharSamp class +// Enumerators. This is typically used to implement dump file readers + +#ifndef CHARSAMP_ENUM_H +#define CHARSAMP_ENUM_H + +#include "char_samp.h" + +namespace tesseract { + +class CharSampEnum { + public: + CharSampEnum(); + virtual ~CharSampEnum(); + virtual bool EnumCharSamp(CharSamp *char_samp, float progress) = 0; +}; +} + +#endif // CHARSAMP_ENUM_H diff --git a/TesseractOCR/include/tesseract/char_samp_set.h b/TesseractOCR/include/tesseract/char_samp_set.h new file mode 100644 index 00000000..d5242825 --- /dev/null +++ b/TesseractOCR/include/tesseract/char_samp_set.h @@ -0,0 +1,73 @@ +/********************************************************************** + * File: char_samp_set.h + * Description: Declaration of a Character Sample Set Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CharSampSet set encapsulates a set of CharSet objects typically +// but not necessarily loaded from a file +// It provides methods to load samples from File, Create a new file and +// Add new char samples to the set + +#ifndef CHAR_SAMP_SET_H +#define CHAR_SAMP_SET_H + +#include +#include +#include +#include "char_samp.h" +#include "char_samp_enum.h" +#include "char_set.h" + +namespace tesseract { + +// chunks of samp pointers to allocate +#define SAMP_ALLOC_BLOCK 10000 + +class CharSampSet { + public: + CharSampSet(); + ~CharSampSet(); + // return sample count + int SampleCount() const { return cnt_; } + // returns samples buffer + CharSamp ** Samples() const { return samp_buff_; } + // Create a CharSampSet set object from a file + static CharSampSet *FromCharDumpFile(string file_name); + // Enumerate the Samples in the set one-by-one calling the enumertor's + // EnumCharSamp method for each sample + static bool EnumSamples(string file_name, CharSampEnum *enumerator); + // Create a new Char Dump file + static FILE *CreateCharDumpFile(string file_name); + // Add a new sample to the set + bool Add(CharSamp *char_samp); + + private: + // sample count + int cnt_; + // the char samp array + CharSamp **samp_buff_; + // Are the samples owned by the set or not. + // Determines whether we should cleanup in the end + bool own_samples_; + // Cleanup + void Cleanup(); + // Load character samples from a file + bool LoadCharSamples(FILE *fp); +}; +} + +#endif // CHAR_SAMP_SET_H diff --git a/TesseractOCR/include/tesseract/char_set.h b/TesseractOCR/include/tesseract/char_set.h new file mode 100644 index 00000000..12aea82d --- /dev/null +++ b/TesseractOCR/include/tesseract/char_set.h @@ -0,0 +1,174 @@ +/********************************************************************** + * File: char_samp_enum.h + * Description: Declaration of a Character Set Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CharSet class encapsulates the list of 32-bit strings/characters that +// Cube supports for a specific language. The char set is loaded from the +// .unicharset file corresponding to a specific language +// Each string has a corresponding int class-id that gets used throughout Cube +// The class provides pass back and forth conversion between the class-id +// and its corresponding 32-bit string. This is done using a hash table that +// maps the string to the class id. + +#ifndef CHAR_SET_H +#define CHAR_SET_H + +#include +#include +#include + +#include "string_32.h" +#include "tessdatamanager.h" +#include "unicharset.h" +#include "cube_const.h" + +namespace tesseract { + +class CharSet { + public: + CharSet(); + ~CharSet(); + + // Returns true if Cube is sharing Tesseract's unicharset. + inline bool SharedUnicharset() { return (unicharset_map_ == NULL); } + + // Returns the class id corresponding to a 32-bit string. Returns -1 + // if the string is not supported. This is done by hashing the + // string and then looking up the string in the hash-bin if there + // are collisions. + inline int ClassID(const char_32 *str) const { + int hash_val = Hash(str); + if (hash_bin_size_[hash_val] == 0) + return -1; + for (int bin = 0; bin < hash_bin_size_[hash_val]; bin++) { + if (class_strings_[hash_bins_[hash_val][bin]]->compare(str) == 0) + return hash_bins_[hash_val][bin]; + } + return -1; + } + // Same as above but using a 32-bit char instead of a string + inline int ClassID(char_32 ch) const { + int hash_val = Hash(ch); + if (hash_bin_size_[hash_val] == 0) + return -1; + for (int bin = 0; bin < hash_bin_size_[hash_val]; bin++) { + if ((*class_strings_[hash_bins_[hash_val][bin]])[0] == ch && + class_strings_[hash_bins_[hash_val][bin]]->length() == 1) { + return hash_bins_[hash_val][bin]; + } + } + return -1; + } + // Retrieve the unicharid in Tesseract's unicharset corresponding + // to a 32-bit string. When Tesseract and Cube share the same + // unicharset, this will just be the class id. + inline int UnicharID(const char_32 *str) const { + int class_id = ClassID(str); + if (class_id == INVALID_UNICHAR_ID) + return INVALID_UNICHAR_ID; + int unichar_id; + if (unicharset_map_) + unichar_id = unicharset_map_[class_id]; + else + unichar_id = class_id; + return unichar_id; + } + // Same as above but using a 32-bit char instead of a string + inline int UnicharID(char_32 ch) const { + int class_id = ClassID(ch); + if (class_id == INVALID_UNICHAR_ID) + return INVALID_UNICHAR_ID; + int unichar_id; + if (unicharset_map_) + unichar_id = unicharset_map_[class_id]; + else + unichar_id = class_id; + return unichar_id; + } + // Returns the 32-bit string corresponding to a class id + inline const char_32 * ClassString(int class_id) const { + if (class_id < 0 || class_id >= class_cnt_) { + return NULL; + } + return reinterpret_cast(class_strings_[class_id]->c_str()); + } + // Returns the count of supported strings + inline int ClassCount() const { return class_cnt_; } + + // Creates CharSet object by reading the unicharset from the + // TessDatamanager, and mapping Cube's unicharset to Tesseract's if + // they differ. + static CharSet *Create(TessdataManager *tessdata_manager, + UNICHARSET *tess_unicharset); + + // Return the UNICHARSET cube is using for recognition internally -- + // ClassId() returns unichar_id's in this unicharset. + UNICHARSET *InternalUnicharset() { return unicharset_; } + + private: + // Hash table configuration params. Determined emperically on + // the supported languages so far (Eng, Ara, Hin). Might need to be + // tuned for speed when more languages are supported + static const int kHashBins = 3001; + static const int kMaxHashSize = 16; + + // Using djb2 hashing function to hash a 32-bit string + // introduced in http://www.cse.yorku.ca/~oz/hash.html + static inline int Hash(const char_32 *str) { + unsigned long hash = 5381; + int c; + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; + return (hash%kHashBins); + } + // Same as above but for a single char + static inline int Hash(char_32 ch) { + char_32 b[2]; + b[0] = ch; + b[1] = 0; + return Hash(b); + } + + // Load the list of supported chars from the given data file + // pointer. If tess_unicharset is non-NULL, mapping each Cube class + // id to a tesseract unicharid. + bool LoadSupportedCharList(FILE *fp, UNICHARSET *tess_unicharset); + + // class count + int class_cnt_; + // hash-bin sizes array + int hash_bin_size_[kHashBins]; + // hash bins + int hash_bins_[kHashBins][kMaxHashSize]; + // supported strings array + string_32 **class_strings_; + // map from class id to secondary (tesseract's) unicharset's ids + int *unicharset_map_; + // A unicharset which is filled in with a Tesseract-style UNICHARSET for + // cube's data if our unicharset is different from tesseract's. + UNICHARSET cube_unicharset_; + // This points to either the tess_unicharset we're passed or cube_unicharset_, + // depending upon whether we just have one unicharset or one for each + // tesseract and cube, respectively. + UNICHARSET *unicharset_; + // has the char set been initialized flag + bool init_; +}; +} + +#endif // CHAR_SET_H diff --git a/TesseractOCR/include/tesseract/chop.h b/TesseractOCR/include/tesseract/chop.h new file mode 100644 index 00000000..bafc99ba --- /dev/null +++ b/TesseractOCR/include/tesseract/chop.h @@ -0,0 +1,44 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: chop.h (Formerly chop.h) + * Description: + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Wed Jul 10 14:47:37 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *******************************************************************************/ + +#ifndef CHOP_H +#define CHOP_H + +/*---------------------------------------------------------------------- + I n c l u d e s +----------------------------------------------------------------------*/ +#include "genericheap.h" +#include "kdpair.h" +#include "seam.h" + +/*---------------------------------------------------------------------- + T y p e s +---------------------------------------------------------------------*/ +#define MAX_NUM_POINTS 50 +// The PointPair elements do NOT own the EDGEPTs. +typedef tesseract::KDPairInc PointPair; +typedef tesseract::GenericHeap PointHeap; + +#endif diff --git a/TesseractOCR/include/tesseract/chopper.h b/TesseractOCR/include/tesseract/chopper.h new file mode 100644 index 00000000..7955a51f --- /dev/null +++ b/TesseractOCR/include/tesseract/chopper.h @@ -0,0 +1,50 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: chopper.h (Formerly chopper.h) + * Description: + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Wed May 15 14:24:26 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ + +#ifndef CHOPPER_H +#define CHOPPER_H + +#include "cutil.h" +#include "matrix.h" +#include "seam.h" +#include "stopper.h" + + +void preserve_outline(EDGEPT *start); + +void preserve_outline_tree(TESSLINE *srcline); + +EDGEPT *restore_outline(EDGEPT *start); + +void restore_outline_tree(TESSLINE *srcline); + +int any_shared_split_points(const GenericVector& seams, SEAM *seam); + +int check_blob(TBLOB *blob); + +inT16 check_seam_order(TBLOB *blob, SEAM *seam); + +inT16 total_containment(TBLOB *blob1, TBLOB *blob2); +#endif diff --git a/TesseractOCR/include/tesseract/cjkpitch.h b/TesseractOCR/include/tesseract/cjkpitch.h new file mode 100644 index 00000000..601ec213 --- /dev/null +++ b/TesseractOCR/include/tesseract/cjkpitch.h @@ -0,0 +1,71 @@ +/////////////////////////////////////////////////////////////////////// +// File: cjkpitch.h +// Description: Code to determine fixed pitchness and the pitch if fixed, +// for CJK text. +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: takenaka@google.com (Hiroshi Takenaka) +// Created: Mon Jun 27 12:48:35 JST 2011 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// +#ifndef CJKPITCH_H_ +#define CJKPITCH_H_ + +#include "blobbox.h" + +// Function to test "fixed-pitchness" of the input text and estimating +// character pitch parameters for it, based on CJK fixed-pitch layout +// model. +// +// This function assumes that a fixed-pitch CJK text has following +// characteristics: +// +// - Most glyphs are designed to fit within the same sized square +// (imaginary body). Also they are aligned to the center of their +// imaginary bodies. +// - The imaginary body is always a regular rectangle. +// - There may be some extra space between character bodies +// (tracking). +// - There may be some extra space after punctuations. +// - The text is *not* space-delimited. Thus spaces are rare. +// - Character may consists of multiple unconnected blobs. +// +// And the function works in two passes. On pass 1, it looks for such +// "good" blobs that has the pitch same pitch on the both side and +// looks like a complete CJK character. Then estimates the character +// pitch for every row, based on those good blobs. If we couldn't find +// enough good blobs for a row, then the pitch is estimated from other +// rows with similar character height instead. +// +// Pass 2 is an iterative process to fit the blobs into fixed-pitch +// character cells. Once we have estimated the character pitch, blobs +// that are almost as large as the pitch can be considered to be +// complete characters. And once we know that some characters are +// complete characters, we can estimate the region occupied by its +// neighbors. And so on. +// +// We repeat the process until all ambiguities are resolved. Then make +// the final decision about fixed-pitchness of each row and compute +// pitch and spacing parameters. +// +// (If a row is considered to be propotional, pitch_decision for the +// row is set to PITCH_CORR_PROP and the later phase +// (i.e. Textord::to_spacing()) should determine its spacing +// parameters) +// +// This function doesn't provide all information required by +// fixed_pitch_words() and the rows need to be processed with +// make_prop_words() even if they are fixed pitched. +void compute_fixed_pitch_cjk(ICOORD page_tr, // top right + TO_BLOCK_LIST *port_blocks); // input list + +#endif // CJKPITCH_H_ diff --git a/TesseractOCR/include/tesseract/classifier_base.h b/TesseractOCR/include/tesseract/classifier_base.h new file mode 100644 index 00000000..8c2b1bbf --- /dev/null +++ b/TesseractOCR/include/tesseract/classifier_base.h @@ -0,0 +1,100 @@ +/********************************************************************** + * File: classifier_base.h + * Description: Declaration of the Base Character Classifier + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CharClassifier class is the abstract class for any character/grapheme +// classifier. + +#ifndef CHAR_CLASSIFIER_BASE_H +#define CHAR_CLASSIFIER_BASE_H + +#include +#include "char_samp.h" +#include "char_altlist.h" +#include "char_set.h" +#include "feature_base.h" +#include "lang_model.h" +#include "tuning_params.h" + +namespace tesseract { +class CharClassifier { + public: + CharClassifier(CharSet *char_set, TuningParams *params, + FeatureBase *feat_extract) { + char_set_ = char_set; + params_ = params; + feat_extract_ = feat_extract; + fold_sets_ = NULL; + fold_set_cnt_ = 0; + fold_set_len_ = NULL; + init_ = false; + case_sensitive_ = true; + } + + virtual ~CharClassifier() { + if (fold_sets_ != NULL) { + for (int fold_set = 0; fold_set < fold_set_cnt_; fold_set++) { + if (fold_sets_[fold_set] != NULL) { + delete []fold_sets_[fold_set]; + } + } + delete []fold_sets_; + fold_sets_ = NULL; + } + if (fold_set_len_ != NULL) { + delete []fold_set_len_; + fold_set_len_ = NULL; + } + if (feat_extract_ != NULL) { + delete feat_extract_; + feat_extract_ = NULL; + } + } + + // pure virtual functions that need to be implemented by any inheriting class + virtual CharAltList * Classify(CharSamp *char_samp) = 0; + virtual int CharCost(CharSamp *char_samp) = 0; + virtual bool Train(CharSamp *char_samp, int ClassID) = 0; + virtual bool SetLearnParam(char *var_name, float val) = 0; + virtual bool Init(const string &data_file_path, const string &lang, + LangModel *lang_mod) = 0; + + // accessors + FeatureBase *FeatureExtractor() {return feat_extract_;} + inline bool CaseSensitive() const { return case_sensitive_; } + inline void SetCaseSensitive(bool case_sensitive) { + case_sensitive_ = case_sensitive; + } + + protected: + virtual void Fold() = 0; + virtual bool LoadFoldingSets(const string &data_file_path, + const string &lang, + LangModel *lang_mod) = 0; + FeatureBase *feat_extract_; + CharSet *char_set_; + TuningParams *params_; + int **fold_sets_; + int *fold_set_len_; + int fold_set_cnt_; + bool init_; + bool case_sensitive_; +}; +} // tesseract + +#endif // CHAR_CLASSIFIER_BASE_H diff --git a/TesseractOCR/include/tesseract/classifier_factory.h b/TesseractOCR/include/tesseract/classifier_factory.h new file mode 100644 index 00000000..f7254d58 --- /dev/null +++ b/TesseractOCR/include/tesseract/classifier_factory.h @@ -0,0 +1,43 @@ +/********************************************************************** + * File: classifier_factory.h + * Description: Declaration of the Base Character Classifier + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CharClassifierFactory provides a single static method to create an +// instance of the desired classifier + +#ifndef CHAR_CLASSIFIER_FACTORY_H +#define CHAR_CLASSIFIER_FACTORY_H + +#include +#include "classifier_base.h" +#include "lang_model.h" + +namespace tesseract { +class CharClassifierFactory { + public: + // Creates a CharClassifier object of the appropriate type depending on the + // classifier type in the settings file + static CharClassifier *Create(const string &data_file_path, + const string &lang, + LangModel *lang_mod, + CharSet *char_set, + TuningParams *params); +}; +} // tesseract + +#endif // CHAR_CLASSIFIER_FACTORY_H diff --git a/TesseractOCR/include/tesseract/classify.h b/TesseractOCR/include/tesseract/classify.h new file mode 100644 index 00000000..de62bbf8 --- /dev/null +++ b/TesseractOCR/include/tesseract/classify.h @@ -0,0 +1,518 @@ +/////////////////////////////////////////////////////////////////////// +// File: classify.h +// Description: classify class. +// Author: Samuel Charron +// +// (C) Copyright 2006, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_CLASSIFY_CLASSIFY_H__ +#define TESSERACT_CLASSIFY_CLASSIFY_H__ + +#include "adaptive.h" +#include "ccstruct.h" +#include "classify.h" +#include "dict.h" +#include "featdefs.h" +#include "fontinfo.h" +#include "intfx.h" +#include "intmatcher.h" +#include "normalis.h" +#include "ratngs.h" +#include "ocrfeatures.h" +#include "unicity_table.h" + +class ScrollView; +class WERD_CHOICE; +class WERD_RES; +struct ADAPT_RESULTS; +struct NORM_PROTOS; + +static const int kUnknownFontinfoId = -1; +static const int kBlankFontinfoId = -2; + +namespace tesseract { + +class ShapeClassifier; +struct ShapeRating; +class ShapeTable; +struct UnicharRating; + +// How segmented is a blob. In this enum, character refers to a classifiable +// unit, but that is too long and character is usually easier to understand. +enum CharSegmentationType { + CST_FRAGMENT, // A partial character. + CST_WHOLE, // A correctly segmented character. + CST_IMPROPER, // More than one but less than 2 characters. + CST_NGRAM // Multiple characters. +}; + +class Classify : public CCStruct { + public: + Classify(); + virtual ~Classify(); + Dict& getDict() { + return dict_; + } + + const ShapeTable* shape_table() const { + return shape_table_; + } + + // Takes ownership of the given classifier, and uses it for future calls + // to CharNormClassifier. + void SetStaticClassifier(ShapeClassifier* static_classifier); + + // Adds a noise classification result that is a bit worse than the worst + // current result, or the worst possible result if no current results. + void AddLargeSpeckleTo(int blob_length, BLOB_CHOICE_LIST *choices); + + // Returns true if the blob is small enough to be a large speckle. + bool LargeSpeckle(const TBLOB &blob); + + /* adaptive.cpp ************************************************************/ + ADAPT_TEMPLATES NewAdaptedTemplates(bool InitFromUnicharset); + int GetFontinfoId(ADAPT_CLASS Class, uinT8 ConfigId); + // Runs the class pruner from int_templates on the given features, returning + // the number of classes output in results. + // int_templates Class pruner tables + // num_features Number of features in blob + // features Array of features + // normalization_factors (input) Array of int_templates->NumClasses fudge + // factors from blob normalization process. + // (Indexed by CLASS_INDEX) + // expected_num_features (input) Array of int_templates->NumClasses + // expected number of features for each class. + // (Indexed by CLASS_INDEX) + // results (output) Sorted Array of pruned classes. + // Array must be sized to take the maximum possible + // number of outputs : int_templates->NumClasses. + int PruneClasses(const INT_TEMPLATES_STRUCT* int_templates, + int num_features, + const INT_FEATURE_STRUCT* features, + const uinT8* normalization_factors, + const uinT16* expected_num_features, + GenericVector* results); + void ReadNewCutoffs(FILE *CutoffFile, bool swap, inT64 end_offset, + CLASS_CUTOFF_ARRAY Cutoffs); + void PrintAdaptedTemplates(FILE *File, ADAPT_TEMPLATES Templates); + void WriteAdaptedTemplates(FILE *File, ADAPT_TEMPLATES Templates); + ADAPT_TEMPLATES ReadAdaptedTemplates(FILE *File); + /* normmatch.cpp ************************************************************/ + FLOAT32 ComputeNormMatch(CLASS_ID ClassId, + const FEATURE_STRUCT& feature, BOOL8 DebugMatch); + void FreeNormProtos(); + NORM_PROTOS *ReadNormProtos(FILE *File, inT64 end_offset); + /* protos.cpp ***************************************************************/ + void ConvertProto(PROTO Proto, int ProtoId, INT_CLASS Class); + INT_TEMPLATES CreateIntTemplates(CLASSES FloatProtos, + const UNICHARSET& target_unicharset); + /* adaptmatch.cpp ***********************************************************/ + + // Learn the given word using its chopped_word, seam_array, denorm, + // box_word, best_state, and correct_text to learn both correctly and + // incorrectly segmented blobs. If filename is not NULL, then LearnBlob + // is called and the data will be written to a file for static training. + // Otherwise AdaptToBlob is called for adaption within a document. + void LearnWord(const char* filename, WERD_RES *word); + + // Builds a blob of length fragments, from the word, starting at start, + // and then learn it, as having the given correct_text. + // If filename is not NULL, then LearnBlob + // is called and the data will be written to a file for static training. + // Otherwise AdaptToBlob is called for adaption within a document. + // threshold is a magic number required by AdaptToChar and generated by + // GetAdaptThresholds. + // Although it can be partly inferred from the string, segmentation is + // provided to explicitly clarify the character segmentation. + void LearnPieces(const char* filename, int start, int length, + float threshold, CharSegmentationType segmentation, + const char* correct_text, WERD_RES *word); + void InitAdaptiveClassifier(bool load_pre_trained_templates); + void InitAdaptedClass(TBLOB *Blob, + CLASS_ID ClassId, + int FontinfoId, + ADAPT_CLASS Class, + ADAPT_TEMPLATES Templates); + void AmbigClassifier(const GenericVector& int_features, + const INT_FX_RESULT_STRUCT& fx_info, + const TBLOB *blob, + INT_TEMPLATES templates, + ADAPT_CLASS *classes, + UNICHAR_ID *ambiguities, + ADAPT_RESULTS *results); + void MasterMatcher(INT_TEMPLATES templates, + inT16 num_features, + const INT_FEATURE_STRUCT* features, + const uinT8* norm_factors, + ADAPT_CLASS* classes, + int debug, + int matcher_multiplier, + const TBOX& blob_box, + const GenericVector& results, + ADAPT_RESULTS* final_results); + // Converts configs to fonts, and if the result is not adapted, and a + // shape_table_ is present, the shape is expanded to include all + // unichar_ids represented, before applying a set of corrections to the + // distance rating in int_result, (see ComputeCorrectedRating.) + // The results are added to the final_results output. + void ExpandShapesAndApplyCorrections(ADAPT_CLASS* classes, + bool debug, + int class_id, + int bottom, int top, + float cp_rating, + int blob_length, + int matcher_multiplier, + const uinT8* cn_factors, + INT_RESULT_STRUCT& int_result, + ADAPT_RESULTS* final_results); + // Applies a set of corrections to the distance im_rating, + // including the cn_correction, miss penalty and additional penalty + // for non-alnums being vertical misfits. Returns the corrected distance. + double ComputeCorrectedRating(bool debug, int unichar_id, double cp_rating, + double im_rating, int feature_misses, + int bottom, int top, + int blob_length, int matcher_multiplier, + const uinT8* cn_factors); + void ConvertMatchesToChoices(const DENORM& denorm, const TBOX& box, + ADAPT_RESULTS *Results, + BLOB_CHOICE_LIST *Choices); + void AddNewResult(ADAPT_RESULTS *results, + CLASS_ID class_id, + int shape_id, + FLOAT32 rating, + bool adapted, + int config, + int fontinfo_id, + int fontinfo_id2); + int GetAdaptiveFeatures(TBLOB *Blob, + INT_FEATURE_ARRAY IntFeatures, + FEATURE_SET *FloatFeatures); + +#ifndef GRAPHICS_DISABLED + void DebugAdaptiveClassifier(TBLOB *Blob, + ADAPT_RESULTS *Results); +#endif + PROTO_ID MakeNewTempProtos(FEATURE_SET Features, + int NumBadFeat, + FEATURE_ID BadFeat[], + INT_CLASS IClass, + ADAPT_CLASS Class, + BIT_VECTOR TempProtoMask); + int MakeNewTemporaryConfig(ADAPT_TEMPLATES Templates, + CLASS_ID ClassId, + int FontinfoId, + int NumFeatures, + INT_FEATURE_ARRAY Features, + FEATURE_SET FloatFeatures); + void MakePermanent(ADAPT_TEMPLATES Templates, + CLASS_ID ClassId, + int ConfigId, + TBLOB *Blob); + void PrintAdaptiveMatchResults(FILE *File, ADAPT_RESULTS *Results); + void RemoveExtraPuncs(ADAPT_RESULTS *Results); + void RemoveBadMatches(ADAPT_RESULTS *Results); + void SetAdaptiveThreshold(FLOAT32 Threshold); + void ShowBestMatchFor(int shape_id, + const INT_FEATURE_STRUCT* features, + int num_features); + // Returns a string for the classifier class_id: either the corresponding + // unicharset debug_str or the shape_table_ debug str. + STRING ClassIDToDebugStr(const INT_TEMPLATES_STRUCT* templates, + int class_id, int config_id) const; + // Converts a classifier class_id index with a config ID to: + // shape_table_ present: a shape_table_ index OR + // No shape_table_: a font ID. + // Without shape training, each class_id, config pair represents a single + // unichar id/font combination, so this function looks up the corresponding + // font id. + // With shape training, each class_id, config pair represents a single + // shape table index, so the fontset_table stores the shape table index, + // and the shape_table_ must be consulted to obtain the actual unichar_id/ + // font combinations that the shape represents. + int ClassAndConfigIDToFontOrShapeID(int class_id, + int int_result_config) const; + // Converts a shape_table_ index to a classifier class_id index (not a + // unichar-id!). Uses a search, so not fast. + int ShapeIDToClassID(int shape_id) const; + UNICHAR_ID *BaselineClassifier( + TBLOB *Blob, const GenericVector& int_features, + const INT_FX_RESULT_STRUCT& fx_info, + ADAPT_TEMPLATES Templates, ADAPT_RESULTS *Results); + int CharNormClassifier(TBLOB *blob, + const TrainingSample& sample, + ADAPT_RESULTS *adapt_results); + + // As CharNormClassifier, but operates on a TrainingSample and outputs to + // a GenericVector of ShapeRating without conversion to classes. + int CharNormTrainingSample(bool pruner_only, int keep_this, + const TrainingSample& sample, + GenericVector* results); + UNICHAR_ID *GetAmbiguities(TBLOB *Blob, CLASS_ID CorrectClass); + void DoAdaptiveMatch(TBLOB *Blob, ADAPT_RESULTS *Results); + void AdaptToChar(TBLOB *Blob, + CLASS_ID ClassId, + int FontinfoId, + FLOAT32 Threshold); + void DisplayAdaptedChar(TBLOB* blob, INT_CLASS_STRUCT* int_class); + bool AdaptableWord(WERD_RES* word); + void EndAdaptiveClassifier(); + void SettupPass1(); + void SettupPass2(); + void AdaptiveClassifier(TBLOB *Blob, BLOB_CHOICE_LIST *Choices); + void ClassifyAsNoise(ADAPT_RESULTS *Results); + void ResetAdaptiveClassifierInternal(); + + int GetCharNormFeature(const INT_FX_RESULT_STRUCT& fx_info, + INT_TEMPLATES templates, + uinT8* pruner_norm_array, + uinT8* char_norm_array); + // Computes the char_norm_array for the unicharset and, if not NULL, the + // pruner_array as appropriate according to the existence of the shape_table. + // The norm_feature is deleted as it is almost certainly no longer needed. + void ComputeCharNormArrays(FEATURE_STRUCT* norm_feature, + INT_TEMPLATES_STRUCT* templates, + uinT8* char_norm_array, + uinT8* pruner_array); + + bool TempConfigReliable(CLASS_ID class_id, const TEMP_CONFIG &config); + void UpdateAmbigsGroup(CLASS_ID class_id, TBLOB *Blob); + + bool AdaptiveClassifierIsFull() { return NumAdaptationsFailed > 0; } + bool LooksLikeGarbage(TBLOB *blob); + void RefreshDebugWindow(ScrollView **win, const char *msg, + int y_offset, const TBOX &wbox); + // intfx.cpp + // Computes the DENORMS for bl(baseline) and cn(character) normalization + // during feature extraction. The input denorm describes the current state + // of the blob, which is usually a baseline-normalized word. + // The Transforms setup are as follows: + // Baseline Normalized (bl) Output: + // We center the grapheme by aligning the x-coordinate of its centroid with + // x=128 and leaving the already-baseline-normalized y as-is. + // + // Character Normalized (cn) Output: + // We align the grapheme's centroid at the origin and scale it + // asymmetrically in x and y so that the 2nd moments are a standard value + // (51.2) ie the result is vaguely square. + // If classify_nonlinear_norm is true: + // A non-linear normalization is setup that attempts to evenly distribute + // edges across x and y. + // + // Some of the fields of fx_info are also setup: + // Length: Total length of outline. + // Rx: Rounded y second moment. (Reversed by convention.) + // Ry: rounded x second moment. + // Xmean: Rounded x center of mass of the blob. + // Ymean: Rounded y center of mass of the blob. + static void SetupBLCNDenorms(const TBLOB& blob, bool nonlinear_norm, + DENORM* bl_denorm, DENORM* cn_denorm, + INT_FX_RESULT_STRUCT* fx_info); + + // Extracts sets of 3-D features of length kStandardFeatureLength (=12.8), as + // (x,y) position and angle as measured counterclockwise from the vector + // <-1, 0>, from blob using two normalizations defined by bl_denorm and + // cn_denorm. See SetpuBLCNDenorms for definitions. + // If outline_cn_counts is not NULL, on return it contains the cumulative + // number of cn features generated for each outline in the blob (in order). + // Thus after the first outline, there were (*outline_cn_counts)[0] features, + // after the second outline, there were (*outline_cn_counts)[1] features etc. + static void ExtractFeatures(const TBLOB& blob, + bool nonlinear_norm, + GenericVector* bl_features, + GenericVector* cn_features, + INT_FX_RESULT_STRUCT* results, + GenericVector* outline_cn_counts); + /* float2int.cpp ************************************************************/ + void ClearCharNormArray(uinT8* char_norm_array); + void ComputeIntCharNormArray(const FEATURE_STRUCT& norm_feature, + uinT8* char_norm_array); + void ComputeIntFeatures(FEATURE_SET Features, INT_FEATURE_ARRAY IntFeatures); + /* intproto.cpp *************************************************************/ + INT_TEMPLATES ReadIntTemplates(FILE *File); + void WriteIntTemplates(FILE *File, INT_TEMPLATES Templates, + const UNICHARSET& target_unicharset); + CLASS_ID GetClassToDebug(const char *Prompt, bool* adaptive_on, + bool* pretrained_on, int* shape_id); + void ShowMatchDisplay(); + /* font detection ***********************************************************/ + UnicityTable& get_fontinfo_table() { + return fontinfo_table_; + } + const UnicityTable& get_fontinfo_table() const { + return fontinfo_table_; + } + UnicityTable& get_fontset_table() { + return fontset_table_; + } + /* mfoutline.cpp ***********************************************************/ + void NormalizeOutlines(LIST Outlines, FLOAT32 *XScale, FLOAT32 *YScale); + /* outfeat.cpp ***********************************************************/ + FEATURE_SET ExtractOutlineFeatures(TBLOB *Blob); + /* picofeat.cpp ***********************************************************/ + FEATURE_SET ExtractPicoFeatures(TBLOB *Blob); + + + // Member variables. + + // Parameters. + BOOL_VAR_H(prioritize_division, FALSE, + "Prioritize blob division over chopping"); + INT_VAR_H(tessedit_single_match, FALSE, "Top choice only from CP"); + BOOL_VAR_H(classify_enable_learning, true, "Enable adaptive classifier"); + INT_VAR_H(classify_debug_level, 0, "Classify debug level"); + + /* mfoutline.cpp ***********************************************************/ + /* control knobs used to control normalization of outlines */ + INT_VAR_H(classify_norm_method, character, "Normalization Method ..."); + double_VAR_H(classify_char_norm_range, 0.2, + "Character Normalization Range ..."); + double_VAR_H(classify_min_norm_scale_x, 0.0, "Min char x-norm scale ..."); + double_VAR_H(classify_max_norm_scale_x, 0.325, "Max char x-norm scale ..."); + double_VAR_H(classify_min_norm_scale_y, 0.0, "Min char y-norm scale ..."); + double_VAR_H(classify_max_norm_scale_y, 0.325, "Max char y-norm scale ..."); + double_VAR_H(classify_max_rating_ratio, 1.5, + "Veto ratio between classifier ratings"); + double_VAR_H(classify_max_certainty_margin, 5.5, + "Veto difference between classifier certainties"); + + /* adaptmatch.cpp ***********************************************************/ + BOOL_VAR_H(tess_cn_matching, 0, "Character Normalized Matching"); + BOOL_VAR_H(tess_bn_matching, 0, "Baseline Normalized Matching"); + BOOL_VAR_H(classify_enable_adaptive_matcher, 1, "Enable adaptive classifier"); + BOOL_VAR_H(classify_use_pre_adapted_templates, 0, + "Use pre-adapted classifier templates"); + BOOL_VAR_H(classify_save_adapted_templates, 0, + "Save adapted templates to a file"); + BOOL_VAR_H(classify_enable_adaptive_debugger, 0, "Enable match debugger"); + BOOL_VAR_H(classify_nonlinear_norm, 0, + "Non-linear stroke-density normalization"); + INT_VAR_H(matcher_debug_level, 0, "Matcher Debug Level"); + INT_VAR_H(matcher_debug_flags, 0, "Matcher Debug Flags"); + INT_VAR_H(classify_learning_debug_level, 0, "Learning Debug Level: "); + double_VAR_H(matcher_good_threshold, 0.125, "Good Match (0-1)"); + double_VAR_H(matcher_great_threshold, 0.0, "Great Match (0-1)"); + double_VAR_H(matcher_perfect_threshold, 0.02, "Perfect Match (0-1)"); + double_VAR_H(matcher_bad_match_pad, 0.15, "Bad Match Pad (0-1)"); + double_VAR_H(matcher_rating_margin, 0.1, "New template margin (0-1)"); + double_VAR_H(matcher_avg_noise_size, 12.0, "Avg. noise blob length: "); + INT_VAR_H(matcher_permanent_classes_min, 1, "Min # of permanent classes"); + INT_VAR_H(matcher_min_examples_for_prototyping, 3, + "Reliable Config Threshold"); + INT_VAR_H(matcher_sufficient_examples_for_prototyping, 5, + "Enable adaption even if the ambiguities have not been seen"); + double_VAR_H(matcher_clustering_max_angle_delta, 0.015, + "Maximum angle delta for prototype clustering"); + double_VAR_H(classify_misfit_junk_penalty, 0.0, + "Penalty to apply when a non-alnum is vertically out of " + "its expected textline position"); + double_VAR_H(rating_scale, 1.5, "Rating scaling factor"); + double_VAR_H(certainty_scale, 20.0, "Certainty scaling factor"); + double_VAR_H(tessedit_class_miss_scale, 0.00390625, + "Scale factor for features not used"); + double_VAR_H(classify_adapted_pruning_factor, 2.5, + "Prune poor adapted results this much worse than best result"); + double_VAR_H(classify_adapted_pruning_threshold, -1.0, + "Threshold at which classify_adapted_pruning_factor starts"); + INT_VAR_H(classify_adapt_proto_threshold, 230, + "Threshold for good protos during adaptive 0-255"); + INT_VAR_H(classify_adapt_feature_threshold, 230, + "Threshold for good features during adaptive 0-255"); + BOOL_VAR_H(disable_character_fragments, TRUE, + "Do not include character fragments in the" + " results of the classifier"); + double_VAR_H(classify_character_fragments_garbage_certainty_threshold, -3.0, + "Exclude fragments that do not match any whole character" + " with at least this certainty"); + BOOL_VAR_H(classify_debug_character_fragments, FALSE, + "Bring up graphical debugging windows for fragments training"); + BOOL_VAR_H(matcher_debug_separate_windows, FALSE, + "Use two different windows for debugging the matching: " + "One for the protos and one for the features."); + STRING_VAR_H(classify_learn_debug_str, "", "Class str to debug learning"); + + /* intmatcher.cpp **********************************************************/ + INT_VAR_H(classify_class_pruner_threshold, 229, + "Class Pruner Threshold 0-255"); + INT_VAR_H(classify_class_pruner_multiplier, 15, + "Class Pruner Multiplier 0-255: "); + INT_VAR_H(classify_cp_cutoff_strength, 7, + "Class Pruner CutoffStrength: "); + INT_VAR_H(classify_integer_matcher_multiplier, 10, + "Integer Matcher Multiplier 0-255: "); + + // Use class variables to hold onto built-in templates and adapted templates. + INT_TEMPLATES PreTrainedTemplates; + ADAPT_TEMPLATES AdaptedTemplates; + + // Create dummy proto and config masks for use with the built-in templates. + BIT_VECTOR AllProtosOn; + BIT_VECTOR AllConfigsOn; + BIT_VECTOR AllConfigsOff; + BIT_VECTOR TempProtoMask; + bool EnableLearning; + /* normmatch.cpp */ + NORM_PROTOS *NormProtos; + /* font detection ***********************************************************/ + UnicityTable fontinfo_table_; + // Without shape training, each class_id, config pair represents a single + // unichar id/font combination, so each fontset_table_ entry holds font ids + // for each config in the class. + // With shape training, each class_id, config pair represents a single + // shape_table_ index, so the fontset_table_ stores the shape_table_ index, + // and the shape_table_ must be consulted to obtain the actual unichar_id/ + // font combinations that the shape represents. + UnicityTable fontset_table_; + + INT_VAR_H(il1_adaption_test, 0, "Dont adapt to i/I at beginning of word"); + BOOL_VAR_H(classify_bln_numeric_mode, 0, + "Assume the input is numbers [0-9]."); + double_VAR_H(speckle_large_max_size, 0.30, "Max large speckle size"); + double_VAR_H(speckle_rating_penalty, 10.0, + "Penalty to add to worst rating for noise"); + + protected: + IntegerMatcher im_; + FEATURE_DEFS_STRUCT feature_defs_; + // If a shape_table_ is present, it is used to remap classifier output in + // ExpandShapesAndApplyCorrections. font_ids referenced by configs actually + // mean an index to the shape_table_ and the choices returned are *all* the + // shape_table_ entries at that index. + ShapeTable* shape_table_; + + private: + Dict dict_; + // The currently active static classifier. + ShapeClassifier* static_classifier_; + + /* variables used to hold performance statistics */ + int NumAdaptationsFailed; + + // Expected number of features in the class pruner, used to penalize + // unknowns that have too few features (like a c being classified as e) so + // it doesn't recognize everything as '@' or '#'. + // CharNormCutoffs is for the static classifier (with no shapetable). + // BaselineCutoffs gets a copy of CharNormCutoffs as an estimate of the real + // value in the adaptive classifier. Both are indexed by unichar_id. + // shapetable_cutoffs_ provides a similar value for each shape in the + // shape_table_ + uinT16* CharNormCutoffs; + uinT16* BaselineCutoffs; + GenericVector shapetable_cutoffs_; + ScrollView* learn_debug_win_; + ScrollView* learn_fragmented_word_debug_win_; + ScrollView* learn_fragments_debug_win_; +}; +} // namespace tesseract + +#endif // TESSERACT_CLASSIFY_CLASSIFY_H__ diff --git a/TesseractOCR/include/tesseract/clst.h b/TesseractOCR/include/tesseract/clst.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/cluster.h b/TesseractOCR/include/tesseract/cluster.h new file mode 100644 index 00000000..53ddf87d --- /dev/null +++ b/TesseractOCR/include/tesseract/cluster.h @@ -0,0 +1,134 @@ +/****************************************************************************** + ** Filename: cluster.h + ** Purpose: Definition of feature space clustering routines + ** Author: Dan Johnson + ** History: 5/29/89, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef CLUSTER_H +#define CLUSTER_H + +#include "kdtree.h" +#include "oldlist.h" + +struct BUCKETS; + +#define MINBUCKETS 5 +#define MAXBUCKETS 39 + +/*---------------------------------------------------------------------- + Types +----------------------------------------------------------------------*/ +typedef struct sample { + unsigned Clustered:1; // TRUE if included in a higher cluster + unsigned Prototype:1; // TRUE if cluster represented by a proto + unsigned SampleCount:30; // number of samples in this cluster + struct sample *Left; // ptr to left sub-cluster + struct sample *Right; // ptr to right sub-cluster + inT32 CharID; // identifier of char sample came from + FLOAT32 Mean[1]; // mean of cluster - SampleSize floats +} CLUSTER; + +typedef CLUSTER SAMPLE; // can refer to as either sample or cluster + +typedef enum { + spherical, elliptical, mixed, automatic +} PROTOSTYLE; + +typedef struct { // parameters to control clustering + PROTOSTYLE ProtoStyle; // specifies types of protos to be made + FLOAT32 MinSamples; // min # of samples per proto - % of total + FLOAT32 MaxIllegal; // max percentage of samples in a cluster which have + // more than 1 feature in that cluster + FLOAT32 Independence; // desired independence between dimensions + FLOAT64 Confidence; // desired confidence in prototypes created + int MagicSamples; // Ideal number of samples in a cluster. +} CLUSTERCONFIG; + +typedef enum { + normal, uniform, D_random, DISTRIBUTION_COUNT +} DISTRIBUTION; + +typedef union { + FLOAT32 Spherical; + FLOAT32 *Elliptical; +} FLOATUNION; + +typedef struct { + unsigned Significant:1; // TRUE if prototype is significant + unsigned Merged:1; // Merged after clustering so do not output + // but kept for display purposes. If it has no + // samples then it was actually merged. + // Otherwise it matched an already significant + // cluster. + unsigned Style:2; // spherical, elliptical, or mixed + unsigned NumSamples:28; // number of samples in the cluster + CLUSTER *Cluster; // ptr to cluster which made prototype + DISTRIBUTION *Distrib; // different distribution for each dimension + FLOAT32 *Mean; // prototype mean + FLOAT32 TotalMagnitude; // total magnitude over all dimensions + FLOAT32 LogMagnitude; // log base e of TotalMagnitude + FLOATUNION Variance; // prototype variance + FLOATUNION Magnitude; // magnitude of density function + FLOATUNION Weight; // weight of density function +} PROTOTYPE; + +typedef struct { + inT16 SampleSize; // number of parameters per sample + PARAM_DESC *ParamDesc; // description of each parameter + inT32 NumberOfSamples; // total number of samples being clustered + KDTREE *KDTree; // for optimal nearest neighbor searching + CLUSTER *Root; // ptr to root cluster of cluster tree + LIST ProtoList; // list of prototypes + inT32 NumChar; // # of characters represented by samples + // cache of reusable histograms by distribution type and number of buckets. + BUCKETS* bucket_cache[DISTRIBUTION_COUNT][MAXBUCKETS + 1 - MINBUCKETS]; +} CLUSTERER; + +typedef struct { + inT32 NumSamples; // number of samples in list + inT32 MaxNumSamples; // maximum size of list + SAMPLE *Sample[1]; // array of ptrs to sample data structures +} SAMPLELIST; + +// low level cluster tree analysis routines. +#define InitSampleSearch(S,C) (((C)==NULL)?(S=NIL_LIST):(S=push(NIL_LIST,(C)))) + +/*-------------------------------------------------------------------------- + Public Function Prototypes +--------------------------------------------------------------------------*/ +CLUSTERER *MakeClusterer (inT16 SampleSize, const PARAM_DESC ParamDesc[]); + +SAMPLE *MakeSample(CLUSTERER * Clusterer, const FLOAT32* Feature, inT32 CharID); + +LIST ClusterSamples(CLUSTERER *Clusterer, CLUSTERCONFIG *Config); + +void FreeClusterer(CLUSTERER *Clusterer); + +void FreeProtoList(LIST *ProtoList); + +void FreePrototype(void *arg); // PROTOTYPE *Prototype); + +CLUSTER *NextSample(LIST *SearchState); + +FLOAT32 Mean(PROTOTYPE *Proto, uinT16 Dimension); + +FLOAT32 StandardDeviation(PROTOTYPE *Proto, uinT16 Dimension); + +inT32 MergeClusters(inT16 N, PARAM_DESC ParamDesc[], inT32 n1, inT32 n2, + FLOAT32 m[], FLOAT32 m1[], FLOAT32 m2[]); + +//--------------Global Data Definitions and Declarations--------------------------- +// define errors that can be trapped +#define ALREADYCLUSTERED 4000 +#endif diff --git a/TesseractOCR/include/tesseract/clusttool.h b/TesseractOCR/include/tesseract/clusttool.h new file mode 100644 index 00000000..a4f3b835 --- /dev/null +++ b/TesseractOCR/include/tesseract/clusttool.h @@ -0,0 +1,68 @@ +/****************************************************************************** + ** Filename: clusttool.h + ** Purpose: Definition of clustering utility tools + ** Author: Dan Johnson + ** History: 6/6/89, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef __CLUSTERTOOL__ +#define __CLUSTERTOOL__ + +//--------------------------Include Files--------------------------------------- +#include "host.h" +#include "cluster.h" +#include + +/*------------------------------------------------------------------------- + Public Funtion Prototype +--------------------------------------------------------------------------*/ +uinT16 ReadSampleSize(FILE *File); + +PARAM_DESC *ReadParamDesc(FILE *File, uinT16 N); + +PROTOTYPE *ReadPrototype(FILE *File, uinT16 N); + +PROTOSTYLE ReadProtoStyle(FILE *File); + +FLOAT32 *ReadNFloats (FILE * File, uinT16 N, FLOAT32 Buffer[]); + +void WriteParamDesc (FILE * File, uinT16 N, PARAM_DESC ParamDesc[]); + +void WritePrototype(FILE *File, uinT16 N, PROTOTYPE *Proto); + +void WriteNFloats (FILE * File, uinT16 N, FLOAT32 Array[]); + +void WriteProtoStyle(FILE *File, PROTOSTYLE ProtoStyle); + +void WriteProtoList( + FILE *File, + uinT16 N, + PARAM_DESC ParamDesc[], + LIST ProtoList, + BOOL8 WriteSigProtos, + BOOL8 WriteInsigProtos); + +//--------------Global Data Definitions and Declarations--------------------- +// define errors that can be trapped +#define ILLEGALSAMPLESIZE 5000 +#define ILLEGALCIRCULARSPEC 5001 +#define ILLEGALMINMAXSPEC 5002 +#define ILLEGALSIGNIFICANCESPEC 5003 +#define ILLEGALSTYLESPEC 5004 +#define ILLEGALSAMPLECOUNT 5005 +#define ILLEGALMEANSPEC 5006 +#define ILLEGALVARIANCESPEC 5007 +#define ILLEGALDISTRIBUTION 5008 +#define ILLEGALFLOAT 5009 +#define ILLEGALESSENTIALSPEC 5013 +#endif diff --git a/TesseractOCR/include/tesseract/colfind.h b/TesseractOCR/include/tesseract/colfind.h new file mode 100644 index 00000000..b89d71f3 --- /dev/null +++ b/TesseractOCR/include/tesseract/colfind.h @@ -0,0 +1,358 @@ +/////////////////////////////////////////////////////////////////////// +// File: colfind.h +// Description: Class to find columns in the grid of BLOBNBOXes. +// Author: Ray Smith +// Created: Thu Feb 21 14:04:01 PST 2008 +// +// (C) Copyright 2008, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_COLFIND_H__ +#define TESSERACT_TEXTORD_COLFIND_H__ + +#include "tabfind.h" +#include "imagefind.h" +#include "colpartitiongrid.h" +#include "colpartitionset.h" +#include "ocrblock.h" +#include "textlineprojection.h" + +class BLOCK_LIST; +struct Boxa; +struct Pixa; +class DENORM; +class ScrollView; +class STATS; +class TO_BLOCK; + +namespace tesseract { + +extern BOOL_VAR_H(textord_tabfind_find_tables, false, "run table detection"); + +class ColPartitionSet; +class ColPartitionSet_LIST; +class ColSegment_LIST; +class ColumnGroup_LIST; +class LineSpacing; +class StrokeWidth; +class TempColumn_LIST; +class EquationDetectBase; + +// The ColumnFinder class finds columns in the grid. +class ColumnFinder : public TabFind { + public: + // Gridsize is an estimate of the text size in the image. A suitable value + // is in TO_BLOCK::line_size after find_components has been used to make + // the blobs. + // bleft and tright are the bounds of the image (rectangle) being processed. + // vlines is a (possibly empty) list of TabVector and vertical_x and y are + // the sum logical vertical vector produced by LineFinder::FindVerticalLines. + // If cjk_script is true, then broken CJK characters are fixed during + // layout analysis to assist in detecting horizontal vs vertically written + // textlines. + ColumnFinder(int gridsize, const ICOORD& bleft, const ICOORD& tright, + int resolution, bool cjk_script, TabVector_LIST* vlines, + TabVector_LIST* hlines, int vertical_x, int vertical_y); + virtual ~ColumnFinder(); + + // Accessors for testing + const DENORM* denorm() const { + return denorm_; + } + const TextlineProjection* projection() const { + return &projection_; + } + void set_cjk_script(bool is_cjk) { + cjk_script_ = is_cjk; + } + + // ====================================================================== + // The main function of ColumnFinder is broken into pieces to facilitate + // optional insertion of orientation and script detection in an efficient + // way. The calling sequence IS MANDATORY however, whether or not + // OSD is being used: + // 1. Construction. + // 2. SetupAndFilterNoise. + // 3. IsVerticallyAlignedText. + // 4. CorrectOrientation. + // 5. FindBlocks. + // 6. Destruction. Use of a single column finder for multiple images does not + // make sense. + // Throughout these steps, the ColPartitions are owned by part_grid_, which + // means that that it must be kept correct. Exception: big_parts_ owns its + // own ColPartitions. + // The BLOBNBOXes are owned by the input TO_BLOCK for the whole time, except + // for a phase in FindBlocks before TransformToBlocks, when they become + // owned by the ColPartitions. The owner() ColPartition of a BLOBNBOX + // indicates more of a betrothal for the majority of layout analysis, ie + // which ColPartition will take ownership when the blobs are release from + // the input TO_BLOCK. Exception: image_bblobs_ owns the fake blobs that + // are part of the image regions, as they are not on any TO_BLOCK list. + // TODO(rays) break up column finder further into smaller classes, as + // there is a lot more to it than column finding now. + // ====================================================================== + + // Performs initial processing on the blobs in the input_block: + // Setup the part_grid, stroke_width_, nontext_map_. + // Obvious noise blobs are filtered out and used to mark the nontext_map_. + // Initial stroke-width analysis is used to get local text alignment + // direction, so the textline projection_ map can be setup. + // On return, IsVerticallyAlignedText may be called (now optionally) to + // determine the gross textline alignment of the page. + void SetupAndFilterNoise(Pix* photo_mask_pix, TO_BLOCK* input_block); + + // Tests for vertical alignment of text (returning true if so), and generates + // a list of blobs (in osd_blobs) for orientation and script detection. + // block is the single block for the whole page or rectangle to be OCRed. + // Note that the vertical alignment may be due to text whose writing direction + // is vertical, like say Japanese, or due to text whose writing direction is + // horizontal but whose text appears vertically aligned because the image is + // not the right way up. + bool IsVerticallyAlignedText(TO_BLOCK* block, BLOBNBOX_CLIST* osd_blobs); + + // Rotates the blobs and the TabVectors so that the gross writing direction + // (text lines) are horizontal and lines are read down the page. + // Applied rotation stored in rotation_. + // A second rotation is calculated for application during recognition to + // make the rotated blobs upright for recognition. + // Subsequent rotation stored in text_rotation_. + // + // Arguments: + // vertical_text_lines is true if the text lines are vertical. + // recognition_rotation [0..3] is the number of anti-clockwise 90 degree + // rotations from osd required for the text to be upright and readable. + void CorrectOrientation(TO_BLOCK* block, bool vertical_text_lines, + int recognition_rotation); + + // Finds blocks of text, image, rule line, table etc, returning them in the + // blocks and to_blocks + // (Each TO_BLOCK points to the basic BLOCK and adds more information.) + // Image blocks are generated by a combination of photo_mask_pix (which may + // NOT be NULL) and the rejected text found during preliminary textline + // finding. + // The input_block is the result of a call to find_components, and contains + // the blobs found in the image or rectangle to be OCRed. These blobs will be + // removed and placed in the output blocks, while unused ones will be deleted. + // If single_column is true, the input is treated as single column, but + // it is still divided into blocks of equal line spacing/text size. + // scaled_color is scaled down by scaled_factor from the input color image, + // and may be NULL if the input was not color. + // grey_pix is optional, but if present must match the photo_mask_pix in size, + // and must be a *real* grey image instead of binary_pix * 255. + // thresholds_pix is expected to be present iff grey_pix is present and + // can be an integer factor reduction of the grey_pix. It represents the + // thresholds that were used to create the binary_pix from the grey_pix. + // Returns -1 if the user hits the 'd' key in the blocks window while running + // in debug mode, which requests a retry with more debug info. + int FindBlocks(PageSegMode pageseg_mode, + Pix* scaled_color, int scaled_factor, + TO_BLOCK* block, Pix* photo_mask_pix, + Pix* thresholds_pix, Pix* grey_pix, + BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks); + + // Get the rotation required to deskew, and its inverse rotation. + void GetDeskewVectors(FCOORD* deskew, FCOORD* reskew); + + // Set the equation detection pointer. + void SetEquationDetect(EquationDetectBase* detect); + + private: + // Displays the blob and block bounding boxes in a window called Blocks. + void DisplayBlocks(BLOCK_LIST* blocks); + // Displays the column edges at each grid y coordinate defined by + // best_columns_. + void DisplayColumnBounds(PartSetVector* sets); + + ////// Functions involved in determining the columns used on the page. ///// + + // Sets up column_sets_ (the determined column layout at each horizontal + // slice). Returns false if the page is empty. + bool MakeColumns(bool single_column); + // Attempt to improve the column_candidates by expanding the columns + // and adding new partitions from the partition sets in src_sets. + // Src_sets may be equal to column_candidates, in which case it will + // use them as a source to improve themselves. + void ImproveColumnCandidates(PartSetVector* src_sets, + PartSetVector* column_sets); + // Prints debug information on the column candidates. + void PrintColumnCandidates(const char* title); + // Finds the optimal set of columns that cover the entire image with as + // few changes in column partition as possible. + void AssignColumns(const PartSetVector& part_sets); + // Finds the biggest range in part_sets_ that has no assigned column, but + // column assignment is possible. + bool BiggestUnassignedRange(int set_count, const bool* any_columns_possible, + int* start, int* end); + // Finds the modal compatible column_set_ index within the given range. + int RangeModalColumnSet(int** column_set_costs, const int* assigned_costs, + int start, int end); + // Given that there are many column_set_id compatible columns in the range, + // shrinks the range to the longest contiguous run of compatibility, allowing + // gaps where no columns are possible, but not where competing columns are + // possible. + void ShrinkRangeToLongestRun(int** column_set_costs, + const int* assigned_costs, + const bool* any_columns_possible, + int column_set_id, + int* best_start, int* best_end); + // Moves start in the direction of step, upto, but not including end while + // the only incompatible regions are no more than kMaxIncompatibleColumnCount + // in size, and the compatible regions beyond are bigger. + void ExtendRangePastSmallGaps(int** column_set_costs, + const int* assigned_costs, + const bool* any_columns_possible, + int column_set_id, + int step, int end, int* start); + // Assigns the given column_set_id to the part_sets_ in the given range. + void AssignColumnToRange(int column_set_id, int start, int end, + int** column_set_costs, int* assigned_costs); + + // Computes the mean_column_gap_. + void ComputeMeanColumnGap(); + + //////// Functions that manipulate ColPartitions in the part_grid_ ///// + //////// to split, merge, find margins, and find types. ////////////// + + // Hoovers up all un-owned blobs and deletes them. + // The rest get released from the block so the ColPartitions can pass + // ownership to the output blocks. + void ReleaseBlobsAndCleanupUnused(TO_BLOCK* block); + // Splits partitions that cross columns where they have nothing in the gap. + void GridSplitPartitions(); + // Merges partitions where there is vertical overlap, within a single column, + // and the horizontal gap is small enough. + void GridMergePartitions(); + // Inserts remaining noise blobs into the most applicable partition if any. + // If there is no applicable partition, then the blobs are deleted. + void InsertRemainingNoise(TO_BLOCK* block); + // Remove partitions that come from horizontal lines that look like + // underlines, but are not part of a table. + void GridRemoveUnderlinePartitions(); + // Add horizontal line separators as partitions. + void GridInsertHLinePartitions(); + // Add vertical line separators as partitions. + void GridInsertVLinePartitions(); + // For every ColPartition in the grid, sets its type based on position + // in the columns. + void SetPartitionTypes(); + // Only images remain with multiple types in a run of partners. + // Sets the type of all in the group to the maximum of the group. + void SmoothPartnerRuns(); + + //////// Functions that make the final output blocks /////// + + // Helper functions for TransformToBlocks. + // Add the part to the temp list in the correct order. + void AddToTempPartList(ColPartition* part, ColPartition_CLIST* temp_list); + // Add everything from the temp list to the work_set assuming correct order. + void EmptyTempPartList(ColPartition_CLIST* temp_list, + WorkingPartSet_LIST* work_set); + + // Transform the grid of partitions to the output blocks. + void TransformToBlocks(BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks); + + // Reflect the blob boxes (but not the outlines) in the y-axis so that + // the blocks get created in the correct RTL order. Rotates the blobs + // in the input_block and the bblobs list. + // The reflection is undone in RotateAndReskewBlocks by + // reflecting the blocks themselves, and then recomputing the blob bounding + // boxes. + void ReflectForRtl(TO_BLOCK* input_block, BLOBNBOX_LIST* bblobs); + + // Undo the deskew that was done in FindTabVectors, as recognition is done + // without correcting blobs or blob outlines for skew. + // Reskew the completed blocks to put them back to the original rotated coords + // that were created by CorrectOrientation. + // If the input_is_rtl, then reflect the blocks in the y-axis to undo the + // reflection that was done before FindTabVectors. + // Blocks that were identified as vertical text (relative to the rotated + // coordinates) are further rotated so the text lines are horizontal. + // blob polygonal outlines are rotated to match the position of the blocks + // that they are in, and their bounding boxes are recalculated to be accurate. + // Record appropriate inverse transformations and required + // classifier transformation in the blocks. + void RotateAndReskewBlocks(bool input_is_rtl, TO_BLOCK_LIST* to_blocks); + + // Computes the rotations for the block (to make textlines horizontal) and + // for the blobs (for classification) and sets the appropriate members + // of the given block. + // Returns the rotation that needs to be applied to the blobs to make + // them sit in the rotated block. + FCOORD ComputeBlockAndClassifyRotation(BLOCK* block); + + // If true then the page language is cjk, so it is safe to perform + // FixBrokenCJK. + bool cjk_script_; + // The minimum gutter width to apply for finding columns. + // Modified when vertical text is detected to prevent detection of + // vertical text lines as columns. + int min_gutter_width_; + // The mean gap between columns over the page. + int mean_column_gap_; + // The rotation vector needed to convert original coords to deskewed. + FCOORD deskew_; + // The rotation vector needed to convert deskewed back to original coords. + FCOORD reskew_; + // The rotation vector used to rotate vertically oriented pages. + FCOORD rotation_; + // The rotation vector needed to convert the rotated back to original coords. + FCOORD rerotate_; + // The additional rotation vector needed to rotate text for recognition. + FCOORD text_rotation_; + // The column_sets_ contain the ordered candidate ColPartitionSets that + // define the possible divisions of the page into columns. + PartSetVector column_sets_; + // A simple array of pointers to the best assigned column division at + // each grid y coordinate. + ColPartitionSet** best_columns_; + // The grid used for creating initial partitions with strokewidth. + StrokeWidth* stroke_width_; + // The grid used to hold ColPartitions after the columns have been determined. + ColPartitionGrid part_grid_; + // List of ColPartitions that are no longer needed after they have been + // turned into regions, but are kept around because they are referenced + // by the part_grid_. + ColPartition_LIST good_parts_; + // List of ColPartitions that are big and might be dropcap or vertically + // joined. + ColPartition_LIST big_parts_; + // List of ColPartitions that have been declared noise. + ColPartition_LIST noise_parts_; + // The fake blobs that are made from the images. + BLOBNBOX_LIST image_bblobs_; + // Horizontal line separators. + TabVector_LIST horizontal_lines_; + // Image map of photo/noise areas on the page. + Pix* nontext_map_; + // Textline projection map. + TextlineProjection projection_; + // Sequence of DENORMS that indicate how to get back to the original image + // coordinate space. The destructor must delete all the DENORMs in the chain. + DENORM* denorm_; + + // Various debug windows that automatically go away on completion. + ScrollView* input_blobs_win_; + + // The equation region detector pointer. Note: This pointer is passed in by + // member function SetEquationDetect, and releasing it is NOT owned by this + // class. + EquationDetectBase* equation_detect_; + + // Allow a subsequent instance to reuse the blocks window. + // Not thread-safe, but multiple threads shouldn't be using windows anyway. + static ScrollView* blocks_win_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_COLFIND_H__ diff --git a/TesseractOCR/include/tesseract/colpartition.h b/TesseractOCR/include/tesseract/colpartition.h new file mode 100644 index 00000000..7f6cd643 --- /dev/null +++ b/TesseractOCR/include/tesseract/colpartition.h @@ -0,0 +1,912 @@ +/////////////////////////////////////////////////////////////////////// +// File: colpartition.h +// Description: Class to hold partitions of the page that correspond +// roughly to text lines. +// Author: Ray Smith +// Created: Thu Aug 14 10:50:01 PDT 2008 +// +// (C) Copyright 2008, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_COLPARTITION_H__ +#define TESSERACT_TEXTORD_COLPARTITION_H__ + +#include "bbgrid.h" +#include "blobbox.h" // For BlobRegionType. +#include "ndminx.h" +#include "ocrblock.h" +#include "rect.h" // For TBOX. +#include "scrollview.h" +#include "tabfind.h" // For WidthCallback. +#include "tabvector.h" // For BLOBNBOX_CLIST. + +namespace tesseract { + +// Number of colors in the color1, color2 arrays. +const int kRGBRMSColors = 4; + +class ColPartition; +class ColPartitionSet; +class ColPartitionGrid; +class WorkingPartSet; +class WorkingPartSet_LIST; + +// An enum to indicate how a partition sits on the columns. +// The order of flowing/heading/pullout must be kept consistent with +// PolyBlockType. +enum ColumnSpanningType { + CST_NOISE, // Strictly between columns. + CST_FLOWING, // Strictly within a single column. + CST_HEADING, // Spans multiple columns. + CST_PULLOUT, // Touches multiple columns, but doesn't span them. + CST_COUNT // Number of entries. +}; + +ELIST2IZEH(ColPartition) +CLISTIZEH(ColPartition) + +/** + * ColPartition is a partition of a horizontal slice of the page. + * It starts out as a collection of blobs at a particular y-coord in the grid, + * but ends up (after merging and uniquing) as an approximate text line. + * ColPartitions are also used to hold a partitioning of the page into + * columns, each representing one column. Although a ColPartition applies + * to a given y-coordinate range, eventually, a ColPartitionSet of ColPartitions + * emerges, which represents the columns over a wide y-coordinate range. + */ +class ColPartition : public ELIST2_LINK { + public: + ColPartition() { + // This empty constructor is here only so that the class can be ELISTIZED. + // TODO(rays) change deep_copy in elst.h line 955 to take a callback copier + // and eliminate CLASSNAME##_copier. + } + /** + * @param blob_type is the blob_region_type_ of the blobs in this partition. + * @param vertical is the direction of logical vertical on the possibly skewed image. + */ + ColPartition(BlobRegionType blob_type, const ICOORD& vertical); + /** + * Constructs a fake ColPartition with no BLOBNBOXes to represent a + * horizontal or vertical line, given a type and a bounding box. + */ + static ColPartition* MakeLinePartition(BlobRegionType blob_type, + const ICOORD& vertical, + int left, int bottom, + int right, int top); + + // Constructs and returns a fake ColPartition with a single fake BLOBNBOX, + // all made from a single TBOX. + // WARNING: Despite being on C_LISTs, the BLOBNBOX owns the C_BLOB and + // the ColPartition owns the BLOBNBOX!!! + // Call DeleteBoxes before deleting the ColPartition. + static ColPartition* FakePartition(const TBOX& box, + PolyBlockType block_type, + BlobRegionType blob_type, + BlobTextFlowType flow); + + // Constructs and returns a ColPartition with the given real BLOBNBOX, + // and sets it up to be a "big" partition (single-blob partition bigger + // than the surrounding text that may be a dropcap, two or more vertically + // touching characters, or some graphic element. + // If the given list is not NULL, the partition is also added to the list. + static ColPartition* MakeBigPartition(BLOBNBOX* box, + ColPartition_LIST* big_part_list); + + ~ColPartition(); + + // Simple accessors. + const TBOX& bounding_box() const { + return bounding_box_; + } + int left_margin() const { + return left_margin_; + } + void set_left_margin(int margin) { + left_margin_ = margin; + } + int right_margin() const { + return right_margin_; + } + void set_right_margin(int margin) { + right_margin_ = margin; + } + int median_top() const { + return median_top_; + } + int median_bottom() const { + return median_bottom_; + } + int median_left() const { + return median_left_; + } + int median_right() const { + return median_right_; + } + int median_size() const { + return median_size_; + } + void set_median_size(int size) { + median_size_ = size; + } + int median_width() const { + return median_width_; + } + void set_median_width(int width) { + median_width_ = width; + } + BlobRegionType blob_type() const { + return blob_type_; + } + void set_blob_type(BlobRegionType t) { + blob_type_ = t; + } + BlobTextFlowType flow() const { + return flow_; + } + void set_flow(BlobTextFlowType f) { + flow_ = f; + } + int good_blob_score() const { + return good_blob_score_; + } + bool good_width() const { + return good_width_; + } + bool good_column() const { + return good_column_; + } + bool left_key_tab() const { + return left_key_tab_; + } + int left_key() const { + return left_key_; + } + bool right_key_tab() const { + return right_key_tab_; + } + int right_key() const { + return right_key_; + } + PolyBlockType type() const { + return type_; + } + void set_type(PolyBlockType t) { + type_ = t; + } + BLOBNBOX_CLIST* boxes() { + return &boxes_; + } + int boxes_count() const { + return boxes_.length(); + } + void set_vertical(const ICOORD& v) { + vertical_ = v; + } + ColPartition_CLIST* upper_partners() { + return &upper_partners_; + } + ColPartition_CLIST* lower_partners() { + return &lower_partners_; + } + void set_working_set(WorkingPartSet* working_set) { + working_set_ = working_set; + } + bool block_owned() const { + return block_owned_; + } + void set_block_owned(bool owned) { + block_owned_ = owned; + } + bool desperately_merged() const { + return desperately_merged_; + } + ColPartitionSet* column_set() const { + return column_set_; + } + void set_side_step(int step) { + side_step_ = step; + } + int bottom_spacing() const { + return bottom_spacing_; + } + void set_bottom_spacing(int spacing) { + bottom_spacing_ = spacing; + } + int top_spacing() const { + return top_spacing_; + } + void set_top_spacing(int spacing) { + top_spacing_ = spacing; + } + + void set_table_type() { + if (type_ != PT_TABLE) { + type_before_table_ = type_; + type_ = PT_TABLE; + } + } + void clear_table_type() { + if (type_ == PT_TABLE) + type_ = type_before_table_; + } + bool inside_table_column() { + return inside_table_column_; + } + void set_inside_table_column(bool val) { + inside_table_column_ = val; + } + ColPartition* nearest_neighbor_above() const { + return nearest_neighbor_above_; + } + void set_nearest_neighbor_above(ColPartition* part) { + nearest_neighbor_above_ = part; + } + ColPartition* nearest_neighbor_below() const { + return nearest_neighbor_below_; + } + void set_nearest_neighbor_below(ColPartition* part) { + nearest_neighbor_below_ = part; + } + int space_above() const { + return space_above_; + } + void set_space_above(int space) { + space_above_ = space; + } + int space_below() const { + return space_below_; + } + void set_space_below(int space) { + space_below_ = space; + } + int space_to_left() const { + return space_to_left_; + } + void set_space_to_left(int space) { + space_to_left_ = space; + } + int space_to_right() const { + return space_to_right_; + } + void set_space_to_right(int space) { + space_to_right_ = space; + } + uinT8* color1() { + return color1_; + } + uinT8* color2() { + return color2_; + } + bool owns_blobs() const { + return owns_blobs_; + } + void set_owns_blobs(bool owns_blobs) { + // Do NOT change ownership flag when there are blobs in the list. + // Immediately set the ownership flag when creating copies. + ASSERT_HOST(boxes_.empty()); + owns_blobs_ = owns_blobs; + } + + // Inline quasi-accessors that require some computation. + + // Returns the middle y-coord of the bounding box. + int MidY() const { + return (bounding_box_.top() + bounding_box_.bottom()) / 2; + } + // Returns the middle y-coord of the median top and bottom. + int MedianY() const { + return (median_top_ + median_bottom_) / 2; + } + // Returns the middle x-coord of the bounding box. + int MidX() const { + return (bounding_box_.left() + bounding_box_.right()) / 2; + } + // Returns the sort key at any given x,y. + int SortKey(int x, int y) const { + return TabVector::SortKey(vertical_, x, y); + } + // Returns the x corresponding to the sortkey, y pair. + int XAtY(int sort_key, int y) const { + return TabVector::XAtY(vertical_, sort_key, y); + } + // Returns the x difference between the two sort keys. + int KeyWidth(int left_key, int right_key) const { + return (right_key - left_key) / vertical_.y(); + } + // Returns the column width between the left and right keys. + int ColumnWidth() const { + return KeyWidth(left_key_, right_key_); + } + // Returns the sort key of the box left edge. + int BoxLeftKey() const { + return SortKey(bounding_box_.left(), MidY()); + } + // Returns the sort key of the box right edge. + int BoxRightKey() const { + return SortKey(bounding_box_.right(), MidY()); + } + // Returns the left edge at the given y, using the sort key. + int LeftAtY(int y) const { + return XAtY(left_key_, y); + } + // Returns the right edge at the given y, using the sort key. + int RightAtY(int y) const { + return XAtY(right_key_, y); + } + // Returns true if the right edge of this is to the left of the right + // edge of other. + bool IsLeftOf(const ColPartition& other) const { + return bounding_box_.right() < other.bounding_box_.right(); + } + // Returns true if the partition contains the given x coordinate at the y. + bool ColumnContains(int x, int y) const { + return LeftAtY(y) - 1 <= x && x <= RightAtY(y) + 1; + } + // Returns true if there are no blobs in the list. + bool IsEmpty() const { + return boxes_.empty(); + } + // Returns true if there is a single blob in the list. + bool IsSingleton() const { + return boxes_.singleton(); + } + // Returns true if this and other overlap horizontally by bounding box. + bool HOverlaps(const ColPartition& other) const { + return bounding_box_.x_overlap(other.bounding_box_); + } + // Returns true if this and other's bounding boxes overlap vertically. + // TODO(rays) Make HOverlaps and VOverlaps truly symmetric. + bool VOverlaps(const ColPartition& other) const { + return bounding_box_.y_gap(other.bounding_box_) < 0; + } + // Returns the vertical overlap (by median) of this and other. + // WARNING! Only makes sense on horizontal partitions! + int VCoreOverlap(const ColPartition& other) const { + return MIN(median_top_, other.median_top_) - + MAX(median_bottom_, other.median_bottom_); + } + // Returns the horizontal overlap (by median) of this and other. + // WARNING! Only makes sense on vertical partitions! + int HCoreOverlap(const ColPartition& other) const { + return MIN(median_right_, other.median_right_) - + MAX(median_left_, other.median_left_); + } + // Returns true if this and other overlap significantly vertically. + // WARNING! Only makes sense on horizontal partitions! + bool VSignificantCoreOverlap(const ColPartition& other) const { + int overlap = VCoreOverlap(other); + int height = MIN(median_top_ - median_bottom_, + other.median_top_ - other.median_bottom_); + return overlap * 3 > height; + } + // Returns true if this and other can be combined without putting a + // horizontal step in either left or right edge of the resulting block. + bool WithinSameMargins(const ColPartition& other) const { + return left_margin_ <= other.bounding_box_.left() && + bounding_box_.left() >= other.left_margin_ && + bounding_box_.right() <= other.right_margin_ && + right_margin_ >= other.bounding_box_.right(); + } + // Returns true if the region types (aligned_text_) match. + // Lines never match anything, as they should never be merged or chained. + bool TypesMatch(const ColPartition& other) const { + return TypesMatch(blob_type_, other.blob_type_); + } + static bool TypesMatch(BlobRegionType type1, BlobRegionType type2) { + return (type1 == type2 || type1 == BRT_UNKNOWN || type2 == BRT_UNKNOWN) && + !BLOBNBOX::IsLineType(type1) && !BLOBNBOX::IsLineType(type2); + } + + // Returns true if the types are similar to each other. + static bool TypesSimilar(PolyBlockType type1, PolyBlockType type2) { + return (type1 == type2 || + (type1 == PT_FLOWING_TEXT && type2 == PT_INLINE_EQUATION) || + (type2 == PT_FLOWING_TEXT && type1 == PT_INLINE_EQUATION)); + } + + // Returns true if partitions is of horizontal line type + bool IsLineType() const { + return PTIsLineType(type_); + } + // Returns true if partitions is of image type + bool IsImageType() const { + return PTIsImageType(type_); + } + // Returns true if partitions is of text type + bool IsTextType() const { + return PTIsTextType(type_); + } + // Returns true if partitions is of pullout(inter-column) type + bool IsPulloutType() const { + return PTIsPulloutType(type_); + } + // Returns true if the partition is of an exclusively vertical type. + bool IsVerticalType() const { + return blob_type_ == BRT_VERT_TEXT || blob_type_ == BRT_VLINE; + } + // Returns true if the partition is of a definite horizontal type. + bool IsHorizontalType() const { + return blob_type_ == BRT_TEXT || blob_type_ == BRT_HLINE; + } + // Returns true is the partition is of a type that cannot be merged. + bool IsUnMergeableType() const { + return BLOBNBOX::UnMergeableType(blob_type_) || type_ == PT_NOISE; + } + // Returns true if this partition is a vertical line + // TODO(nbeato): Use PartitionType enum when Ray's code is submitted. + bool IsVerticalLine() const { + return IsVerticalType() && IsLineType(); + } + // Returns true if this partition is a horizontal line + // TODO(nbeato): Use PartitionType enum when Ray's code is submitted. + bool IsHorizontalLine() const { + return IsHorizontalType() && IsLineType(); + } + + // Adds the given box to the partition, updating the partition bounds. + // The list of boxes in the partition is updated, ensuring that no box is + // recorded twice, and the boxes are kept in increasing left position. + void AddBox(BLOBNBOX* box); + + // Removes the given box from the partition, updating the bounds. + void RemoveBox(BLOBNBOX* box); + + // Returns the tallest box in the partition, as measured perpendicular to the + // presumed flow of text. + BLOBNBOX* BiggestBox(); + + // Returns the bounding box excluding the given box. + TBOX BoundsWithoutBox(BLOBNBOX* box); + + // Claims the boxes in the boxes_list by marking them with a this owner + // pointer. + void ClaimBoxes(); + + // NULL the owner of the blobs in this partition, so they can be deleted + // independently of the ColPartition. + void DisownBoxes(); + // NULL the owner of the blobs in this partition that are owned by this + // partition, so they can be deleted independently of the ColPartition. + // Any blobs that are not owned by this partition get to keep their owner + // without an assert failure. + void DisownBoxesNoAssert(); + + // Delete the boxes that this partition owns. + void DeleteBoxes(); + + // Reflects the partition in the y-axis, assuming that its blobs have + // already been done. Corrects only a limited part of the members, since + // this function is assumed to be used shortly after initial creation, which + // is before a lot of the members are used. + void ReflectInYAxis(); + + // Returns true if this is a legal partition - meaning that the conditions + // left_margin <= bounding_box left + // left_key <= bounding box left key + // bounding box left <= bounding box right + // and likewise for right margin and key + // are all met. + bool IsLegal(); + + // Returns true if the left and right edges are approximately equal. + bool MatchingColumns(const ColPartition& other) const; + + // Returns true if the colors match for two text partitions. + bool MatchingTextColor(const ColPartition& other) const; + + // Returns true if the sizes match for two text partitions, + // taking orientation into account + bool MatchingSizes(const ColPartition& other) const; + + // Returns true if there is no tabstop violation in merging this and other. + bool ConfirmNoTabViolation(const ColPartition& other) const; + + // Returns true if other has a similar stroke width to this. + bool MatchingStrokeWidth(const ColPartition& other, + double fractional_tolerance, + double constant_tolerance) const; + // Returns true if candidate is an acceptable diacritic base char merge + // with this as the diacritic. + bool OKDiacriticMerge(const ColPartition& candidate, bool debug) const; + + // Sets the sort key using either the tab vector, or the bounding box if + // the tab vector is NULL. If the tab_vector lies inside the bounding_box, + // use the edge of the box as a key any way. + void SetLeftTab(const TabVector* tab_vector); + void SetRightTab(const TabVector* tab_vector); + + // Copies the left/right tab from the src partition, but if take_box is + // true, copies the box instead and uses that as a key. + void CopyLeftTab(const ColPartition& src, bool take_box); + void CopyRightTab(const ColPartition& src, bool take_box); + + // Returns the left rule line x coord of the leftmost blob. + int LeftBlobRule() const; + // Returns the right rule line x coord of the rightmost blob. + int RightBlobRule() const; + + // Returns the density value for a particular BlobSpecialTextType. + float SpecialBlobsDensity(const BlobSpecialTextType type) const; + // Returns the number of blobs for a particular BlobSpecialTextType. + int SpecialBlobsCount(const BlobSpecialTextType type); + // Set the density value for a particular BlobSpecialTextType, should ONLY be + // used for debugging or testing. In production code, use + // ComputeSpecialBlobsDensity instead. + void SetSpecialBlobsDensity( + const BlobSpecialTextType type, const float density); + // Compute the SpecialTextType density of blobs, where we assume + // that the SpecialTextType in the boxes_ has been set. + void ComputeSpecialBlobsDensity(); + + // Add a partner above if upper, otherwise below. + // Add them uniquely and keep the list sorted by box left. + // Partnerships are added symmetrically to partner and this. + void AddPartner(bool upper, ColPartition* partner); + // Removes the partner from this, but does not remove this from partner. + // This asymmetric removal is so as not to mess up the iterator that is + // working on partner's partner list. + void RemovePartner(bool upper, ColPartition* partner); + // Returns the partner if the given partner is a singleton, otherwise NULL. + ColPartition* SingletonPartner(bool upper); + + // Merge with the other partition and delete it. + void Absorb(ColPartition* other, WidthCallback* cb); + + // Returns true if the overlap between this and the merged pair of + // merge candidates is sufficiently trivial to be allowed. + // The merged box can graze the edge of this by the ok_box_overlap + // if that exceeds the margin to the median top and bottom. + bool OKMergeOverlap(const ColPartition& merge1, const ColPartition& merge2, + int ok_box_overlap, bool debug); + + // Find the blob at which to split this to minimize the overlap with the + // given box. Returns the first blob to go in the second partition. + BLOBNBOX* OverlapSplitBlob(const TBOX& box); + + // Split this partition keeping the first half in this and returning + // the second half. + // Splits by putting the split_blob and the blobs that follow + // in the second half, and the rest in the first half. + ColPartition* SplitAtBlob(BLOBNBOX* split_blob); + + // Splits this partition at the given x coordinate, returning the right + // half and keeping the left half in this. + ColPartition* SplitAt(int split_x); + + // Recalculates all the coordinate limits of the partition. + void ComputeLimits(); + + // Returns the number of boxes that overlap the given box. + int CountOverlappingBoxes(const TBOX& box); + + // Computes and sets the type_, first_column_, last_column_ and column_set_. + // resolution refers to the ppi resolution of the image. + void SetPartitionType(int resolution, ColPartitionSet* columns); + + // Returns the PartitionType from the current BlobRegionType and a column + // flow spanning type ColumnSpanningType, generated by + // ColPartitionSet::SpanningType, that indicates how the partition sits + // in the columns. + PolyBlockType PartitionType(ColumnSpanningType flow) const; + + // Returns the first and last column touched by this partition. + // resolution refers to the ppi resolution of the image. + void ColumnRange(int resolution, ColPartitionSet* columns, + int* first_col, int* last_col); + + // Sets the internal flags good_width_ and good_column_. + void SetColumnGoodness(WidthCallback* cb); + + // Determines whether the blobs in this partition mostly represent + // a leader (fixed pitch sequence) and sets the member blobs accordingly. + // Note that height is assumed to have been tested elsewhere, and that this + // function will find most fixed-pitch text as leader without a height filter. + // Leader detection is limited to sequences of identical width objects, + // such as .... or ----, so patterns, such as .-.-.-.-. will not be found. + bool MarkAsLeaderIfMonospaced(); + // Given the result of TextlineProjection::EvaluateColPartition, (positive for + // horizontal text, negative for vertical text, and near zero for non-text), + // sets the blob_type_ and flow_ for this partition to indicate whether it + // is strongly or weakly vertical or horizontal text, or non-text. + void SetRegionAndFlowTypesFromProjectionValue(int value); + + // Sets all blobs with the partition blob type and flow, but never overwrite + // leader blobs, as we need to be able to identify them later. + void SetBlobTypes(); + + // Returns true if a decent baseline can be fitted through the blobs. + // Works for both horizontal and vertical text. + bool HasGoodBaseline(); + + // Adds this ColPartition to a matching WorkingPartSet if one can be found, + // otherwise starts a new one in the appropriate column, ending the previous. + void AddToWorkingSet(const ICOORD& bleft, const ICOORD& tright, + int resolution, ColPartition_LIST* used_parts, + WorkingPartSet_LIST* working_set); + + // From the given block_parts list, builds one or more BLOCKs and + // corresponding TO_BLOCKs, such that the line spacing is uniform in each. + // Created blocks are appended to the end of completed_blocks and to_blocks. + // The used partitions are put onto used_parts, as they may still be referred + // to in the partition grid. bleft, tright and resolution are the bounds + // and resolution of the original image. + static void LineSpacingBlocks(const ICOORD& bleft, const ICOORD& tright, + int resolution, + ColPartition_LIST* block_parts, + ColPartition_LIST* used_parts, + BLOCK_LIST* completed_blocks, + TO_BLOCK_LIST* to_blocks); + // Constructs a block from the given list of partitions. + // Arguments are as LineSpacingBlocks above. + static TO_BLOCK* MakeBlock(const ICOORD& bleft, const ICOORD& tright, + ColPartition_LIST* block_parts, + ColPartition_LIST* used_parts); + + // Constructs a block from the given list of vertical text partitions. + // Currently only creates rectangular blocks. + static TO_BLOCK* MakeVerticalTextBlock(const ICOORD& bleft, + const ICOORD& tright, + ColPartition_LIST* block_parts, + ColPartition_LIST* used_parts); + + // Makes a TO_ROW matching this and moves all the blobs to it, transferring + // ownership to to returned TO_ROW. + TO_ROW* MakeToRow(); + + + // Returns a copy of everything except the list of boxes. The resulting + // ColPartition is only suitable for keeping in a column candidate list. + ColPartition* ShallowCopy() const; + // Returns a copy of everything with a shallow copy of the blobs. + // The blobs are still owned by their original parent, so they are + // treated as read-only. + ColPartition* CopyButDontOwnBlobs(); + + #ifndef GRAPHICS_DISABLED + // Provides a color for BBGrid to draw the rectangle. + ScrollView::Color BoxColor() const; + #endif // GRAPHICS_DISABLED + + // Prints debug information on this. + void Print() const; + // Prints debug information on the colors. + void PrintColors(); + + // Sets the types of all partitions in the run to be the max of the types. + void SmoothPartnerRun(int working_set_count); + + // Cleans up the partners of the given type so that there is at most + // one partner. This makes block creation simpler. + // If get_desperate is true, goes to more desperate merge methods + // to merge flowing text before breaking partnerships. + void RefinePartners(PolyBlockType type, bool get_desparate, + ColPartitionGrid* grid); + + // Returns true if this column partition is in the same column as + // part. This function will only work after the SetPartitionType function + // has been called on both column partitions. This is useful for + // doing a SideSearch when you want things in the same page column. + bool IsInSameColumnAs(const ColPartition& part) const; + + // Sets the column bounds. Primarily used in testing. + void set_first_column(int column) { + first_column_ = column; + } + void set_last_column(int column) { + last_column_ = column; + } + + private: + // enum to refer to the entries in a neigbourhood of lines. + // Used by SmoothSpacings to test for blips with OKSpacingBlip. + enum SpacingNeighbourhood { + PN_ABOVE2, + PN_ABOVE1, + PN_UPPER, + PN_LOWER, + PN_BELOW1, + PN_BELOW2, + PN_COUNT + }; + + // Cleans up the partners above if upper is true, else below. + // If get_desperate is true, goes to more desperate merge methods + // to merge flowing text before breaking partnerships. + void RefinePartnersInternal(bool upper, bool get_desperate, + ColPartitionGrid* grid); + // Restricts the partners to only desirable types. For text and BRT_HLINE this + // means the same type_ , and for image types it means any image type. + void RefinePartnersByType(bool upper, ColPartition_CLIST* partners); + // Remove transitive partnerships: this<->a, and a<->b and this<->b. + // Gets rid of this<->b, leaving a clean chain. + // Also if we have this<->a and a<->this, then gets rid of this<->a, as + // this has multiple partners. + void RefinePartnerShortcuts(bool upper, ColPartition_CLIST* partners); + // If multiple text partners can be merged, then do so. + // If desperate is true, then an increase in overlap with the merge is + // allowed. If the overlap increases, then the desperately_merged_ flag + // is set, indicating that the textlines probably need to be regenerated + // by aggressive line fitting/splitting, as there are probably vertically + // joined blobs that cross textlines. + void RefineTextPartnersByMerge(bool upper, bool desperate, + ColPartition_CLIST* partners, + ColPartitionGrid* grid); + // Keep the partner with the biggest overlap. + void RefinePartnersByOverlap(bool upper, ColPartition_CLIST* partners); + + // Return true if bbox belongs better in this than other. + bool ThisPartitionBetter(BLOBNBOX* bbox, const ColPartition& other); + + // Smoothes the spacings in the list into groups of equal linespacing. + // resolution is the resolution of the original image, used as a basis + // for thresholds in change of spacing. page_height is in pixels. + static void SmoothSpacings(int resolution, int page_height, + ColPartition_LIST* parts); + + // Returns true if the parts array of pointers to partitions matches the + // condition for a spacing blip. See SmoothSpacings for what this means + // and how it is used. + static bool OKSpacingBlip(int resolution, int median_spacing, + ColPartition** parts); + + // Returns true if both the top and bottom spacings of this match the given + // spacing to within suitable margins dictated by the image resolution. + bool SpacingEqual(int spacing, int resolution) const; + + // Returns true if both the top and bottom spacings of this and other + // match to within suitable margins dictated by the image resolution. + bool SpacingsEqual(const ColPartition& other, int resolution) const; + + // Returns true if the sum spacing of this and other match the given + // spacing (or twice the given spacing) to within a suitable margin dictated + // by the image resolution. + bool SummedSpacingOK(const ColPartition& other, + int spacing, int resolution) const; + + // Returns a suitable spacing margin that can be applied to bottoms of + // text lines, based on the resolution and the stored side_step_. + int BottomSpacingMargin(int resolution) const; + + // Returns a suitable spacing margin that can be applied to tops of + // text lines, based on the resolution and the stored side_step_. + int TopSpacingMargin(int resolution) const; + + // Returns true if the median text sizes of this and other agree to within + // a reasonable multiplicative factor. + bool SizesSimilar(const ColPartition& other) const; + + // Computes and returns in start, end a line segment formed from a + // forwards-iterated group of left edges of partitions that satisfy the + // condition that the rightmost left margin is to the left of the + // leftmost left bounding box edge. + // TODO(rays) Not good enough. Needs improving to tightly wrap text in both + // directions, and to loosely wrap images. + static void LeftEdgeRun(ColPartition_IT* part_it, + ICOORD* start, ICOORD* end); + // Computes and returns in start, end a line segment formed from a + // backwards-iterated group of right edges of partitions that satisfy the + // condition that the leftmost right margin is to the right of the + // rightmost right bounding box edge. + // TODO(rays) Not good enough. Needs improving to tightly wrap text in both + // directions, and to loosely wrap images. + static void RightEdgeRun(ColPartition_IT* part_it, + ICOORD* start, ICOORD* end); + + // The margins are determined by the position of the nearest vertically + // overlapping neighbour to the side. They indicate the maximum extent + // that the block/column may be extended without touching something else. + // Leftmost coordinate that the region may occupy over the y limits. + int left_margin_; + // Rightmost coordinate that the region may occupy over the y limits. + int right_margin_; + // Bounding box of all blobs in the partition. + TBOX bounding_box_; + // Median top and bottom of blobs in this partition. + int median_bottom_; + int median_top_; + // Median height of blobs in this partition. + // TODO(rays) rename median_height_. + int median_size_; + // Median left and right of blobs in this partition. + int median_left_; + int median_right_; + // Median width of blobs in this partition. + int median_width_; + // blob_region_type_ for the blobs in this partition. + BlobRegionType blob_type_; + BlobTextFlowType flow_; // Quality of text flow. + // Total of GoodTextBlob results for all blobs in the partition. + int good_blob_score_; + // True if this partition has a common width. + bool good_width_; + // True if this is a good column candidate. + bool good_column_; + // True if the left_key_ is from a tab vector. + bool left_key_tab_; + // True if the right_key_ is from a tab vector. + bool right_key_tab_; + // Left and right sort keys for the edges of the partition. + // If the respective *_key_tab_ is true then this key came from a tab vector. + // If not, then the class promises to keep the key equal to the sort key + // for the respective edge of the bounding box at the MidY, so that + // LeftAtY and RightAtY always returns an x coordinate on the line parallel + // to vertical_ through the bounding box edge at MidY. + int left_key_; + int right_key_; + // Type of this partition after looking at its relation to the columns. + PolyBlockType type_; + // All boxes in the partition stored in increasing left edge coordinate. + BLOBNBOX_CLIST boxes_; + // The global vertical skew direction. + ICOORD vertical_; + // The partitions above that matched this. + ColPartition_CLIST upper_partners_; + // The partitions below that matched this. + ColPartition_CLIST lower_partners_; + // The WorkingPartSet it lives in while blocks are being made. + WorkingPartSet* working_set_; + // Flag is true when AddBox is sorting vertically, false otherwise. + bool last_add_was_vertical_; + // True when the partition's ownership has been taken from the grid and + // placed in a working set, or, after that, in the good_parts_ list. + bool block_owned_; + // Flag to indicate that this partition was subjected to a desperate merge, + // and therefore the textlines need rebuilding. + bool desperately_merged_; + // The first and last column that this partition applies to. + // Flowing partitions (see type_) will have an equal first and last value + // of the form 2n + 1, where n is the zero-based index into the partitions + // in column_set_. (See ColPartitionSet::GetColumnByIndex). + // Heading partitions will have unequal values of the same form. + // Pullout partitions will have equal values, but may have even values, + // indicating placement between columns. + int first_column_; + int last_column_; + // Column_set_ is the column layout applicable to this ColPartition. + ColPartitionSet* column_set_; + // Linespacing data. + int side_step_; // Median y-shift to next blob on same line. + int top_spacing_; // Line spacing from median_top_. + int bottom_spacing_; // Line spacing from median_bottom_. + + // Type of this partition before considering it as a table cell. This is + // used to revert the type if a partition is first marked as a table cell but + // later filtering steps decide it does not belong to a table + PolyBlockType type_before_table_; + bool inside_table_column_; // Check whether the current partition has been + // assigned to a table column + // Nearest neighbor above with major x-overlap + ColPartition* nearest_neighbor_above_; + // Nearest neighbor below with major x-overlap + ColPartition* nearest_neighbor_below_; + int space_above_; // Distance from nearest_neighbor_above + int space_below_; // Distance from nearest_neighbor_below + int space_to_left_; // Distance from the left edge of the column + int space_to_right_; // Distance from the right edge of the column + // Color foreground/background data. + uinT8 color1_[kRGBRMSColors]; + uinT8 color2_[kRGBRMSColors]; + bool owns_blobs_; // Does the partition own its blobs? + // The density of special blobs. + float special_blobs_densities_[BSTT_COUNT]; +}; + +// Typedef it now in case it becomes a class later. +typedef GridSearch ColPartitionGridSearch; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_COLPARTITION_H__ diff --git a/TesseractOCR/include/tesseract/colpartitiongrid.h b/TesseractOCR/include/tesseract/colpartitiongrid.h new file mode 100644 index 00000000..40946e57 --- /dev/null +++ b/TesseractOCR/include/tesseract/colpartitiongrid.h @@ -0,0 +1,249 @@ +/////////////////////////////////////////////////////////////////////// +// File: colpartitionrid.h +// Description: Class collecting code that acts on a BBGrid of ColPartitions. +// Author: Ray Smith +// Created: Mon Oct 05 08:42:01 PDT 2009 +// +// (C) Copyright 2009, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_COLPARTITIONGRID_H__ +#define TESSERACT_TEXTORD_COLPARTITIONGRID_H__ + +#include "bbgrid.h" +#include "colpartition.h" +#include "colpartitionset.h" + +namespace tesseract { + +class TabFind; + +// ColPartitionGrid is a BBGrid of ColPartition. +// It collects functions that work on the grid. +class ColPartitionGrid : public BBGrid { + public: + ColPartitionGrid(); + ColPartitionGrid(int gridsize, const ICOORD& bleft, const ICOORD& tright); + + virtual ~ColPartitionGrid(); + + // Handles a click event in a display window. + void HandleClick(int x, int y); + + // Merges ColPartitions in the grid that look like they belong in the same + // textline. + // For all partitions in the grid, calls the box_cb permanent callback + // to compute the search box, seaches the box, and if a candidate is found, + // calls the confirm_cb to check any more rules. If the confirm_cb returns + // true, then the partitions are merged. + // Both callbacks are deleted before returning. + void Merges(TessResultCallback2* box_cb, + TessResultCallback2* confirm_cb); + + // For the given partition, calls the box_cb permanent callback + // to compute the search box, searches the box, and if a candidate is found, + // calls the confirm_cb to check any more rules. If the confirm_cb returns + // true, then the partitions are merged. + // Returns true if the partition is consumed by one or more merges. + bool MergePart(TessResultCallback2* box_cb, + TessResultCallback2* confirm_cb, + ColPartition* part); + + // Finds all the ColPartitions in the grid that overlap with the given + // box and returns them SortByBoxLeft(ed) and uniqued in the given list. + // Any partition equal to not_this (may be NULL) is excluded. + void FindOverlappingPartitions(const TBOX& box, const ColPartition* not_this, + ColPartition_CLIST* parts); + + // Finds and returns the best candidate ColPartition to merge with part, + // selected from the candidates list, based on the minimum increase in + // pairwise overlap among all the partitions overlapped by the combined box. + // If overlap_increase is not NULL then it returns the increase in overlap + // that would result from the merge. + // See colpartitiongrid.cpp for a diagram. + ColPartition* BestMergeCandidate( + const ColPartition* part, ColPartition_CLIST* candidates, bool debug, + TessResultCallback2* confirm_cb, + int* overlap_increase); + + // Split partitions where it reduces overlap between their bounding boxes. + // ColPartitions are after all supposed to be a partitioning of the blobs + // AND of the space on the page! + // Blobs that cause overlaps get removed, put in individual partitions + // and added to the big_parts list. They are most likely characters on + // 2 textlines that touch, or something big like a dropcap. + void SplitOverlappingPartitions(ColPartition_LIST* big_parts); + + // Filters partitions of source_type by looking at local neighbours. + // Where a majority of neighbours have a text type, the partitions are + // changed to text, where the neighbours have image type, they are changed + // to image, and partitions that have no definite neighbourhood type are + // left unchanged. + // im_box and rerotation are used to map blob coordinates onto the + // nontext_map, which is used to prevent the spread of text neighbourhoods + // into images. + // Returns true if anything was changed. + bool GridSmoothNeighbours(BlobTextFlowType source_type, Pix* nontext_map, + const TBOX& im_box, const FCOORD& rerotation); + + // Compute the mean RGB of the light and dark pixels in each ColPartition + // and also the rms error in the linearity of color. + void ComputePartitionColors(Pix* scaled_color, int scaled_factor, + const FCOORD& rerotation); + + // Reflects the grid and its colpartitions in the y-axis, assuming that + // all blob boxes have already been done. + void ReflectInYAxis(); + + // Rotates the grid and its colpartitions by the given angle, assuming that + // all blob boxes have already been done. + void Deskew(const FCOORD& deskew); + + // Transforms the grid of partitions to the output blocks, putting each + // partition into a separate block. We don't really care about the order, + // as we just want to get as much text as possible without trying to organize + // it into proper blocks or columns. + void ExtractPartitionsAsBlocks(BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks); + + // Sets the left and right tabs of the partitions in the grid. + void SetTabStops(TabFind* tabgrid); + + // Makes the ColPartSets and puts them in the PartSetVector ready + // for finding column bounds. Returns false if no partitions were found. + // Each ColPartition in the grid is placed in a single ColPartSet based + // on the bottom-left of its bounding box. + bool MakeColPartSets(PartSetVector* part_sets); + + // Makes a single ColPartitionSet consisting of a single ColPartition that + // represents the total horizontal extent of the significant content on the + // page. Used for the single column setting in place of automatic detection. + // Returns NULL if the page is empty of significant content. + ColPartitionSet* MakeSingleColumnSet(WidthCallback* cb); + + // Mark the BLOBNBOXes in each partition as being owned by that partition. + void ClaimBoxes(); + + // Retypes all the blobs referenced by the partitions in the grid. + // Image blobs are sliced on the grid boundaries to give the tab finder + // a better handle on the edges of the images, and the actual blobs are + // returned in the im_blobs list, as they are not owned by the block. + void ReTypeBlobs(BLOBNBOX_LIST* im_blobs); + + // The boxes within the partitions have changed (by deskew) so recompute + // the bounds of all the partitions and reinsert them into the grid. + void RecomputeBounds(int gridsize, const ICOORD& bleft, + const ICOORD& tright, const ICOORD& vertical); + + // Improves the margins of the ColPartitions in the grid by calling + // FindPartitionMargins on each. + void GridFindMargins(ColPartitionSet** best_columns); + + // Improves the margins of the ColPartitions in the list by calling + // FindPartitionMargins on each. + void ListFindMargins(ColPartitionSet** best_columns, + ColPartition_LIST* parts); + + // Deletes all the partitions in the grid after disowning all the blobs. + void DeleteParts(); + + // Deletes all the partitions in the grid that are of type BRT_UNKNOWN and + // all the blobs in them. + void DeleteUnknownParts(TO_BLOCK* block); + + // Finds and marks text partitions that represent figure captions. + void FindFigureCaptions(); + + //////// Functions that manipulate ColPartitions in the grid /////// + //////// to find chains of partner partitions of the same type. /////// + // For every ColPartition in the grid, finds its upper and lower neighbours. + void FindPartitionPartners(); + // Finds the best partner in the given direction for the given partition. + // Stores the result with AddPartner. + void FindPartitionPartners(bool upper, ColPartition* part); + // Finds the best partner in the given direction for the given partition. + // Stores the result with AddPartner. + void FindVPartitionPartners(bool to_the_left, ColPartition* part); + // For every ColPartition with multiple partners in the grid, reduces the + // number of partners to 0 or 1. If get_desperate is true, goes to more + // desperate merge methods to merge flowing text before breaking partnerships. + void RefinePartitionPartners(bool get_desperate); + + private: + // Finds and returns a list of candidate ColPartitions to merge with part. + // The candidates must overlap search_box, and when merged must not + // overlap any other partitions that are not overlapped by each individually. + void FindMergeCandidates(const ColPartition* part, const TBOX& search_box, + bool debug, ColPartition_CLIST* candidates); + + // Smoothes the region type/flow type of the given part by looking at local + // neigbours and the given image mask. Searches a padded rectangle with the + // padding truncated on one size of the part's box in turn for each side, + // using the result (if any) that has the least distance to all neighbours + // that contribute to the decision. This biases in favor of rectangular + // regions without completely enforcing them. + // If a good decision cannot be reached, the part is left unchanged. + // im_box and rerotation are used to map blob coordinates onto the + // nontext_map, which is used to prevent the spread of text neighbourhoods + // into images. + // Returns true if the partition was changed. + bool SmoothRegionType(Pix* nontext_map, + const TBOX& im_box, + const FCOORD& rerotation, + bool debug, + ColPartition* part); + // Executes the search for SmoothRegionType in a single direction. + // Creates a bounding box that is padded in all directions except direction, + // and searches it for other partitions. Finds the nearest collection of + // partitions that makes a decisive result (if any) and returns the type + // and the distance of the collection. If there are any pixels in the + // nontext_map, then the decision is biased towards image. + BlobRegionType SmoothInOneDirection(BlobNeighbourDir direction, + Pix* nontext_map, + const TBOX& im_box, + const FCOORD& rerotation, + bool debug, + const ColPartition& part, + int* best_distance); + // Counts the partitions in the given search_box by appending the gap + // distance (scaled by dist_scaling) of the part from the base_part to the + // vector of the appropriate type for the partition. Prior to return, the + // vectors in the dists array are sorted in increasing order. + // dists must be an array of GenericVectors of size NPT_COUNT. + void AccumulatePartDistances(const ColPartition& base_part, + const ICOORD& dist_scaling, + const TBOX& search_box, + Pix* nontext_map, + const TBOX& im_box, + const FCOORD& rerotation, + bool debug, + GenericVector* dists); + + // Improves the margins of the ColPartition by searching for + // neighbours that vertically overlap significantly. + void FindPartitionMargins(ColPartitionSet* columns, ColPartition* part); + + // Starting at x, and going in the specified direction, upto x_limit, finds + // the margin for the given y range by searching sideways, + // and ignoring not_this. + int FindMargin(int x, bool right_to_left, int x_limit, + int y_bottom, int y_top, const ColPartition* not_this); +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_COLPARTITIONGRID_H__ diff --git a/TesseractOCR/include/tesseract/colpartitionset.h b/TesseractOCR/include/tesseract/colpartitionset.h new file mode 100644 index 00000000..4c261665 --- /dev/null +++ b/TesseractOCR/include/tesseract/colpartitionset.h @@ -0,0 +1,170 @@ +/////////////////////////////////////////////////////////////////////// +// File: colpartitionset.h +// Description: Class to hold a list of ColPartitions of the page that +// correspond roughly to columns. +// Author: Ray Smith +// Created: Thu Aug 14 10:50:01 PDT 2008 +// +// (C) Copyright 2008, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_COLPARTITIONSET_H__ +#define TESSERACT_TEXTORD_COLPARTITIONSET_H__ + +#include "colpartition.h" // For ColPartition_LIST. +#include "genericvector.h" // For GenericVector. +#include "rect.h" // For TBOX. +#include "tabvector.h" // For BLOBNBOX_CLIST. + +namespace tesseract { + +class WorkingPartSet_LIST; +class ColSegment_LIST; +class ColPartitionSet; +typedef GenericVector PartSetVector; + +// ColPartitionSet is a class that holds a list of ColPartitions. +// Its main use is in holding a candidate partitioning of the width of the +// image into columns, where each member ColPartition is a single column. +// ColPartitionSets are used in building the column layout of a page. +class ColPartitionSet : public ELIST_LINK { + public: + ColPartitionSet() { + } + explicit ColPartitionSet(ColPartition_LIST* partitions); + explicit ColPartitionSet(ColPartition* partition); + + ~ColPartitionSet(); + + // Simple accessors. + const TBOX& bounding_box() const { + return bounding_box_; + } + bool Empty() { + return parts_.empty(); + } + int ColumnCount() { + return parts_.length(); + } + + // Return an element of the parts_ list from its index. + ColPartition* GetColumnByIndex(int index); + + // Return the ColPartition that contains the given coords, if any, else NULL. + ColPartition* ColumnContaining(int x, int y); + + // Return the bounding boxes of columns at the given y-range + void GetColumnBoxes(int y_bottom, int y_top, ColSegment_LIST *segments); + + // Extract all the parts from the list, relinquishing ownership. + void RelinquishParts(); + + // Attempt to improve this by adding partitions or expanding partitions. + void ImproveColumnCandidate(WidthCallback* cb, PartSetVector* src_sets); + + // If this set is good enough to represent a new partitioning into columns, + // add it to the vector of sets, otherwise delete it. + void AddToColumnSetsIfUnique(PartSetVector* column_sets, WidthCallback* cb); + + // Return true if the partitions in other are all compatible with the columns + // in this. + bool CompatibleColumns(bool debug, ColPartitionSet* other, WidthCallback* cb); + + // Returns the total width of all blobs in the part_set that do not lie + // within an approved column. Used as a cost measure for using this + // column set over another that might be compatible. + int UnmatchedWidth(ColPartitionSet* part_set); + + // Return true if this ColPartitionSet makes a legal column candidate by + // having legal individual partitions and non-overlapping adjacent pairs. + bool LegalColumnCandidate(); + + // Return a copy of this. If good_only will only copy the Good ColPartitions. + ColPartitionSet* Copy(bool good_only); + + // Display the edges of the columns at the given y coords. + void DisplayColumnEdges(int y_bottom, int y_top, ScrollView* win); + + // Return the ColumnSpanningType that best explains the columns overlapped + // by the given coords(left,right,y), with the given margins. + // Also return the first and last column index touched by the coords and + // the leftmost spanned column. + // Column indices are 2n + 1 for real colums (0 based) and even values + // represent the gaps in between columns, with 0 being left of the leftmost. + // resolution refers to the ppi resolution of the image. It may be 0 if only + // the first_col and last_col are required. + ColumnSpanningType SpanningType(int resolution, + int left, int right, int height, int y, + int left_margin, int right_margin, + int* first_col, int* last_col, + int* first_spanned_col); + + // The column_set has changed. Close down all in-progress WorkingPartSets in + // columns that do not match and start new ones for the new columns in this. + // As ColPartitions are turned into BLOCKs, the used ones are put in + // used_parts, as they still need to be referenced in the grid. + void ChangeWorkColumns(const ICOORD& bleft, const ICOORD& tright, + int resolution, ColPartition_LIST* used_parts, + WorkingPartSet_LIST* working_set); + + // Accumulate the widths and gaps into the given variables. + void AccumulateColumnWidthsAndGaps(int* total_width, int* width_samples, + int* total_gap, int* gap_samples); + + // Provide debug output for this ColPartitionSet and all the ColPartitions. + void Print(); + + private: + // Add the given partition to the list in the appropriate place. + void AddPartition(ColPartition* new_part, ColPartition_IT* it); + + // Compute the coverage and good column count. Coverage is the amount of the + // width of the page (in pixels) that is covered by ColPartitions, which are + // used to provide candidate column layouts. + // Coverage is split into good and bad. Good coverage is provided by + // ColPartitions of a frequent width (according to the callback function + // provided by TabFinder::WidthCB, which accesses stored statistics on the + // widths of ColParititions) and bad coverage is provided by all other + // ColPartitions, even if they have tab vectors at both sides. Thus: + // |-----------------------------------------------------------------| + // | Double width heading | + // |-----------------------------------------------------------------| + // |-------------------------------| |-------------------------------| + // | Common width ColParition | | Common width ColPartition | + // |-------------------------------| |-------------------------------| + // the layout with two common-width columns has better coverage than the + // double width heading, because the coverage is "good," even though less in + // total coverage than the heading, because the heading coverage is "bad." + void ComputeCoverage(); + + // Adds the coverage, column count and box for a single partition, + // without adding it to the list. (Helper factored from ComputeCoverage.) + void AddPartitionCoverageAndBox(const ColPartition& part); + + // The partitions in this column candidate. + ColPartition_LIST parts_; + // The number of partitions that have a frequent column width. + int good_column_count_; + // Total width of all the good ColPartitions. + int good_coverage_; + // Total width of all the bad ColPartitions. + int bad_coverage_; + // Bounding box of all partitions in the set. + TBOX bounding_box_; +}; + +ELISTIZEH(ColPartitionSet) + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_COLPARTITION_H__ diff --git a/TesseractOCR/include/tesseract/commandlineflags.h b/TesseractOCR/include/tesseract/commandlineflags.h new file mode 100644 index 00000000..11b0f82c --- /dev/null +++ b/TesseractOCR/include/tesseract/commandlineflags.h @@ -0,0 +1,83 @@ +/********************************************************************** + * File: commandlineflags.h + * Description: Header file for commandline flag parsing. + * Author: Ranjith Unnikrishnan + * Created: July 2013 + * + * (C) Copyright 2013, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ +#ifndef TESSERACT_TRAINING_COMMANDLINEFLAGS_H_ +#define TESSERACT_TRAINING_COMMANDLINEFLAGS_H_ + +#ifdef USE_STD_NAMESPACE + +#include +#include "tprintf.h" +#include "params.h" + +#define INT_PARAM_FLAG(name, val, comment) \ + INT_VAR(FLAGS_##name, val, comment) +#define DECLARE_INT_PARAM_FLAG(name) \ + extern INT_VAR_H(FLAGS_##name, 0, "") +#define DOUBLE_PARAM_FLAG(name, val, comment) \ + double_VAR(FLAGS_##name, val, comment) +#define DECLARE_DOUBLE_PARAM_FLAG(name) \ + extern double_VAR_H(FLAGS_##name, "", "") +#define BOOL_PARAM_FLAG(name, val, comment) \ + BOOL_VAR(FLAGS_##name, val, comment) +#define DECLARE_BOOL_PARAM_FLAG(name) \ + extern BOOL_VAR_H(FLAGS_##name, 0, "") +#define STRING_PARAM_FLAG(name, val, comment) \ + STRING_VAR(FLAGS_##name, val, comment) +#define DECLARE_STRING_PARAM_FLAG(name) \ + extern STRING_VAR_H(FLAGS_##name, "", "") + +#else + +#include "base/commandlineflags.h" +#define INT_PARAM_FLAG(name, val, comment) \ + DEFINE_int32(name, val, comment) +#define DECLARE_INT_PARAM_FLAG(name) \ + DECLARE_int32(name) +#define DOUBLE_PARAM_FLAG(name, val, comment) \ + DEFINE_double(name, val, comment) +#define DECLARE_DOUBLE_PARAM_FLAG(name) \ + DECLARE_double(name) +#define BOOL_PARAM_FLAG(name, val, comment) \ + DEFINE_bool(name, val, comment) +#define DECLARE_BOOL_PARAM_FLAG(name) \ + DECLARE_bool(name) +#define STRING_PARAM_FLAG(name, val, comment) \ + DEFINE_string(name, val, comment) +#define DECLARE_STRING_PARAM_FLAG(name) \ + DECLARE_string(name) + +#endif + +namespace tesseract { + +// Parse commandline flags and values. Prints the usage string and exits on +// input of --help or --helpshort. +// +// If remove_flags is true, the argv pointer is advanced so that (*argv)[1] +// points to the first non-flag argument, (*argv)[0] points to the same string +// as before, and argc is decremented to reflect the new shorter length of argv. +// eg. If the input *argv is +// { "program", "--foo=4", "--bar=true", "file1", "file2" } with *argc = 5, the +// output *argv is { "program", "file1", "file2" } with *argc = 3 +void ParseCommandLineFlags(const char* usage, int* argc, + char*** argv, const bool remove_flags); + +} + +#endif // TESSERACT_TRAINING_COMMANDLINEFLAGS_H_ diff --git a/TesseractOCR/include/tesseract/commontraining.h b/TesseractOCR/include/tesseract/commontraining.h new file mode 100644 index 00000000..7f38cf51 --- /dev/null +++ b/TesseractOCR/include/tesseract/commontraining.h @@ -0,0 +1,170 @@ +// Copyright 2008 Google Inc. All Rights Reserved. +// Author: scharron@google.com (Samuel Charron) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef TESSERACT_TRAINING_COMMONTRAINING_H__ +#define TESSERACT_TRAINING_COMMONTRAINING_H__ + +#include "cluster.h" +#include "commandlineflags.h" +#include "featdefs.h" +#include "intproto.h" +#include "oldlist.h" + +namespace tesseract { +class Classify; +class MasterTrainer; +class ShapeTable; +} + +////////////////////////////////////////////////////////////////////////////// +// Globals /////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +extern FEATURE_DEFS_STRUCT feature_defs; + +// Must be defined in the file that "implements" commonTraining facilities. +extern CLUSTERCONFIG Config; + +////////////////////////////////////////////////////////////////////////////// +// Structs /////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +typedef struct +{ + char *Label; + int SampleCount; + int font_sample_count; + LIST List; +} +LABELEDLISTNODE, *LABELEDLIST; + +typedef struct +{ + char* Label; + int NumMerged[MAX_NUM_PROTOS]; + CLASS_TYPE Class; +}MERGE_CLASS_NODE; +typedef MERGE_CLASS_NODE* MERGE_CLASS; + + +////////////////////////////////////////////////////////////////////////////// +// Functions ///////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void ParseArguments(int* argc, char*** argv); + +namespace tesseract { + +// Helper loads shape table from the given file. +ShapeTable* LoadShapeTable(const STRING& file_prefix); +// Helper to write the shape_table. +void WriteShapeTable(const STRING& file_prefix, const ShapeTable& shape_table); + +// Creates a MasterTraininer and loads the training data into it: +// Initializes feature_defs and IntegerFX. +// Loads the shape_table if shape_table != NULL. +// Loads initial unicharset from -U command-line option. +// If FLAGS_input_trainer is set, loads the majority of data from there, else: +// Loads font info from -F option. +// Loads xheights from -X option. +// Loads samples from .tr files in remaining command-line args. +// Deletes outliers and computes canonical samples. +// If FLAGS_output_trainer is set, saves the trainer for future use. +// Computes canonical and cloud features. +// If shape_table is not NULL, but failed to load, make a fake flat one, +// as shape clustering was not run. +MasterTrainer* LoadTrainingData(int argc, const char* const * argv, + bool replication, + ShapeTable** shape_table, + STRING* file_prefix); +} // namespace tesseract. + +const char *GetNextFilename(int argc, const char* const * argv); + +LABELEDLIST FindList( + LIST List, + char *Label); + +LABELEDLIST NewLabeledList( + const char *Label); + +void ReadTrainingSamples(const FEATURE_DEFS_STRUCT& feature_defs, + const char *feature_name, int max_samples, + UNICHARSET* unicharset, + FILE* file, LIST* training_samples); + +void WriteTrainingSamples( + const FEATURE_DEFS_STRUCT &FeatureDefs, + char *Directory, + LIST CharList, + const char *program_feature_type); + +void FreeTrainingSamples( + LIST CharList); + +void FreeLabeledList( + LABELEDLIST LabeledList); + +void FreeLabeledClassList( + LIST ClassListList); + +CLUSTERER *SetUpForClustering( + const FEATURE_DEFS_STRUCT &FeatureDefs, + LABELEDLIST CharSample, + const char *program_feature_type); + +LIST RemoveInsignificantProtos( + LIST ProtoList, + BOOL8 KeepSigProtos, + BOOL8 KeepInsigProtos, + int N); + +void CleanUpUnusedData( + LIST ProtoList); + +void MergeInsignificantProtos( + LIST ProtoList, + const char *label, + CLUSTERER *Clusterer, + CLUSTERCONFIG *Config); + +MERGE_CLASS FindClass( + LIST List, + const char *Label); + +MERGE_CLASS NewLabeledClass( + const char *Label); + +void FreeTrainingSamples( + LIST CharList); + +CLASS_STRUCT* SetUpForFloat2Int(const UNICHARSET& unicharset, + LIST LabeledClassList); + +void Normalize( + float *Values); + +void FreeNormProtoList( + LIST CharList); + +void AddToNormProtosList( + LIST* NormProtoList, + LIST ProtoList, + char *CharName); + +int NumberOfProtos( + LIST ProtoList, + BOOL8 CountSigProtos, + BOOL8 CountInsigProtos); + + +void allocNormProtos(); +#endif // TESSERACT_TRAINING_COMMONTRAINING_H__ diff --git a/TesseractOCR/include/tesseract/con_comp.h b/TesseractOCR/include/tesseract/con_comp.h new file mode 100644 index 00000000..4d000154 --- /dev/null +++ b/TesseractOCR/include/tesseract/con_comp.h @@ -0,0 +1,124 @@ +/********************************************************************** + * File: con_comp.h + * Description: Declaration of a Connected Component class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef CONCOMP_H +#define CONCOMP_H + +// The ConComp class implements the functionality needed for a +// Connected Component object and Connected Component (ConComp) points. +// The points consituting a connected component are kept in a linked-list +// The Concomp class provided methods to: +// 1- Compare components in L2R and R2L reading orders. +// 2- Merge ConComps +// 3- Compute the windowed vertical pixel density histogram for a specific +// windows size +// 4- Segment a ConComp based on the local windowed vertical pixel +// density histogram local minima + +namespace tesseract { + +// Implments a ConComp point in a linked list of points +class ConCompPt { + public: + ConCompPt(int x, int y) { + x_ = x; + y_ = y; + next_pt_ = NULL; + } + inline int x() { return x_; } + inline int y() { return y_; } + inline void Shift(int dx, int dy) { + x_ += dx; + y_ += dy; + } + inline ConCompPt * Next() { return next_pt_; } + inline void SetNext(ConCompPt *pt) { next_pt_ = pt; } + + private: + int x_; + int y_; + ConCompPt *next_pt_; +}; + +class ConComp { + public: + ConComp(); + virtual ~ConComp(); + // accessors + inline ConCompPt *Head() { return head_; } + inline int Left() const { return left_; } + inline int Top() const { return top_; } + inline int Right() const { return right_; } + inline int Bottom() const { return bottom_; } + inline int Width() const { return right_ - left_ + 1; } + inline int Height() const { return bottom_ - top_ + 1; } + + // Comparer used for sorting L2R reading order + inline static int Left2RightComparer(const void *comp1, + const void *comp2) { + return (*(reinterpret_cast(comp1)))->left_ + + (*(reinterpret_cast(comp1)))->right_ - + (*(reinterpret_cast(comp2)))->left_ - + (*(reinterpret_cast(comp2)))->right_; + } + + // Comparer used for sorting R2L reading order + inline static int Right2LeftComparer(const void *comp1, + const void *comp2) { + return (*(reinterpret_cast(comp2)))->right_ - + (*(reinterpret_cast(comp1)))->right_; + } + + // accessors for attribues of a ConComp + inline bool LeftMost() const { return left_most_; } + inline bool RightMost() const { return right_most_; } + inline void SetLeftMost(bool left_most) { left_most_ = left_most; } + inline void SetRightMost(bool right_most) { right_most_ = right_most; + } + inline int ID () const { return id_; } + inline void SetID(int id) { id_ = id; } + inline int PtCnt () const { return pt_cnt_; } + // Add a new pt + bool Add(int x, int y); + // Merge two connected components in-place + bool Merge(ConComp *con_comp); + // Shifts the co-ordinates of all points by the specified x & y deltas + void Shift(int dx, int dy); + // segments a concomp based on pixel density histogram local minima + ConComp **Segment(int max_hist_wnd, int *concomp_cnt); + // creates the vertical pixel density histogram of the concomp + int *CreateHistogram(int max_hist_wnd); + // find out the seg pts by looking for local minima in the histogram + int *SegmentHistogram(int *hist_array, int *seg_pt_cnt); + + private: + int id_; + bool left_most_; + bool right_most_; + int left_; + int top_; + int right_; + int bottom_; + ConCompPt *head_; + ConCompPt *tail_; + int pt_cnt_; +}; +} + +#endif // CONCOMP_H diff --git a/TesseractOCR/include/tesseract/const.h b/TesseractOCR/include/tesseract/const.h new file mode 100644 index 00000000..33f8fa44 --- /dev/null +++ b/TesseractOCR/include/tesseract/const.h @@ -0,0 +1,23 @@ +/************************************************************************** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. +**************************************************************************/ + +#ifndef CONST_H +#define CONST_H + +/*This file contains constants which are global to the entire system*/ +#define SPLINESIZE 23 // max spline parts to a line + +#define PI 3.14159265359 // pi + +#define EDGEPTFLAGS 4 // concavity,length etc. + +#endif diff --git a/TesseractOCR/include/tesseract/control.h b/TesseractOCR/include/tesseract/control.h old mode 100755 new mode 100644 index 080c82aa..2f76a47c --- a/TesseractOCR/include/tesseract/control.h +++ b/TesseractOCR/include/tesseract/control.h @@ -30,7 +30,6 @@ #include "ratngs.h" #include "statistc.h" #include "pageres.h" -#include "notdll.h" enum ACCEPTABLE_WERD_TYPE { diff --git a/TesseractOCR/include/tesseract/conv_net_classifier.h b/TesseractOCR/include/tesseract/conv_net_classifier.h new file mode 100644 index 00000000..e9bcd8c2 --- /dev/null +++ b/TesseractOCR/include/tesseract/conv_net_classifier.h @@ -0,0 +1,94 @@ +/********************************************************************** + * File: conv_net_classifier.h + * Description: Declaration of Convolutional-NeuralNet Character Classifier + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The ConvNetCharClassifier inherits from the base classifier class: +// "CharClassifierBase". It implements a Convolutional Neural Net classifier +// instance of the base classifier. It uses the Tesseract Neural Net library +// The Neural Net takes a scaled version of a bitmap and feeds it to a +// Convolutional Neural Net as input and performs a FeedForward. Each output +// of the net corresponds to class_id in the CharSet passed at construction +// time. +// Afterwards, the outputs of the Net are "folded" using the folding set +// (if any) +#ifndef CONV_NET_CLASSIFIER_H +#define CONV_NET_CLASSIFIER_H + +#include +#include "char_samp.h" +#include "char_altlist.h" +#include "char_set.h" +#include "feature_base.h" +#include "classifier_base.h" +#include "neural_net.h" +#include "lang_model.h" +#include "tuning_params.h" + +namespace tesseract { + +// Folding Ratio is the ratio of the max-activation of members of a folding +// set that is used to compute the min-activation of the rest of the set +static const float kFoldingRatio = 0.75; + +class ConvNetCharClassifier : public CharClassifier { + public: + ConvNetCharClassifier(CharSet *char_set, TuningParams *params, + FeatureBase *feat_extract); + virtual ~ConvNetCharClassifier(); + // The main training function. Given a sample and a class ID the classifier + // updates its parameters according to its learning algorithm. This function + // is currently not implemented. TODO(ahmadab): implement end-2-end training + virtual bool Train(CharSamp *char_samp, int ClassID); + // A secondary function needed for training. Allows the trainer to set the + // value of any train-time paramter. This function is currently not + // implemented. TODO(ahmadab): implement end-2-end training + virtual bool SetLearnParam(char *var_name, float val); + // Externally sets the Neural Net used by the classifier. Used for training + void SetNet(tesseract::NeuralNet *net); + + // Classifies an input charsamp and return a CharAltList object containing + // the possible candidates and corresponding scores + virtual CharAltList * Classify(CharSamp *char_samp); + // Computes the cost of a specific charsamp being a character (versus a + // non-character: part-of-a-character OR more-than-one-character) + virtual int CharCost(CharSamp *char_samp); + + + private: + // Neural Net object used for classification + tesseract::NeuralNet *char_net_; + // data buffers used to hold Neural Net inputs and outputs + float *net_input_; + float *net_output_; + + // Init the classifier provided a data-path and a language string + virtual bool Init(const string &data_file_path, const string &lang, + LangModel *lang_mod); + // Loads the NeuralNets needed for the classifier + bool LoadNets(const string &data_file_path, const string &lang); + // Loads the folding sets provided a data-path and a language string + virtual bool LoadFoldingSets(const string &data_file_path, + const string &lang, + LangModel *lang_mod); + // Folds the output of the NeuralNet using the loaded folding sets + virtual void Fold(); + // Scales the input char_samp and feeds it to the NeuralNet as input + bool RunNets(CharSamp *char_samp); +}; +} +#endif // CONV_NET_CLASSIFIER_H diff --git a/TesseractOCR/include/tesseract/coutln.h b/TesseractOCR/include/tesseract/coutln.h old mode 100755 new mode 100644 index 6dd60ff7..fd0b6736 --- a/TesseractOCR/include/tesseract/coutln.h +++ b/TesseractOCR/include/tesseract/coutln.h @@ -27,6 +27,8 @@ #include "blckerr.h" #include "scrollview.h" +class DENORM; + #define INTERSECTING MAX_INT16//no winding number //mask to get step @@ -37,15 +39,38 @@ enum C_OUTLINE_FLAGS COUT_INVERSE //White on black blob }; +// Simple struct to hold the 3 values needed to compute a more precise edge +// position and direction. The offset_numerator is the difference between the +// grey threshold and the mean pixel value. pixel_diff is the difference between +// the pixels in the edge. Consider the following row of pixels: p1 p2 p3 p4 p5 +// Say the image was thresholded at threshold t, making p1, p2, p3 black +// and p4, p5 white (p1, p2, p3 < t, and p4, p5 >= t), but suppose that +// max(p[i+1] - p[i]) is p3 - p2. Then the extrapolated position of the edge, +// based on the maximum gradient, is at the crack between p2 and p3 plus the +// offset (t - (p2+p3)/2)/(p3 - p2). We store the pixel difference p3-p2 +// denominator in pixel_diff and the offset numerator, relative to the original +// binary edge (t - (p2+p3)/2) - (p3 -p2) in offset_numerator. +// The sign of offset_numerator and pixel_diff are manipulated to ensure +// that the pixel_diff, which will be used as a weight, is always positive. +// The direction stores the quantized feature direction for the given step +// computed from the edge gradient. (Using binary_angle_plus_pi.) +// If the pixel_diff is zero, it means that the direction of the gradient +// is in conflict with the step direction, so this step is to be ignored. +struct EdgeOffset { + inT8 offset_numerator; + uinT8 pixel_diff; + uinT8 direction; +}; + class DLLSYM C_OUTLINE; //forward declaration struct Pix; ELISTIZEH (C_OUTLINE) -class DLLSYM C_OUTLINE:public ELIST_LINK -{ - public: - C_OUTLINE() { //empty constructor +class DLLSYM C_OUTLINE:public ELIST_LINK { + public: + C_OUTLINE() { //empty constructor steps = NULL; + offsets = NULL; } C_OUTLINE( //constructor CRACKEDGE *startpt, //from edge detector @@ -65,6 +90,7 @@ class DLLSYM C_OUTLINE:public ELIST_LINK if (steps != NULL) free_mem(steps); steps = NULL; + delete [] offsets; } BOOL8 flag( //test flag @@ -104,26 +130,73 @@ class DLLSYM C_OUTLINE:public ELIST_LINK //squeeze 4 into byte } - //get start position - const ICOORD &start_pos() const { - return start; - } inT32 pathlength() const { //get path length return stepcount; } // Return step at a given index as a DIR128. - DIR128 step_dir(inT16 index) const { + DIR128 step_dir(int index) const { return DIR128((inT16)(((steps[index/4] >> (index%4 * 2)) & STEP_MASK) << (DIRBITS - 2))); } // Return the step vector for the given outline position. - ICOORD step(inT16 index) const { //index of step - return step_coords[(steps[index/4] >> (index%4 * 2)) & STEP_MASK]; + ICOORD step(int index) const { // index of step + return step_coords[chain_code(index)]; + } + // get start position + const ICOORD &start_pos() const { + return start; + } + // Returns the position at the given index on the outline. + // NOT to be used lightly, as it has to iterate the outline to find out. + ICOORD position_at_index(int index) const { + ICOORD pos = start; + for (int i = 0; i < index; ++i) + pos += step(i); + return pos; + } + // Returns the sub-pixel accurate position given the integer position pos + // at the given index on the outline. pos may be a return value of + // position_at_index, or computed by repeatedly adding step to the + // start_pos() in the usual way. + FCOORD sub_pixel_pos_at_index(const ICOORD& pos, int index) const { + const ICOORD& step_to_next(step(index)); + FCOORD f_pos(pos.x() + step_to_next.x() / 2.0f, + pos.y() + step_to_next.y() / 2.0f); + if (offsets != NULL && offsets[index].pixel_diff > 0) { + float offset = offsets[index].offset_numerator; + offset /= offsets[index].pixel_diff; + if (step_to_next.x() != 0) + f_pos.set_y(f_pos.y() + offset); + else + f_pos.set_x(f_pos.x() + offset); + } + return f_pos; + } + // Returns the step direction for the given index or -1 if there is none. + int direction_at_index(int index) const { + if (offsets != NULL && offsets[index].pixel_diff > 0) + return offsets[index].direction; + return -1; + } + // Returns the edge strength for the given index. + // If there are no recorded edge strengths, returns 1 (assuming the image + // is binary). Returns 0 if the gradient direction conflicts with the + // step direction, indicating that this position could be skipped. + int edge_strength_at_index(int index) const { + if (offsets != NULL) + return offsets[index].pixel_diff; + return 1; + } + // Return the step as a chain code (0-3) related to the standard feature + // direction of binary_angle_plus_pi by: + // chain_code * 64 = feature direction. + int chain_code(int index) const { // index of step + return (steps[index / 4] >> (index % 4 * 2)) & STEP_MASK; } - inT32 area(); //return area - inT32 perimeter(); // Total perimeter of self and 1st level children. - inT32 outer_area(); //return area + inT32 area() const; // Returns area of self and 1st level children. + inT32 perimeter() const; // Total perimeter of self and 1st level children. + inT32 outer_area() const; // Returns area of self only. inT32 count_transitions( //count maxima inT32 threshold); //size threshold @@ -143,6 +216,12 @@ class DLLSYM C_OUTLINE:public ELIST_LINK void move( // reposition outline const ICOORD vec); // by vector + // Returns true if *this and its children are legally nested. + // The outer area of a child should have the opposite sign to the + // parent. If not, it means we have discarded an outline in between + // (probably due to excessive length). + bool IsLegallyNested() const; + // If this outline is smaller than the given min_size, delete this and // remove from its list, via *it, after checking that *it points to this. // Otherwise, if any children of this are too small, delete them. @@ -150,6 +229,13 @@ class DLLSYM C_OUTLINE:public ELIST_LINK // then this is extracted from *it, so an iteration can continue. void RemoveSmallRecursive(int min_size, C_OUTLINE_IT* it); + // Adds sub-pixel resolution EdgeOffsets for the outline if the supplied + // pix is 8-bit. Does nothing otherwise. + void ComputeEdgeOffsets(int threshold, Pix* pix); + // Adds sub-pixel resolution EdgeOffsets for the outline using only + // a binary image source. + void ComputeBinaryOffsets(); + // Renders the outline to the given pix, with left and top being // the coords of the upper-left corner of the pix. void render(int left, int top, Pix* pix) const; @@ -162,6 +248,10 @@ class DLLSYM C_OUTLINE:public ELIST_LINK void plot( //draw one ScrollView* window, //window to draw in ScrollView::Color colour) const; //colour to draw it + // Draws the outline in the given colour, normalized using the given denorm, + // making use of sub-pixel accurate information if available. + void plot_normed(const DENORM& denorm, ScrollView::Color colour, + ScrollView* window) const; #endif // GRAPHICS_DISABLED C_OUTLINE& operator=(const C_OUTLINE& source); @@ -174,15 +264,28 @@ class DLLSYM C_OUTLINE:public ELIST_LINK static ICOORD chain_step(int chaindir); + // The maximum length of any outline. The stepcount is stored as 16 bits, + // but it is probably not a good idea to increase this constant by much + // and switch to 32 bits, as it plays an important role in keeping huge + // outlines invisible, which prevents bad speed behavior. + static const int kMaxOutlineLength = 16000; + private: + // Helper for ComputeBinaryOffsets. Increments pos, dir_counts, pos_totals + // by the step, increment, and vertical step ? x : y position * increment + // at step s Mod stepcount respectively. Used to add or subtract the + // direction and position to/from accumulators of a small neighbourhood. + void increment_step(int s, int increment, ICOORD* pos, int* dir_counts, + int* pos_totals) const; int step_mem() const { return (stepcount+3) / 4; } - TBOX box; //boudning box - ICOORD start; //start coord - uinT8 *steps; //step array - inT16 stepcount; //no of steps - BITS16 flags; //flags about outline - C_OUTLINE_LIST children; //child elements + TBOX box; // bounding box + ICOORD start; // start coord + inT16 stepcount; // no of steps + BITS16 flags; // flags about outline + uinT8 *steps; // step array + EdgeOffset* offsets; // Higher precision edge. + C_OUTLINE_LIST children; // child elements static ICOORD step_coords[4]; }; #endif diff --git a/TesseractOCR/include/tesseract/crakedge.h b/TesseractOCR/include/tesseract/crakedge.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/cube_const.h b/TesseractOCR/include/tesseract/cube_const.h new file mode 100644 index 00000000..36d40bbc --- /dev/null +++ b/TesseractOCR/include/tesseract/cube_const.h @@ -0,0 +1,41 @@ +/********************************************************************** + * File: const.h + * Description: Defintions of constants used by Cube + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef CUBE_CONST_H +#define CUBE_CONST_H + +// Scale used to normalize a log-prob to a cost +#define PROB2COST_SCALE 4096.0 +// Maximum possible cost (-log prob of MIN_PROB) +#define MIN_PROB_COST 65536 +// Probability corresponding to the max cost MIN_PROB_COST +#define MIN_PROB 0.000000113 +// Worst possible cost (returned on failure) +#define WORST_COST 0x40000 +// Oversegmentation hysteresis thresholds +#define HIST_WND_RATIO 0.1f +#define SEG_PT_WND_RATIO 0.1f + +#ifdef _WIN32 +#ifdef __GNUC__ +#include +#endif +#endif + +#endif // CUBE_CONST_H diff --git a/TesseractOCR/include/tesseract/cube_line_object.h b/TesseractOCR/include/tesseract/cube_line_object.h new file mode 100644 index 00000000..037ae6b6 --- /dev/null +++ b/TesseractOCR/include/tesseract/cube_line_object.h @@ -0,0 +1,67 @@ +/********************************************************************** + * File: cube_line_object.h + * Description: Declaration of the Cube Line Object Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CubeLineObject implements an objects that holds a line of text +// Each line is broken into phrases. Phrases are blocks within the line that +// are unambiguously separate collections of words + +#ifndef CUBE_LINE_OBJECT_H +#define CUBE_LINE_OBJECT_H + +#include "cube_reco_context.h" +#include "cube_object.h" +#include "allheaders.h" + +namespace tesseract { +class CubeLineObject { + public: + CubeLineObject(CubeRecoContext *cntxt, Pix *pix); + ~CubeLineObject(); + + // accessors + inline int PhraseCount() { + if (!processed_ && !Process()) { + return 0; + } + return phrase_cnt_; + } + inline CubeObject **Phrases() { + if (!processed_ && !Process()) { + return NULL; + } + return phrases_; + } + + private: + CubeRecoContext *cntxt_; + bool own_pix_; + bool processed_; + Pix *line_pix_; + CubeObject **phrases_; + int phrase_cnt_; + bool Process(); + // Compute the least word breaking threshold that is required to produce a + // valid set of phrases. Phrases are validated using the Aspect ratio + // constraints specified in the language specific Params object + int ComputeWordBreakThreshold(int con_comp_cnt, ConComp **con_comps, + bool rtl); +}; +} + +#endif // CUBE_LINE_OBJECT_H diff --git a/TesseractOCR/include/tesseract/cube_line_segmenter.h b/TesseractOCR/include/tesseract/cube_line_segmenter.h new file mode 100644 index 00000000..43d19e57 --- /dev/null +++ b/TesseractOCR/include/tesseract/cube_line_segmenter.h @@ -0,0 +1,156 @@ +/********************************************************************** + * File: cube_page_segmenter.h + * Description: Declaration of the Cube Page Segmenter Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// TODO(ahmadab) +// This is really a makeshift line segmenter that works well for Arabic +// This should eventually be replaced by Ray Smith's Page segmenter +// There are lots of magic numbers below that were determined empirically +// but not thoroughly tested + +#ifndef CUBE_LINE_SEGMENTER_H +#define CUBE_LINE_SEGMENTER_H + +#include "cube_reco_context.h" +#include "allheaders.h" + +namespace tesseract { + +class CubeLineSegmenter { + public: + CubeLineSegmenter(CubeRecoContext *cntxt, Pix *img); + ~CubeLineSegmenter(); + + // Accessor functions + Pix *PostProcessedImage() { + if (init_ == false && Init() == false) { + return NULL; + } + return img_; + } + int ColumnCnt() { + if (init_ == false && Init() == false) { + return 0; + } + return columns_->n; + } + Box *Column(int col) { + if (init_ == false && Init() == false) { + return NULL; + } + + return columns_->boxa->box[col]; + } + int LineCnt() { + if (init_ == false && Init() == false) { + return 0; + } + + return line_cnt_; + } + Pixa *ConComps() { + if (init_ == false && Init() == false) { + return NULL; + } + + return con_comps_; + } + Pixaa *Columns() { + if (init_ == false && Init() == false) { + return NULL; + } + + return columns_; + } + inline double AlefHgtEst() { return est_alef_hgt_; } + inline double DotHgtEst() { return est_dot_hgt_; } + Pix *Line(int line, Box **line_box); + + private: + static const float kMinValidLineHgtRatio; + static const int kLineSepMorphMinHgt; + static const int kHgtBins; + static const int kMaxConnCompHgt; + static const int kMaxConnCompWid; + static const int kMaxHorzAspectRatio; + static const int kMaxVertAspectRatio; + static const int kMinWid; + static const int kMinHgt; + static const double kMaxValidLineRatio; + + // Cube Reco context + CubeRecoContext *cntxt_; + // Original image + Pix *orig_img_; + // Post processed image + Pix *img_; + // Init flag + bool init_; + // Output Line and column info + int line_cnt_; + Pixaa *columns_; + Pixa *con_comps_; + Pixa *lines_pixa_; + // Estimates for sizes of ALEF and DOT needed for Arabic analysis + double est_alef_hgt_; + double est_dot_hgt_; + + // Init the page analysis + bool Init(); + // Performs line segmentation + bool LineSegment(); + // Cleanup function + Pix *CleanUp(Pix *pix); + // compute validity ratio for a line + double ValidityRatio(Pix *line_mask_pix, Box *line_box); + // validate line + bool ValidLine(Pix *line_mask_pix, Box *line_box); + // split a line continuously until valid or fail + Pixa *SplitLine(Pix *line_mask_pix, Box *line_box); + // do a desperate attempt at cracking lines + Pixa *CrackLine(Pix *line_mask_pix, Box *line_box); + Pixa *CrackLine(Pix *line_mask_pix, Box *line_box, int line_cnt); + // Checks of a line is too small + bool SmallLine(Box *line_box); + // Compute the connected components in a line + Boxa * ComputeLineConComps(Pix *line_mask_pix, Box *line_box, + Pixa **con_comps_pixa); + // create a union of two arbitrary pix + Pix *PixUnion(Pix *dest_pix, Box *dest_box, Pix *src_pix, Box *src_box); + // create a union of a pixa subset + Pix *Pixa2Pix(Pixa *pixa, Box **dest_box, int start_pix, int pix_cnt); + // create a union of a pixa + Pix *Pixa2Pix(Pixa *pixa, Box **dest_box); + // merges a number of lines into one line given a bounding box and a mask + bool MergeLine(Pix *line_mask_pix, Box *line_box, + Pixa *lines, Boxaa *lines_con_comps); + // Creates new set of lines from the computed columns + bool AddLines(Pixa *lines); + // Estimate the parameters of the font(s) used in the page + bool EstimateFontParams(); + // perform a vertical Closing with the specified threshold + // returning the resulting conn comps as a pixa + Pixa *VerticalClosing(Pix *pix, int thresold, Boxa **boxa); + // Index the specific pixa using RTL reading order + int *IndexRTL(Pixa *pixa); + // Implements a rudimentary page & line segmenter + bool FindLines(); +}; +} + +#endif // CUBE_LINE_SEGMENTER_H diff --git a/TesseractOCR/include/tesseract/cube_object.h b/TesseractOCR/include/tesseract/cube_object.h new file mode 100644 index 00000000..e1a85145 --- /dev/null +++ b/TesseractOCR/include/tesseract/cube_object.h @@ -0,0 +1,171 @@ +/********************************************************************** + * File: cube_object.h + * Description: Declaration of the Cube Object Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CubeObject class is the main class used to perform recognition of +// a specific char_samp as a single word. +// To recognize a word, a CubeObject is constructed for this word. +// A Call to RecognizeWord is then issued specifying the language model that +// will be used during recognition. If none is specified, the default language +// model in the CubeRecoContext is used. The CubeRecoContext is passed at +// construction time +// +// The typical usage pattern for Cube is shown below: +// +// // Create and initialize Tesseract object and get its +// // CubeRecoContext object (note that Tesseract object owns it, +// // so it will be freed when the Tesseract object is freed). +// tesseract::Tesseract *tess_obj = new tesseract::Tesseract(); +// tess_obj->init_tesseract(data_path, lang, tesseract::OEM_CUBE_ONLY); +// CubeRecoContext *cntxt = tess_obj->GetCubeRecoContext(); +// CHECK(cntxt != NULL) << "Unable to create a Cube reco context"; +// . +// . +// . +// // Do this to recognize a word in pix whose co-ordinates are +// // (left,top,width,height) +// tesseract::CubeObject *cube_obj; +// cube_obj = new tesseract::CubeObject(cntxt, pix, +// left, top, width, height); +// +// // Get back Cube's list of answers +// tesseract::WordAltList *alt_list = cube_obj->RecognizeWord(); +// CHECK(alt_list != NULL && alt_list->AltCount() > 0); +// +// // Get the string and cost of every alternate +// for (int alt = 0; alt < alt_list->AltCount(); alt++) { +// // Return the result as a UTF-32 string +// string_32 res_str32 = alt_list->Alt(alt); +// // Convert to UTF8 if need-be +// string res_str; +// CubeUtils::UTF32ToUTF8(res_str32.c_str(), &res_str); +// // Get the string cost. This should get bigger as you go deeper +// // in the list +// int cost = alt_list->AltCost(alt); +// } +// +// // Call this once you are done recognizing this word +// delete cube_obj; +// +// // Call this once you are done recognizing all words with +// // for the current language +// delete tess_obj; +// +// Note that if the language supports "Italics" (see the CubeRecoContext), the +// RecognizeWord function attempts to de-slant the word. + +#ifndef CUBE_OBJECT_H +#define CUBE_OBJECT_H + +#include "char_samp.h" +#include "word_altlist.h" +#include "beam_search.h" +#include "cube_search_object.h" +#include "tess_lang_model.h" +#include "cube_reco_context.h" + +namespace tesseract { + +// minimum aspect ratio needed to normalize a char_samp before recognition +static const float kMinNormalizationAspectRatio = 3.5; +// minimum probability a top alt choice must meet before having +// deslanted processing applied to it +static const float kMinProbSkipDeslanted = 0.25; + +class CubeObject { + public: + // Different flavors of constructor. They just differ in the way the + // word image is specified + CubeObject(CubeRecoContext *cntxt, CharSamp *char_samp); + CubeObject(CubeRecoContext *cntxt, Pix *pix, + int left, int top, int wid, int hgt); + ~CubeObject(); + + // Perform the word recognition using the specified language mode. If none + // is specified, the default language model in the CubeRecoContext is used. + // Returns the sorted list of alternate word answers + WordAltList *RecognizeWord(LangModel *lang_mod = NULL); + // Same as RecognizeWord but recognizes as a phrase + WordAltList *RecognizePhrase(LangModel *lang_mod = NULL); + // Computes the cost of a specific string. This is done by performing + // recognition of a language model that allows only the specified word. + // The alternate list(s) will be permanently modified. + int WordCost(const char *str); + // Recognizes a single character and returns the list of results. + CharAltList *RecognizeChar(); + + // Returns the BeamSearch object that resulted from the last call to + // RecognizeWord + inline BeamSearch *BeamObj() const { + return (deslanted_ == true ? deslanted_beam_obj_ : beam_obj_); + } + // Returns the WordAltList object that resulted from the last call to + // RecognizeWord + inline WordAltList *AlternateList() const { + return (deslanted_ == true ? deslanted_alt_list_ : alt_list_); + } + // Returns the CubeSearchObject object that resulted from the last call to + // RecognizeWord + inline CubeSearchObject *SrchObj() const { + return (deslanted_ == true ? deslanted_srch_obj_ : srch_obj_); + } + // Returns the CharSamp object that resulted from the last call to + // RecognizeWord. Note that this object is not necessarily identical to the + // one passed at construction time as normalization might have occurred + inline CharSamp *CharSample() const { + return (deslanted_ == true ? deslanted_char_samp_ : char_samp_); + } + + // Set the ownership of the CharSamp + inline void SetCharSampOwnership(bool own_char_samp) { + own_char_samp_ = own_char_samp; + } + + protected: + // Normalize the CharSamp if its aspect ratio exceeds the below constant. + bool Normalize(); + + private: + // minimum segment count needed to normalize a char_samp before recognition + static const int kMinNormalizationSegmentCnt = 4; + + // Data member initialization function + void Init(); + // Free alternate lists. + void Cleanup(); + // Perform the actual recognition using the specified language mode. If none + // is specified, the default language model in the CubeRecoContext is used. + // Returns the sorted list of alternate answers. Called by both + // RecognizerWord (word_mode is true) or RecognizePhrase (word mode is false) + WordAltList *Recognize(LangModel *lang_mod, bool word_mode); + + CubeRecoContext *cntxt_; + BeamSearch *beam_obj_; + BeamSearch *deslanted_beam_obj_; + bool own_char_samp_; + bool deslanted_; + CharSamp *char_samp_; + CharSamp *deslanted_char_samp_; + CubeSearchObject *srch_obj_; + CubeSearchObject *deslanted_srch_obj_; + WordAltList *alt_list_; + WordAltList *deslanted_alt_list_; +}; +} + +#endif // CUBE_OBJECT_H diff --git a/TesseractOCR/include/tesseract/cube_reco_context.h b/TesseractOCR/include/tesseract/cube_reco_context.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/cube_search_object.h b/TesseractOCR/include/tesseract/cube_search_object.h new file mode 100644 index 00000000..8452417a --- /dev/null +++ b/TesseractOCR/include/tesseract/cube_search_object.h @@ -0,0 +1,122 @@ +/********************************************************************** + * File: cube_search_object.h + * Description: Declaration of the Cube Search Object Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CubeSearchObject class represents a char_samp (a word bitmap) that is +// being searched for characters (or recognizeable entities). +// The Class detects the connected components and peforms an oversegmentation +// on each ConComp. The result of which is a list of segments that are ordered +// in reading order. +// The class provided methods that inquire about the number of segments, the +// CharSamp corresponding to any segment range and the recognition results +// of any segment range +// An object of Class CubeSearchObject is used by the BeamSearch algorithm +// to recognize a CharSamp into a list of word alternates + +#ifndef CUBE_SEARCH_OBJECT_H +#define CUBE_SEARCH_OBJECT_H + +#include "search_object.h" +#include "char_samp.h" +#include "conv_net_classifier.h" +#include "cube_reco_context.h" +#include "allheaders.h" + +namespace tesseract { +class CubeSearchObject : public SearchObject { + public: + CubeSearchObject(CubeRecoContext *cntxt, CharSamp *samp); + ~CubeSearchObject(); + + // returns the Segmentation Point count of the CharSamp owned by the class + int SegPtCnt(); + // Recognize the set of segments given by the specified range and return + // a list of possible alternate answers + CharAltList * RecognizeSegment(int start_pt, int end_pt); + // Returns the CharSamp corresponding to the specified segment range + CharSamp *CharSample(int start_pt, int end_pt); + // Returns a leptonica box corresponding to the specified segment range + Box *CharBox(int start_pt, int end_pt); + // Returns the cost of having a space before the specified segmentation pt + int SpaceCost(int seg_pt); + // Returns the cost of not having a space before the specified + // segmentation pt + int NoSpaceCost(int seg_pt); + // Returns the cost of not having any spaces within the specified range + // of segmentation points + int NoSpaceCost(int seg_pt, int end_pt); + + private: + // Maximum reasonable segment count + static const int kMaxSegmentCnt = 128; + // Use cropped samples + static const bool kUseCroppedChars; + + // reading order flag + bool rtl_; + // cached dimensions of char samp + int left_; + int itop_; + int wid_; + int hgt_; + // minimum and maximum and possible inter-segment gaps for spaces + int min_spc_gap_; + int max_spc_gap_; + // initialization flag + bool init_; + // maximum segments per character: Cached from tuning parameters object + int max_seg_per_char_; + // char sample to be processed + CharSamp *samp_; + // segment count + int segment_cnt_; + // segments of the processed char samp + ConComp **segments_; + // Cache data members: + // There are two caches kept; a CharSamp cache and a CharAltList cache + // Each is a 2-D array of CharSamp and CharAltList pointers respectively + // hence the triple pointer. + CharAltList ***reco_cache_; + CharSamp ***samp_cache_; + // Cached costs of space and no-space after every segment. Computed only + // in phrase mode + int *space_cost_; + int *no_space_cost_; + + // init and allocate variables, perform segmentation + bool Init(); + // Cleanup + void Cleanup(); + // Perform segmentation of the bitmap by detecting connected components, + // segmenting each connected component using windowed vertical pixel density + // histogram and sorting the resulting segments in reading order + // Returns true on success + bool Segment(); + // validate the segment ranges. + inline bool IsValidSegmentRange(int start_pt, int end_pt) { + return (end_pt > start_pt && start_pt >= -1 && start_pt < segment_cnt_ && + end_pt >= 0 && end_pt <= segment_cnt_ && + end_pt <= (start_pt + max_seg_per_char_)); + } + // computes the space and no space costs at gaps between segments + // return true on sucess + bool ComputeSpaceCosts(); +}; +} + +#endif // CUBE_SEARCH_OBJECT_H diff --git a/TesseractOCR/include/tesseract/cube_tuning_params.h b/TesseractOCR/include/tesseract/cube_tuning_params.h new file mode 100644 index 00000000..8b125872 --- /dev/null +++ b/TesseractOCR/include/tesseract/cube_tuning_params.h @@ -0,0 +1,57 @@ +/********************************************************************** + * File: cube_tuning_params.h + * Description: Declaration of the CubeTuningParameters Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CubeTuningParams class abstracts all the parameters that are used +// in Cube and are tuned/learned during the training process. Inherits +// from the TuningParams class. + +#ifndef CUBE_TUNING_PARAMS_H +#define CUBE_TUNING_PARAMS_H + +#include +#include "tuning_params.h" + +namespace tesseract { +class CubeTuningParams : public TuningParams { + public: + CubeTuningParams(); + ~CubeTuningParams(); + + // Accessor functions + inline double OODWgt() { return ood_wgt_; } + inline double NumWgt() { return num_wgt_; } + + inline void SetOODWgt(double wgt) { ood_wgt_ = wgt; } + inline void SetNumWgt(double wgt) { num_wgt_ = wgt; } + + // Create an object given the data file path and the language by loading + // the approporiate file + static CubeTuningParams * Create(const string &data_file, + const string &lang); + // Save and load the tuning parameters to a specified file + bool Save(string file_name); + bool Load(string file_name); + + private: + double ood_wgt_; + double num_wgt_; +}; +} + +#endif // CUBE_TUNING_PARAMS_H diff --git a/TesseractOCR/include/tesseract/cube_utils.h b/TesseractOCR/include/tesseract/cube_utils.h new file mode 100644 index 00000000..765012cd --- /dev/null +++ b/TesseractOCR/include/tesseract/cube_utils.h @@ -0,0 +1,83 @@ +/********************************************************************** + * File: cube_utils.h + * Description: Declaration of the Cube Utilities Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + *(C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0(the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The CubeUtils class provides miscellaneous utility and helper functions +// to the rest of the Cube Engine + +#ifndef CUBE_UTILS_H +#define CUBE_UTILS_H + +#include +#include + +#include "allheaders.h" +#include "const.h" +#include "char_set.h" +#include "char_samp.h" + +namespace tesseract { +class CubeUtils { + public: + CubeUtils(); + ~CubeUtils(); + + // Converts a probability value to a cost by getting the -log() of the + // probability value to a known base + static int Prob2Cost(double prob_val); + // Converts a cost to probability by getting the exp(-normalized cost) + static double Cost2Prob(int cost); + // Computes the length of a 32-bit char buffer + static int StrLen(const char_32 *str); + // Compares two 32-bit char buffers + static int StrCmp(const char_32 *str1, const char_32 *str2); + // Duplicates a 32-bit char buffer + static char_32 *StrDup(const char_32 *str); + // Creates a CharSamp from an Pix and a bounding box + static CharSamp *CharSampleFromPix(Pix *pix, + int left, int top, int wid, int hgt); + // Creates a Pix from a CharSamp + static Pix *PixFromCharSample(CharSamp *char_samp); + // read the contents of a file to a string + static bool ReadFileToString(const string &file_name, string *str); + // split a string into vectors using any of the specified delimiters + static void SplitStringUsing(const string &str, const string &delims, + vector *str_vec); + // UTF-8 to UTF-32 convesion functions + static void UTF8ToUTF32(const char *utf8_str, string_32 *str32); + static void UTF32ToUTF8(const char_32 *utf32_str, string *str); + // Returns true if input word has either 1) all-one-case, or 2) + // first character upper-case, and remaining characters lower-case. + // If char_set is not NULL, uses tesseract's unicharset functions + // to determine case properties. Otherwise, uses C-locale-dependent + // functions, which may be unreliable on non-ASCII characters. + static bool IsCaseInvariant(const char_32 *str32, CharSet *char_set); + // Returns char_32 pointer to the lower-case-transformed version of + // the input string or NULL on error. If char_set is NULL returns NULL. + // Return array must be freed by caller. + static char_32 *ToLower(const char_32 *str32, CharSet *char_set); + // Returns char_32 pointer to the upper-case-transformed version of + // the input string or NULL on error. If char_set is NULL returns NULL. + // Return array must be freed by caller. + static char_32 *ToUpper(const char_32 *str32, CharSet *char_set); + private: + static unsigned char *GetImageData(Pix *pix, + int left, int top, int wid, int hgt); +}; +} // namespace tesseract +#endif // CUBE_UTILS_H diff --git a/TesseractOCR/include/tesseract/cubeclassifier.h b/TesseractOCR/include/tesseract/cubeclassifier.h old mode 100755 new mode 100644 index 6359cc51..98bdb5cf --- a/TesseractOCR/include/tesseract/cubeclassifier.h +++ b/TesseractOCR/include/tesseract/cubeclassifier.h @@ -32,6 +32,7 @@ class ShapeTable; class TessClassifier; class Tesseract; class TrainingSample; +struct UnicharRating; // Cube implementation of a ShapeClassifier. class CubeClassifier : public ShapeClassifier { @@ -41,9 +42,9 @@ class CubeClassifier : public ShapeClassifier { // Classifies the given [training] sample, writing to results. // See ShapeClassifier for a full description. - virtual int ClassifySample(const TrainingSample& sample, Pix* page_pix, - int debug, int keep_this, - GenericVector* results); + virtual int UnicharClassifySample(const TrainingSample& sample, Pix* page_pix, + int debug, UNICHAR_ID keep_this, + GenericVector* results); // Provides access to the ShapeTable that this classifier works with. virtual const ShapeTable* GetShapeTable() const; @@ -61,9 +62,9 @@ class CubeTessClassifier : public ShapeClassifier { // Classifies the given [training] sample, writing to results. // See ShapeClassifier for a full description. - virtual int ClassifySample(const TrainingSample& sample, Pix* page_pix, - int debug, int keep_this, - GenericVector* results); + virtual int UnicharClassifySample(const TrainingSample& sample, Pix* page_pix, + int debug, UNICHAR_ID keep_this, + GenericVector* results); // Provides access to the ShapeTable that this classifier works with. virtual const ShapeTable* GetShapeTable() const; diff --git a/TesseractOCR/include/tesseract/cutil.h b/TesseractOCR/include/tesseract/cutil.h new file mode 100644 index 00000000..29439e2e --- /dev/null +++ b/TesseractOCR/include/tesseract/cutil.h @@ -0,0 +1,136 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: cutil.h + * Description: General utility functions + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Wed Dec 5 15:40:26 1990 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + ******************************************************************************** +Revision 1.1 2007/02/02 23:39:07 theraysmith +Fixed portability issues + +Revision 1.1.1.1 2004/02/20 19:39:06 slumos +Import original HP distribution + +*/ + +#ifndef CUTILH +#define CUTILH + +/*---------------------------------------------------------------------- + I n c l u d e s +----------------------------------------------------------------------*/ +#include +#include +#include + +#include "host.h" +#include "tprintf.h" + +/*---------------------------------------------------------------------- + T y p e s +----------------------------------------------------------------------*/ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define CHARS_PER_LINE 500 + +#if defined(__STDC__) || defined(__cplusplus) || MAC_OR_DOS +# define _ARGS(s) s +#else +# define _ARGS(s) () +#endif + +//typedef int (*int_proc) (void); +typedef void (*void_proc) (...); +typedef void *(*void_star_proc) _ARGS ((...)); + +typedef int (*int_void) (void); +typedef void (*void_void) (void); +typedef int (*int_compare) (void *, void *); +typedef void (*void_dest) (void *); + +/*---------------------------------------------------------------------- + M a c r o s +----------------------------------------------------------------------*/ +/********************************************************************** + * new_line + * + * Print a new line character on stdout. + **********************************************************************/ + +#define new_line() \ + tprintf("\n") + +/********************************************************************** + * print_string + * + * Print a string on stdout. + **********************************************************************/ + +#define print_string(str) \ + printf ("%s\n", str) + +/********************************************************************** + * strfree + * + * Reserve a spot in memory for the string to be stored. Copy the string + * to it and return the result. + **********************************************************************/ + +#define strfree(s) (free_string(s)) + +/********************************************************************** + * strsave + * + * Reserve a spot in memory for the string to be stored. Copy the string + * to it and return the result. + **********************************************************************/ + +#define strsave(s) \ + ((s) != NULL ? \ + ((char*) strcpy (alloc_string(strlen(s)+1), s)) : \ + (NULL)) + +/*---------------------------------------------------------------------- + F u n c t i o n s +----------------------------------------------------------------------*/ +long long_rand(long limit); + +FILE *open_file(const char *filename, const char *mode); + +bool exists_file(const char *filename); + +/* util.c +long long_rand + _ARGS ((long limit)); + +FILE *open_file + _ARGS((char *filename, + char *mode)); + +#undef _ARGS +*/ +#include "cutil_class.h" +#endif diff --git a/TesseractOCR/include/tesseract/cutil_class.h b/TesseractOCR/include/tesseract/cutil_class.h new file mode 100644 index 00000000..06d32543 --- /dev/null +++ b/TesseractOCR/include/tesseract/cutil_class.h @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////// +// File: cutil.h +// Description: cutil class. +// Author: Samuel Charron +// +// (C) Copyright 2006, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_CUTIL_CUTIL_CLASS_H__ +#define TESSERACT_CUTIL_CUTIL_CLASS_H__ + +#include "ccutil.h" +#include "const.h" +#include "strngs.h" + +namespace tesseract { + +class CUtil : public CCUtil { + public: + CUtil(); + ~CUtil(); + void read_variables(const char *filename, bool global_only); +}; + +} // namespace tesseract + +#endif // TESSERACT_CUTIL_CUTIL_CLASS_H__ diff --git a/TesseractOCR/include/tesseract/cutoffs.h b/TesseractOCR/include/tesseract/cutoffs.h new file mode 100644 index 00000000..907e9453 --- /dev/null +++ b/TesseractOCR/include/tesseract/cutoffs.h @@ -0,0 +1,45 @@ +/****************************************************************************** + ** Filename: cutoffs.h + ** Purpose: Routines to manipulate an array of class cutoffs. + ** Author: Dan Johnson + ** History: Wed Feb 20 09:34:20 1991, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef CUTOFFS_H +#define CUTOFFS_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "matchdefs.h" + +typedef uinT16 CLASS_CUTOFF_ARRAY[MAX_NUM_CLASSES]; + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ + +/* +#if defined(__STDC__) || defined(__cplusplus) +# define _ARGS(s) s +#else +# define _ARGS(s) () +#endif*/ + +/* cutoffs.c +void ReadNewCutoffs + _ARGS((char *Filename, + CLASS_CUTOFF_ARRAY Cutoffs)); +#undef _ARGS +*/ +#endif diff --git a/TesseractOCR/include/tesseract/danerror.h b/TesseractOCR/include/tesseract/danerror.h new file mode 100644 index 00000000..1e4a547b --- /dev/null +++ b/TesseractOCR/include/tesseract/danerror.h @@ -0,0 +1,35 @@ +/****************************************************************************** + ** Filename: danerror.h + ** Purpose: Definition of error trapping routines. + ** Author: Dan Johnson + ** History: 4/3/89, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef DANERROR_H +#define DANERROR_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#define NOERROR 0 +#define DO_NOTHING 0 + +typedef int TRAPERROR; +typedef void (*VOID_PROC) (); + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +void DoError(int Error, const char *Message); + +#endif diff --git a/TesseractOCR/include/tesseract/dawg.h b/TesseractOCR/include/tesseract/dawg.h new file mode 100644 index 00000000..a487d3fd --- /dev/null +++ b/TesseractOCR/include/tesseract/dawg.h @@ -0,0 +1,557 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: dawg.h (Formerly dawg.h) + * Description: Definition of a class that represents Directed Accyclic Word + * Graph (DAWG), functions to build and manipulate the DAWG. + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Wed Jun 19 16:50:24 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ + +#ifndef DICT_DAWG_H_ +#define DICT_DAWG_H_ + +/*---------------------------------------------------------------------- + I n c l u d e s +----------------------------------------------------------------------*/ + +#include "elst.h" +#include "ratngs.h" +#include "params.h" +#include "tesscallback.h" + +#ifndef __GNUC__ +#ifdef _WIN32 +#define NO_EDGE (inT64) 0xffffffffffffffffi64 +#endif /*_WIN32*/ +#else +#define NO_EDGE (inT64) 0xffffffffffffffffll +#endif /*__GNUC__*/ + +/*---------------------------------------------------------------------- + T y p e s +----------------------------------------------------------------------*/ +class UNICHARSET; + +typedef uinT64 EDGE_RECORD; +typedef EDGE_RECORD *EDGE_ARRAY; +typedef inT64 EDGE_REF; +typedef inT64 NODE_REF; +typedef EDGE_REF *NODE_MAP; + +namespace tesseract { + +struct NodeChild { + UNICHAR_ID unichar_id; + EDGE_REF edge_ref; + NodeChild(UNICHAR_ID id, EDGE_REF ref): unichar_id(id), edge_ref(ref) {} + NodeChild(): unichar_id(INVALID_UNICHAR_ID), edge_ref(NO_EDGE) {} +}; + +typedef GenericVector NodeChildVector; +typedef GenericVector SuccessorList; +typedef GenericVector SuccessorListsVector; + +enum DawgType { + DAWG_TYPE_PUNCTUATION, + DAWG_TYPE_WORD, + DAWG_TYPE_NUMBER, + DAWG_TYPE_PATTERN, + + DAWG_TYPE_COUNT // number of enum entries +}; + +/*---------------------------------------------------------------------- + C o n s t a n t s +----------------------------------------------------------------------*/ + +#define FORWARD_EDGE (inT32) 0 +#define BACKWARD_EDGE (inT32) 1 +#define MAX_NODE_EDGES_DISPLAY (inT64) 100 +#define MARKER_FLAG (inT64) 1 +#define DIRECTION_FLAG (inT64) 2 +#define WERD_END_FLAG (inT64) 4 +#define LETTER_START_BIT 0 +#define NUM_FLAG_BITS 3 +#define REFFORMAT "%lld" + +static const bool kDawgSuccessors[DAWG_TYPE_COUNT][DAWG_TYPE_COUNT] = { + { 0, 1, 1, 0 }, // for DAWG_TYPE_PUNCTUATION + { 1, 0, 0, 0 }, // for DAWG_TYPE_WORD + { 1, 0, 0, 0 }, // for DAWG_TYPE_NUMBER + { 0, 0, 0, 0 }, // for DAWG_TYPE_PATTERN +}; + +static const char kWildcard[] = "*"; + + +/*---------------------------------------------------------------------- + C l a s s e s a n d S t r u c t s +----------------------------------------------------------------------*/ +// +/// Abstract class (an interface) that declares methods needed by the +/// various tesseract classes to operate on SquishedDawg and Trie objects. +/// +/// This class initializes all the edge masks (since their usage by +/// SquishedDawg and Trie is identical) and implements simple accessors +/// for each of the fields encoded in an EDGE_RECORD. +/// This class also implements word_in_dawg() and check_for_words() +/// (since they use only the public methods of SquishedDawg and Trie +/// classes that are inherited from the Dawg base class). +// +class Dawg { + public: + /// Magic number to determine endianness when reading the Dawg from file. + static const inT16 kDawgMagicNumber = 42; + /// A special unichar id that indicates that any appropriate pattern + /// (e.g.dicitonary word, 0-9 digit, etc) can be inserted instead + /// Used for expressing patterns in punctuation and number Dawgs. + static const UNICHAR_ID kPatternUnicharID = 0; + + inline DawgType type() const { return type_; } + inline const STRING &lang() const { return lang_; } + inline PermuterType permuter() const { return perm_; } + + virtual ~Dawg() {}; + + /// Returns true if the given word is in the Dawg. + bool word_in_dawg(const WERD_CHOICE &word) const; + + // Returns true if the given word prefix is not contraindicated by the dawg. + // If requires_complete is true, then the exact complete word must be present. + bool prefix_in_dawg(const WERD_CHOICE &prefix, bool requires_complete) const; + + /// Checks the Dawg for the words that are listed in the requested file. + /// Returns the number of words in the given file missing from the Dawg. + int check_for_words(const char *filename, + const UNICHARSET &unicharset, + bool enable_wildcard) const; + + // For each word in the Dawg, call the given (permanent) callback with the + // text (UTF-8) version of the word. + void iterate_words(const UNICHARSET &unicharset, + TessCallback1 *cb) const; + + // For each word in the Dawg, call the given (permanent) callback with the + // text (UTF-8) version of the word. + void iterate_words(const UNICHARSET &unicharset, + TessCallback1 *cb) const; + + // Pure virtual function that should be implemented by the derived classes. + + /// Returns the edge that corresponds to the letter out of this node. + virtual EDGE_REF edge_char_of(NODE_REF node, UNICHAR_ID unichar_id, + bool word_end) const = 0; + + /// Fills the given NodeChildVector with all the unichar ids (and the + /// corresponding EDGE_REFs) for which there is an edge out of this node. + virtual void unichar_ids_of(NODE_REF node, NodeChildVector *vec, + bool word_end) const = 0; + + /// Returns the next node visited by following the edge + /// indicated by the given EDGE_REF. + virtual NODE_REF next_node(EDGE_REF edge_ref) const = 0; + + /// Returns true if the edge indicated by the given EDGE_REF + /// marks the end of a word. + virtual bool end_of_word(EDGE_REF edge_ref) const = 0; + + /// Returns UNICHAR_ID stored in the edge indicated by the given EDGE_REF. + virtual UNICHAR_ID edge_letter(EDGE_REF edge_ref) const = 0; + + /// Prints the contents of the node indicated by the given NODE_REF. + /// At most max_num_edges will be printed. + virtual void print_node(NODE_REF node, int max_num_edges) const = 0; + + /// Fills vec with unichar ids that represent the character classes + /// of the given unichar_id. + virtual void unichar_id_to_patterns(UNICHAR_ID unichar_id, + const UNICHARSET &unicharset, + GenericVector *vec) const {}; + + /// Returns the given EDGE_REF if the EDGE_RECORD that it points to has + /// a self loop and the given unichar_id matches the unichar_id stored in the + /// EDGE_RECORD, returns NO_EDGE otherwise. + virtual EDGE_REF pattern_loop_edge( + EDGE_REF edge_ref, UNICHAR_ID unichar_id, bool word_end) const { + return false; + } + + protected: + Dawg() {} + + /// Returns the next node visited by following this edge. + inline NODE_REF next_node_from_edge_rec(const EDGE_RECORD &edge_rec) const { + return ((edge_rec & next_node_mask_) >> next_node_start_bit_); + } + /// Returns the marker flag of this edge. + inline bool marker_flag_from_edge_rec(const EDGE_RECORD &edge_rec) const { + return (edge_rec & (MARKER_FLAG << flag_start_bit_)) != 0; + } + /// Returns the direction flag of this edge. + inline int direction_from_edge_rec(const EDGE_RECORD &edge_rec) const { + return ((edge_rec & (DIRECTION_FLAG << flag_start_bit_))) ? + BACKWARD_EDGE : FORWARD_EDGE; + } + /// Returns true if this edge marks the end of a word. + inline bool end_of_word_from_edge_rec(const EDGE_RECORD &edge_rec) const { + return (edge_rec & (WERD_END_FLAG << flag_start_bit_)) != 0; + } + /// Returns UNICHAR_ID recorded in this edge. + inline UNICHAR_ID unichar_id_from_edge_rec( + const EDGE_RECORD &edge_rec) const { + return ((edge_rec & letter_mask_) >> LETTER_START_BIT); + } + /// Sets the next node link for this edge in the Dawg. + inline void set_next_node_in_edge_rec( + EDGE_RECORD *edge_rec, EDGE_REF value) { + *edge_rec &= (~next_node_mask_); + *edge_rec |= ((value << next_node_start_bit_) & next_node_mask_); + } + /// Sets this edge record to be the last one in a sequence of edges. + inline void set_marker_flag_in_edge_rec(EDGE_RECORD *edge_rec) { + *edge_rec |= (MARKER_FLAG << flag_start_bit_); + } + /// Sequentially compares the given values of unichar ID, next node + /// and word end marker with the values in the given EDGE_RECORD. + /// Returns: 1 if at any step the given input value exceeds + /// that of edge_rec (and all the values already + /// checked are the same) + /// 0 if edge_rec_match() returns true + /// -1 otherwise + inline int given_greater_than_edge_rec(NODE_REF next_node, + bool word_end, + UNICHAR_ID unichar_id, + const EDGE_RECORD &edge_rec) const { + UNICHAR_ID curr_unichar_id = unichar_id_from_edge_rec(edge_rec); + NODE_REF curr_next_node = next_node_from_edge_rec(edge_rec); + bool curr_word_end = end_of_word_from_edge_rec(edge_rec); + if (edge_rec_match(next_node, word_end, unichar_id, curr_next_node, + curr_word_end, curr_unichar_id)) return 0; + if (unichar_id > curr_unichar_id) return 1; + if (unichar_id == curr_unichar_id) { + if (next_node > curr_next_node) return 1; + if (next_node == curr_next_node) { + if (word_end > curr_word_end) return 1; + } + } + return -1; + } + /// Returns true if all the values are equal (any value matches + /// next_node if next_node == NO_EDGE, any value matches word_end + /// if word_end is false). + inline bool edge_rec_match(NODE_REF next_node, + bool word_end, + UNICHAR_ID unichar_id, + NODE_REF other_next_node, + bool other_word_end, + UNICHAR_ID other_unichar_id) const { + return ((unichar_id == other_unichar_id) && + (next_node == NO_EDGE || next_node == other_next_node) && + (!word_end || (word_end == other_word_end))); + } + + /// Sets type_, lang_, perm_, unicharset_size_. + /// Initializes the values of various masks from unicharset_size_. + void init(DawgType type, const STRING &lang, + PermuterType perm, int unicharset_size, int debug_level); + + /// Matches all of the words that are represented by this string. + /// If wilcard is set to something other than INVALID_UNICHAR_ID, + /// the *'s in this string are interpreted as wildcards. + /// WERD_CHOICE param is not passed by const so that wildcard searches + /// can modify it and work without having to copy WERD_CHOICEs. + bool match_words(WERD_CHOICE *word, inT32 index, + NODE_REF node, UNICHAR_ID wildcard) const; + + // Recursively iterate over all words in a dawg (see public iterate_words). + void iterate_words_rec(const WERD_CHOICE &word_so_far, + NODE_REF to_explore, + TessCallback1 *cb) const; + + // Member Variables. + DawgType type_; + STRING lang_; + /// Permuter code that should be used if the word is found in this Dawg. + PermuterType perm_; + // Variables to construct various edge masks. Formerly: + // #define NEXT_EDGE_MASK (inT64) 0xfffffff800000000i64 + // #define FLAGS_MASK (inT64) 0x0000000700000000i64 + // #define LETTER_MASK (inT64) 0x00000000ffffffffi64 + int unicharset_size_; + int flag_start_bit_; + int next_node_start_bit_; + uinT64 next_node_mask_; + uinT64 flags_mask_; + uinT64 letter_mask_; + // Level of debug statements to print to stdout. + int debug_level_; +}; + +// +// DawgPosition keeps track of where we are in the primary dawg we're searching +// as well as where we may be in the "punctuation dawg" which may provide +// surrounding context. +// +// Example: +// punctuation dawg -- space is the "pattern character" +// " " // no punctuation +// "' '" // leading and trailing apostrophes +// " '" // trailing apostrophe +// word dawg: +// "cat" +// "cab" +// "cat's" +// +// DawgPosition(dawg_index, dawg_ref, punc_index, punc_ref, rtp) +// +// DawgPosition(-1, NO_EDGE, p, pe, false) +// We're in the punctuation dawg, no other dawg has been started. +// (1) If there's a pattern edge as a punc dawg child of us, +// for each punc-following dawg starting with ch, produce: +// Result: DawgPosition(k, w, p', false) +// (2) If there's a valid continuation in the punc dawg, produce: +// Result: DawgPosition(-k, NO_EDGE, p', false) +// +// DawgPosition(k, w, -1, NO_EDGE, false) +// We're in dawg k. Going back to punctuation dawg is not an option. +// Follow ch in dawg k. +// +// DawgPosition(k, w, p, pe, false) +// We're in dawg k. Continue in dawg k and/or go back to the punc dawg. +// If ending, check that the punctuation dawg is also ok to end here. +// +// DawgPosition(k, w, p, pe true) +// We're back in the punctuation dawg. Continuing there is the only option. +struct DawgPosition { + DawgPosition() + : dawg_index(-1), dawg_ref(NO_EDGE), punc_ref(NO_EDGE), + back_to_punc(false) {} + DawgPosition(int dawg_idx, EDGE_REF dawgref, + int punc_idx, EDGE_REF puncref, + bool backtopunc) + : dawg_index(dawg_idx), dawg_ref(dawgref), + punc_index(punc_idx), punc_ref(puncref), + back_to_punc(backtopunc) { + } + bool operator==(const DawgPosition &other) { + return dawg_index == other.dawg_index && + dawg_ref == other.dawg_ref && + punc_index == other.punc_index && + punc_ref == other.punc_ref && + back_to_punc == other.back_to_punc; + } + + inT8 dawg_index; + EDGE_REF dawg_ref; + inT8 punc_index; + EDGE_REF punc_ref; + // Have we returned to the punc dawg at the end of the word? + bool back_to_punc; +}; + +class DawgPositionVector : public GenericVector { + public: + /// Overload destructor, since clear() does not delete data_[] any more. + ~DawgPositionVector() { + if (size_reserved_ > 0) { + delete[] data_; + size_used_ = 0; + size_reserved_ = 0; + } + } + /// Overload clear() in order to avoid allocating/deallocating memory + /// when clearing the vector and re-inserting entries into it later. + void clear() { size_used_ = 0; } + /// Adds an entry for the given dawg_index with the given node to the vec. + /// Returns false if the same entry already exists in the vector, + /// true otherwise. + inline bool add_unique(const DawgPosition &new_pos, + bool debug, + const char *debug_msg) { + for (int i = 0; i < size_used_; ++i) { + if (data_[i] == new_pos) return false; + } + push_back(new_pos); + if (debug) { + tprintf("%s[%d, " REFFORMAT "] [punc: " REFFORMAT "%s]\n", + debug_msg, new_pos.dawg_index, new_pos.dawg_ref, + new_pos.punc_ref, new_pos.back_to_punc ? " returned" : ""); + } + return true; + } +}; + +// +/// Concrete class that can operate on a compacted (squished) Dawg (read, +/// search and write to file). This class is read-only in the sense that +/// new words can not be added to an instance of SquishedDawg. +/// The underlying representation of the nodes and edges in SquishedDawg +/// is stored as a contiguous EDGE_ARRAY (read from file or given as an +/// argument to the constructor). +// +class SquishedDawg : public Dawg { + public: + SquishedDawg(FILE *file, DawgType type, const STRING &lang, + PermuterType perm, int debug_level) { + read_squished_dawg(file, type, lang, perm, debug_level); + num_forward_edges_in_node0 = num_forward_edges(0); + } + SquishedDawg(const char* filename, DawgType type, + const STRING &lang, PermuterType perm, int debug_level) { + FILE *file = fopen(filename, "rb"); + if (file == NULL) { + tprintf("Failed to open dawg file %s\n", filename); + exit(1); + } + read_squished_dawg(file, type, lang, perm, debug_level); + num_forward_edges_in_node0 = num_forward_edges(0); + fclose(file); + } + SquishedDawg(EDGE_ARRAY edges, int num_edges, DawgType type, + const STRING &lang, PermuterType perm, + int unicharset_size, int debug_level) : + edges_(edges), num_edges_(num_edges) { + init(type, lang, perm, unicharset_size, debug_level); + num_forward_edges_in_node0 = num_forward_edges(0); + if (debug_level > 3) print_all("SquishedDawg:"); + } + ~SquishedDawg(); + + int NumEdges() { return num_edges_; } + + /// Returns the edge that corresponds to the letter out of this node. + EDGE_REF edge_char_of(NODE_REF node, UNICHAR_ID unichar_id, + bool word_end) const; + + /// Fills the given NodeChildVector with all the unichar ids (and the + /// corresponding EDGE_REFs) for which there is an edge out of this node. + void unichar_ids_of(NODE_REF node, NodeChildVector *vec, + bool word_end) const { + EDGE_REF edge = node; + if (!edge_occupied(edge) || edge == NO_EDGE) return; + assert(forward_edge(edge)); // we don't expect any backward edges to + do { // be present when this funciton is called + if (!word_end || end_of_word_from_edge_rec(edges_[edge])) { + vec->push_back(NodeChild(unichar_id_from_edge_rec(edges_[edge]), edge)); + } + } while (!last_edge(edge++)); + } + + /// Returns the next node visited by following the edge + /// indicated by the given EDGE_REF. + NODE_REF next_node(EDGE_REF edge) const { + return next_node_from_edge_rec((edges_[edge])); + } + + /// Returns true if the edge indicated by the given EDGE_REF + /// marks the end of a word. + bool end_of_word(EDGE_REF edge_ref) const { + return end_of_word_from_edge_rec((edges_[edge_ref])); + } + + /// Returns UNICHAR_ID stored in the edge indicated by the given EDGE_REF. + UNICHAR_ID edge_letter(EDGE_REF edge_ref) const { + return unichar_id_from_edge_rec((edges_[edge_ref])); + } + + /// Prints the contents of the node indicated by the given NODE_REF. + /// At most max_num_edges will be printed. + void print_node(NODE_REF node, int max_num_edges) const; + + /// Writes the squished/reduced Dawg to a file. + void write_squished_dawg(FILE *file); + + /// Opens the file with the given filename and writes the + /// squished/reduced Dawg to the file. + void write_squished_dawg(const char *filename) { + FILE *file = fopen(filename, "wb"); + if (file == NULL) { + tprintf("Error opening %s\n", filename); + exit(1); + } + this->write_squished_dawg(file); + fclose(file); + } + + private: + /// Sets the next node link for this edge. + inline void set_next_node(EDGE_REF edge_ref, EDGE_REF value) { + set_next_node_in_edge_rec(&(edges_[edge_ref]), value); + } + /// Sets the edge to be empty. + inline void set_empty_edge(EDGE_REF edge_ref) { + (edges_[edge_ref] = next_node_mask_); + } + /// Goes through all the edges and clears each one out. + inline void clear_all_edges() { + for (int edge = 0; edge < num_edges_; edge++) set_empty_edge(edge); + } + /// Clears the last flag of this edge. + inline void clear_marker_flag(EDGE_REF edge_ref) { + (edges_[edge_ref] &= ~(MARKER_FLAG << flag_start_bit_)); + } + /// Returns true if this edge is in the forward direction. + inline bool forward_edge(EDGE_REF edge_ref) const { + return (edge_occupied(edge_ref) && + (FORWARD_EDGE == direction_from_edge_rec(edges_[edge_ref]))); + } + /// Returns true if this edge is in the backward direction. + inline bool backward_edge(EDGE_REF edge_ref) const { + return (edge_occupied(edge_ref) && + (BACKWARD_EDGE == direction_from_edge_rec(edges_[edge_ref]))); + } + /// Returns true if the edge spot in this location is occupied. + inline bool edge_occupied(EDGE_REF edge_ref) const { + return (edges_[edge_ref] != next_node_mask_); + } + /// Returns true if this edge is the last edge in a sequence. + inline bool last_edge(EDGE_REF edge_ref) const { + return (edges_[edge_ref] & (MARKER_FLAG << flag_start_bit_)) != 0; + } + + /// Counts and returns the number of forward edges in this node. + inT32 num_forward_edges(NODE_REF node) const; + + /// Reads SquishedDawg from a file. + void read_squished_dawg(FILE *file, DawgType type, const STRING &lang, + PermuterType perm, int debug_level); + + /// Prints the contents of an edge indicated by the given EDGE_REF. + void print_edge(EDGE_REF edge) const; + + /// Prints the contents of the SquishedDawg. + void print_all(const char* msg) { + tprintf("\n__________________________\n%s\n", msg); + for (int i = 0; i < num_edges_; ++i) print_edge(i); + tprintf("__________________________\n"); + } + /// Constructs a mapping from the memory node indices to disk node indices. + NODE_MAP build_node_map(inT32 *num_nodes) const; + + + // Member variables. + EDGE_ARRAY edges_; + int num_edges_; + int num_forward_edges_in_node0; +}; + +} // namespace tesseract + +#endif // DICT_DAWG_H_ diff --git a/TesseractOCR/include/tesseract/dawg_cache.h b/TesseractOCR/include/tesseract/dawg_cache.h new file mode 100644 index 00000000..cd1721a7 --- /dev/null +++ b/TesseractOCR/include/tesseract/dawg_cache.h @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////// +// File: dawg_cache.h +// Description: A class that knows about loading and caching dawgs. +// Author: David Eger +// Created: Fri Jan 27 12:08:00 PST 2012 +// +// (C) Copyright 2012, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_DICT_DAWG_CACHE_H_ +#define TESSERACT_DICT_DAWG_CACHE_H_ + +#include "dawg.h" +#include "object_cache.h" +#include "strngs.h" +#include "tessdatamanager.h" + +namespace tesseract { + +class DawgCache { + public: + Dawg *GetSquishedDawg( + const STRING &lang, + const char *data_file_name, + TessdataType tessdata_dawg_type, + int debug_level); + + // If we manage the given dawg, decrement its count, + // and possibly delete it if the count reaches zero. + // If dawg is unknown to us, return false. + bool FreeDawg(Dawg *dawg) { + return dawgs_.Free(dawg); + } + + // Free up any currently unused dawgs. + void DeleteUnusedDawgs() { + dawgs_.DeleteUnusedObjects(); + } + + private: + ObjectCache dawgs_; +}; + +} // namespace tesseract + +#endif // TESSERACT_DICT_DAWG_CACHE_H_ diff --git a/TesseractOCR/include/tesseract/degradeimage.h b/TesseractOCR/include/tesseract/degradeimage.h new file mode 100644 index 00000000..189494ca --- /dev/null +++ b/TesseractOCR/include/tesseract/degradeimage.h @@ -0,0 +1,36 @@ +/********************************************************************** + * File: degradeimage.h + * Description: Function to degrade an image (usually of text) as if it + * has been printed and then scanned. + * Authors: Ray Smith + * Created: Tue Nov 19 2013 + * + * (C) Copyright 2013, Google Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + **********************************************************************/ +#ifndef TESSERACT_TRAINING_DEGRADEIMAGE_H_ +#define TESSERACT_TRAINING_DEGRADEIMAGE_H_ + +struct Pix; + +namespace tesseract { + +// Degrade the pix as if by a print/copy/scan cycle with exposure > 0 +// corresponding to darkening on the copier and <0 lighter and 0 not copied. +// If rotation is not NULL, the clockwise rotation in radians is saved there. +// The input pix must be 8 bit grey. (Binary with values 0 and 255 is OK.) +// The input image is destroyed and a different image returned. +struct Pix* DegradeImage(struct Pix* input, int exposure, float* rotation); + +} // namespace tesseract + +#endif // TESSERACT_TRAINING_DEGRADEIMAGE_H_ diff --git a/TesseractOCR/include/tesseract/detlinefit.h b/TesseractOCR/include/tesseract/detlinefit.h old mode 100755 new mode 100644 index 9f43098c..12afbb79 --- a/TesseractOCR/include/tesseract/detlinefit.h +++ b/TesseractOCR/include/tesseract/detlinefit.h @@ -20,6 +20,8 @@ #ifndef TESSERACT_CCSTRUCT_DETLINEFIT_H_ #define TESSERACT_CCSTRUCT_DETLINEFIT_H_ +#include "genericvector.h" +#include "kdpair.h" #include "points.h" namespace tesseract { @@ -59,13 +61,38 @@ class DetLineFit { // Delete all Added points. void Clear(); - // Add a new point. Takes a copy - the pt doesn't need to stay in scope. + // Adds a new point. Takes a copy - the pt doesn't need to stay in scope. // Add must be called on points in sequence along the line. void Add(const ICOORD& pt); + // Associates a half-width with the given point if a point overlaps the + // previous point by more than half the width, and its distance is further + // than the previous point, then the more distant point is ignored in the + // distance calculation. Useful for ignoring i dots and other diacritics. + void Add(const ICOORD& pt, int halfwidth); - // Fit a line to the points, returning the fitted line as a pair of + // Fits a line to the points, returning the fitted line as a pair of // points, and the upper quartile error. - double Fit(ICOORD* pt1, ICOORD* pt2); + double Fit(ICOORD* pt1, ICOORD* pt2) { + return Fit(0, 0, pt1, pt2); + } + // Fits a line to the points, ignoring the skip_first initial points and the + // skip_last final points, returning the fitted line as a pair of points, + // and the upper quartile error. + double Fit(int skip_first, int skip_last, ICOORD* pt1, ICOORD* pt2); + + // Constrained fit with a supplied direction vector. Finds the best line_pt, + // that is one of the supplied points having the median cross product with + // direction, ignoring points that have a cross product outside of the range + // [min_dist, max_dist]. Returns the resulting error metric using the same + // reduced set of points. + // *Makes use of floating point arithmetic* + double ConstrainedFit(const FCOORD& direction, + double min_dist, double max_dist, + bool debug, ICOORD* line_pt); + + // Returns true if there were enough points at the last call to Fit or + // ConstrainedFit for the fitted points to be used on a badly fitted line. + bool SufficientPointsForIndependentFit() const; // Backwards compatible fit returning a gradient and constant. // Deprecated. Prefer Fit(ICOORD*, ICOORD*) where possible, but use this @@ -73,12 +100,61 @@ class DetLineFit { double Fit(float* m, float* c); // Backwards compatible constrained fit with a supplied gradient. + // Deprecated. Use ConstrainedFit(const FCOORD& direction) where possible + // to avoid potential difficulties with infinite gradients. double ConstrainedFit(double m, float* c); private: - double ComputeErrors(const ICOORD start, const ICOORD end, int* distances); + // Simple struct to hold an ICOORD point and a halfwidth representing half + // the "width" (supposedly approximately parallel to the direction of the + // line) of each point, such that distant points can be discarded when they + // overlap nearer points. (Think i dot and other diacritics or noise.) + struct PointWidth { + PointWidth() : pt(ICOORD(0, 0)), halfwidth(0) {} + PointWidth(const ICOORD& pt0, int halfwidth0) + : pt(pt0), halfwidth(halfwidth0) {} + + ICOORD pt; + int halfwidth; + }; + // Type holds the distance of each point from the fitted line and the point + // itself. Use of double allows integer distances from ICOORDs to be stored + // exactly, and also the floating point results from ConstrainedFit. + typedef KDPairInc DistPointPair; + + // Computes and returns the squared evaluation metric for a line fit. + double EvaluateLineFit(); + + // Computes the absolute values of the precomputed distances_, + // and returns the squared upper-quartile error distance. + double ComputeUpperQuartileError(); + + // Returns the number of sample points that have an error more than threshold. + int NumberOfMisfittedPoints(double threshold) const; + + // Computes all the cross product distances of the points from the line, + // storing the actual (signed) cross products in distances_. + // Ignores distances of points that are further away than the previous point, + // and overlaps the previous point by at least half. + void ComputeDistances(const ICOORD& start, const ICOORD& end); + + // Computes all the cross product distances of the points perpendicular to + // the given direction, ignoring distances outside of the give distance range, + // storing the actual (signed) cross products in distances_. + void ComputeConstrainedDistances(const FCOORD& direction, + double min_dist, double max_dist); - ICOORDELT_LIST pt_list_; // All the added points. + // Stores all the source points in the order they were given and their + // halfwidths, if any. + GenericVector pts_; + // Stores the computed perpendicular distances of (some of) the pts_ from a + // given vector (assuming it goes through the origin, making it a line). + // Since the distances may be a subset of the input points, and get + // re-ordered by the nth_item function, the original point is stored + // along side the distance. + GenericVector distances_; // Distances of points. + // The squared length of the vector used to compute distances_. + double square_length_; }; } // namespace tesseract. diff --git a/TesseractOCR/include/tesseract/devanagari_processing.h b/TesseractOCR/include/tesseract/devanagari_processing.h new file mode 100644 index 00000000..a512460d --- /dev/null +++ b/TesseractOCR/include/tesseract/devanagari_processing.h @@ -0,0 +1,206 @@ +// Copyright 2008 Google Inc. All Rights Reserved. +// Author: shobhitsaxena@google.com (Shobhit Saxena) + +#ifndef TESSERACT_TEXTORD_DEVNAGARI_PROCESSING_H_ +#define TESSERACT_TEXTORD_DEVNAGARI_PROCESSING_H_ + +#include "ocrblock.h" +#include "params.h" + +struct Pix; +struct Box; +struct Boxa; + +extern +INT_VAR_H(devanagari_split_debuglevel, 0, + "Debug level for split shiro-rekha process."); + +extern +BOOL_VAR_H(devanagari_split_debugimage, 0, + "Whether to create a debug image for split shiro-rekha process."); + +class TBOX; + +namespace tesseract { + +class PixelHistogram { + public: + PixelHistogram() { + hist_ = NULL; + length_ = 0; + } + + ~PixelHistogram() { + Clear(); + } + + void Clear() { + if (hist_) { + delete[] hist_; + } + length_ = 0; + } + + int* const hist() const { + return hist_; + } + + int length() const { + return length_; + } + + // Methods to construct histograms from images. These clear any existing data. + void ConstructVerticalCountHist(Pix* pix); + void ConstructHorizontalCountHist(Pix* pix); + + // This method returns the global-maxima for the histogram. The frequency of + // the global maxima is returned in count, if specified. + int GetHistogramMaximum(int* count) const; + + private: + int* hist_; + int length_; +}; + +class ShiroRekhaSplitter { + public: + enum SplitStrategy { + NO_SPLIT = 0, // No splitting is performed for the phase. + MINIMAL_SPLIT, // Blobs are split minimally. + MAXIMAL_SPLIT // Blobs are split maximally. + }; + + ShiroRekhaSplitter(); + virtual ~ShiroRekhaSplitter(); + + // Top-level method to perform splitting based on current settings. + // Returns true if a split was actually performed. + // If split_for_pageseg is true, the pageseg_split_strategy_ is used for + // splitting. If false, the ocr_split_strategy_ is used. + bool Split(bool split_for_pageseg); + + // Clears the memory held by this object. + void Clear(); + + // Refreshes the words in the segmentation block list by using blobs in the + // input blob list. + // The segmentation block list must be set. + void RefreshSegmentationWithNewBlobs(C_BLOB_LIST* new_blobs); + + // Returns true if the split strategies for pageseg and ocr are different. + bool HasDifferentSplitStrategies() const { + return pageseg_split_strategy_ != ocr_split_strategy_; + } + + // This only keeps a copy of the block list pointer. At split call, the list + // object should still be alive. This block list is used as a golden + // segmentation when performing splitting. + void set_segmentation_block_list(BLOCK_LIST* block_list) { + segmentation_block_list_ = block_list; + } + + static const int kUnspecifiedXheight = -1; + + void set_global_xheight(int xheight) { + global_xheight_ = xheight; + } + + void set_perform_close(bool perform) { + perform_close_ = perform; + } + + // Returns the image obtained from shiro-rekha splitting. The returned object + // is owned by this class. Callers may want to clone the returned pix to keep + // it alive beyond the life of ShiroRekhaSplitter object. + Pix* splitted_image() { + return splitted_image_; + } + + // On setting the input image, a clone of it is owned by this class. + void set_orig_pix(Pix* pix); + + // Returns the input image provided to the object. This object is owned by + // this class. Callers may want to clone the returned pix to work with it. + Pix* orig_pix() { + return orig_pix_; + } + + SplitStrategy ocr_split_strategy() const { + return ocr_split_strategy_; + } + + void set_ocr_split_strategy(SplitStrategy strategy) { + ocr_split_strategy_ = strategy; + } + + SplitStrategy pageseg_split_strategy() const { + return pageseg_split_strategy_; + } + + void set_pageseg_split_strategy(SplitStrategy strategy) { + pageseg_split_strategy_ = strategy; + } + + BLOCK_LIST* segmentation_block_list() { + return segmentation_block_list_; + } + + // This method dumps a debug image to the specified location. + void DumpDebugImage(const char* filename) const; + + // This method returns the computed mode-height of blobs in the pix. + // It also prunes very small blobs from calculation. Could be used to provide + // a global xheight estimate for images which have the same point-size text. + static int GetModeHeight(Pix* pix); + + private: + // Method to perform a close operation on the input image. The xheight + // estimate decides the size of sel used. + static void PerformClose(Pix* pix, int xheight_estimate); + + // This method resolves the cc bbox to a particular row and returns the row's + // xheight. This uses block_list_ if available, else just returns the + // global_xheight_ estimate currently set in the object. + int GetXheightForCC(Box* cc_bbox); + + // Returns a list of regions (boxes) which should be cleared in the original + // image so as to perform shiro-rekha splitting. Pix is assumed to carry one + // (or less) word only. Xheight measure could be the global estimate, the row + // estimate, or unspecified. If unspecified, over splitting may occur, since a + // conservative estimate of stroke width along with an associated multiplier + // is used in its place. It is advisable to have a specified xheight when + // splitting for classification/training. + void SplitWordShiroRekha(SplitStrategy split_strategy, + Pix* pix, + int xheight, + int word_left, + int word_top, + Boxa* regions_to_clear); + + // Returns a new box object for the corresponding TBOX, based on the original + // image's coordinate system. + Box* GetBoxForTBOX(const TBOX& tbox) const; + + // This method returns y-extents of the shiro-rekha computed from the input + // word image. + static void GetShiroRekhaYExtents(Pix* word_pix, + int* shirorekha_top, + int* shirorekha_bottom, + int* shirorekha_ylevel); + + Pix* orig_pix_; // Just a clone of the input image passed. + Pix* splitted_image_; // Image produced after the last splitting round. The + // object is owned by this class. + SplitStrategy pageseg_split_strategy_; + SplitStrategy ocr_split_strategy_; + Pix* debug_image_; + // This block list is used as a golden segmentation when performing splitting. + BLOCK_LIST* segmentation_block_list_; + int global_xheight_; + bool perform_close_; // Whether a morphological close operation should be + // performed before CCs are run through splitting. +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_DEVNAGARI_PROCESSING_H_ diff --git a/TesseractOCR/include/tesseract/dict.h b/TesseractOCR/include/tesseract/dict.h new file mode 100644 index 00000000..e95a3e5d --- /dev/null +++ b/TesseractOCR/include/tesseract/dict.h @@ -0,0 +1,637 @@ +/////////////////////////////////////////////////////////////////////// +// File: dict.h +// Description: dict class. +// Author: Samuel Charron +// +// (C) Copyright 2006, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_DICT_DICT_H_ +#define TESSERACT_DICT_DICT_H_ + +#include "ambigs.h" +#include "dawg.h" +#include "dawg_cache.h" +#include "host.h" +#include "oldlist.h" +#include "ratngs.h" +#include "stopper.h" +#include "trie.h" +#include "unicharset.h" +#include "params_training_featdef.h" + +class MATRIX; +class WERD_RES; + +#define MAX_WERD_LENGTH (inT64) 128 +#define NO_RATING -1 + +/** Struct used to hold temporary information about fragments. */ +struct CHAR_FRAGMENT_INFO { + UNICHAR_ID unichar_id; + const CHAR_FRAGMENT *fragment; + int num_fragments; + float rating; + float certainty; +}; + +namespace tesseract { + +typedef GenericVector DawgVector; + +// +// Constants +// +static const int kRatingPad = 4; +static const char kDictWildcard[] = "\u2606"; // WHITE STAR +static const int kDictMaxWildcards = 2; // max wildcards for a word +// TODO(daria): If hyphens are different in different languages and can be +// inferred from training data we should load their values dynamically. +static const char kHyphenSymbol[] = "-"; +static const char kSlashSymbol[] = "/"; +static const char kQuestionSymbol[] = "?"; +static const char kApostropheSymbol[] = "'"; +static const float kSimCertaintyScale = -10.0; // similarity matcher scaling +static const float kSimCertaintyOffset = -10.0; // similarity matcher offset +static const float kSimilarityFloor = 100.0; // worst E*L product to stop on +static const int kDocDictMaxRepChars = 4; + +// Enum for describing whether the x-height for the word is consistent: +// 0 - everything is good. +// 1 - there are one or two secondary (but consistent) baselines +// [think subscript and superscript], or there is an oversized +// first character. +// 2 - the word is inconsistent. +enum XHeightConsistencyEnum {XH_GOOD, XH_SUBNORMAL, XH_INCONSISTENT}; + +struct DawgArgs { + DawgArgs(DawgPositionVector *d, DawgPositionVector *up, PermuterType p) + : active_dawgs(d), updated_dawgs(up), permuter(p) {} + + DawgPositionVector *active_dawgs; + DawgPositionVector *updated_dawgs; + PermuterType permuter; +}; + +class Dict { + public: + Dict(CCUtil* image_ptr); + ~Dict(); + const CCUtil* getCCUtil() const { + return ccutil_; + } + CCUtil* getCCUtil() { + return ccutil_; + } + const UNICHARSET& getUnicharset() const { + return getCCUtil()->unicharset; + } + UNICHARSET& getUnicharset() { + return getCCUtil()->unicharset; + } + const UnicharAmbigs &getUnicharAmbigs() const { + return getCCUtil()->unichar_ambigs; + } + + // Returns true if unichar_id is a word compounding character like - or /. + inline bool compound_marker(UNICHAR_ID unichar_id) { + const GenericVector& normed_ids = + getUnicharset().normed_ids(unichar_id); + return normed_ids.size() == 1 && + (normed_ids[0] == hyphen_unichar_id_ || + normed_ids[0] == slash_unichar_id_); + } + // Returns true if unichar_id is an apostrophe-like character that may + // separate prefix/suffix words from a main body word. + inline bool is_apostrophe(UNICHAR_ID unichar_id) { + const GenericVector& normed_ids = + getUnicharset().normed_ids(unichar_id); + return normed_ids.size() == 1 && normed_ids[0] == apostrophe_unichar_id_; + } + + /* hyphen.cpp ************************************************************/ + + /// Returns true if we've recorded the beginning of a hyphenated word. + inline bool hyphenated() const { return + !last_word_on_line_ && hyphen_word_; + } + /// Size of the base word (the part on the line before) of a hyphenated word. + inline int hyphen_base_size() const { + return this->hyphenated() ? hyphen_word_->length() : 0; + } + /// If this word is hyphenated copy the base word (the part on + /// the line before) of a hyphenated word into the given word. + /// This function assumes that word is not NULL. + inline void copy_hyphen_info(WERD_CHOICE *word) const { + if (this->hyphenated()) { + *word = *hyphen_word_; + if (hyphen_debug_level) word->print("copy_hyphen_info: "); + } + } + /// Check whether the word has a hyphen at the end. + inline bool has_hyphen_end(UNICHAR_ID unichar_id, bool first_pos) const { + if (!last_word_on_line_ || first_pos) + return false; + const GenericVector& normed_ids = + getUnicharset().normed_ids(unichar_id); + return normed_ids.size() == 1 && normed_ids[0] == hyphen_unichar_id_; + } + /// Same as above, but check the unichar at the end of the word. + inline bool has_hyphen_end(const WERD_CHOICE &word) const { + int word_index = word.length() - 1; + return has_hyphen_end(word.unichar_id(word_index), word_index == 0); + } + /// Unless the previous word was the last one on the line, and the current + /// one is not (thus it is the first one on the line), erase hyphen_word_, + /// clear hyphen_active_dawgs_, update last_word_on_line_. + void reset_hyphen_vars(bool last_word_on_line); + /// Update hyphen_word_, and copy the given DawgPositionVectors into + /// hyphen_active_dawgs_ . + void set_hyphen_word(const WERD_CHOICE &word, + const DawgPositionVector &active_dawgs); + + /* permdawg.cpp ************************************************************/ + // Note: Functions in permdawg.cpp are only used by NoDangerousAmbig(). + // When this function is refactored, permdawg.cpp can be removed. + + /// Copies word into best_choice if its rating is smaller + /// than that of best_choice. + inline void update_best_choice(const WERD_CHOICE &word, + WERD_CHOICE *best_choice) { + if (word.rating() < best_choice->rating()) { + *best_choice = word; + } + } + /// Fill the given active_dawgs vector with dawgs that could contain the + /// beginning of the word. If hyphenated() returns true, copy the entries + /// from hyphen_active_dawgs_ instead. + void init_active_dawgs(DawgPositionVector *active_dawgs, + bool ambigs_mode) const; + // Fill the given vector with the default collection of any-length dawgs + void default_dawgs(DawgPositionVector *anylength_dawgs, + bool suppress_patterns) const; + + + /// Recursively explore all the possible character combinations in + /// the given char_choices. Use go_deeper_dawg_fxn() to explore all the + /// dawgs in the dawgs_ vector in parallel and discard invalid words. + /// + /// Allocate and return a WERD_CHOICE with the best valid word found. + WERD_CHOICE *dawg_permute_and_select( + const BLOB_CHOICE_LIST_VECTOR &char_choices, float rating_limit); + /// If the choice being composed so far could be a dictionary word + /// and we have not reached the end of the word keep exploring the + /// char_choices further. + void go_deeper_dawg_fxn( + const char *debug, const BLOB_CHOICE_LIST_VECTOR &char_choices, + int char_choice_index, const CHAR_FRAGMENT_INFO *prev_char_frag_info, + bool word_ending, WERD_CHOICE *word, float certainties[], + float *limit, WERD_CHOICE *best_choice, int *attempts_left, + void *void_more_args); + + /// Pointer to go_deeper function. + void (Dict::*go_deeper_fxn_)(const char *debug, + const BLOB_CHOICE_LIST_VECTOR &char_choices, + int char_choice_index, + const CHAR_FRAGMENT_INFO *prev_char_frag_info, + bool word_ending, WERD_CHOICE *word, + float certainties[], float *limit, + WERD_CHOICE *best_choice, int *attempts_left, + void *void_more_args); + // + // Helper functions for dawg_permute_and_select(). + // + void permute_choices( + const char *debug, + const BLOB_CHOICE_LIST_VECTOR &char_choices, + int char_choice_index, + const CHAR_FRAGMENT_INFO *prev_char_frag_info, + WERD_CHOICE *word, + float certainties[], + float *limit, + WERD_CHOICE *best_choice, + int *attempts_left, + void *more_args); + + void append_choices( + const char *debug, + const BLOB_CHOICE_LIST_VECTOR &char_choices, + const BLOB_CHOICE &blob_choice, + int char_choice_index, + const CHAR_FRAGMENT_INFO *prev_char_frag_info, + WERD_CHOICE *word, + float certainties[], + float *limit, + WERD_CHOICE *best_choice, + int *attempts_left, + void *more_args); + + bool fragment_state_okay(UNICHAR_ID curr_unichar_id, + float curr_rating, float curr_certainty, + const CHAR_FRAGMENT_INFO *prev_char_frag_info, + const char *debug, int word_ending, + CHAR_FRAGMENT_INFO *char_frag_info); + + /* stopper.cpp *************************************************************/ + bool NoDangerousAmbig(WERD_CHOICE *BestChoice, + DANGERR *fixpt, + bool fix_replaceable, + MATRIX* ratings); + // Replaces the corresponding wrong ngram in werd_choice with the correct + // one. The whole correct n-gram is inserted into the ratings matrix and + // the werd_choice: no more fragments!. Rating and certainty of new entries + // in matrix and werd_choice are the sum and mean of the wrong ngram + // respectively. + // E.g. for werd_choice mystring'' and ambiguity ''->": werd_choice becomes + // mystring", with a new entry in the ratings matrix for ". + void ReplaceAmbig(int wrong_ngram_begin_index, int wrong_ngram_size, + UNICHAR_ID correct_ngram_id, WERD_CHOICE *werd_choice, + MATRIX *ratings); + + /// Returns the length of the shortest alpha run in WordChoice. + int LengthOfShortestAlphaRun(const WERD_CHOICE &WordChoice); + /// Returns true if the certainty of the BestChoice word is within a + /// reasonable range of the average certainties for the best choices for + /// each character in the segmentation. This test is used to catch words + /// in which one character is much worse than the other characters in the + /// word (i.e. false will be returned in that case). The algorithm computes + /// the mean and std deviation of the certainties in the word with the worst + /// certainty thrown out. + int UniformCertainties(const WERD_CHOICE& word); + /// Returns true if the given best_choice is good enough to stop. + bool AcceptableChoice(const WERD_CHOICE& best_choice, + XHeightConsistencyEnum xheight_consistency); + /// Returns false if the best choice for the current word is questionable + /// and should be tried again on the second pass or should be flagged to + /// the user. + bool AcceptableResult(WERD_RES* word); + void EndDangerousAmbigs(); + /// Prints the current choices for this word to stdout. + void DebugWordChoices(); + /// Sets up stopper variables in preparation for the first pass. + void SettupStopperPass1(); + /// Sets up stopper variables in preparation for the second pass. + void SettupStopperPass2(); + /* context.cpp *************************************************************/ + /// Check a string to see if it matches a set of lexical rules. + int case_ok(const WERD_CHOICE &word, const UNICHARSET &unicharset); + /// Returns true if the word looks like an absolute garbage + /// (e.g. image mistakenly recognized as text). + bool absolute_garbage(const WERD_CHOICE &word, const UNICHARSET &unicharset); + + /* dict.cpp ****************************************************************/ + + /// Initialize Dict class - load dawgs from [lang].traineddata and + /// user-specified wordlist and parttern list. + static DawgCache *GlobalDawgCache(); + void Load(DawgCache *dawg_cache); + void End(); + + // Resets the document dictionary analogous to ResetAdaptiveClassifier. + void ResetDocumentDictionary() { + if (pending_words_ != NULL) + pending_words_->clear(); + if (document_words_ != NULL) + document_words_->clear(); + } + + /** + * Returns the maximal permuter code (from ccstruct/ratngs.h) if in light + * of the current state the letter at word_index in the given word + * is allowed according to at least one of the dawgs in dawgs_, + * otherwise returns NO_PERM. + * + * The state is described by void_dawg_args, which are interpreted as + * DawgArgs and contain relevant active dawg positions. + * Each entry in the active_dawgs vector contains an index + * into the dawgs_ vector and an EDGE_REF that indicates the last edge + * followed in the dawg. It also may contain a position in the punctuation + * dawg which describes surrounding punctuation (see struct DawgPosition). + * + * Input: + * At word_index 0 dawg_args->active_dawgs should contain an entry for each + * dawg that may start at the beginning of a word, with punc_ref and edge_ref + * initialized to NO_EDGE. Since the punctuation dawg includes the empty + * pattern " " (meaning anything without surrounding punctuation), having a + * single entry for the punctuation dawg will cover all dawgs reachable + * therefrom -- that includes all number and word dawgs. The only dawg + * non-reachable from the punctuation_dawg is the pattern dawg. + * If hyphen state needs to be applied, initial dawg_args->active_dawgs can + * be copied from the saved hyphen state (maintained by Dict). + * For word_index > 0 the corresponding state (active_dawgs and punc position) + * can be obtained from dawg_args->updated_dawgs passed to + * def_letter_is_okay for word_index-1. + * Note: the function assumes that active_dawgs, nd updated_dawgs + * member variables of dawg_args are not NULL. + * + * Output: + * The function fills in dawg_args->updated_dawgs vector with the + * entries for dawgs that contain the word up to the letter at word_index. + * + */ + + // + int def_letter_is_okay(void* void_dawg_args, + UNICHAR_ID unichar_id, bool word_end) const; + + int (Dict::*letter_is_okay_)(void* void_dawg_args, + UNICHAR_ID unichar_id, bool word_end) const; + /// Calls letter_is_okay_ member function. + int LetterIsOkay(void* void_dawg_args, + UNICHAR_ID unichar_id, bool word_end) const { + return (this->*letter_is_okay_)(void_dawg_args, unichar_id, word_end); + } + + + /// Probability in context function used by the ngram permuter. + double (Dict::*probability_in_context_)(const char* lang, + const char* context, + int context_bytes, + const char* character, + int character_bytes); + /// Calls probability_in_context_ member function. + double ProbabilityInContext(const char* context, + int context_bytes, + const char* character, + int character_bytes) { + return (this->*probability_in_context_)( + getCCUtil()->lang.string(), + context, context_bytes, + character, character_bytes); + } + + /// Default (no-op) implementation of probability in context function. + double def_probability_in_context( + const char* lang, const char* context, int context_bytes, + const char* character, int character_bytes) { + (void) context; + (void) context_bytes; + (void) character; + (void) character_bytes; + return 0.0; + } + double ngram_probability_in_context(const char* lang, + const char* context, + int context_bytes, + const char* character, + int character_bytes); + + // Interface with params model. + float (Dict::*params_model_classify_)(const char *lang, void *path); + float ParamsModelClassify(const char *lang, void *path); + // Call params_model_classify_ member function. + float CallParamsModelClassify(void *path) { + ASSERT_HOST(params_model_classify_ != NULL); // ASSERT_HOST -> assert + return (this->*params_model_classify_)( + getCCUtil()->lang.string(), path); + } + + inline void SetWildcardID(UNICHAR_ID id) { wildcard_unichar_id_ = id; } + inline const UNICHAR_ID WildcardID() const { + return wildcard_unichar_id_; + } + /// Return the number of dawgs in the dawgs_ vector. + inline const int NumDawgs() const { return dawgs_.size(); } + /// Return i-th dawg pointer recorded in the dawgs_ vector. + inline const Dawg *GetDawg(int index) const { return dawgs_[index]; } + /// Return the points to the punctuation dawg. + inline const Dawg *GetPuncDawg() const { return punc_dawg_; } + /// Return the points to the unambiguous words dawg. + inline const Dawg *GetUnambigDawg() const { return unambig_dawg_; } + /// Returns the appropriate next node given the EDGE_REF. + static inline NODE_REF GetStartingNode(const Dawg *dawg, EDGE_REF edge_ref) { + if (edge_ref == NO_EDGE) return 0; // beginning to explore the dawg + NODE_REF node = dawg->next_node(edge_ref); + if (node == 0) node = NO_EDGE; // end of word + return node; + } + + // Given a unichar from a string and a given dawg, return the unichar + // we should use to match in that dawg type. (for example, in the number + // dawg, all numbers are transformed to kPatternUnicharId). + inline UNICHAR_ID char_for_dawg(UNICHAR_ID ch, const Dawg *dawg) const { + if (!dawg) return ch; + switch (dawg->type()) { + case DAWG_TYPE_NUMBER: + return getUnicharset().get_isdigit(ch) ? Dawg::kPatternUnicharID : ch; + default: + return ch; + } + } + + /// For each of the character classes of the given unichar_id (and the + /// unichar_id itself) finds the corresponding outgoing node or self-loop + /// in the given dawg and (after checking that it is valid) records it in + /// dawg_args->updated_ative_dawgs. Updates current_permuter if any valid + /// edges were found. + void ProcessPatternEdges(const Dawg *dawg, const DawgPosition &info, + UNICHAR_ID unichar_id, bool word_end, + DawgPositionVector *updated_dawgs, + PermuterType *current_permuter) const; + + /// Read/Write/Access special purpose dawgs which contain words + /// only of a certain length (used for phrase search for + /// non-space-delimited languages). + + /// Check all the DAWGs to see if this word is in any of them. + inline static bool valid_word_permuter(uinT8 perm, bool numbers_ok) { + return (perm == SYSTEM_DAWG_PERM || perm == FREQ_DAWG_PERM || + perm == DOC_DAWG_PERM || perm == USER_DAWG_PERM || + perm == USER_PATTERN_PERM || perm == COMPOUND_PERM || + (numbers_ok && perm == NUMBER_PERM)); + } + int valid_word(const WERD_CHOICE &word, bool numbers_ok) const; + int valid_word(const WERD_CHOICE &word) const { + return valid_word(word, false); // return NO_PERM for words with digits + } + int valid_word_or_number(const WERD_CHOICE &word) const { + return valid_word(word, true); // return NUMBER_PERM for valid numbers + } + /// This function is used by api/tesseract_cube_combiner.cpp + int valid_word(const char *string) const { + WERD_CHOICE word(string, getUnicharset()); + return valid_word(word); + } + // Do the two WERD_CHOICEs form a meaningful bigram? + bool valid_bigram(const WERD_CHOICE &word1, const WERD_CHOICE &word2) const; + /// Returns true if the word contains a valid punctuation pattern. + /// Note: Since the domains of punctuation symbols and symblos + /// used in numbers are not disjoint, a valid number might contain + /// an invalid punctuation pattern (e.g. .99). + bool valid_punctuation(const WERD_CHOICE &word); + /// Returns true if a good answer is found for the unknown blob rating. + int good_choice(const WERD_CHOICE &choice); + /// Adds a word found on this document to the document specific dictionary. + void add_document_word(const WERD_CHOICE &best_choice); + /// Adjusts the rating of the given word. + void adjust_word(WERD_CHOICE *word, + bool nonword, XHeightConsistencyEnum xheight_consistency, + float additional_adjust, + bool modify_rating, + bool debug); + /// Set wordseg_rating_adjust_factor_ to the given value. + inline void SetWordsegRatingAdjustFactor(float f) { + wordseg_rating_adjust_factor_ = f; + } + + private: + /** Private member variables. */ + CCUtil* ccutil_; + /** + * Table that stores ambiguities computed during training + * (loaded when NoDangerousAmbigs() is called for the first time). + * Each entry i in the table stores a set of amibiguities whose + * wrong ngram starts with unichar id i. + */ + UnicharAmbigs *dang_ambigs_table_; + /** Same as above, but for ambiguities with replace flag set. */ + UnicharAmbigs *replace_ambigs_table_; + /** Additional certainty padding allowed before a word is rejected. */ + FLOAT32 reject_offset_; + // Cached UNICHAR_IDs: + UNICHAR_ID wildcard_unichar_id_; // kDictWildcard. + UNICHAR_ID apostrophe_unichar_id_; // kApostropheSymbol. + UNICHAR_ID question_unichar_id_; // kQuestionSymbol. + UNICHAR_ID slash_unichar_id_; // kSlashSymbol. + UNICHAR_ID hyphen_unichar_id_; // kHyphenSymbol. + // Hyphen-related variables. + WERD_CHOICE *hyphen_word_; + DawgPositionVector hyphen_active_dawgs_; + bool last_word_on_line_; + // List of lists of "equivalent" UNICHAR_IDs for the purposes of dictionary + // matching. The first member of each list is taken as canonical. For + // example, the first list contains hyphens and dashes with the first symbol + // being the ASCII hyphen minus. + GenericVector > equivalent_symbols_; + // Dawg Cache reference - this is who we ask to allocate/deallocate dawgs. + DawgCache *dawg_cache_; + bool dawg_cache_is_ours_; // we should delete our own dawg_cache_ + // Dawgs. + DawgVector dawgs_; + SuccessorListsVector successors_; + Trie *pending_words_; + // bigram_dawg_ points to a dawg of two-word bigrams which always supercede if + // any of them are present on the best choices list for a word pair. + // the bigrams are stored as space-separated words where: + // (1) leading and trailing punctuation has been removed from each word and + // (2) any digits have been replaced with '?' marks. + Dawg *bigram_dawg_; + /// The following pointers are only cached for convenience. + /// The dawgs will be deleted when dawgs_ vector is destroyed. + // TODO(daria): need to support multiple languages in the future, + // so maybe will need to maintain a list of dawgs of each kind. + Dawg *freq_dawg_; + Dawg *unambig_dawg_; + Dawg *punc_dawg_; + Trie *document_words_; + /// Current segmentation cost adjust factor for word rating. + /// See comments in incorporate_segcost. + float wordseg_rating_adjust_factor_; + // File for recording ambiguities discovered during dictionary search. + FILE *output_ambig_words_file_; + + public: + /// Variable members. + /// These have to be declared and initialized after image_ptr_, which contains + /// the pointer to the params vector - the member of its base CCUtil class. + STRING_VAR_H(user_words_suffix, "", "A list of user-provided words."); + STRING_VAR_H(user_patterns_suffix, "", + "A list of user-provided patterns."); + BOOL_VAR_H(load_system_dawg, true, "Load system word dawg."); + BOOL_VAR_H(load_freq_dawg, true, "Load frequent word dawg."); + BOOL_VAR_H(load_unambig_dawg, true, "Load unambiguous word dawg."); + BOOL_VAR_H(load_punc_dawg, true, + "Load dawg with punctuation patterns."); + BOOL_VAR_H(load_number_dawg, true, "Load dawg with number patterns."); + BOOL_VAR_H(load_bigram_dawg, true, + "Load dawg with special word bigrams."); + double_VAR_H(xheight_penalty_subscripts, 0.125, + "Score penalty (0.1 = 10%) added if there are subscripts " + "or superscripts in a word, but it is otherwise OK."); + double_VAR_H(xheight_penalty_inconsistent, 0.25, + "Score penalty (0.1 = 10%) added if an xheight is " + "inconsistent."); + double_VAR_H(segment_penalty_dict_frequent_word, 1.0, + "Score multiplier for word matches which have good case and" + "are frequent in the given language (lower is better)."); + + double_VAR_H(segment_penalty_dict_case_ok, 1.1, + "Score multiplier for word matches that have good case " + "(lower is better)."); + + double_VAR_H(segment_penalty_dict_case_bad, 1.3125, + "Default score multiplier for word matches, which may have " + "case issues (lower is better)."); + + // TODO(daria): remove this param when ngram permuter is deprecated. + double_VAR_H(segment_penalty_ngram_best_choice, 1.24, + "Multipler to for the best choice from the ngram model."); + + double_VAR_H(segment_penalty_dict_nonword, 1.25, + "Score multiplier for glyph fragment segmentations which " + "do not match a dictionary word (lower is better)."); + + double_VAR_H(segment_penalty_garbage, 1.50, + "Score multiplier for poorly cased strings that are not in" + " the dictionary and generally look like garbage (lower is" + " better)."); + STRING_VAR_H(output_ambig_words_file, "", + "Output file for ambiguities found in the dictionary"); + INT_VAR_H(dawg_debug_level, 0, "Set to 1 for general debug info" + ", to 2 for more details, to 3 to see all the debug messages"); + INT_VAR_H(hyphen_debug_level, 0, "Debug level for hyphenated words."); + INT_VAR_H(max_viterbi_list_size, 10, "Maximum size of viterbi list."); + BOOL_VAR_H(use_only_first_uft8_step, false, + "Use only the first UTF8 step of the given string" + " when computing log probabilities."); + double_VAR_H(certainty_scale, 20.0, "Certainty scaling factor"); + double_VAR_H(stopper_nondict_certainty_base, -2.50, + "Certainty threshold for non-dict words"); + double_VAR_H(stopper_phase2_certainty_rejection_offset, 1.0, + "Reject certainty offset"); + INT_VAR_H(stopper_smallword_size, 2, + "Size of dict word to be treated as non-dict word"); + double_VAR_H(stopper_certainty_per_char, -0.50, + "Certainty to add for each dict char above small word size."); + double_VAR_H(stopper_allowable_character_badness, 3.0, + "Max certaintly variation allowed in a word (in sigma)"); + INT_VAR_H(stopper_debug_level, 0, "Stopper debug level"); + BOOL_VAR_H(stopper_no_acceptable_choices, false, + "Make AcceptableChoice() always return false. Useful" + " when there is a need to explore all segmentations"); + BOOL_VAR_H(save_raw_choices, false, + "Deprecated- backward compatability only"); + INT_VAR_H(tessedit_truncate_wordchoice_log, 10, "Max words to keep in list"); + STRING_VAR_H(word_to_debug, "", "Word for which stopper debug information" + " should be printed to stdout"); + STRING_VAR_H(word_to_debug_lengths, "", + "Lengths of unichars in word_to_debug"); + INT_VAR_H(fragments_debug, 0, "Debug character fragments"); + BOOL_VAR_H(segment_nonalphabetic_script, false, + "Don't use any alphabetic-specific tricks." + "Set to true in the traineddata config file for" + " scripts that are cursive or inherently fixed-pitch"); + BOOL_VAR_H(save_doc_words, 0, "Save Document Words"); + double_VAR_H(doc_dict_pending_threshold, 0.0, + "Worst certainty for using pending dictionary"); + double_VAR_H(doc_dict_certainty_threshold, -2.25, "Worst certainty" + " for words that can be inserted into the document dictionary"); + INT_VAR_H(max_permuter_attempts, 10000, "Maximum number of different" + " character choices to consider during permutation." + " This limit is especially useful when user patterns" + " are specified, since overly generic patterns can result in" + " dawg search exploring an overly large number of options."); +}; +} // namespace tesseract + +#endif // THIRD_PARTY_TESSERACT_DICT_DICT_H_ diff --git a/TesseractOCR/include/tesseract/docqual.h b/TesseractOCR/include/tesseract/docqual.h old mode 100755 new mode 100644 index 61fa6f46..15fde0dc --- a/TesseractOCR/include/tesseract/docqual.h +++ b/TesseractOCR/include/tesseract/docqual.h @@ -21,7 +21,6 @@ #define DOCQUAL_H #include "control.h" -#include "notdll.h" enum GARBAGE_LEVEL { diff --git a/TesseractOCR/include/tesseract/doubleptr.h b/TesseractOCR/include/tesseract/doubleptr.h new file mode 100644 index 00000000..4cef16b5 --- /dev/null +++ b/TesseractOCR/include/tesseract/doubleptr.h @@ -0,0 +1,93 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +/////////////////////////////////////////////////////////////////////// +// File: doubleptr.h +// Description: Double-ended pointer that keeps pointing correctly even +// when reallocated or copied. +// Author: Ray Smith +// Created: Wed Mar 14 12:22:57 PDT 2012 +// +// (C) Copyright 2012, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_CCUTIL_DOUBLEPTR_H_ +#define TESSERACT_CCUTIL_DOUBLEPTR_H_ + +#include "errcode.h" + +namespace tesseract { + +// A smart pointer class that implements a double-ended pointer. Each end +// points to the other end. The copy constructor and operator= have MOVE +// semantics, meaning that the relationship with the other end moves to the +// destination of the copy, leaving the source unattached. +// For this reason both the copy constructor and the operator= take a non-const +// reference argument, and the const reference versions cannot be used. +// DoublePtr is useful to incorporate into structures that are part of a +// collection such as GenericVector or STL containers, where reallocs can +// relocate the members. DoublePtr is also useful in a GenericHeap, where it +// can correctly maintain the pointer to an element of the heap despite it +// getting moved around on the heap. +class DoublePtr { + public: + DoublePtr() : other_end_(NULL) {} + // Copy constructor steals the partner off src and is therefore a non + // const reference arg. + // Copying a const DoublePtr generates a compiler error. + DoublePtr(DoublePtr& src) { + other_end_ = src.other_end_; + if (other_end_ != NULL) { + other_end_->other_end_ = this; + src.other_end_ = NULL; + } + } + // Operator= steals the partner off src, and therefore needs src to be a non- + // const reference. + // Assigning from a const DoublePtr generates a compiler error. + void operator=(DoublePtr& src) { + Disconnect(); + other_end_ = src.other_end_; + if (other_end_ != NULL) { + other_end_->other_end_ = this; + src.other_end_ = NULL; + } + } + + // Connects this and other, discarding any existing connections. + void Connect(DoublePtr* other) { + other->Disconnect(); + Disconnect(); + other->other_end_ = this; + other_end_ = other; + } + // Disconnects this and other, making OtherEnd() return NULL for both. + void Disconnect() { + if (other_end_ != NULL) { + other_end_->other_end_ = NULL; + other_end_ = NULL; + } + } + // Returns the pointer to the other end of the double pointer. + DoublePtr* OtherEnd() const { + return other_end_; + } + + private: + // Pointer to the other end of the link. It is always true that either + // other_end_ == NULL or other_end_->other_end_ == this. + DoublePtr* other_end_; +}; + +} // namespace tesseract. + +#endif // THIRD_PARTY_TESSERACT_CCUTIL_DOUBLEPTR_H_ diff --git a/TesseractOCR/include/tesseract/dppoint.h b/TesseractOCR/include/tesseract/dppoint.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/drawedg.h b/TesseractOCR/include/tesseract/drawedg.h new file mode 100644 index 00000000..339432fd --- /dev/null +++ b/TesseractOCR/include/tesseract/drawedg.h @@ -0,0 +1,34 @@ +/********************************************************************** + * File: drawedg.h (Formerly drawedge.h) + * Description: Collection of functions to draw things to do with edge detection. + * Author: Ray Smith + * Created: Thu Jun 06 13:29:20 BST 1991 + * + * (C) Copyright 1991, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef DRAWEDG_H +#define DRAWEDG_H + +#include "scrollview.h" +#include "crakedge.h" + +ScrollView* create_edges_window( //make window + ICOORD page_tr //size of image + ); +void draw_raw_edge( //draw the cracks + ScrollView* fd, //window to draw in + CRACKEDGE *start, //start of loop + ScrollView::Color colour //colour to draw in + ); +#endif diff --git a/TesseractOCR/include/tesseract/imgscale.h b/TesseractOCR/include/tesseract/drawfx.h old mode 100755 new mode 100644 similarity index 58% rename from TesseractOCR/include/tesseract/imgscale.h rename to TesseractOCR/include/tesseract/drawfx.h index 335c0b01..bf08c3b4 --- a/TesseractOCR/include/tesseract/imgscale.h +++ b/TesseractOCR/include/tesseract/drawfx.h @@ -1,8 +1,8 @@ /********************************************************************** - * File: imgscale.h (Formerly dyn_prog.h) - * Description: Dynamic programming for smart scaling of images. - * Author: Phil Cheatle - * Created: Wed Nov 18 16:12:03 GMT 1992 + * File: drawfx.h (Formerly drawfx.h) + * Description: Draw things to do with feature extraction. + * Author: Ray Smith + * Created: Mon Jan 27 11:02:16 GMT 1992 * * (C) Copyright 1992, Hewlett-Packard Ltd. ** Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,16 +17,16 @@ * **********************************************************************/ -#ifndef IMGSCALE_H -#define IMGSCALE_H +#ifndef DRAWFX_H +#define DRAWFX_H -void dyn_prog( //The clever bit - int n, - int *x, - int *y, - int ymax, - int *oldx, - int *oldy, - int oldn, - float factor); +#include "params.h" +#include "scrollview.h" + +extern STRING_VAR_H (fx_debugfile, DEBUG_WIN_NAME, "Name of debugfile"); +extern ScrollView* fx_win; +extern FILE *fx_debug; +void create_fx_win(); //make features win +void clear_fx_win(); //make features win +void create_fxdebug_win(); //make gradients win #endif diff --git a/TesseractOCR/include/tesseract/drawtord.h b/TesseractOCR/include/tesseract/drawtord.h new file mode 100644 index 00000000..f19d1adc --- /dev/null +++ b/TesseractOCR/include/tesseract/drawtord.h @@ -0,0 +1,99 @@ +/********************************************************************** + * File: drawtord.h (Formerly drawto.h) + * Description: Draw things to do with textord. + * Author: Ray Smith + * Created: Thu Jul 30 15:40:57 BST 1992 + * + * (C) Copyright 1992, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef DRAWTORD_H +#define DRAWTORD_H + +#include "params.h" +#include "scrollview.h" +#include "pitsync1.h" +#include "blobbox.h" + +#define NO_SMD "none" + +extern BOOL_VAR_H (textord_show_fixed_cuts, FALSE, +"Draw fixed pitch cell boundaries"); +extern STRING_VAR_H (to_debugfile, DEBUG_WIN_NAME, "Name of debugfile"); +extern STRING_VAR_H (to_smdfile, NO_SMD, "Name of SMD file"); +extern ScrollView* to_win; +extern FILE *to_debug; +// Creates a static display window for textord, and returns a pointer to it. +ScrollView* create_to_win(ICOORD page_tr); +void close_to_win(); // Destroy the textord window. +void create_todebug_win(); //make gradients win +void plot_box_list( //make gradients win + ScrollView* win, //window to draw in + BLOBNBOX_LIST *list, //blob list + ScrollView::Color body_colour //colour to draw + ); +void plot_to_row( //draw a row + TO_ROW *row, //row to draw + ScrollView::Color colour, //colour to draw in + FCOORD rotation //rotation for line + ); +void plot_parallel_row( //draw a row + TO_ROW *row, //row to draw + float gradient, //gradients of lines + inT32 left, //edge of block + ScrollView::Color colour, //colour to draw in + FCOORD rotation //rotation for line + ); +void draw_occupation ( //draw projection +inT32 xleft, //edge of block +inT32 ybottom, //bottom of block +inT32 min_y, //coordinate limits +inT32 max_y, inT32 occupation[], //projection counts +inT32 thresholds[] //for drop out +); +void draw_meanlines( //draw a block + TO_BLOCK *block, //block to draw + float gradient, //gradients of lines + inT32 left, //edge of block + ScrollView::Color colour, //colour to draw in + FCOORD rotation //rotation for line + ); +void plot_word_decisions( //draw words + ScrollView* win, //window tro draw in + inT16 pitch, //of block + TO_ROW *row //row to draw + ); +void plot_fp_cells( //draw words + ScrollView* win, //window tro draw in + ScrollView::Color colour, //colour of lines + BLOBNBOX_IT *blob_it, //blobs + inT16 pitch, //of block + inT16 blob_count, //no of real blobs + STATS *projection, //vertical + inT16 projection_left, //edges //scale factor + inT16 projection_right, + float projection_scale); +void plot_fp_cells2( //draw words + ScrollView* win, //window tro draw in + ScrollView::Color colour, //colour of lines + TO_ROW *row, //for location + FPSEGPT_LIST *seg_list //segments to plot + ); +void plot_row_cells( //draw words + ScrollView* win, //window tro draw in + ScrollView::Color colour, //colour of lines + TO_ROW *row, //for location + float xshift, //amount of shift + ICOORDELT_LIST *cells //cells to draw + ); +#endif diff --git a/TesseractOCR/include/tesseract/edgblob.h b/TesseractOCR/include/tesseract/edgblob.h new file mode 100644 index 00000000..daf5daac --- /dev/null +++ b/TesseractOCR/include/tesseract/edgblob.h @@ -0,0 +1,95 @@ +/********************************************************************** + * File: edgblob.h (Formerly edgeloop.h) + * Description: Functions to clean up an outline before approximation. + * Author: Ray Smith + * Created: Tue Mar 26 16:56:25 GMT 1991 + * + * (C) Copyright 1991, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef EDGBLOB_H +#define EDGBLOB_H + +#include "scrollview.h" +#include "params.h" +#include "ocrblock.h" +#include "coutln.h" +#include "crakedge.h" + +#define BUCKETSIZE 16 + +class OL_BUCKETS +{ + public: + OL_BUCKETS( //constructor + ICOORD bleft, //corners + ICOORD tright); + + ~OL_BUCKETS () { //cleanup + delete[]buckets; + } + C_OUTLINE_LIST *operator () (//array access + inT16 x, //image coords + inT16 y); + //first non-empty bucket + C_OUTLINE_LIST *start_scan() { + for (index = 0; buckets[index].empty () && index < bxdim * bydim - 1; + index++); + return &buckets[index]; + } + //next non-empty bucket + C_OUTLINE_LIST *scan_next() { + for (; buckets[index].empty () && index < bxdim * bydim - 1; index++); + return &buckets[index]; + } + inT32 count_children( //recursive sum + C_OUTLINE *outline, //parent outline + inT32 max_count); // max output + inT32 outline_complexity( // new version of count_children + C_OUTLINE *outline, // parent outline + inT32 max_count, // max output + inT16 depth); // level of recursion + void extract_children( //single level get + C_OUTLINE *outline, //parent outline + C_OUTLINE_IT *it); //destination iterator + + private: + C_OUTLINE_LIST * buckets; //array of buckets + inT16 bxdim; //size of array + inT16 bydim; + ICOORD bl; //corners + ICOORD tr; + inT32 index; //for extraction scan +}; + +void extract_edges(Pix* pix, // thresholded image + BLOCK* block); // block to scan +void outlines_to_blobs( //find blobs + BLOCK *block, //block to scan + ICOORD bleft, //block box //outlines in block + ICOORD tright, + C_OUTLINE_LIST *outlines); +void fill_buckets( //find blobs + C_OUTLINE_LIST *outlines, //outlines in block + OL_BUCKETS *buckets //output buckets + ); +void empty_buckets( //find blobs + BLOCK *block, //block to scan + OL_BUCKETS *buckets //output buckets + ); +BOOL8 capture_children( //find children + OL_BUCKETS *buckets, //bucket sort clanss + C_BLOB_IT *reject_it, //dead grandchildren + C_OUTLINE_IT *blob_it //output outlines + ); +#endif diff --git a/TesseractOCR/include/tesseract/edgloop.h b/TesseractOCR/include/tesseract/edgloop.h new file mode 100644 index 00000000..266676f5 --- /dev/null +++ b/TesseractOCR/include/tesseract/edgloop.h @@ -0,0 +1,49 @@ +/********************************************************************** + * File: edgloop.h (Formerly edgeloop.h) + * Description: Functions to clean up an outline before approximation. + * Author: Ray Smith + * Created: Tue Mar 26 16:56:25 GMT 1991 + * + * (C) Copyright 1991, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef EDGLOOP_H +#define EDGLOOP_H + +#include "scrollview.h" +#include "params.h" +#include "pdblock.h" +#include "coutln.h" +#include "crakedge.h" + +#define BUCKETSIZE 16 + + +extern INT_VAR_H (edges_children_per_grandchild, 10, +"Importance ratio for chucking outlines"); +extern INT_VAR_H (edges_children_count_limit, 45, +"Max holes allowed in blob"); +extern double_VAR_H (edges_childarea, 0.5, +"Max area fraction of child outline"); +extern double_VAR_H (edges_boxarea, 0.8, +"Min area fraction of grandchild for box"); +void complete_edge(CRACKEDGE *start, //start of loop + C_OUTLINE_IT* outline_it); +ScrollView::Color check_path_legal( //certify outline + CRACKEDGE *start //start of loop + ); +inT16 loop_bounding_box( //get bounding box + CRACKEDGE *&start, //edge loop + ICOORD &botleft, //bounding box + ICOORD &topright); +#endif diff --git a/TesseractOCR/include/tesseract/efio.h b/TesseractOCR/include/tesseract/efio.h new file mode 100644 index 00000000..ad706efa --- /dev/null +++ b/TesseractOCR/include/tesseract/efio.h @@ -0,0 +1,32 @@ +/****************************************************************************** + ** Filename: efio.h + ** Purpose: Definition of file I/O routines + ** Author: Dan Johnson + ** History: 5/21/89, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef EFIO_H +#define EFIO_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include + +#define FOPENERROR 3000 + +/**---------------------------------------------------------------------------- + Public Function Prototype +----------------------------------------------------------------------------**/ +FILE *Efopen(const char *Name, const char *Mode); +#endif diff --git a/TesseractOCR/include/tesseract/elst.h b/TesseractOCR/include/tesseract/elst.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/elst2.h b/TesseractOCR/include/tesseract/elst2.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/emalloc.h b/TesseractOCR/include/tesseract/emalloc.h new file mode 100644 index 00000000..6fda20a5 --- /dev/null +++ b/TesseractOCR/include/tesseract/emalloc.h @@ -0,0 +1,44 @@ +/****************************************************************************** + ** Filename: emalloc.h + ** Purpose: Definition of memory allocation routines. + ** Author: Dan Johnson + ** History: 4/3/89, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef EMALLOC_H +#define EMALLOC_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "host.h" +#include "callcpp.h" + +#define NOTENOUGHMEMORY 2000 +#define ILLEGALMALLOCREQUEST 2001 + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +void *Emalloc(int Size); + +void *Erealloc(void *ptr, int size); + +void Efree(void *ptr); + + +/**---------------------------------------------------------------------------- + Global Data Definitions and Declarations +----------------------------------------------------------------------------**/ + +#endif diff --git a/TesseractOCR/include/tesseract/equationdetect.h b/TesseractOCR/include/tesseract/equationdetect.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/equationdetectbase.h b/TesseractOCR/include/tesseract/equationdetectbase.h new file mode 100644 index 00000000..d47c74a5 --- /dev/null +++ b/TesseractOCR/include/tesseract/equationdetectbase.h @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////// +// File: equationdetectbase.h +// Description: The base class equation detection class. +// Author: Zongyi (Joe) Liu (joeliu@google.com) +// Created: Fri Aug 31 11:13:01 PST 2011 +// +// (C) Copyright 2011, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_EQUATIONDETECTBASE_H__ +#define TESSERACT_TEXTORD_EQUATIONDETECTBASE_H__ + +class BLOBNBOX_LIST; +class TO_BLOCK; +struct Pix; + +namespace tesseract { + +class ColPartitionGrid; +class ColPartitionSet; + +class EquationDetectBase { + public: + EquationDetectBase(); + virtual ~EquationDetectBase(); + + // Iterate over the blobs inside to_block, and set the blobs that we want to + // process to BSTT_NONE. (By default, they should be BSTT_SKIP). The function + // returns 0 upon success. + virtual int LabelSpecialText(TO_BLOCK* to_block) = 0; + + // Interface to find possible equation partition grid from part_grid. This + // should be called after IdentifySpecialText function. + virtual int FindEquationParts(ColPartitionGrid* part_grid, + ColPartitionSet** best_columns) = 0; + + // Debug function: Render a bounding box on pix based on the value of its + // special_text_type, specifically: + // BSTT_MATH: red box + // BSTT_DIGIT: cyan box + // BSTT_ITALIC: green box + // BSTT_UNCLEAR: blue box + // All others: yellow box + static void RenderSpecialText(Pix* pix, BLOBNBOX* blob); +}; + +}; // namespace tesseract + +#endif // TESSERACT_TEXTORD_EQUATIONDETECTBASE_H__ diff --git a/TesseractOCR/include/tesseract/errcode.h b/TesseractOCR/include/tesseract/errcode.h old mode 100755 new mode 100644 index 2bc2a03c..89385d2b --- a/TesseractOCR/include/tesseract/errcode.h +++ b/TesseractOCR/include/tesseract/errcode.h @@ -81,21 +81,29 @@ class TESS_API ERRCODE { // error handler class const ERRCODE ASSERT_FAILED = "Assert failed"; -#define ASSERT_HOST(x) if (!(x)) \ -{ \ - ASSERT_FAILED.error(#x,ABORT,"in file %s, line %d", \ - __FILE__,__LINE__); \ -} - -void signal_exit( // - int signal_code //Signal which - ); -extern "C" -{ - void err_exit(); - //The real signal - void signal_termination_handler(int sig); -}; +#define ASSERT_HOST(x) if (!(x)) \ + { \ + ASSERT_FAILED.error(#x, ABORT, "in file %s, line %d", \ + __FILE__, __LINE__); \ + } + +#ifdef _MSC_VER +#define ASSERT_HOST_MSG(x, msg, ...) if (!(x)) \ + { \ + tprintf(msg); \ + ASSERT_FAILED.error(#x, ABORT, "in file %s, line %d", \ + __FILE__, __LINE__); \ + } +#else +#define ASSERT_HOST_MSG(x, msg...) if (!(x)) \ + { \ + tprintf(msg); \ + ASSERT_FAILED.error(#x, ABORT, "in file %s, line %d", \ + __FILE__, __LINE__); \ + } +#endif + +void signal_exit(int signal_code); void set_global_loc_code(int loc_code); diff --git a/TesseractOCR/include/tesseract/errorcounter.h b/TesseractOCR/include/tesseract/errorcounter.h new file mode 100644 index 00000000..cdcd79c8 --- /dev/null +++ b/TesseractOCR/include/tesseract/errorcounter.h @@ -0,0 +1,227 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef THIRD_PARTY_TESSERACT_CLASSIFY_ERRORCOUNTER_H_ +#define THIRD_PARTY_TESSERACT_CLASSIFY_ERRORCOUNTER_H_ + +#include "genericvector.h" +#include "matrix.h" +#include "statistc.h" + +struct Pix; +template class UnicityTable; + +namespace tesseract { + +struct FontInfo; +class FontInfoTable; +class SampleIterator; +class ShapeClassifier; +class TrainingSample; +struct UnicharRating; + +// Enumeration of the different types of error count. +// Error counts work as follows: +// +// Ground truth is a valid unichar-id / font-id pair: +// Number of classifier answers? +// 0 >0 +// CT_REJECT unichar-id matches top shape? +// __________ yes! no +// CT_UNICHAR_TOP_OK CT_UNICHAR_TOP1_ERR +// Top shape-id has multiple unichars? 2nd shape unichar id matches? +// yes! no yes! no +// CT_OK_MULTI_UNICHAR | _____ CT_UNICHAR_TOP2_ERR +// Font attributes match? Any unichar-id matches? +// yes! no yes! no +// CT_FONT_ATTR_OK CT_FONT_ATTR_ERR ______ CT_UNICHAR_TOPN_ERR +// | __________________ _________________ +// Top shape-id has multiple font attrs? +// yes! no +// CT_OK_MULTI_FONT +// _____________________________ +// +// Note that multiple counts may be activated for a single sample! +// +// Ground truth is for a fragment/n-gram that is NOT in the unicharset. +// This is called junk and is expected to be rejected: +// Number of classifier answers? +// 0 >0 +// CT_REJECTED_JUNK CT_ACCEPTED_JUNK +// +// Also, CT_NUM_RESULTS stores the mean number of results, and CT_RANK stores +// the mean rank of the correct result, counting from 0, and with an error +// receiving the number of answers as the correct rank. +// +// Keep in sync with the ReportString function. +enum CountTypes { + CT_UNICHAR_TOP_OK, // Top shape contains correct unichar id. + // The rank of the results in TOP1, TOP2, TOPN is determined by a gap of + // kRatingEpsilon from the first result in each group. The real top choice + // is measured using TOPTOP. + CT_UNICHAR_TOP1_ERR, // Top shape does not contain correct unichar id. + CT_UNICHAR_TOP2_ERR, // Top 2 shapes don't contain correct unichar id. + CT_UNICHAR_TOPN_ERR, // No output shape contains correct unichar id. + CT_UNICHAR_TOPTOP_ERR, // Very top choice not correct. + CT_OK_MULTI_UNICHAR, // Top shape id has correct unichar id, and others. + CT_OK_JOINED, // Top shape id is correct but marked joined. + CT_OK_BROKEN, // Top shape id is correct but marked broken. + CT_REJECT, // Classifier hates this. + CT_FONT_ATTR_ERR, // Top unichar OK, but font attributes incorrect. + CT_OK_MULTI_FONT, // CT_FONT_ATTR_OK but there are multiple font attrs. + CT_NUM_RESULTS, // Number of answers produced. + CT_RANK, // Rank of correct answer. + CT_REJECTED_JUNK, // Junk that was correctly rejected. + CT_ACCEPTED_JUNK, // Junk that was incorrectly classified otherwise. + + CT_SIZE // Number of types for array sizing. +}; + +// Class to encapsulate all the functionality and sub-structures required +// to count errors for an isolated character classifier (ShapeClassifier). +class ErrorCounter { + public: + // Computes and returns the unweighted boosting_mode error rate of the given + // classifier. Can be used for testing, or inside an iterative training + // system, including one that uses boosting. + // report_levels: + // 0 = no output. + // 1 = bottom-line error rate. + // 2 = bottom-line error rate + time. + // 3 = font-level error rate + time. + // 4 = list of all errors + short classifier debug output on 16 errors. + // 5 = list of all errors + short classifier debug output on 25 errors. + // * The boosting_mode determines which error type is used for computing the + // scaled_error output, and setting the is_error flag in the samples. + // * The fontinfo_table is used to get string font names for the debug + // output, and also to count font attributes errors. + // * The page_images vector may contain a Pix* (which may be NULL) for each + // page index assigned to the samples. + // * The it provides encapsulated iteration over some sample set. + // * The outputs unichar_error, scaled_error and totals_report are all + // optional. + // * If not NULL, unichar error gets the top1 unichar error rate. + // * Scaled_error gets the error chosen by boosting_mode weighted by the + // weights on the samples. + // * Fonts_report gets a string summarizing the error rates for each font in + // both human-readable form and as a tab-separated list of error counts. + // The human-readable form is all before the first tab. + // * The return value is the un-weighted version of the scaled_error. + static double ComputeErrorRate(ShapeClassifier* classifier, + int report_level, CountTypes boosting_mode, + const FontInfoTable& fontinfo_table, + const GenericVector& page_images, + SampleIterator* it, + double* unichar_error, + double* scaled_error, + STRING* fonts_report); + // Tests a pair of classifiers, debugging errors of the new against the old. + // See errorcounter.h for description of arguments. + // Iterates over the samples, calling the classifiers in normal/silent mode. + // If the new_classifier makes a boosting_mode error that the old_classifier + // does not, and the appropriate, it will then call the new_classifier again + // with a debug flag and a keep_this argument to find out what is going on. + static void DebugNewErrors(ShapeClassifier* new_classifier, + ShapeClassifier* old_classifier, + CountTypes boosting_mode, + const FontInfoTable& fontinfo_table, + const GenericVector& page_images, + SampleIterator* it); + + private: + // Simple struct to hold an array of counts. + struct Counts { + Counts(); + // Adds other into this for computing totals. + void operator+=(const Counts& other); + + int n[CT_SIZE]; + }; + + // Constructor is private. Only anticipated use of ErrorCounter is via + // the static ComputeErrorRate. + ErrorCounter(const UNICHARSET& unicharset, int fontsize); + ~ErrorCounter(); + + // Accumulates the errors from the classifier results on a single sample. + // Returns true if debug is true and a CT_UNICHAR_TOPN_ERR error occurred. + // boosting_mode selects the type of error to be used for boosting and the + // is_error_ member of sample is set according to whether the required type + // of error occurred. The font_table provides access to font properties + // for error counting and shape_table is used to understand the relationship + // between unichar_ids and shape_ids in the results + bool AccumulateErrors(bool debug, CountTypes boosting_mode, + const FontInfoTable& font_table, + const GenericVector& results, + TrainingSample* sample); + + // Accumulates counts for junk. Counts only whether the junk was correctly + // rejected or not. + bool AccumulateJunk(bool debug, const GenericVector& results, + TrainingSample* sample); + + // Creates a report of the error rate. The report_level controls the detail + // that is reported to stderr via tprintf: + // 0 -> no output. + // >=1 -> bottom-line error rate. + // >=3 -> font-level error rate. + // boosting_mode determines the return value. It selects which (un-weighted) + // error rate to return. + // The fontinfo_table from MasterTrainer provides the names of fonts. + // The it determines the current subset of the training samples. + // If not NULL, the top-choice unichar error rate is saved in unichar_error. + // If not NULL, the report string is saved in fonts_report. + // (Ignoring report_level). + double ReportErrors(int report_level, CountTypes boosting_mode, + const FontInfoTable& fontinfo_table, + const SampleIterator& it, + double* unichar_error, + STRING* fonts_report); + + // Sets the report string to a combined human and machine-readable report + // string of the error rates. + // Returns false if there is no data, leaving report unchanged, unless + // even_if_empty is true. + static bool ReportString(bool even_if_empty, const Counts& counts, + STRING* report); + + // Computes the error rates and returns in rates which is an array of size + // CT_SIZE. Returns false if there is no data, leaving rates unchanged. + static bool ComputeRates(const Counts& counts, double rates[CT_SIZE]); + + + // Total scaled error used by boosting algorithms. + double scaled_error_; + // Difference in result rating to be thought of as an "equal" choice. + double rating_epsilon_; + // Vector indexed by font_id from the samples of error accumulators. + GenericVector font_counts_; + // Counts of the results that map each unichar_id (from samples) to an + // incorrect shape_id. + GENERIC_2D_ARRAY unichar_counts_; + // Count of the number of times each shape_id occurs, is correct, and multi- + // unichar. + GenericVector multi_unichar_counts_; + // Histogram of scores (as percent) for correct answers. + STATS ok_score_hist_; + // Histogram of scores (as percent) for incorrect answers. + STATS bad_score_hist_; + // Unicharset for printing character ids in results. + const UNICHARSET& unicharset_; +}; + +} // namespace tesseract. + +#endif /* THIRD_PARTY_TESSERACT_CLASSIFY_ERRORCOUNTER_H_ */ diff --git a/TesseractOCR/include/tesseract/extern.h b/TesseractOCR/include/tesseract/extern.h new file mode 100644 index 00000000..ebbe4dfe --- /dev/null +++ b/TesseractOCR/include/tesseract/extern.h @@ -0,0 +1,32 @@ +#ifndef EXTERN_H +#define EXTERN_H + +/* -*-C-*- + ******************************************************************************** + * + * File: extern.h (Formerly extern.h) + * Description: External definitions for C or C++ + * Author: Mark Seaman, OCR Technology + * Created: Tue Mar 20 14:01:22 1990 + * Modified: Tue Mar 20 14:02:09 1990 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Experimental (Do Not Distribute) + * + * (c) Copyright 1990, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + ******************************************************************************** + */ + +#define EXTERN extern + +#endif diff --git a/TesseractOCR/include/tesseract/extract.h b/TesseractOCR/include/tesseract/extract.h new file mode 100644 index 00000000..1f80c20e --- /dev/null +++ b/TesseractOCR/include/tesseract/extract.h @@ -0,0 +1,40 @@ +/****************************************************************************** + ** Filename: extract.h + ** Purpose: Interface to high level generic feature extraction. + ** Author: Dan Johnson + ** History: 1/21/90, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef EXTRACT_H +#define EXTRACT_H + +#include "featdefs.h" +#include + +class DENORM; + +/*----------------------------------------------------------------------------- + Public Function Prototypes +-----------------------------------------------------------------------------*/ +// Deprecated! Will be deleted soon! +// In the meantime, as all TBLOBs, Blob is in baseline normalized coords. +// See SetupBLCNDenorms in intfx.cpp for other args. +CHAR_DESC ExtractBlobFeatures(const FEATURE_DEFS_STRUCT &FeatureDefs, + const DENORM& bl_denorm, const DENORM& cn_denorm, + const INT_FX_RESULT_STRUCT& fx_info, TBLOB *Blob); + +/*--------------------------------------------------------------------------- + Private Function Prototypes +----------------------------------------------------------------------------*/ +void ExtractorStub(); +#endif diff --git a/TesseractOCR/include/tesseract/featdefs.h b/TesseractOCR/include/tesseract/featdefs.h new file mode 100644 index 00000000..e1870910 --- /dev/null +++ b/TesseractOCR/include/tesseract/featdefs.h @@ -0,0 +1,86 @@ +/****************************************************************************** + ** Filename: featdefs.h + ** Purpose: Definitions of currently defined feature types. + ** Author: Dan Johnson + ** History: Mon May 21 08:28:01 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef FEATDEFS_H +#define FEATDEFS_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "ocrfeatures.h" + +/* Enumerate the different types of features currently defined. */ +#define NUM_FEATURE_TYPES 4 +extern const char* kMicroFeatureType; +extern const char* kCNFeatureType; +extern const char* kIntFeatureType; +extern const char* kGeoFeatureType; + +/* define error traps which can be triggered by this module.*/ +#define ILLEGAL_SHORT_NAME 2000 + +/* A character is described by multiple sets of extracted features. Each + set contains a number of features of a particular type, for example, a + set of bays, or a set of closures, or a set of microfeatures. Each + feature consists of a number of parameters. All features within a + feature set contain the same number of parameters.*/ + +struct CHAR_DESC_STRUCT { + uinT32 NumFeatureSets; + FEATURE_SET FeatureSets[NUM_FEATURE_TYPES]; +}; +typedef CHAR_DESC_STRUCT *CHAR_DESC; + +struct FEATURE_DEFS_STRUCT { + inT32 NumFeatureTypes; + const FEATURE_DESC_STRUCT* FeatureDesc[NUM_FEATURE_TYPES]; + const FEATURE_EXT_STRUCT* FeatureExtractors[NUM_FEATURE_TYPES]; + int FeatureEnabled[NUM_FEATURE_TYPES]; +}; +typedef FEATURE_DEFS_STRUCT *FEATURE_DEFS; + +/*---------------------------------------------------------------------- + Generic functions for manipulating character descriptions +----------------------------------------------------------------------*/ +void InitFeatureDefs(FEATURE_DEFS_STRUCT *featuredefs); + +void FreeCharDescription(CHAR_DESC CharDesc); + +CHAR_DESC NewCharDescription(const FEATURE_DEFS_STRUCT &FeatureDefs); + +bool ValidCharDescription(const FEATURE_DEFS_STRUCT &FeatureDefs, + CHAR_DESC CharDesc); + +void WriteCharDescription(const FEATURE_DEFS_STRUCT &FeatureDefs, + FILE *File, CHAR_DESC CharDesc); + +CHAR_DESC ReadCharDescription(const FEATURE_DEFS_STRUCT &FeatureDefs, + FILE *File); + +int ShortNameToFeatureType(const FEATURE_DEFS_STRUCT &FeatureDefs, + const char *ShortName); + +/**---------------------------------------------------------------------------- + Global Data Definitions and Declarations +----------------------------------------------------------------------------**/ +extern const FEATURE_DESC_STRUCT MicroFeatureDesc; +extern const FEATURE_DESC_STRUCT PicoFeatDesc; +extern const FEATURE_DESC_STRUCT CharNormDesc; +extern const FEATURE_DESC_STRUCT OutlineFeatDesc; +extern const FEATURE_DESC_STRUCT IntFeatDesc; +extern const FEATURE_DESC_STRUCT GeoFeatDesc; +#endif diff --git a/TesseractOCR/include/tesseract/feature_base.h b/TesseractOCR/include/tesseract/feature_base.h new file mode 100644 index 00000000..032bc73c --- /dev/null +++ b/TesseractOCR/include/tesseract/feature_base.h @@ -0,0 +1,55 @@ +/********************************************************************** + * File: feature_base.h + * Description: Declaration of the Feature Base Class + * Author: Ping Ping (xiupingping), Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The FeatureBase class is the base class for any Feature Extraction class +// It provided 3 pure virtual functions (to inherit): +// 1- FeatureCnt: A method to returns the count of features +// 2- ComputeFeatures: A method to compute the features for a given CharSamp +// 3- ComputeFeatureBitmap: A method to render a visualization of the features +// to a CharSamp. This is mainly used by visual-debuggers + +#ifndef FEATURE_BASE_H +#define FEATURE_BASE_H + +#include "char_samp.h" +#include "tuning_params.h" + +namespace tesseract { +class FeatureBase { + public: + explicit FeatureBase(TuningParams *params) + : params_(params) { + } + virtual ~FeatureBase() {} + + // Compute the features for a given CharSamp + virtual bool ComputeFeatures(CharSamp *char_samp, float *features) = 0; + // Render a visualization of the features to a CharSamp. + // This is mainly used by visual-debuggers + virtual CharSamp *ComputeFeatureBitmap(CharSamp *char_samp) = 0; + // Returns the count of features + virtual int FeatureCnt() = 0; + + protected: + TuningParams *params_; +}; +} + +#endif // FEATURE_BASE_H + diff --git a/TesseractOCR/include/tesseract/feature_bmp.h b/TesseractOCR/include/tesseract/feature_bmp.h new file mode 100644 index 00000000..2a84941b --- /dev/null +++ b/TesseractOCR/include/tesseract/feature_bmp.h @@ -0,0 +1,53 @@ +/********************************************************************** + * File: feature_bmp.h + * Description: Declaration of the Bitmap Feature Class + * Author: PingPing xiu (xiupingping) & Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The FeatureBmp class implements a Bitmap feature extractor class. It +// inherits from the FeatureBase class +// The Bitmap feature vectors is the the bitmap of the specified CharSamp +// scaled to a fixed grid size and then augmented by a 5 aux features that +// describe the size, aspect ration and placement within a word + +#ifndef FEATURE_BMP_H +#define FEATURE_BMP_H + +#include "char_samp.h" +#include "feature_base.h" + +namespace tesseract { +class FeatureBmp : public FeatureBase { + public: + explicit FeatureBmp(TuningParams *params); + virtual ~FeatureBmp(); + // Render a visualization of the features to a CharSamp. + // This is mainly used by visual-debuggers + virtual CharSamp *ComputeFeatureBitmap(CharSamp *samp); + // Compute the features for a given CharSamp + virtual bool ComputeFeatures(CharSamp *samp, float *features); + // Returns the count of features + virtual int FeatureCnt() { + return 5 + (conv_grid_size_ * conv_grid_size_); + } + + protected: + // grid size, cached from the TuningParams object + int conv_grid_size_; +}; +} + +#endif // FEATURE_BMP_H diff --git a/TesseractOCR/include/tesseract/feature_chebyshev.h b/TesseractOCR/include/tesseract/feature_chebyshev.h new file mode 100644 index 00000000..13c2d96d --- /dev/null +++ b/TesseractOCR/include/tesseract/feature_chebyshev.h @@ -0,0 +1,57 @@ +/********************************************************************** + * File: feature_chebyshev.h + * Description: Declaration of the Chebyshev coefficients Feature Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The FeatureChebyshev class implements a Bitmap feature extractor class. It +// inherits from the FeatureBase class +// The feature vector is the composed of the chebyshev coefficients of 4 time +// sequences. The time sequences are the left, top, right & bottom +// bitmap profiles of the input samples + +#ifndef FEATURE_CHEBYSHEV_H +#define FEATURE_CHEBYSHEV_H + +#include "char_samp.h" +#include "feature_base.h" + +namespace tesseract { +class FeatureChebyshev : public FeatureBase { + public: + explicit FeatureChebyshev(TuningParams *params); + virtual ~FeatureChebyshev(); + // Render a visualization of the features to a CharSamp. + // This is mainly used by visual-debuggers + virtual CharSamp *ComputeFeatureBitmap(CharSamp *samp); + // Compute the features for a given CharSamp + virtual bool ComputeFeatures(CharSamp *samp, float *features); + // Returns the count of features + virtual int FeatureCnt() { + return (4 * kChebychevCoefficientCnt); + } + + protected: + static const int kChebychevCoefficientCnt = 40; + // Compute Chebychev coefficients for the specified vector + void ChebyshevCoefficients(const vector &input, + int coeff_cnt, float *coeff); + // Compute the features for a given CharSamp + bool ComputeChebyshevCoefficients(CharSamp *samp, float *features); +}; +} + +#endif // FEATURE_CHEBYSHEV_H diff --git a/TesseractOCR/include/tesseract/feature_hybrid.h b/TesseractOCR/include/tesseract/feature_hybrid.h new file mode 100644 index 00000000..dc94a526 --- /dev/null +++ b/TesseractOCR/include/tesseract/feature_hybrid.h @@ -0,0 +1,56 @@ +/********************************************************************** + * File: feature_chebyshev.h + * Description: Declaration of the Chebyshev coefficients Feature Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The FeatureHybrid class implements a Bitmap feature extractor class. It +// inherits from the FeatureBase class +// This class describes the a hybrid feature vector composed by combining +// the bitmap and the chebyshev feature vectors + +#ifndef FEATURE_HYBRID_H +#define FEATURE_HYBRID_H + +#include "char_samp.h" +#include "feature_bmp.h" +#include "feature_chebyshev.h" + +namespace tesseract { +class FeatureHybrid : public FeatureBase { + public: + explicit FeatureHybrid(TuningParams *params); + virtual ~FeatureHybrid(); + // Render a visualization of the features to a CharSamp. + // This is mainly used by visual-debuggers + virtual CharSamp *ComputeFeatureBitmap(CharSamp *samp); + // Compute the features for a given CharSamp + virtual bool ComputeFeatures(CharSamp *samp, float *features); + // Returns the count of features + virtual int FeatureCnt() { + if (feature_bmp_ == NULL || feature_chebyshev_ == NULL) { + return 0; + } + return feature_bmp_->FeatureCnt() + feature_chebyshev_->FeatureCnt(); + } + + protected: + FeatureBmp *feature_bmp_; + FeatureChebyshev *feature_chebyshev_; +}; +} + +#endif // FEATURE_HYBRID_H diff --git a/TesseractOCR/include/tesseract/fileerr.h b/TesseractOCR/include/tesseract/fileerr.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/fileio.h b/TesseractOCR/include/tesseract/fileio.h new file mode 100644 index 00000000..76b4f2e2 --- /dev/null +++ b/TesseractOCR/include/tesseract/fileio.h @@ -0,0 +1,101 @@ +/********************************************************************** + * File: fileio.h + * Description: File I/O utilities. + * Author: Samuel Charron + * Created: Tuesday, July 9, 2013 + * + * (C) Copyright 2013, Google Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required + * by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + **********************************************************************/ +#ifndef TESSERACT_TRAINING_FILEIO_H_ +#define TESSERACT_TRAINING_FILEIO_H_ + +#include +#include +#include + +#ifdef USE_STD_NAMESPACE +using std::string; +#endif + +namespace tesseract { + +// A class to manipulate FILE*s. +class File { + public: + // Try to open the file 'filename' in mode 'mode'. + // Stop the program if it cannot open it. + static FILE* OpenOrDie(const string& filename, const string& mode); + static FILE* Open(const string& filename, const string& mode); + + // Try to open the file 'filename' and to write 'str' in it. + // Stop the program if it fails. + static void WriteStringToFileOrDie(const string& str, const string& filename); + + // Return true if the file 'filename' is readable. + static bool Readable(const string& filename); + + static void ReadFileToStringOrDie(const string& filename, string* out); + static bool ReadFileToString(const string& filename, string* out); + + // Helper methods + + // Concatenate file paths removing any extra intervening '/' symbols. + static string JoinPath(const string& prefix, const string& suffix); + // Delete a filename or all filenames matching a glob pattern. + static bool Delete(const char* pathname); + static bool DeleteMatchingFiles(const char* pattern); +}; + +// A class to manipulate Files for reading. +class InputBuffer { + public: + explicit InputBuffer(FILE* stream); + // 'size' is ignored. + InputBuffer(FILE* stream, size_t size); + + ~InputBuffer(); + + // Read data until end-of-file or a \n is read. + // The data is stored in '*out', excluding the \n if present. + // Return false if an error occurs or at end-of-file, true otherwise. + bool ReadLine(string* out); + + // Close the FILE* used by InputBuffer. + // Return false if an error occurs, true otherwise. + bool CloseFile(); + + private: + FILE* stream_; + int filesize_; +}; + +// A class to manipulate Files for writing. +class OutputBuffer { + public: + explicit OutputBuffer(FILE* stream); + // 'size' is ignored. + OutputBuffer(FILE* stream, size_t size); + + ~OutputBuffer(); + + // Write string 'str' to the open FILE*. + void WriteString(const string& str); + + // Close the FILE* used by InputBuffer. + // Return false if an error occurs, true otherwise. + bool CloseFile(); + + private: + FILE* stream_; +}; + +} // namespace tesseract +#endif // TESSERACT_TRAINING_FILEIO_H_ diff --git a/TesseractOCR/include/tesseract/findseam.h b/TesseractOCR/include/tesseract/findseam.h new file mode 100644 index 00000000..f1da0792 --- /dev/null +++ b/TesseractOCR/include/tesseract/findseam.h @@ -0,0 +1,44 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: findseam.h (Formerly findseam.h) + * Description: + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Thu May 16 17:05:17 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ + +#ifndef FINDSEAM_H +#define FINDSEAM_H + +/*---------------------------------------------------------------------- + I n c l u d e s +----------------------------------------------------------------------*/ +#include "seam.h" +#include "genericheap.h" +#include "kdpair.h" +#include "chop.h" + +// The SeamPair elements own their SEAMs and delete them upon destruction. +typedef tesseract::KDPtrPairInc SeamPair; +typedef tesseract::GenericHeap SeamQueue; + +typedef tesseract::KDPtrPairDec SeamDecPair; +typedef tesseract::GenericHeap SeamPile; + +#endif diff --git a/TesseractOCR/include/tesseract/fixspace.h b/TesseractOCR/include/tesseract/fixspace.h old mode 100755 new mode 100644 index 56c30187..5233bda2 --- a/TesseractOCR/include/tesseract/fixspace.h +++ b/TesseractOCR/include/tesseract/fixspace.h @@ -24,7 +24,6 @@ #include "pageres.h" #include "params.h" -#include "notdll.h" void initialise_search(WERD_RES_LIST &src_list, WERD_RES_LIST &new_list); void transform_to_next_perm(WERD_RES_LIST &words); diff --git a/TesseractOCR/include/tesseract/flexfx.h b/TesseractOCR/include/tesseract/flexfx.h new file mode 100644 index 00000000..21c4fa26 --- /dev/null +++ b/TesseractOCR/include/tesseract/flexfx.h @@ -0,0 +1,36 @@ +/****************************************************************************** + ** Filename: flexfx.h + ** Purpose: Interface to flexible feature extractor. + ** Author: Dan Johnson + ** History: Wed May 23 13:36:58 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef FLEXFX_H +#define FLEXFX_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "featdefs.h" +#include + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +// As with all TBLOBs this one is also baseline normalized. +CHAR_DESC ExtractFlexFeatures(const FEATURE_DEFS_STRUCT &FeatureDefs, + TBLOB *Blob, const DENORM& bl_denorm, + const DENORM& cn_denorm, + const INT_FX_RESULT_STRUCT& fx_info); + +#endif diff --git a/TesseractOCR/include/tesseract/float2int.h b/TesseractOCR/include/tesseract/float2int.h new file mode 100644 index 00000000..4f0a21be --- /dev/null +++ b/TesseractOCR/include/tesseract/float2int.h @@ -0,0 +1,30 @@ +/****************************************************************************** + ** Filename: float2int.h + ** Purpose: Routines for converting float features to int features + ** Author: Dan Johnson + ** History: Wed Mar 13 08:06:41 1991, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef FLOAT2INT_H +#define FLOAT2INT_H + +/*----------------------------------------------------------------------------- + Include Files and Type Defines +-----------------------------------------------------------------------------*/ +#include "intmatcher.h" +#include "ocrfeatures.h" + +#define INT_FEAT_RANGE 256 +#define BASELINE_Y_SHIFT (0.25) + +#endif diff --git a/TesseractOCR/include/tesseract/fontinfo.h b/TesseractOCR/include/tesseract/fontinfo.h old mode 100755 new mode 100644 index 49f7b93c..8b903814 --- a/TesseractOCR/include/tesseract/fontinfo.h +++ b/TesseractOCR/include/tesseract/fontinfo.h @@ -25,8 +25,12 @@ #include "host.h" #include "unichar.h" +template class UnicityTable; + namespace tesseract { +class BitVector; + // Struct for information about spacing between characters in a particular font. struct FontSpacingInfo { inT16 x_gap_before; @@ -40,8 +44,15 @@ struct FontSpacingInfo { * serif, fraktur */ struct FontInfo { - FontInfo() : name(NULL), spacing_vec(NULL) {} + FontInfo() : name(NULL), properties(0), universal_id(0), spacing_vec(NULL) {} ~FontInfo() {} + + // Writes to the given file. Returns false in case of error. + bool Serialize(FILE* fp) const; + // Reads from the given file. Returns false in case of error. + // If swap is true, assumes a big/little-endian swap is needed. + bool DeSerialize(bool swap, FILE* fp); + // Reserves unicharset_size spots in spacing_vec. void init_spacing(int unicharset_size) { spacing_vec = new GenericVector(); @@ -112,6 +123,35 @@ struct FontSet { int* configs; // FontInfo ids }; +// Class that adds a bit of functionality on top of GenericVector to +// implement a table of FontInfo that replaces UniCityTable. +// TODO(rays) change all references once all existing traineddata files +// are replaced. +class FontInfoTable : public GenericVector { + public: + FontInfoTable(); + ~FontInfoTable(); + + // Writes to the given file. Returns false in case of error. + bool Serialize(FILE* fp) const; + // Reads from the given file. Returns false in case of error. + // If swap is true, assumes a big/little-endian swap is needed. + bool DeSerialize(bool swap, FILE* fp); + + // Returns true if the given set of fonts includes one with the same + // properties as font_id. + bool SetContainsFontProperties(int font_id, + const GenericVector& font_set) const; + // Returns true if the given set of fonts includes multiple properties. + bool SetContainsMultipleFontProperties( + const GenericVector& font_set) const; + + // Moves any non-empty FontSpacingInfo entries from other to this. + void MoveSpacingInfoFrom(FontInfoTable* other); + // Moves this to the target unicity table. + void MoveTo(UnicityTable* target); +}; + // Compare FontInfo structures. bool CompareFontInfo(const FontInfo& fi1, const FontInfo& fi2); // Compare FontSet structures. diff --git a/TesseractOCR/include/tesseract/fpchop.h b/TesseractOCR/include/tesseract/fpchop.h new file mode 100644 index 00000000..4e4a78bc --- /dev/null +++ b/TesseractOCR/include/tesseract/fpchop.h @@ -0,0 +1,132 @@ +/********************************************************************** + * File: fpchop.h (Formerly fp_chop.h) + * Description: Code to chop fixed pitch text into character cells. + * Author: Ray Smith + * Created: Thu Sep 16 11:14:15 BST 1993 + * + * (C) Copyright 1993, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef FPCHOP_H +#define FPCHOP_H + +#include "params.h" +#include "blobbox.h" + +class C_OUTLINE_FRAG:public ELIST_LINK +{ + public: + C_OUTLINE_FRAG() { //empty constructor + steps = NULL; + stepcount = 0; + } + ~C_OUTLINE_FRAG () { + if (steps != NULL) + delete [] steps; + } + //start coord + C_OUTLINE_FRAG(ICOORD start_pt, + ICOORD end_pt, //end coord + C_OUTLINE *outline, //source of steps + inT16 start_index, + inT16 end_index); + //other end + C_OUTLINE_FRAG(C_OUTLINE_FRAG *head, inT16 tail_y); + C_OUTLINE *close(); //copy to outline + C_OUTLINE_FRAG & operator= ( //assign + const C_OUTLINE_FRAG & src); + + ICOORD start; //start coord + ICOORD end; //end coord + DIR128 *steps; //step array + inT32 stepcount; //no of steps + C_OUTLINE_FRAG *other_end; //head if a tail + inT16 ycoord; //coord of cut pt + + private: +}; + +ELISTIZEH(C_OUTLINE_FRAG) + +extern +INT_VAR_H (textord_fp_chop_error, 2, +"Max allowed bending of chop cells"); +extern +double_VAR_H (textord_fp_chop_snap, 0.5, +"Max distance of chop pt from vertex"); +ROW *fixed_pitch_words( //find lines + TO_ROW *row, //row to do + FCOORD rotation //for drawing + ); +WERD *add_repeated_word( //move repeated word + WERD_IT *rep_it, //repeated words + inT16 &rep_left, //left edge of word + inT16 &prev_chop_coord, //previous word end + uinT8 &blanks, //no of blanks + float pitch, //char cell size + WERD_IT *word_it //list of words + ); +void split_to_blob( //split the blob + BLOBNBOX *blob, //blob to split + inT16 chop_coord, //place to chop + float pitch_error, //allowed deviation + C_OUTLINE_LIST *left_coutlines, //for cblobs + C_OUTLINE_LIST *right_coutlines); +void fixed_chop_cblob( //split the blob + C_BLOB *blob, //blob to split + inT16 chop_coord, //place to chop + float pitch_error, //allowed deviation + C_OUTLINE_LIST *left_outlines, //left half of chop + C_OUTLINE_LIST *right_outlines //right half of chop + ); +void fixed_split_coutline( //chop the outline + C_OUTLINE *srcline, //source outline + inT16 chop_coord, //place to chop + float pitch_error, //allowed deviation + C_OUTLINE_IT *left_it, //left half of chop + C_OUTLINE_IT *right_it //right half of chop + ); +BOOL8 fixed_chop_coutline( //chop the outline + C_OUTLINE *srcline, //source outline + inT16 chop_coord, //place to chop + float pitch_error, //allowed deviation + C_OUTLINE_FRAG_LIST *left_frags, //left half of chop + C_OUTLINE_FRAG_LIST *right_frags //right half of chop + ); +void save_chop_cfragment( //chop the outline + inT16 head_index, //head of fragment + ICOORD head_pos, //head of fragment + inT16 tail_index, //tail of fragment + ICOORD tail_pos, //tail of fragment + C_OUTLINE *srcline, //source of edgesteps + C_OUTLINE_FRAG_LIST *frags //fragment list + ); +void add_frag_to_list( //ordered add + C_OUTLINE_FRAG *frag, //fragment to add + C_OUTLINE_FRAG_LIST *frags //fragment list + ); +void close_chopped_cfragments( //chop the outline + C_OUTLINE_FRAG_LIST *frags, //list to clear + C_OUTLINE_LIST *children, //potential children + float pitch_error, //allowed shrinkage + C_OUTLINE_IT *dest_it //output list + ); +C_OUTLINE *join_chopped_fragments( //join pieces + C_OUTLINE_FRAG *bottom, //bottom of cut + C_OUTLINE_FRAG *top //top of cut + ); +void join_segments( //join pieces + C_OUTLINE_FRAG *bottom, //bottom of cut + C_OUTLINE_FRAG *top //top of cut + ); +#endif diff --git a/TesseractOCR/include/tesseract/fpoint.h b/TesseractOCR/include/tesseract/fpoint.h new file mode 100644 index 00000000..e3fca911 --- /dev/null +++ b/TesseractOCR/include/tesseract/fpoint.h @@ -0,0 +1,54 @@ +/****************************************************************************** + ** Filename: fpoint.h + ** Purpose: Abstract data type for 2D points (floating point coords) + ** Author: Dan Johnson + ** History: Thu Apr 12 10:50:01 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef FPOINT_H +#define FPOINT_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "host.h" +#include +#include + +/* define data structure to hold 2D points or vectors using floating point */ +typedef struct +{ + FLOAT32 x, y; +} FPOINT; +typedef FPOINT FVECTOR; + +/**---------------------------------------------------------------------------- + Macros +----------------------------------------------------------------------------**/ +/* macros for computing miscellaneous functions of 2 points */ +#define XDelta(A,B) ( (B).x - (A).x ) +#define YDelta(A,B) ( (B).y - (A).y ) +#define SlopeFrom(A,B) ( YDelta(A,B) / XDelta(A,B) ) +#define AngleFrom(A,B) ( atan2((double) YDelta(A,B), \ + (double) XDelta(A,B) ) ) + +#define XIntersectionOf(A,B,X) ( SlopeFrom(A,B) * ((X) - A.x) + A.y) + +/*------------------------------------------------------------------------- + Public Function Prototypes +---------------------------------------------------------------------------*/ + +FLOAT32 DistanceBetween(FPOINT A, FPOINT B); + +FLOAT32 NormalizedAngleFrom(FPOINT *Point1, FPOINT *Point2, FLOAT32 FullScale); +#endif diff --git a/TesseractOCR/include/tesseract/freelist.h b/TesseractOCR/include/tesseract/freelist.h new file mode 100644 index 00000000..7647fd5e --- /dev/null +++ b/TesseractOCR/include/tesseract/freelist.h @@ -0,0 +1,43 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: freelist.h (Formerly freelist.h) + * Description: Memory allocator + * Author: Mark Seaman, OCR Technology + * Created: Wed May 30 13:50:28 1990 + * Modified: Mon Dec 10 15:15:25 1990 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Experimental (Do Not Distribute) + * + * (c) Copyright 1990, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ + +#ifndef FREELIST_H +#define FREELIST_H + +/*---------------------------------------------------------------------- + I n c l u d e s +----------------------------------------------------------------------*/ +#include + +/*---------------------------------------------------------------------- + F u n c t i o n s +----------------------------------------------------------------------*/ +int *memalloc(int size); + +int *memrealloc(void *ptr, int size, int oldsize); + +void memfree(void *element); + +#endif diff --git a/TesseractOCR/include/tesseract/fxdefs.h b/TesseractOCR/include/tesseract/fxdefs.h new file mode 100644 index 00000000..67f1b2b3 --- /dev/null +++ b/TesseractOCR/include/tesseract/fxdefs.h @@ -0,0 +1,25 @@ +/****************************************************************************** + ** Filename: fxdefs.h + ** Purpose: Generic interface definitions for feature extractors + ** Author: Dan Johnson + ** History: Fri Jan 19 09:04:14 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef FXDEFS_H +#define FXDEFS_H + +#include "featdefs.h" + +void SetupExtractors(FEATURE_DEFS_STRUCT *FeatureDefs); + +#endif diff --git a/TesseractOCR/include/tesseract/gap_map.h b/TesseractOCR/include/tesseract/gap_map.h new file mode 100644 index 00000000..914e8dbd --- /dev/null +++ b/TesseractOCR/include/tesseract/gap_map.h @@ -0,0 +1,39 @@ +#ifndef GAP_MAP_H +#define GAP_MAP_H + +#include "blobbox.h" + +class GAPMAP +{ + public: + GAPMAP( //constructor + TO_BLOCK *block); + + ~GAPMAP () { //destructor + if (map != NULL) + free_mem(map); + } + + BOOL8 table_gap( //Is gap a table? + inT16 left, //From here + inT16 right); //To here + + private: + inT16 total_rows; //in block + inT16 min_left; //Left extreme + inT16 max_right; //Right extreme + inT16 bucket_size; // half an x ht + inT16 *map; //empty counts + inT16 map_max; //map[0..max_map] defind + BOOL8 any_tabs; +}; + +/*-----------------------------*/ + +extern BOOL_VAR_H (gapmap_debug, FALSE, "Say which blocks have tables"); +extern BOOL_VAR_H (gapmap_use_ends, FALSE, +"Use large space at start and end of rows"); +extern BOOL_VAR_H (gapmap_no_isolated_quanta, FALSE, +"Ensure gaps not less than 2quanta wide"); +extern double_VAR_H (gapmap_big_gaps, 1.75, "xht multiplier"); +#endif diff --git a/TesseractOCR/include/tesseract/genblob.h b/TesseractOCR/include/tesseract/genblob.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/genericheap.h b/TesseractOCR/include/tesseract/genericheap.h new file mode 100644 index 00000000..bb5f8ddc --- /dev/null +++ b/TesseractOCR/include/tesseract/genericheap.h @@ -0,0 +1,229 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +/////////////////////////////////////////////////////////////////////// +// File: genericheap.h +// Description: Template heap class. +// Author: Ray Smith, based on Dan Johnson's original code. +// Created: Wed Mar 14 08:13:00 PDT 2012 +// +// (C) Copyright 2012, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#include "errcode.h" +#include "genericvector.h" + +#ifndef TESSERACT_CCUTIL_GENERICHEAP_H_ +#define TESSERACT_CCUTIL_GENERICHEAP_H_ + +namespace tesseract { + +// GenericHeap requires 1 template argument: +// Pair will normally be either KDPairInc or KDPairDec +// for some arbitrary Key and scalar, smart pointer, or non-ownership pointer +// Data type, according to whether a MIN heap or a MAX heap is desired, +// respectively. Using KDPtrPairInc or KDPtrPairDec, +// GenericHeap can also handle simple Data pointers and own them. +// If no additional data is required, Pair can also be a scalar, since +// GenericHeap doesn't look inside it except for operator<. +// +// The heap is stored as a packed binary tree in an array hosted by a +// GenericVector, with the invariant that the children of each node are +// both NOT Pair::operator< the parent node. KDPairInc defines Pair::operator< +// to use Key::operator< to generate a MIN heap and KDPairDec defines +// Pair::operator< to use Key::operator> to generate a MAX heap by reversing +// all the comparisons. +// See http://en.wikipedia.org/wiki/Heap_(data_structure) for more detail on +// the basic heap implementation. +// +// Insertion and removal are both O(log n) and, unlike the STL heap, an +// explicit Reshuffle function allows a node to be repositioned in time O(log n) +// after changing its value. +// +// Accessing the element for revaluation is a more complex matter, since the +// index and pointer can be changed arbitrarily by heap operations. +// Revaluation can be done by making the Data type in the Pair derived from or +// contain a DoublePtr as its first data element, making it possible to convert +// the pointer to a Pair using KDPairInc::RecastDataPointer. +template +class GenericHeap { + public: + GenericHeap() {} + // The initial size is only a GenericVector::reserve. It is not enforced as + // the size limit of the heap. Caller must implement their own enforcement. + explicit GenericHeap(int initial_size) { + heap_.reserve(initial_size); + } + + // Simple accessors. + bool empty() const { + return heap_.empty(); + } + int size() const { + return heap_.size(); + } + int size_reserved() const { + return heap_.size_reserved(); + } + void clear() { + // Clear truncates to 0 to keep the number reserved in tact. + heap_.truncate(0); + } + // Provides access to the underlying vector. + // Caution! any changes that modify the keys will invalidate the heap! + GenericVector* heap() { + return &heap_; + } + // Provides read-only access to an element of the underlying vector. + const Pair& get(int index) const { + return heap_[index]; + } + + // Add entry to the heap, keeping the smallest item at the top, by operator<. + // Note that *entry is used as the source of operator=, but it is non-const + // to allow for a smart pointer to be contained within. + // Time = O(log n). + void Push(Pair* entry) { + int hole_index = heap_.size(); + // Make a hole in the end of heap_ and sift it up to be the correct + // location for the new *entry. To avoid needing a default constructor + // for primitive types, and to allow for use of DoublePtr in the Pair + // somewhere, we have to incur a double copy here. + heap_.push_back(*entry); + *entry = heap_.back(); + hole_index = SiftUp(hole_index, *entry); + heap_[hole_index] = *entry; + } + + // Get the value of the top (smallest, defined by operator< ) element. + const Pair& PeekTop() const { + return heap_[0]; + } + + // Removes the top element of the heap. If entry is not NULL, the element + // is copied into *entry, otherwise it is discarded. + // Returns false if the heap was already empty. + // Time = O(log n). + bool Pop(Pair* entry) { + int new_size = heap_.size() - 1; + if (new_size < 0) + return false; // Already empty. + if (entry != NULL) + *entry = heap_[0]; + if (new_size > 0) { + // Sift the hole at the start of the heap_ downwards to match the last + // element. + Pair hole_pair = heap_[new_size]; + heap_.truncate(new_size); + int hole_index = SiftDown(0, hole_pair); + heap_[hole_index] = hole_pair; + } else { + heap_.truncate(new_size); + } + return true; + } + + // Removes the MAXIMUM element of the heap. (MIN from a MAX heap.) If entry is + // not NULL, the element is copied into *entry, otherwise it is discarded. + // Time = O(n). Returns false if the heap was already empty. + bool PopWorst(Pair* entry) { + int heap_size = heap_.size(); + if (heap_size == 0) return false; // It cannot be empty! + + // Find the maximum element. Its index is guaranteed to be greater than + // the index of the parent of the last element, since by the heap invariant + // the parent must be less than or equal to the children. + int worst_index = heap_size - 1; + int end_parent = ParentNode(worst_index); + for (int i = worst_index - 1; i > end_parent; --i) { + if (heap_[worst_index] < heap_[i]) + worst_index = i; + } + // Extract the worst element from the heap, leaving a hole at worst_index. + if (entry != NULL) + *entry = heap_[worst_index]; + --heap_size; + if (heap_size > 0) { + // Sift the hole upwards to match the last element of the heap_ + Pair hole_pair = heap_[heap_size]; + int hole_index = SiftUp(worst_index, hole_pair); + heap_[hole_index] = hole_pair; + } + heap_.truncate(heap_size); + return true; + } + + // The pointed-to Pair has changed its key value, so the location of pair + // is reshuffled to maintain the heap invariant. + // Must be a valid pointer to an element of the heap_! + // Caution! Since GenericHeap is based on GenericVector, reallocs may occur + // whenever the vector is extended and elements may get shuffled by any + // Push or Pop operation. Therefore use this function only if Data in Pair is + // of type DoublePtr, derived (first) from DoublePtr, or has a DoublePtr as + // its first element. Reshuffles the heap to maintain the invariant. + // Time = O(log n). + void Reshuffle(Pair* pair) { + int index = pair - &heap_[0]; + Pair hole_pair = heap_[index]; + index = SiftDown(index, hole_pair); + index = SiftUp(index, hole_pair); + heap_[index] = hole_pair; + } + + private: + // A hole in the heap exists at hole_index, and we want to fill it with the + // given pair. SiftUp sifts the hole upward to the correct position and + // returns the destination index without actually putting pair there. + int SiftUp(int hole_index, const Pair& pair) { + int parent; + while (hole_index > 0 && pair < heap_[parent = ParentNode(hole_index)]) { + heap_[hole_index] = heap_[parent]; + hole_index = parent; + } + return hole_index; + } + + // A hole in the heap exists at hole_index, and we want to fill it with the + // given pair. SiftDown sifts the hole downward to the correct position and + // returns the destination index without actually putting pair there. + int SiftDown(int hole_index, const Pair& pair) { + int heap_size = heap_.size(); + int child; + while ((child = LeftChild(hole_index)) < heap_size) { + if (child + 1 < heap_size && heap_[child + 1] < heap_[child]) + ++child; + if (heap_[child] < pair) { + heap_[hole_index] = heap_[child]; + hole_index = child; + } else { + break; + } + } + return hole_index; + } + + // Functions to navigate the tree. Unlike the original implementation, we + // store the root at index 0. + int ParentNode(int index) const { + return (index + 1) / 2 - 1; + } + int LeftChild(int index) const { + return index * 2 + 1; + } + + private: + GenericVector heap_; +}; + +} // namespace tesseract + +#endif // TESSERACT_CCUTIL_GENERICHEAP_H_ diff --git a/TesseractOCR/include/tesseract/genericvector.h b/TesseractOCR/include/tesseract/genericvector.h old mode 100755 new mode 100644 index 5ac3532a..5f053aac --- a/TesseractOCR/include/tesseract/genericvector.h +++ b/TesseractOCR/include/tesseract/genericvector.h @@ -20,6 +20,7 @@ #ifndef TESSERACT_CCUTIL_GENERICVECTOR_H_ #define TESSERACT_CCUTIL_GENERICVECTOR_H_ +#include #include #include @@ -27,6 +28,7 @@ #include "errcode.h" #include "helpers.h" #include "ndminx.h" +#include "strngs.h" // Use PointerVector below in preference to GenericVector, as that // provides automatic deletion of pointers, [De]Serialize that works, and @@ -34,8 +36,13 @@ template class GenericVector { public: - GenericVector() { this->init(kDefaultVectorSize); } - explicit GenericVector(int size) { this->init(size); } + GenericVector() { + init(kDefaultVectorSize); + } + GenericVector(int size, T init_val) { + init(size); + init_to_size(size, init_val); + } // Copy GenericVector(const GenericVector& other) { @@ -45,7 +52,7 @@ class GenericVector { GenericVector &operator+=(const GenericVector& other); GenericVector &operator=(const GenericVector& other); - virtual ~GenericVector(); + ~GenericVector(); // Reserve some memory. void reserve(int size); @@ -59,6 +66,9 @@ class GenericVector { int size() const { return size_used_; } + int size_reserved() const { + return size_reserved_; + } int length() const { return size_used_; @@ -73,6 +83,8 @@ class GenericVector { T &get(int index) const; T &back() const; T &operator[](int index) const; + // Returns the last object and removes it. + T pop_back(); // Return the index of the T object. // This method NEEDS a compare_callback to be passed to @@ -105,11 +117,11 @@ class GenericVector { // Removes an element at the given index and // shifts the remaining elements to the left. - virtual void remove(int index); + void remove(int index); // Truncates the array to the given size by removing the end. // If the current size is less, the array is not expanded. - virtual void truncate(int size) { + void truncate(int size) { if (size < size_used_) size_used_ = size; } @@ -126,7 +138,7 @@ class GenericVector { // All the owned callbacks are also deleted. // If you don't want the callbacks to be deleted, before calling clear, set // the callback to NULL. - virtual void clear(); + void clear(); // Delete objects pointed to by data_[i] void delete_data_pointers(); @@ -147,12 +159,12 @@ class GenericVector { bool read(FILE* f, TessResultCallback3* cb, bool swap); // Writes a vector of simple types to the given file. Assumes that bitwise // read/write of T will work. Returns false in case of error. - virtual bool Serialize(FILE* fp) const; + bool Serialize(FILE* fp) const; // Reads a vector of simple types from the given file. Assumes that bitwise // read/write will work with ReverseN according to sizeof(T). // Returns false in case of error. // If swap is true, assumes a big/little-endian swap is needed. - virtual bool DeSerialize(bool swap, FILE* fp); + bool DeSerialize(bool swap, FILE* fp); // Writes a vector of classes to the given file. Assumes the existence of // bool T::Serialize(FILE* fp) const that returns false in case of error. // Returns false in case of error. @@ -262,7 +274,32 @@ class GenericVector { return result; } + // Returns the index of what would be the target_index_th item in the array + // if the members were sorted, without actually sorting. Members are + // shuffled around, but it takes O(n) time. + // NOTE: uses operator< and operator== on the members. + int choose_nth_item(int target_index) { + // Make sure target_index is legal. + if (target_index < 0) + target_index = 0; // ensure legal + else if (target_index >= size_used_) + target_index = size_used_ - 1; + unsigned int seed = 1; + return choose_nth_item(target_index, 0, size_used_, &seed); + } + + // Swaps the elements with the given indices. + void swap(int index1, int index2) { + if (index1 != index2) { + T tmp = data_[index1]; + data_[index1] = data_[index2]; + data_[index2] = tmp; + } + } + protected: + // Internal recursive version of choose_nth_item. + int choose_nth_item(int target_index, int start, int end, unsigned int* seed); // Init the object, allocating size memory. void init(int size); @@ -281,6 +318,40 @@ class GenericVector { namespace tesseract { +// Function to read a GenericVector from a whole file. +// Returns false on failure. +typedef bool (*FileReader)(const STRING& filename, GenericVector* data); +// Function to write a GenericVector to a whole file. +// Returns false on failure. +typedef bool (*FileWriter)(const GenericVector& data, + const STRING& filename); +// The default FileReader loads the whole file into the vector of char, +// returning false on error. +inline bool LoadDataFromFile(const STRING& filename, + GenericVector* data) { + FILE* fp = fopen(filename.string(), "rb"); + if (fp == NULL) return false; + fseek(fp, 0, SEEK_END); + size_t size = ftell(fp); + fseek(fp, 0, SEEK_SET); + // Pad with a 0, just in case we treat the result as a string. + data->init_to_size(size + 1, 0); + bool result = fread(&(*data)[0], 1, size, fp) == size; + fclose(fp); + return result; +} +// The default FileWriter writes the vector of char to the filename file, +// returning false on error. +inline bool SaveDataToFile(const GenericVector& data, + const STRING& filename) { + FILE* fp = fopen(filename.string(), "wb"); + if (fp == NULL) return false; + bool result = + static_cast(fwrite(&data[0], 1, data.size(), fp)) == data.size(); + fclose(fp); + return result; +} + template bool cmp_eq(T const & t1, T const & t2) { return t1 == t2; @@ -328,7 +399,7 @@ class PointerVector : public GenericVector { public: PointerVector() : GenericVector() { } explicit PointerVector(int size) : GenericVector(size) { } - virtual ~PointerVector() { + ~PointerVector() { // Clear must be called here, even though it is called again by the base, // as the base will call the wrong clear. clear(); @@ -355,14 +426,14 @@ class PointerVector : public GenericVector { // Removes an element at the given index and // shifts the remaining elements to the left. - virtual void remove(int index) { + void remove(int index) { delete GenericVector::data_[index]; GenericVector::remove(index); } // Truncates the array to the given size by removing the end. // If the current size is less, the array is not expanded. - virtual void truncate(int size) { + void truncate(int size) { for (int i = size; i < GenericVector::size_used_; ++i) delete GenericVector::data_[i]; GenericVector::truncate(size); @@ -394,14 +465,14 @@ class PointerVector : public GenericVector { // All the owned callbacks are also deleted. // If you don't want the callbacks to be deleted, before calling clear, set // the callback to NULL. - virtual void clear() { + void clear() { GenericVector::delete_data_pointers(); GenericVector::clear(); } // Writes a vector of simple types to the given file. Assumes that bitwise // read/write of T will work. Returns false in case of error. - virtual bool Serialize(FILE* fp) const { + bool Serialize(FILE* fp) const { inT32 used = GenericVector::size_used_; if (fwrite(&used, sizeof(used), 1, fp) != 1) return false; for (int i = 0; i < used; ++i) { @@ -416,7 +487,7 @@ class PointerVector : public GenericVector { // Also needs T::T(), as new T is used in this function. // Returns false in case of error. // If swap is true, assumes a big/little-endian swap is needed. - virtual bool DeSerialize(bool swap, FILE* fp) { + bool DeSerialize(bool swap, FILE* fp) { inT32 reserved; if (fread(&reserved, sizeof(reserved), 1, fp) != 1) return false; if (swap) Reverse32(&reserved); @@ -427,9 +498,15 @@ class PointerVector : public GenericVector { T* item = NULL; if (non_null) { item = new T; - if (!item->DeSerialize(swap, fp)) return false; + if (!item->DeSerialize(swap, fp)) { + delete item; + return false; + } + this->push_back(item); + } else { + // Null elements should keep their place in the vector. + this->push_back(NULL); } - this->push_back(item); } return true; } @@ -515,7 +592,8 @@ T &GenericVector::get(int index) const { template T &GenericVector::operator[](int index) const { - return data_[index]; + assert(index >= 0 && index < size_used_); + return data_[index]; } template @@ -523,6 +601,12 @@ T &GenericVector::back() const { ASSERT_HOST(size_used_ > 0); return data_[size_used_ - 1]; } +// Returns the last object and removes it. +template +T GenericVector::pop_back() { + ASSERT_HOST(size_used_ > 0); + return data_[--size_used_]; +} // Return the object from an index. template @@ -536,7 +620,7 @@ void GenericVector::set(T t, int index) { // at the specified index. template void GenericVector::insert(T t, int index) { - ASSERT_HOST(index >= 0 && index < size_used_); + ASSERT_HOST(index >= 0 && index <= size_used_); if (size_reserved_ == size_used_) double_the_size(); for (int i = size_used_; i > index; --i) { @@ -642,7 +726,8 @@ void GenericVector::set_clear_callback(TessCallback1* cb) { // Add a callback to be called to delete the elements when the array took // their ownership. template -void GenericVector::set_compare_callback(TessResultCallback2* cb) { +void GenericVector::set_compare_callback( + TessResultCallback2* cb) { compare_cb_ = cb; } @@ -804,4 +889,65 @@ void GenericVector::sort() { sort(&tesseract::sort_cmp); } +// Internal recursive version of choose_nth_item. +// The algorithm used comes from "Algorithms" by Sedgewick: +// http://books.google.com/books/about/Algorithms.html?id=idUdqdDXqnAC +// The principle is to choose a random pivot, and move everything less than +// the pivot to its left, and everything greater than the pivot to the end +// of the array, then recurse on the part that contains the desired index, or +// just return the answer if it is in the equal section in the middle. +// The random pivot guarantees average linear time for the same reason that +// n times vector::push_back takes linear time on average. +// target_index, start and and end are all indices into the full array. +// Seed is a seed for rand_r for thread safety purposes. Its value is +// unimportant as the random numbers do not affect the result except +// between equal answers. +template +int GenericVector::choose_nth_item(int target_index, int start, int end, + unsigned int* seed) { + // Number of elements to process. + int num_elements = end - start; + // Trivial cases. + if (num_elements <= 1) + return start; + if (num_elements == 2) { + if (data_[start] < data_[start + 1]) { + return target_index > start ? start + 1 : start; + } else { + return target_index > start ? start : start + 1; + } + } + // Place the pivot at start. + #ifndef rand_r // _MSC_VER, ANDROID + srand(*seed); + #define rand_r(seed) rand() + #endif // _MSC_VER + int pivot = rand_r(seed) % num_elements + start; + swap(pivot, start); + // The invariant condition here is that items [start, next_lesser) are less + // than the pivot (which is at index next_lesser) and items + // [prev_greater, end) are greater than the pivot, with items + // [next_lesser, prev_greater) being equal to the pivot. + int next_lesser = start; + int prev_greater = end; + for (int next_sample = start + 1; next_sample < prev_greater;) { + if (data_[next_sample] < data_[next_lesser]) { + swap(next_lesser++, next_sample++); + } else if (data_[next_sample] == data_[next_lesser]) { + ++next_sample; + } else { + swap(--prev_greater, next_sample); + } + } + // Now the invariant is set up, we recurse on just the section that contains + // the desired index. + if (target_index < next_lesser) + return choose_nth_item(target_index, start, next_lesser, seed); + else if (target_index < prev_greater) + return next_lesser; // In equal bracket. + else + return choose_nth_item(target_index, prev_greater, end, seed); +} + + #endif // TESSERACT_CCUTIL_GENERICVECTOR_H_ diff --git a/TesseractOCR/include/tesseract/gettimeofday.h b/TesseractOCR/include/tesseract/gettimeofday.h new file mode 100644 index 00000000..c34215b1 --- /dev/null +++ b/TesseractOCR/include/tesseract/gettimeofday.h @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////// +// File: gettimeofday.h +// Description: Header file for gettimeofday.cpp +// Author: tomp2010, zdenop +// Created: Tue Feb 21 21:38:00 CET 2012 +// +// (C) Copyright 2012, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef VS2008_PORT_GETTIMEOFDAY_H_ +#define VS2008_PORT_GETTIMEOFDAY_H_ + +#ifdef _WIN32 +#include // timeval is defined in here. +#endif + +typedef struct timezone tz; + +int gettimeofday(struct timeval * tp, struct timezone * tzp); + +#endif // VS2008_PORT_GETTIMEOFDAY_H_ diff --git a/TesseractOCR/include/tesseract/globaloc.h b/TesseractOCR/include/tesseract/globaloc.h old mode 100755 new mode 100644 index b5086a2e..41438194 --- a/TesseractOCR/include/tesseract/globaloc.h +++ b/TesseractOCR/include/tesseract/globaloc.h @@ -20,17 +20,16 @@ #ifndef GLOBALOC_H #define GLOBALOC_H -#include "hosthplb.h" -#include "notdll.h" +#include "host.h" + +// Saves a clone of the given pix, and notes its resolution in thread-specific +// data, so that the image can be written prior to a crash. +struct Pix; +void SavePixForCrash(int resolution, Pix* pix); + +void signal_exit(int signal_code); -void signal_exit( // - int signal_code //Signal which - ); -//extern "C" { void err_exit(); - //The real signal -void signal_termination_handler(int sig); -//}; void set_global_loc_code(int loc_code); diff --git a/TesseractOCR/include/tesseract/globals.h b/TesseractOCR/include/tesseract/globals.h new file mode 100644 index 00000000..3907697e --- /dev/null +++ b/TesseractOCR/include/tesseract/globals.h @@ -0,0 +1,35 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: globals.h (Formerly globals.h) + * Description: Global Variables for Wise Owl + * Author: Mark Seaman, OCR Technology + * Created: Thu Dec 21 11:38:36 1989 + * Modified: Thu Jan 4 17:13:00 1990 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Experimental (Do Not Distribute) + * + * (c) Copyright 1989, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ +#ifndef GLOBALS_H +#define GLOBALS_H + +#include "const.h" +#include "unicharset.h" +#include "strngs.h" + +#include + + +#endif diff --git a/TesseractOCR/include/tesseract/gradechop.h b/TesseractOCR/include/tesseract/gradechop.h new file mode 100644 index 00000000..469a140b --- /dev/null +++ b/TesseractOCR/include/tesseract/gradechop.h @@ -0,0 +1,69 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: gradechop.h (Formerly gradechop.h) + * Description: + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Tue Jul 9 16:40:39 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ + +#ifndef GRADECHOP_H +#define GRADECHOP_H + +/*---------------------------------------------------------------------- + I n c l u d e s +----------------------------------------------------------------------*/ +#include "seam.h" +#include "ndminx.h" + +/*---------------------------------------------------------------------- + T y p e s +----------------------------------------------------------------------*/ +typedef inT16 BOUNDS_RECT[4]; + +/*---------------------------------------------------------------------- + M a c r o s +----------------------------------------------------------------------*/ +/********************************************************************** + * partial_split_priority + * + * Assign a priority to this split based on the features that it has. + * Grade it according to the different rating schemes and return the + * value of its goodness. + **********************************************************************/ + +#define partial_split_priority(split) \ +(grade_split_length (split) + \ + grade_sharpness (split)) \ + + +/********************************************************************** + * split_bounds_overlap + * + * Check to see if this split might overlap with this outline. Return + * TRUE if there is a positive overlap in the bounding boxes of the two. + **********************************************************************/ + +#define split_bounds_overlap(split,outline) \ +(outline->topleft.x <= MAX (split->point1->pos.x,split->point2->pos.x) && \ + outline->botright.x >= MIN (split->point1->pos.x,split->point2->pos.x) && \ + outline->botright.y <= MAX (split->point1->pos.y,split->point2->pos.y) && \ + outline->topleft.y >= MIN (split->point1->pos.y,split->point2->pos.y)) + +#endif diff --git a/TesseractOCR/include/tesseract/hashfn.h b/TesseractOCR/include/tesseract/hashfn.h old mode 100755 new mode 100644 index 3c7f2c33..3d488bad --- a/TesseractOCR/include/tesseract/hashfn.h +++ b/TesseractOCR/include/tesseract/hashfn.h @@ -1,10 +1,10 @@ /********************************************************************** * File: hashfn.h (Formerly hash.h) - * Description: Simple hash function. - * Author: Ray Smith - * Created: Thu Jan 16 11:47:59 GMT 1992 + * Description: Portability hacks for hash_map, hash_set and unique_ptr. + * Author: Ray Smith + * Created: Wed Jan 08 14:08:25 PST 2014 * - * (C) Copyright 1992, Hewlett-Packard Ltd. + * (C) Copyright 2014, Google Inc. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at @@ -20,11 +20,66 @@ #ifndef HASHFN_H #define HASHFN_H -#include "host.h" +#ifdef USE_STD_NAMESPACE +#if (__cplusplus >= 201103L) || defined(_MSC_VER) // Visual Studio +#include +#include +#define hash_map std::unordered_map +#if (_MSC_VER >= 1500 && _MSC_VER < 1600) // Visual Studio 2008 +using namespace std::tr1; +#else // _MSC_VER +using std::unordered_map; +using std::unordered_set; +#include +#define SmartPtr std::unique_ptr +#define HAVE_UNIQUE_PTR +#endif // _MSC_VER +#elif (defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ > 0)) || \ + __GNUC__ >= 4)) // gcc +// hash_set is deprecated in gcc +#include +#include +using __gnu_cxx::hash_map; +using __gnu_cxx::hash_set; +#define unordered_map hash_map +#define unordered_set hash_set +#else +#include +#include +#endif // gcc +#else // USE_STD_NAMESPACE +#include +#include +#define unordered_map hash_map +#define unordered_set hash_set +#endif // USE_STD_NAMESPACE -inT32 hash( //hash function - inT32 bits, //bits in hash function - void *key, //key to hash - inT32 keysize //size of key - ); -#endif +#ifndef HAVE_UNIQUE_PTR +// Trivial smart ptr. Expand to add features of std::unique_ptr as required. +template class SmartPtr { + public: + SmartPtr() : ptr_(NULL) {} + explicit SmartPtr(T* ptr) : ptr_(ptr) {} + ~SmartPtr() { + delete ptr_; + } + + T* get() const { + return ptr_; + } + void reset(T* ptr) { + if (ptr_ != NULL) delete ptr_; + ptr_ = ptr; + } + bool operator==(const T* ptr) const { + return ptr_ == ptr; + } + T* operator->() const { + return ptr_; + } + private: + T* ptr_; +}; +#endif // HAVE_UNIQUE_PTR + +#endif // HASHFN_H diff --git a/TesseractOCR/include/tesseract/helpers.h b/TesseractOCR/include/tesseract/helpers.h old mode 100755 new mode 100644 index 8bd64b00..a913eb82 --- a/TesseractOCR/include/tesseract/helpers.h +++ b/TesseractOCR/include/tesseract/helpers.h @@ -30,7 +30,7 @@ // Remove newline (if any) at the end of the string. inline void chomp_string(char *str) { - int last_index = (int)strlen(str) - 1; + int last_index = strlen(str) - 1; while (last_index >= 0 && (str[last_index] == '\n' || str[last_index] == '\r')) { str[last_index--] = '\0'; @@ -42,6 +42,14 @@ inline void SkipNewline(FILE *file) { if (fgetc(file) != '\n') fseek(file, -1, SEEK_CUR); } +// Swaps the two args pointed to by the pointers. +// Operator= and copy constructor must work on T. +template inline void Swap(T* p1, T* p2) { + T tmp(*p2); + *p2 = *p1; + *p1 = tmp; +} + // qsort function to sort 2 floats. inline int sort_floats(const void *arg1, const void *arg2) { float diff = *((float *) arg1) - *((float *) arg2); diff --git a/TesseractOCR/include/tesseract/host.h b/TesseractOCR/include/tesseract/host.h old mode 100755 new mode 100644 index 5c27d706..e233dda7 --- a/TesseractOCR/include/tesseract/host.h +++ b/TesseractOCR/include/tesseract/host.h @@ -125,7 +125,7 @@ typedef unsigned char BOOL8; #define MIN_INT8 0x80 #define MIN_INT16 0x8000 -#define MIN_INT32 0x80000000 +#define MIN_INT32 static_cast(0x80000000) #define MIN_UINT8 0x00 #define MIN_UINT16 0x0000 #define MIN_UINT32 0x00000000 diff --git a/TesseractOCR/include/tesseract/hosthplb.h b/TesseractOCR/include/tesseract/hosthplb.h deleted file mode 100755 index d81d9bc5..00000000 --- a/TesseractOCR/include/tesseract/hosthplb.h +++ /dev/null @@ -1 +0,0 @@ -#include "host.h" diff --git a/TesseractOCR/include/tesseract/hpddef.h b/TesseractOCR/include/tesseract/hpddef.h deleted file mode 100755 index bb90c428..00000000 --- a/TesseractOCR/include/tesseract/hpddef.h +++ /dev/null @@ -1,39 +0,0 @@ -/********************************************************************** - * File: hpddef.h - * Description: Defines for dll symbols for handpd.dll. - * Author: Ray Smith - * Created: Tue Apr 30 17:15:01 MDT 1996 - * - * (C) Copyright 1996, Hewlett-Packard Co. - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** http://www.apache.org/licenses/LICENSE-2.0 - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - * - **********************************************************************/ - -//This file does NOT use the usual single inclusion code as it -//is necessary to allow it to be executed every time it is included. -//#ifndef HPDDEF_H -//#define HPDDEF_H - -#undef DLLSYM -#ifndef __IPEDLL -# define DLLSYM -#else -# ifdef __BUILDING_HANDPD__ -# define DLLSYM DLLEXPORT -# else -# define DLLSYM DLLIMPORT -# endif -#endif -#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__) -# pragma import on -#endif - -//#endif diff --git a/TesseractOCR/include/tesseract/hpdsizes.h b/TesseractOCR/include/tesseract/hpdsizes.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/hybrid_neural_net_classifier.h b/TesseractOCR/include/tesseract/hybrid_neural_net_classifier.h new file mode 100644 index 00000000..0ab9ba12 --- /dev/null +++ b/TesseractOCR/include/tesseract/hybrid_neural_net_classifier.h @@ -0,0 +1,90 @@ +/********************************************************************** + * File: conv_net_classifier.h + * Description: Declaration of Convolutional-NeuralNet Character Classifier + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef HYBRID_NEURAL_NET_CLASSIFIER_H +#define HYBRID_NEURAL_NET_CLASSIFIER_H + +#include +#include + +#include "char_samp.h" +#include "char_altlist.h" +#include "char_set.h" +#include "classifier_base.h" +#include "feature_base.h" +#include "lang_model.h" +#include "neural_net.h" +#include "tuning_params.h" + +namespace tesseract { + +// Folding Ratio is the ratio of the max-activation of members of a folding +// set that is used to compute the min-activation of the rest of the set +// static const float kFoldingRatio = 0.75; // see conv_net_classifier.h + +class HybridNeuralNetCharClassifier : public CharClassifier { + public: + HybridNeuralNetCharClassifier(CharSet *char_set, TuningParams *params, + FeatureBase *feat_extract); + virtual ~HybridNeuralNetCharClassifier(); + // The main training function. Given a sample and a class ID the classifier + // updates its parameters according to its learning algorithm. This function + // is currently not implemented. TODO(ahmadab): implement end-2-end training + virtual bool Train(CharSamp *char_samp, int ClassID); + // A secondary function needed for training. Allows the trainer to set the + // value of any train-time paramter. This function is currently not + // implemented. TODO(ahmadab): implement end-2-end training + virtual bool SetLearnParam(char *var_name, float val); + // Externally sets the Neural Net used by the classifier. Used for training + void SetNet(tesseract::NeuralNet *net); + + // Classifies an input charsamp and return a CharAltList object containing + // the possible candidates and corresponding scores + virtual CharAltList *Classify(CharSamp *char_samp); + // Computes the cost of a specific charsamp being a character (versus a + // non-character: part-of-a-character OR more-than-one-character) + virtual int CharCost(CharSamp *char_samp); + + private: + // Neural Net object used for classification + vector nets_; + vector net_wgts_; + + // data buffers used to hold Neural Net inputs and outputs + float *net_input_; + float *net_output_; + + // Init the classifier provided a data-path and a language string + virtual bool Init(const string &data_file_path, const string &lang, + LangModel *lang_mod); + // Loads the NeuralNets needed for the classifier + bool LoadNets(const string &data_file_path, const string &lang); + // Load folding sets + // This function returns true on success or if the file can't be read, + // returns false if an error is encountered. + virtual bool LoadFoldingSets(const string &data_file_path, + const string &lang, + LangModel *lang_mod); + // Folds the output of the NeuralNet using the loaded folding sets + virtual void Fold(); + // Scales the input char_samp and feeds it to the NeuralNet as input + bool RunNets(CharSamp *char_samp); +}; +} +#endif // HYBRID_NEURAL_NET_CLASSIFIER_H diff --git a/TesseractOCR/include/tesseract/icuerrorcode.h b/TesseractOCR/include/tesseract/icuerrorcode.h new file mode 100644 index 00000000..a606415f --- /dev/null +++ b/TesseractOCR/include/tesseract/icuerrorcode.h @@ -0,0 +1,66 @@ +/********************************************************************** + * File: icuerrorcode.h + * Description: Wrapper class for UErrorCode, with conversion operators for + * direct use in ICU C and C++ APIs. + * Author: Fredrik Roubert + * Created: Thu July 4 2013 + * + * Features: + * - The constructor initializes the internal UErrorCode to U_ZERO_ERROR, + * removing one common source of errors. + * - Same use in C APIs taking a UErrorCode* (pointer) and C++ taking + * UErrorCode& (reference), via conversion operators. + * - Automatic checking for success when it goes out of scope. On failure, + * the destructor will log an error message and exit. + * + * Most of ICU will handle errors gracefully and provide sensible fallbacks. + * Using IcuErrorCode, it is therefore possible to write very compact code + * that does sensible things on failure and provides logging for debugging. + * + * Example: + * IcuErrorCode icuerrorcode; + * return collator.compareUTF8(a, b, icuerrorcode) == UCOL_EQUAL; + * + * (C) Copyright 2013, Google Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + **********************************************************************/ +#ifndef TESSERACT_CCUTIL_ICUERRORCODE_H_ +#define TESSERACT_CCUTIL_ICUERRORCODE_H_ + +#include "tprintf.h" +#include "unicode/errorcode.h" // From libicu + +namespace tesseract { + +class IcuErrorCode : public icu::ErrorCode { + public: + IcuErrorCode() {} + virtual ~IcuErrorCode() { + if (isFailure()) { + handleFailure(); + } + } + + protected: + virtual void handleFailure() const { + tprintf("ICU ERROR: %s", errorName()); + exit(errorCode); + } + + private: + // Disallow implicit copying of object. + IcuErrorCode(const IcuErrorCode&); + void operator=(const IcuErrorCode&); +}; + +} // namespace tesseract +#endif // TESSERACT_CCUTIL_ICUERRORCODE_H_ diff --git a/TesseractOCR/include/tesseract/imagefind.h b/TesseractOCR/include/tesseract/imagefind.h new file mode 100644 index 00000000..1bf408eb --- /dev/null +++ b/TesseractOCR/include/tesseract/imagefind.h @@ -0,0 +1,159 @@ +/////////////////////////////////////////////////////////////////////// +// File: imagefind.h +// Description: Class to find image and drawing regions in an image +// and create a corresponding list of empty blobs. +// Author: Ray Smith +// Created: Fri Aug 01 10:50:01 PDT 2008 +// +// (C) Copyright 2008, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_IMAGEFIND_H__ +#define TESSERACT_TEXTORD_IMAGEFIND_H__ + +#include "host.h" + +struct Boxa; +struct Pix; +struct Pixa; +class TBOX; +class FCOORD; +class TO_BLOCK; +class BLOBNBOX_LIST; + +namespace tesseract { + +class ColPartitionGrid; +class ColPartition_LIST; +class TabFind; + +// The ImageFind class is a simple static function wrapper class that +// exposes the FindImages function and some useful helper functions. +class ImageFind { + public: + // Finds image regions within the BINARY source pix (page image) and returns + // the image regions as a mask image. + // The returned pix may be NULL, meaning no images found. + // If not NULL, it must be PixDestroyed by the caller. + static Pix* FindImages(Pix* pix); + + // Generates a Boxa, Pixa pair from the input binary (image mask) pix, + // analgous to pixConnComp, except that connected components which are nearly + // rectangular are replaced with solid rectangles. + // The returned boxa, pixa may be NULL, meaning no images found. + // If not NULL, they must be destroyed by the caller. + // Resolution of pix should match the source image (Tesseract::pix_binary_) + // so the output coordinate systems match. + static void ConnCompAndRectangularize(Pix* pix, Boxa** boxa, Pixa** pixa); + + // Returns true if there is a rectangle in the source pix, such that all + // pixel rows and column slices outside of it have less than + // min_fraction of the pixels black, and within max_skew_gradient fraction + // of the pixels on the inside, there are at least max_fraction of the + // pixels black. In other words, the inside of the rectangle looks roughly + // rectangular, and the outside of it looks like extra bits. + // On return, the rectangle is defined by x_start, y_start, x_end and y_end. + // Note: the algorithm is iterative, allowing it to slice off pixels from + // one edge, allowing it to then slice off more pixels from another edge. + static bool pixNearlyRectangular(Pix* pix, + double min_fraction, double max_fraction, + double max_skew_gradient, + int* x_start, int* y_start, + int* x_end, int* y_end); + + // Given an input pix, and a bounding rectangle, the sides of the rectangle + // are shrunk inwards until they bound any black pixels found within the + // original rectangle. Returns false if the rectangle contains no black + // pixels at all. + static bool BoundsWithinRect(Pix* pix, int* x_start, int* y_start, + int* x_end, int* y_end); + + // Given a point in 3-D (RGB) space, returns the squared Euclidean distance + // of the point from the given line, defined by a pair of points in the 3-D + // (RGB) space, line1 and line2. + static double ColorDistanceFromLine(const uinT8* line1, const uinT8* line2, + const uinT8* point); + + // Returns the leptonica combined code for the given RGB triplet. + static uinT32 ComposeRGB(uinT32 r, uinT32 g, uinT32 b); + + // Returns the input value clipped to a uinT8. + static uinT8 ClipToByte(double pixel); + + // Computes the light and dark extremes of color in the given rectangle of + // the given pix, which is factor smaller than the coordinate system in rect. + // The light and dark points are taken to be the upper and lower 8th-ile of + // the most deviant of R, G and B. The value of the other 2 channels are + // computed by linear fit against the most deviant. + // The colors of the two point are returned in color1 and color2, with the + // alpha channel set to a scaled mean rms of the fits. + // If color_map1 is not null then it and color_map2 get rect pasted in them + // with the two calculated colors, and rms map gets a pasted rect of the rms. + // color_map1, color_map2 and rms_map are assumed to be the same scale as pix. + static void ComputeRectangleColors(const TBOX& rect, Pix* pix, int factor, + Pix* color_map1, Pix* color_map2, + Pix* rms_map, + uinT8* color1, uinT8* color2); + + // Returns true if there are no black pixels in between the boxes. + // The im_box must represent the bounding box of the pix in tesseract + // coordinates, which may be negative, due to rotations to make the textlines + // horizontal. The boxes are rotated by rotation, which should undo such + // rotations, before mapping them onto the pix. + static bool BlankImageInBetween(const TBOX& box1, const TBOX& box2, + const TBOX& im_box, const FCOORD& rotation, + Pix* pix); + + // Returns the number of pixels in box in the pix. + // The im_box must represent the bounding box of the pix in tesseract + // coordinates, which may be negative, due to rotations to make the textlines + // horizontal. The boxes are rotated by rotation, which should undo such + // rotations, before mapping them onto the pix. + static int CountPixelsInRotatedBox(TBOX box, const TBOX& im_box, + const FCOORD& rotation, Pix* pix); + + + // Locates all the image partitions in the part_grid, that were found by a + // previous call to FindImagePartitions, marks them in the image_mask, + // removes them from the grid, and deletes them. This makes it possble to + // call FindImagePartitions again to produce less broken-up and less + // overlapping image partitions. + // rerotation specifies how to rotate the partition coords to match + // the image_mask, since this function is used after orientation correction. + static void TransferImagePartsToImageMask(const FCOORD& rerotation, + ColPartitionGrid* part_grid, + Pix* image_mask); + + // Runs a CC analysis on the image_pix mask image, and creates + // image partitions from them, cutting out strong text, and merging with + // nearby image regions such that they don't interfere with text. + // Rotation and rerotation specify how to rotate image coords to match + // the blob and partition coords and back again. + // The input/output part_grid owns all the created partitions, and + // the partitions own all the fake blobs that belong in the partitions. + // Since the other blobs in the other partitions will be owned by the block, + // ColPartitionGrid::ReTypeBlobs must be called afterwards to fix this + // situation and collect the image blobs. + static void FindImagePartitions(Pix* image_pix, + const FCOORD& rotation, + const FCOORD& rerotation, + TO_BLOCK* block, + TabFind* tab_grid, + ColPartitionGrid* part_grid, + ColPartition_LIST* big_parts); +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_LINEFIND_H__ + diff --git a/TesseractOCR/include/tesseract/indexmapbidi.h b/TesseractOCR/include/tesseract/indexmapbidi.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/input_file_buffer.h b/TesseractOCR/include/tesseract/input_file_buffer.h new file mode 100644 index 00000000..5aa7465c --- /dev/null +++ b/TesseractOCR/include/tesseract/input_file_buffer.h @@ -0,0 +1,31 @@ +// Copyright 2008 Google Inc. +// All Rights Reserved. +// Author: ahmadab@google.com (Ahmad Abdulkader) +// +// input_file_buffer.h: Declarations of a class for an object that +// represents an input file buffer. +// + +#ifndef INPUT_FILE_BUFFER_H +#define INPUT_FILE_BUFFER_H + +#include +#include +#ifdef USE_STD_NAMESPACE +using std::string; +#endif + +namespace tesseract { +class InputFileBuffer { + public: + explicit InputFileBuffer(const string &file_name); + virtual ~InputFileBuffer(); + int Read(void *buffer, int bytes_to_read); + + protected: + string file_name_; + FILE *fp_; +}; +} + +#endif // INPUT_FILE_BUFFER_H__ diff --git a/TesseractOCR/include/tesseract/intfeaturedist.h b/TesseractOCR/include/tesseract/intfeaturedist.h new file mode 100644 index 00000000..8cfcb3be --- /dev/null +++ b/TesseractOCR/include/tesseract/intfeaturedist.h @@ -0,0 +1,80 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +/////////////////////////////////////////////////////////////////////// +// File: intfeaturedist.h +// Description: Fast set-difference-based feature distance calculator. +// Created: Thu Sep 01 12:14:30 PDT 2011 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_CLASSIFY_INTFEATUREDIST_H_ +#define TESSERACT_CLASSIFY_INTFEATUREDIST_H_ + +#include "genericvector.h" + +namespace tesseract { + +class IntFeatureMap; + +// Feature distance calculator designed to provide a fast distance calculation +// based on set difference between a given feature set and many other feature +// sets in turn. +// Representation of a feature set as an array of bools that are sparsely +// true, and companion arrays that allow fast feature set distance +// calculations with allowance of offsets in position. +// Init is expensive, so for greatest efficiency, to re-initialize for a new +// feature set, use Set(..., false) on the SAME feature set as was used to +// setup with Set(..., true), to return to its initialized state before +// reuse with Set(..., true) on a new feature set. +class IntFeatureDist { + public: + IntFeatureDist(); + ~IntFeatureDist(); + + // Initialize the bool array to the given size of feature space. + // The feature_map is just borrowed, and must exist for the entire + // lifetime of the IntFeatureDist. + void Init(const IntFeatureMap* feature_map); + + // Setup the map for the given indexed_features that have been indexed by + // feature_map. After use, use Set(..., false) to reset to the initial state + // as this is faster than calling Init for sparse spaces. + void Set(const GenericVector& indexed_features, + int canonical_count, bool value); + + // Compute the distance between the given feature vector and the last + // Set feature vector. + double FeatureDistance(const GenericVector& features) const; + double DebugFeatureDistance(const GenericVector& features) const; + + private: + // Clear all data. + void Clear(); + + // Size of the indexed feature space. + int size_; + // Total weight of features currently stored in the maps. + double total_feature_weight_; + // Pointer to IntFeatureMap given at Init to find offset features. + const IntFeatureMap* feature_map_; + // Array of bools indicating presence of a feature. + bool* features_; + // Array indicating the presence of a feature offset by one unit. + bool* features_delta_one_; + // Array indicating the presence of a feature offset by two units. + bool* features_delta_two_; +}; + +} // namespace tesseract + +#endif // TESSERACT_CLASSIFY_INTFEATUREDIST_H_ diff --git a/TesseractOCR/include/tesseract/intfeaturemap.h b/TesseractOCR/include/tesseract/intfeaturemap.h new file mode 100644 index 00000000..55c5b5cf --- /dev/null +++ b/TesseractOCR/include/tesseract/intfeaturemap.h @@ -0,0 +1,163 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +/////////////////////////////////////////////////////////////////////// +// File: intfeaturemap.h +// Description: Encapsulation of IntFeatureSpace with IndexMapBiDi +// to provide a subspace mapping and fast feature lookup. +// Created: Tue Oct 26 08:58:30 PDT 2010 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_CLASSIFY_INTFEATUREMAP_H__ +#define TESSERACT_CLASSIFY_INTFEATUREMAP_H__ + +#include "intfeaturespace.h" +#include "indexmapbidi.h" +#include "intproto.h" + +namespace tesseract { + +class SampleIterator; + +// Number of positive and negative offset maps. +static const int kNumOffsetMaps = 2; + +// Class to map a feature space defined by INT_FEATURE_STRUCT to a compact +// down-sampled subspace of actually used features. +// The IntFeatureMap copes with 2 stages of transformation: +// The first step is down-sampling (re-quantization) and converting to a +// single index value from the 3-D input: +// INT_FEATURE_STRUCT <-> index feature (via IntFeatureSpace) and +// the second is a feature-space compaction to map only the feature indices +// that are actually used. This saves space in classifiers that are built +// using the mapped feature space. +// index (sparse) feature <-> map (compact) feature via IndexMapBiDi. +// Although the transformations are reversible, the inverses are lossy and do +// not return the exact input INT_FEATURE_STRUCT, due to the many->one nature +// of both transformations. +class IntFeatureMap { + public: + IntFeatureMap(); + ~IntFeatureMap(); + + // Accessors. + int sparse_size() const { + return feature_space_.Size(); + } + int compact_size() const { + return compact_size_; + } + const IntFeatureSpace& feature_space() const { + return feature_space_; + } + const IndexMapBiDi& feature_map() const { + return feature_map_; + } + + // Pseudo-accessors. + int IndexFeature(const INT_FEATURE_STRUCT& f) const; + int MapFeature(const INT_FEATURE_STRUCT& f) const; + int MapIndexFeature(int index_feature) const; + INT_FEATURE_STRUCT InverseIndexFeature(int index_feature) const; + INT_FEATURE_STRUCT InverseMapFeature(int map_feature) const; + void DeleteMapFeature(int map_feature); + bool IsMapFeatureDeleted(int map_feature) const; + + // Copies the given feature_space and uses it as the index feature map + // from INT_FEATURE_STRUCT. + void Init(const IntFeatureSpace& feature_space); + + // Helper to return an offset index feature. In this context an offset + // feature with a dir of +/-1 is a feature of a similar direction, + // but shifted perpendicular to the direction of the feature. An offset + // feature with a dir of +/-2 is feature at the same position, but rotated + // by +/- one [compact] quantum. Returns the index of the generated offset + // feature, or -1 if it doesn't exist. Dir should be in + // [-kNumOffsetMaps, kNumOffsetMaps] to indicate the relative direction. + // A dir of 0 is an identity transformation. + // Both input and output are from the index(sparse) feature space, not + // the mapped/compact feature space, but the offset feature is the minimum + // distance moved from the input to guarantee that it maps to the next + // available quantum in the mapped/compact space. + int OffsetFeature(int index_feature, int dir) const; + + // Computes the features used by the subset of samples defined by + // the iterator and sets up the feature mapping. + // Returns the size of the compacted feature space. + int FindNZFeatureMapping(SampleIterator* it); + + // After deleting some features, finish setting up the mapping, and map + // all the samples. Returns the size of the compacted feature space. + int FinalizeMapping(SampleIterator* it); + + // Indexes the given array of features to a vector of sorted indices. + void IndexAndSortFeatures(const INT_FEATURE_STRUCT* features, + int num_features, + GenericVector* sorted_features) const { + feature_space_.IndexAndSortFeatures(features, num_features, + sorted_features); + } + // Maps the given array of index/sparse features to an array of map/compact + // features. + // Assumes the input is sorted. The output indices are sorted and uniqued. + // Returns the number of "missed" features, being features that + // don't map to the compact feature space. + int MapIndexedFeatures(const GenericVector& index_features, + GenericVector* map_features) const { + return feature_map_.MapFeatures(index_features, map_features); + } + + // Prints the map features from the set in human-readable form. + void DebugMapFeatures(const GenericVector& map_features) const; + + private: + void Clear(); + + // Helper to compute an offset index feature. In this context an offset + // feature with a dir of +/-1 is a feature of a similar direction, + // but shifted perpendicular to the direction of the feature. An offset + // feature with a dir of +/-2 is feature at the same position, but rotated + // by +/- one [compact] quantum. Returns the index of the generated offset + // feature, or -1 if it doesn't exist. Dir should be in + // [-kNumOffsetMaps, kNumOffsetMaps] to indicate the relative direction. + // A dir of 0 is an identity transformation. + // Both input and output are from the index(sparse) feature space, not + // the mapped/compact feature space, but the offset feature is the minimum + // distance moved from the input to guarantee that it maps to the next + // available quantum in the mapped/compact space. + int ComputeOffsetFeature(int index_feature, int dir) const; + + // True if the mapping has changed since it was last finalized. + bool mapping_changed_; + // Size of the compacted feature space, after unused features are removed. + int compact_size_; + // Feature space quantization definition and indexing from INT_FEATURE_STRUCT. + IntFeatureSpace feature_space_; + // Mapping from indexed feature space to the compacted space with unused + // features mapping to -1. + IndexMapBiDi feature_map_; + // Index tables to map a feature index to the corresponding feature after a + // shift perpendicular to the feature direction, or a rotation in place. + // An entry of -1 indicates that there is no corresponding feature. + // Array of arrays of size feature_space_.Size() owned by this class. + int* offset_plus_[kNumOffsetMaps]; + int* offset_minus_[kNumOffsetMaps]; + + // Don't use default copy and assign! + IntFeatureMap(const IntFeatureMap&); + void operator=(const IntFeatureMap&); +}; + +} // namespace tesseract. + +#endif // TESSERACT_CLASSIFY_INTFEATUREMAP_H__ diff --git a/TesseractOCR/include/tesseract/intfeaturespace.h b/TesseractOCR/include/tesseract/intfeaturespace.h new file mode 100644 index 00000000..e1e8e6ec --- /dev/null +++ b/TesseractOCR/include/tesseract/intfeaturespace.h @@ -0,0 +1,110 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +/////////////////////////////////////////////////////////////////////// +// File: intfeaturespace.h +// Description: Indexed feature space based on INT_FEATURE_STRUCT. +// Created: Wed Mar 24 10:55:30 PDT 2010 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_CLASSIFY_INTFEATURESPACE_H__ +#define TESSERACT_CLASSIFY_INTFEATURESPACE_H__ + +#include "genericvector.h" +#include "intproto.h" + +// Extent of x,y,theta in the input feature space. [0,255]. +const int kIntFeatureExtent = 256; +// Extent of x,y,theta dimensions in the quantized feature space. +const int kBoostXYBuckets = 16; +const int kBoostDirBuckets = 16; + +namespace tesseract { + +class IndexMap; + +// Down-sampling quantization of the INT_FEATURE_STRUCT feature space and +// conversion to a single scalar index value, used as a binary feature space. +class IntFeatureSpace { + public: + IntFeatureSpace(); + // Default copy constructors and assignment OK! + + // Setup the feature space with the given dimensions. + void Init(uinT8 xbuckets, uinT8 ybuckets, uinT8 thetabuckets); + + // Serializes the feature space definition to the given file. + // Returns false on error. + bool Serialize(FILE* fp) const; + + // DeSerializes the feature space definition from the given file. + // If swap is true, the data is big/little-endian swapped. + // Returns false on error. + bool DeSerialize(bool swap, FILE* fp); + + // Returns the total size of the feature space. + int Size() const { + return static_cast(x_buckets_) * y_buckets_ * theta_buckets_; + } + // Returns an INT_FEATURE_STRUCT corresponding to the given index. + // This is the inverse of the Index member. + INT_FEATURE_STRUCT PositionFromIndex(int index) const; + + // Returns a 1-dimensional index corresponding to the given feature value. + // Range is [0, Size()-1]. Inverse of PositionFromIndex member. + int Index(const INT_FEATURE_STRUCT& f) const { + return (XBucket(f.X) * y_buckets_ + YBucket(f.Y)) * theta_buckets_ + + ThetaBucket(f.Theta); + } + // Bulk calls to Index. Maps the given array of features to a vector of + // inT32 indices in the same order as the input. + void IndexFeatures(const INT_FEATURE_STRUCT* features, int num_features, + GenericVector* mapped_features) const; + // Bulk calls to Index. Maps the given array of features to a vector of + // sorted inT32 indices. + void IndexAndSortFeatures(const INT_FEATURE_STRUCT* features, + int num_features, + GenericVector* sorted_features) const; + // Returns a feature space index for the given x,y position in a display + // window, or -1 if the feature is a miss. + int XYToFeatureIndex(int x, int y) const; + + protected: + // Converters to generate indices for individual feature dimensions. + int XBucket(int x) const { + int bucket = x * x_buckets_ / kIntFeatureExtent; + return ClipToRange(bucket, 0, static_cast(x_buckets_) - 1); + } + int YBucket(int y) const { + int bucket = y * y_buckets_ / kIntFeatureExtent; + return ClipToRange(bucket, 0, static_cast(y_buckets_) - 1); + } + // Use DivRounded for theta so that exactly vertical and horizontal are in + // the middle of a bucket. The Modulo takes care of the wrap-around. + int ThetaBucket(int theta) const { + int bucket = DivRounded(theta * theta_buckets_, kIntFeatureExtent); + return Modulo(bucket, theta_buckets_); + } + // Returns an INT_FEATURE_STRUCT corresponding to the given buckets. + INT_FEATURE_STRUCT PositionFromBuckets(int x, int y, int theta) const; + + // Feature space definition - serialized. + uinT8 x_buckets_; + uinT8 y_buckets_; + uinT8 theta_buckets_; +}; + +} // namespace tesseract. + + +#endif // TESSERACT_CLASSIFY_INTFEATURESPACE_H__ diff --git a/TesseractOCR/include/tesseract/intfx.h b/TesseractOCR/include/tesseract/intfx.h new file mode 100644 index 00000000..26c43537 --- /dev/null +++ b/TesseractOCR/include/tesseract/intfx.h @@ -0,0 +1,75 @@ +/****************************************************************************** + ** Filename: intfx.h + ** Purpose: Interface to high level integer feature extractor. + ** Author: Robert Moss + ** History: Tue May 21 15:51:57 MDT 1991, RWM, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef INTFX_H +#define INTFX_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "blobs.h" +#include "intproto.h" +#include "normalis.h" +#include + +class DENORM; + +namespace tesseract { +class TrainingSample; +} + +struct INT_FX_RESULT_STRUCT { + inT32 Length; // total length of all outlines + inT16 Xmean, Ymean; // center of mass of all outlines + inT16 Rx, Ry; // radius of gyration + inT16 NumBL, NumCN; // number of features extracted + inT16 Width; // Width of blob in BLN coords. + uinT8 YBottom; // Bottom of blob in BLN coords. + uinT8 YTop; // Top of blob in BLN coords. +}; + +// The standard feature length +const double kStandardFeatureLength = 64.0 / 5; + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +void InitIntegerFX(); + +// Returns a vector representing the direction of a feature with the given +// theta direction in an INT_FEATURE_STRUCT. +FCOORD FeatureDirection(uinT8 theta); + +namespace tesseract { + // Generates a TrainingSample from a TBLOB. Extracts features and sets + // the bounding box, so classifiers that operate on the image can work. + // TODO(rays) BlobToTrainingSample must remain a global function until + // the FlexFx and FeatureDescription code can be removed and LearnBlob + // made a member of Classify. + TrainingSample* BlobToTrainingSample( + const TBLOB& blob, bool nonlinear_norm, INT_FX_RESULT_STRUCT* fx_info, + GenericVector* bl_features); +} + +// Deprecated! Prefer tesseract::Classify::ExtractFeatures instead. +bool ExtractIntFeat(const TBLOB& blob, + bool nonlinear_norm, + INT_FEATURE_ARRAY BLFeat, + INT_FEATURE_ARRAY CNFeat, + INT_FX_RESULT_STRUCT* Results); + +#endif diff --git a/TesseractOCR/include/tesseract/intmatcher.h b/TesseractOCR/include/tesseract/intmatcher.h new file mode 100644 index 00000000..8df6d6fd --- /dev/null +++ b/TesseractOCR/include/tesseract/intmatcher.h @@ -0,0 +1,217 @@ +/****************************************************************************** + ** Filename: intmatcher.h + ** Purpose: Interface to high level generic classifier routines. + ** Author: Robert Moss + ** History: Wed Feb 13 15:24:15 MST 1991, RWM, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef INTMATCHER_H +#define INTMATCHER_H + +#include "params.h" + +// Character fragments could be present in the trained templaes +// but turned on/off on the language-by-language basis or depending +// on particular properties of the corpus (e.g. when we expect the +// images to have low exposure). +extern BOOL_VAR_H(disable_character_fragments, FALSE, + "Do not include character fragments in the" + " results of the classifier"); + +extern INT_VAR_H(classify_integer_matcher_multiplier, 10, + "Integer Matcher Multiplier 0-255: "); + + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "intproto.h" +#include "cutoffs.h" + +struct INT_RESULT_STRUCT { + INT_RESULT_STRUCT() : Rating(0.0f), Config(0), Config2(0), FeatureMisses(0) {} + + FLOAT32 Rating; + // TODO(rays) It might be desirable for these to be able to represent a + // null config. + uinT8 Config; + uinT8 Config2; + uinT16 FeatureMisses; +}; + +typedef INT_RESULT_STRUCT *INT_RESULT; + + +struct CP_RESULT_STRUCT { + CP_RESULT_STRUCT() : Rating(0.0f), Class(0) {} + + FLOAT32 Rating; + INT_RESULT_STRUCT IMResult; + CLASS_ID Class; +}; + +/*---------------------------------------------------------------------------- + Variables +-----------------------------------------------------------------------------*/ + +extern INT_VAR_H(classify_adapt_proto_thresh, 230, + "Threshold for good protos during adaptive 0-255: "); + +extern INT_VAR_H(classify_adapt_feature_thresh, 230, + "Threshold for good features during adaptive 0-255: "); + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ + +#define SE_TABLE_BITS 9 +#define SE_TABLE_SIZE 512 + +struct ScratchEvidence { + uinT8 feature_evidence_[MAX_NUM_CONFIGS]; + int sum_feature_evidence_[MAX_NUM_CONFIGS]; + uinT8 proto_evidence_[MAX_NUM_PROTOS][MAX_PROTO_INDEX]; + + void Clear(const INT_CLASS class_template); + void ClearFeatureEvidence(const INT_CLASS class_template); + void NormalizeSums(INT_CLASS ClassTemplate, inT16 NumFeatures, + inT32 used_features); + void UpdateSumOfProtoEvidences( + INT_CLASS ClassTemplate, BIT_VECTOR ConfigMask, inT16 NumFeatures); +}; + + +class IntegerMatcher { + public: + // Integer Matcher Theta Fudge (0-255). + static const int kIntThetaFudge = 128; + // Bits in Similarity to Evidence Lookup (8-9). + static const int kEvidenceTableBits = 9; + // Integer Evidence Truncation Bits (8-14). + static const int kIntEvidenceTruncBits = 14; + // Similarity to Evidence Table Exponential Multiplier. + static const float kSEExponentialMultiplier; + // Center of Similarity Curve. + static const float kSimilarityCenter; + + IntegerMatcher() : classify_debug_level_(0) {} + + void Init(tesseract::IntParam *classify_debug_level); + + void Match(INT_CLASS ClassTemplate, + BIT_VECTOR ProtoMask, + BIT_VECTOR ConfigMask, + inT16 NumFeatures, + const INT_FEATURE_STRUCT* Features, + INT_RESULT Result, + int AdaptFeatureThreshold, + int Debug, + bool SeparateDebugWindows); + + // Applies the CN normalization factor to the given rating and returns + // the modified rating. + float ApplyCNCorrection(float rating, int blob_length, + int normalization_factor, int matcher_multiplier); + + int FindGoodProtos(INT_CLASS ClassTemplate, + BIT_VECTOR ProtoMask, + BIT_VECTOR ConfigMask, + uinT16 BlobLength, + inT16 NumFeatures, + INT_FEATURE_ARRAY Features, + PROTO_ID *ProtoArray, + int AdaptProtoThreshold, + int Debug); + + int FindBadFeatures(INT_CLASS ClassTemplate, + BIT_VECTOR ProtoMask, + BIT_VECTOR ConfigMask, + uinT16 BlobLength, + inT16 NumFeatures, + INT_FEATURE_ARRAY Features, + FEATURE_ID *FeatureArray, + int AdaptFeatureThreshold, + int Debug); + + private: + int UpdateTablesForFeature( + INT_CLASS ClassTemplate, + BIT_VECTOR ProtoMask, + BIT_VECTOR ConfigMask, + int FeatureNum, + const INT_FEATURE_STRUCT* Feature, + ScratchEvidence *evidence, + int Debug); + + int FindBestMatch(INT_CLASS ClassTemplate, + const ScratchEvidence &tables, + INT_RESULT Result); + +#ifndef GRAPHICS_DISABLED + void DebugFeatureProtoError( + INT_CLASS ClassTemplate, + BIT_VECTOR ProtoMask, + BIT_VECTOR ConfigMask, + const ScratchEvidence &tables, + inT16 NumFeatures, + int Debug); + + void DisplayProtoDebugInfo( + INT_CLASS ClassTemplate, + BIT_VECTOR ProtoMask, + BIT_VECTOR ConfigMask, + const ScratchEvidence &tables, + bool SeparateDebugWindows); + + void DisplayFeatureDebugInfo( + INT_CLASS ClassTemplate, + BIT_VECTOR ProtoMask, + BIT_VECTOR ConfigMask, + inT16 NumFeatures, + const INT_FEATURE_STRUCT* Features, + int AdaptFeatureThreshold, + int Debug, + bool SeparateDebugWindows); + + void DebugBestMatch(int BestMatch, INT_RESULT Result); +#endif + + + private: + uinT8 similarity_evidence_table_[SE_TABLE_SIZE]; + uinT32 evidence_table_mask_; + uinT32 mult_trunc_shift_bits_; + uinT32 table_trunc_shift_bits_; + tesseract::IntParam *classify_debug_level_; + uinT32 evidence_mult_mask_; +}; + +/**---------------------------------------------------------------------------- + Private Function Prototypes +----------------------------------------------------------------------------**/ +void IMDebugConfiguration(INT_FEATURE FeatureNum, + uinT16 ActualProtoNum, + uinT8 Evidence, + BIT_VECTOR ConfigMask, + uinT32 ConfigWord); + +void IMDebugConfigurationSum(INT_FEATURE FeatureNum, + uinT8 *FeatureEvidence, + inT32 ConfigCount); + +void HeapSort (int n, register int ra[], register int rb[]); + +/**---------------------------------------------------------------------------- + Global Data Definitions and Declarations +----------------------------------------------------------------------------**/ +#endif diff --git a/TesseractOCR/include/tesseract/intproto.h b/TesseractOCR/include/tesseract/intproto.h new file mode 100644 index 00000000..056e2123 --- /dev/null +++ b/TesseractOCR/include/tesseract/intproto.h @@ -0,0 +1,265 @@ +/****************************************************************************** + ** Filename: intproto.h + ** Purpose: Definition of data structures for integer protos. + ** Author: Dan Johnson + ** History: Thu Feb 7 12:58:45 1991, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef INTPROTO_H +#define INTPROTO_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "genericvector.h" +#include "matchdefs.h" +#include "mfoutline.h" +#include "protos.h" +#include "scrollview.h" +#include "unicharset.h" + +class FCOORD; + +/* define order of params in pruners */ +#define PRUNER_X 0 +#define PRUNER_Y 1 +#define PRUNER_ANGLE 2 + +/* definition of coordinate system offsets for each table parameter */ +#define ANGLE_SHIFT (0.0) +#define X_SHIFT (0.5) +#define Y_SHIFT (0.5) + +#define MAX_PROTO_INDEX 24 +#define BITS_PER_WERD static_cast(8 * sizeof(uinT32)) +/* Script detection: increase this number to 128 */ +#define MAX_NUM_CONFIGS 64 +#define MAX_NUM_PROTOS 512 +#define PROTOS_PER_PROTO_SET 64 +#define MAX_NUM_PROTO_SETS (MAX_NUM_PROTOS / PROTOS_PER_PROTO_SET) +#define NUM_PP_PARAMS 3 +#define NUM_PP_BUCKETS 64 +#define NUM_CP_BUCKETS 24 +#define CLASSES_PER_CP 32 +#define NUM_BITS_PER_CLASS 2 +#define CLASS_PRUNER_CLASS_MASK (~(~0 << NUM_BITS_PER_CLASS)) +#define CLASSES_PER_CP_WERD (CLASSES_PER_CP / NUM_BITS_PER_CLASS) +#define PROTOS_PER_PP_WERD BITS_PER_WERD +#define BITS_PER_CP_VECTOR (CLASSES_PER_CP * NUM_BITS_PER_CLASS) +#define MAX_NUM_CLASS_PRUNERS ((MAX_NUM_CLASSES + CLASSES_PER_CP - 1) / \ + CLASSES_PER_CP) +#define WERDS_PER_CP_VECTOR (BITS_PER_CP_VECTOR / BITS_PER_WERD) +#define WERDS_PER_PP_VECTOR ((PROTOS_PER_PROTO_SET+BITS_PER_WERD-1)/ \ + BITS_PER_WERD) +#define WERDS_PER_PP (NUM_PP_PARAMS * NUM_PP_BUCKETS * \ + WERDS_PER_PP_VECTOR) +#define WERDS_PER_CP (NUM_CP_BUCKETS * NUM_CP_BUCKETS * \ + NUM_CP_BUCKETS * WERDS_PER_CP_VECTOR) +#define WERDS_PER_CONFIG_VEC ((MAX_NUM_CONFIGS + BITS_PER_WERD - 1) / \ + BITS_PER_WERD) + +/* The first 3 dimensions of the CLASS_PRUNER_STRUCT are the + * 3 axes of the quantized feature space. + * The position of the the bits recorded for each class in the + * 4th dimension is determined by using CPrunerWordIndexFor(c), + * where c is the corresponding class id. */ +struct CLASS_PRUNER_STRUCT { + uinT32 p[NUM_CP_BUCKETS][NUM_CP_BUCKETS][NUM_CP_BUCKETS][WERDS_PER_CP_VECTOR]; +}; + +typedef struct +{ + inT8 A; + uinT8 B; + inT8 C; + uinT8 Angle; + uinT32 Configs[WERDS_PER_CONFIG_VEC]; +} + + +INT_PROTO_STRUCT, *INT_PROTO; + +typedef uinT32 PROTO_PRUNER[NUM_PP_PARAMS][NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR]; + +typedef struct +{ + PROTO_PRUNER ProtoPruner; + INT_PROTO_STRUCT Protos[PROTOS_PER_PROTO_SET]; +} + + +PROTO_SET_STRUCT, *PROTO_SET; + +typedef uinT32 CONFIG_PRUNER[NUM_PP_PARAMS][NUM_PP_BUCKETS][4]; + + +typedef struct +{ + uinT16 NumProtos; + uinT8 NumProtoSets; + uinT8 NumConfigs; + PROTO_SET ProtoSets[MAX_NUM_PROTO_SETS]; + uinT8 *ProtoLengths; + uinT16 ConfigLengths[MAX_NUM_CONFIGS]; + int font_set_id; // FontSet id, see above +} + + +INT_CLASS_STRUCT, *INT_CLASS; + +typedef struct +{ + int NumClasses; + int NumClassPruners; + INT_CLASS Class[MAX_NUM_CLASSES]; + CLASS_PRUNER_STRUCT* ClassPruners[MAX_NUM_CLASS_PRUNERS]; +} + + +INT_TEMPLATES_STRUCT, *INT_TEMPLATES; + +/* definitions of integer features*/ +#define MAX_NUM_INT_FEATURES 512 +#define INT_CHAR_NORM_RANGE 256 + +struct INT_FEATURE_STRUCT { + INT_FEATURE_STRUCT() : X(0), Y(0), Theta(0), CP_misses(0) { } + // Builds a feature from an FCOORD for position with all the necessary + // clipping and rounding. + INT_FEATURE_STRUCT(const FCOORD& pos, uinT8 theta); + // Builds a feature from ints with all the necessary clipping and casting. + INT_FEATURE_STRUCT(int x, int y, int theta); + + uinT8 X; + uinT8 Y; + uinT8 Theta; + inT8 CP_misses; + + void print() const { + tprintf("(%d,%d):%d\n", X, Y, Theta); + } +}; + +typedef INT_FEATURE_STRUCT *INT_FEATURE; + +typedef INT_FEATURE_STRUCT INT_FEATURE_ARRAY[MAX_NUM_INT_FEATURES]; + +enum IntmatcherDebugAction { + IDA_ADAPTIVE, + IDA_STATIC, + IDA_SHAPE_INDEX, + IDA_BOTH +}; + +/**---------------------------------------------------------------------------- + Macros +----------------------------------------------------------------------------**/ + +#define MaxNumIntProtosIn(C) (C->NumProtoSets * PROTOS_PER_PROTO_SET) +#define SetForProto(P) (P / PROTOS_PER_PROTO_SET) +#define IndexForProto(P) (P % PROTOS_PER_PROTO_SET) +#define ProtoForProtoId(C,P) (&((C->ProtoSets[SetForProto (P)])-> \ + Protos [IndexForProto (P)])) +#define PPrunerWordIndexFor(I) (((I) % PROTOS_PER_PROTO_SET) / \ + PROTOS_PER_PP_WERD) +#define PPrunerBitIndexFor(I) ((I) % PROTOS_PER_PP_WERD) +#define PPrunerMaskFor(I) (1 << PPrunerBitIndexFor (I)) + +#define MaxNumClassesIn(T) (T->NumClassPruners * CLASSES_PER_CP) +#define LegalClassId(c) ((c) >= 0 && (c) <= MAX_CLASS_ID) +#define UnusedClassIdIn(T,c) ((T)->Class[c] == NULL) +#define ClassForClassId(T,c) ((T)->Class[c]) +#define ClassPrunersFor(T) ((T)->ClassPruner) +#define CPrunerIdFor(c) ((c) / CLASSES_PER_CP) +#define CPrunerFor(T,c) ((T)->ClassPruners[CPrunerIdFor(c)]) +#define CPrunerWordIndexFor(c) (((c) % CLASSES_PER_CP) / CLASSES_PER_CP_WERD) +#define CPrunerBitIndexFor(c) (((c) % CLASSES_PER_CP) % CLASSES_PER_CP_WERD) +#define CPrunerMaskFor(L,c) (((L)+1) << CPrunerBitIndexFor (c) * NUM_BITS_PER_CLASS) + +/* DEBUG macros*/ +#define PRINT_MATCH_SUMMARY 0x001 +#define DISPLAY_FEATURE_MATCHES 0x002 +#define DISPLAY_PROTO_MATCHES 0x004 +#define PRINT_FEATURE_MATCHES 0x008 +#define PRINT_PROTO_MATCHES 0x010 +#define CLIP_MATCH_EVIDENCE 0x020 + +#define MatchDebuggingOn(D) (D) +#define PrintMatchSummaryOn(D) ((D) & PRINT_MATCH_SUMMARY) +#define DisplayFeatureMatchesOn(D) ((D) & DISPLAY_FEATURE_MATCHES) +#define DisplayProtoMatchesOn(D) ((D) & DISPLAY_PROTO_MATCHES) +#define PrintFeatureMatchesOn(D) ((D) & PRINT_FEATURE_MATCHES) +#define PrintProtoMatchesOn(D) ((D) & PRINT_PROTO_MATCHES) +#define ClipMatchEvidenceOn(D) ((D) & CLIP_MATCH_EVIDENCE) + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +void AddIntClass(INT_TEMPLATES Templates, CLASS_ID ClassId, INT_CLASS Class); + +int AddIntConfig(INT_CLASS Class); + +int AddIntProto(INT_CLASS Class); + +void AddProtoToClassPruner(PROTO Proto, + CLASS_ID ClassId, + INT_TEMPLATES Templates); + +void AddProtoToProtoPruner(PROTO Proto, int ProtoId, + INT_CLASS Class, bool debug); + +int BucketFor(FLOAT32 Param, FLOAT32 Offset, int NumBuckets); + +int CircBucketFor(FLOAT32 Param, FLOAT32 Offset, int NumBuckets); + +void UpdateMatchDisplay(); + +void ConvertConfig(BIT_VECTOR Config, int ConfigId, INT_CLASS Class); + +void DisplayIntFeature(const INT_FEATURE_STRUCT* Feature, FLOAT32 Evidence); + +void DisplayIntProto(INT_CLASS Class, PROTO_ID ProtoId, FLOAT32 Evidence); + +INT_CLASS NewIntClass(int MaxNumProtos, int MaxNumConfigs); + +INT_TEMPLATES NewIntTemplates(); + +void free_int_templates(INT_TEMPLATES templates); + +void ShowMatchDisplay(); + +namespace tesseract { + +// Clears the given window and draws the featurespace guides for the +// appropriate normalization method. +void ClearFeatureSpaceWindow(NORM_METHOD norm_method, ScrollView* window); + +} // namespace tesseract. + +/*----------------------------------------------------------------------------*/ +#ifndef GRAPHICS_DISABLED +void RenderIntFeature(ScrollView *window, const INT_FEATURE_STRUCT* Feature, + ScrollView::Color color); + +void InitIntMatchWindowIfReqd(); + +void InitProtoDisplayWindowIfReqd(); + +void InitFeatureDisplayWindowIfReqd(); + +// Creates a window of the appropriate size for displaying elements +// in feature space. +ScrollView* CreateFeatureSpaceWindow(const char* name, int xpos, int ypos); +#endif // GRAPHICS_DISABLED + +#endif diff --git a/TesseractOCR/include/tesseract/ipoints.h b/TesseractOCR/include/tesseract/ipoints.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/kdpair.h b/TesseractOCR/include/tesseract/kdpair.h new file mode 100644 index 00000000..bb7743ed --- /dev/null +++ b/TesseractOCR/include/tesseract/kdpair.h @@ -0,0 +1,189 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +/////////////////////////////////////////////////////////////////////// +// File: kdpair.h +// Description: Template pair class like STL pair but geared towards +// the Key+Data design pattern in which some data needs +// to be sorted or kept in a heap sorted on some separate key. +// Author: Ray Smith. +// Created: Thu Mar 15 14:48:05 PDT 2012 +// +// (C) Copyright 2012, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_CCUTIL_KDPAIR_H_ +#define TESSERACT_CCUTIL_KDPAIR_H_ + +#include "genericvector.h" + +namespace tesseract { + +// A useful base struct to facilitate the common operation of sorting a vector +// of simple or smart-pointer data using a separate key. Similar to STL pair. +template +struct KDPair { + KDPair() {} + KDPair(Key k, Data d) : data(d), key(k) {} + + int operator==(const KDPair& other) const { + return key == other.key; + } + + // WARNING! Keep data as the first element! KDPairInc and KDPairDec depend + // on the order of these elements so they can downcast pointers appropriately + // for use by GenericHeap::Reshuffle. + Data data; + Key key; +}; +// Specialization of KDPair to provide operator< for sorting in increasing order +// and recasting of data pointers for use with DoublePtr. +template +struct KDPairInc : public KDPair { + KDPairInc() {} + KDPairInc(Key k, Data d) : KDPair(k, d) {} + // Operator< facilitates sorting in increasing order. + int operator<(const KDPairInc& other) const { + return this->key < other.key; + } + // Returns the input Data pointer recast to a KDPairInc pointer. + // Just casts a pointer to the first element to a pointer to the whole struct. + static KDPairInc* RecastDataPointer(Data* data_ptr) { + return reinterpret_cast(data_ptr); + } +}; +// Specialization of KDPair to provide operator< for sorting in decreasing order +// and recasting of data pointers for use with DoublePtr. +template +struct KDPairDec : public KDPair { + KDPairDec() {} + KDPairDec(Key k, Data d) : KDPair(k, d) {} + // Operator< facilitates sorting in decreasing order by using operator> on + // the key values. + int operator<(const KDPairDec& other) const { + return this->key > other.key; + } + // Returns the input Data pointer recast to a KDPairDec pointer. + // Just casts a pointer to the first element to a pointer to the whole struct. + static KDPairDec* RecastDataPointer(Data* data_ptr) { + return reinterpret_cast(data_ptr); + } +}; + +// A useful base class to facilitate the common operation of sorting a vector +// of owned pointer data using a separate key. This class owns its data pointer, +// deleting it when it has finished with it, and providing copy constructor and +// operator= that have move semantics so that the data does not get copied and +// only a single instance of KDPtrPair holds a specific data pointer. +template +class KDPtrPair { + public: + KDPtrPair() : data_(NULL) {} + KDPtrPair(Key k, Data* d) : data_(d), key_(k) {} + // Copy constructor steals the pointer from src and NULLs it in src, thereby + // moving the (single) ownership of the data. + KDPtrPair(KDPtrPair& src) : data_(src.data_), key_(src.key_) { + src.data_ = NULL; + } + // Destructor deletes data, assuming it is the sole owner. + ~KDPtrPair() { + delete this->data_; + this->data_ = NULL; + } + // Operator= steals the pointer from src and NULLs it in src, thereby + // moving the (single) ownership of the data. + void operator=(KDPtrPair& src) { + delete this->data_; + this->data_ = src.data_; + src.data_ = NULL; + this->key_ = src.key_; + } + + int operator==(const KDPtrPair& other) const { + return key_ == other.key_; + } + + // Accessors. + const Key& key() const { + return key_; + } + void set_key(const Key& new_key) { + key_ = new_key; + } + const Data* data() const { + return data_; + } + // Sets the data pointer, taking ownership of the data. + void set_data(Data* new_data) { + delete data_; + data_ = new_data; + } + // Relinquishes ownership of the data pointer (setting it to NULL). + Data* extract_data() { + Data* result = data_; + data_ = NULL; + return result; + } + + private: + // Data members are private to keep deletion of data_ encapsulated. + Data* data_; + Key key_; +}; +// Specialization of KDPtrPair to provide operator< for sorting in increasing +// order. +template +struct KDPtrPairInc : public KDPtrPair { + // Since we are doing non-standard stuff we have to duplicate *all* the + // constructors and operator=. + KDPtrPairInc() : KDPtrPair() {} + KDPtrPairInc(Key k, Data* d) : KDPtrPair(k, d) {} + KDPtrPairInc(KDPtrPairInc& src) : KDPtrPair(src) {} + void operator=(KDPtrPairInc& src) { + KDPtrPair::operator=(src); + } + // Operator< facilitates sorting in increasing order. + int operator<(const KDPtrPairInc& other) const { + return this->key() < other.key(); + } +}; +// Specialization of KDPtrPair to provide operator< for sorting in decreasing +// order. +template +struct KDPtrPairDec : public KDPtrPair { + // Since we are doing non-standard stuff we have to duplicate *all* the + // constructors and operator=. + KDPtrPairDec() : KDPtrPair() {} + KDPtrPairDec(Key k, Data* d) : KDPtrPair(k, d) {} + KDPtrPairDec(KDPtrPairDec& src) : KDPtrPair(src) {} + void operator=(KDPtrPairDec& src) { + KDPtrPair::operator=(src); + } + // Operator< facilitates sorting in decreasing order by using operator> on + // the key values. + int operator<(const KDPtrPairDec& other) const { + return this->key() > other.key(); + } +}; + +// Specialization for a pair of ints in increasing order. +typedef KDPairInc IntKDPair; + +// Vector of IntKDPair. +class KDVector : public GenericVector { + // TODO(rays) Add some code to manipulate a KDVector. For now there + // is nothing and this class is effectively a specialization typedef. +}; + +} // namespace tesseract + +#endif // TESSERACT_CCUTIL_KDPAIR_H_ diff --git a/TesseractOCR/include/tesseract/kdtree.h b/TesseractOCR/include/tesseract/kdtree.h new file mode 100644 index 00000000..1294ea3c --- /dev/null +++ b/TesseractOCR/include/tesseract/kdtree.h @@ -0,0 +1,96 @@ +/****************************************************************************** + ** Filename: kdtree.h + ** Purpose: Definition of K-D tree access routines. + ** Author: Dan Johnson + ** History: 3/11/89, DSJ, Created. + ** 5/23/89, DSJ, Added circular feature capability. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef KDTREE_H +#define KDTREE_H + +/*----------------------------------------------------------------------------- + Include Files and Type Defines +-----------------------------------------------------------------------------*/ +#include "host.h" +#include "cutil.h" +#include "ocrfeatures.h" + +/** +NOTE: All circular parameters of all keys must be in the range + +Min <= Param < Max + +where Min and Max are specified in the KeyDesc parameter passed to +MakeKDTree. All KD routines assume that this is true and will not operate +correctly if circular parameters outside the specified range are used. +*/ + +struct KDNODE { + FLOAT32 *Key; /**< search key */ + void *Data; /**< data that corresponds to key */ + FLOAT32 BranchPoint; /**< needed to make deletes work efficiently */ + FLOAT32 LeftBranch; /**< used to optimize search pruning */ + FLOAT32 RightBranch; /**< used to optimize search pruning */ + struct KDNODE *Left; /**< ptrs for KD tree structure */ + struct KDNODE *Right; +}; + +struct KDTREE { + inT16 KeySize; /* number of dimensions in the tree */ + KDNODE Root; /* Root.Left points to actual root node */ + PARAM_DESC KeyDesc[1]; /* description of each dimension */ +}; + +/*---------------------------------------------------------------------------- + Macros +-----------------------------------------------------------------------------*/ +#define RootOf(T) ((T)->Root.Left->Data) + +/*----------------------------------------------------------------------------- + Public Function Prototypes +-----------------------------------------------------------------------------*/ +KDTREE *MakeKDTree(inT16 KeySize, const PARAM_DESC KeyDesc[]); + +void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data); + +void KDDelete(KDTREE * Tree, FLOAT32 Key[], void *Data); + +void KDNearestNeighborSearch( + KDTREE *Tree, FLOAT32 Query[], int QuerySize, FLOAT32 MaxDistance, + int *NumberOfResults, void **NBuffer, FLOAT32 DBuffer[]); + +void KDWalk(KDTREE *Tree, void_proc Action, void *context); + +void FreeKDTree(KDTREE *Tree); + +/*----------------------------------------------------------------------------- + Private Function Prototypes +-----------------------------------------------------------------------------*/ +KDNODE *MakeKDNode(KDTREE *tree, FLOAT32 Key[], void *Data, int Index); + +void FreeKDNode(KDNODE *Node); + +FLOAT32 DistanceSquared(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[]); + +FLOAT32 ComputeDistance(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[]); + +int QueryInSearch(KDTREE *tree); + +void Walk(KDTREE *tree, void_proc action, void *context, + KDNODE *SubTree, inT32 Level); + +void InsertNodes(KDTREE *tree, KDNODE *nodes); + +void FreeSubTree(KDNODE *SubTree); +#endif diff --git a/TesseractOCR/include/tesseract/lang_mod_edge.h b/TesseractOCR/include/tesseract/lang_mod_edge.h new file mode 100644 index 00000000..19897942 --- /dev/null +++ b/TesseractOCR/include/tesseract/lang_mod_edge.h @@ -0,0 +1,73 @@ +/********************************************************************** + * File: lang_mod_edge.h + * Description: Declaration of the Language Model Edge Base Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The LangModEdge abstracts an Edge in the language model trie +// This is an abstract class that any Language Model Edge should inherit from +// It provides methods for: +// 1- Returns the class ID corresponding to the edge +// 2- If the edge is a valid EndOfWord (EOW) +// 3- If the edge is coming from a OutOfDictionary (OOF) state machine +// 4- If the edge is a Terminal (has no children) +// 5- A Hash of the edge that will be used to retrieve the edge +// quickly from the BeamSearch lattice +// 6- If two edges are identcial +// 7- Returns a verbal description of the edge (use by debuggers) +// 8- the language model cost of the edge (if any) +// 9- The string corresponding to this edge +// 10- Getting and setting the "Root" status of the edge + +#ifndef LANG_MOD_EDGE_H +#define LANG_MOD_EDGE_H + +#include "cube_tuning_params.h" +#include "char_set.h" + +namespace tesseract { + +class LangModEdge { + public: + LangModEdge() {} + virtual ~LangModEdge() {} + + // The string corresponding to this edge + virtual const char_32 * EdgeString() const = 0; + // Returns the class ID corresponding to the edge + virtual int ClassID() const = 0; + // If the edge is the root edge + virtual bool IsRoot() const = 0; + // Set the Root flag + virtual void SetRoot(bool flag) = 0; + // If the edge is a valid EndOfWord (EOW) + virtual bool IsEOW() const = 0; + // is the edge is coming from a OutOfDictionary (OOF) state machine + virtual bool IsOOD() const = 0; + // Is the edge is a Terminal (has no children) + virtual bool IsTerminal() const = 0; + // Returns A hash of the edge that will be used to retrieve the edge + virtual unsigned int Hash() const = 0; + // Are the two edges identcial? + virtual bool IsIdentical(LangModEdge *edge) const = 0; + // a verbal description of the edge (use by debuggers) + virtual char *Description() const = 0; + // the language model cost of the edge (if any) + virtual int PathCost() const = 0; +}; +} + +#endif // LANG_MOD_EDGE_H diff --git a/TesseractOCR/include/tesseract/lang_model.h b/TesseractOCR/include/tesseract/lang_model.h new file mode 100644 index 00000000..a29bc1e3 --- /dev/null +++ b/TesseractOCR/include/tesseract/lang_model.h @@ -0,0 +1,78 @@ +/********************************************************************** + * File: lang_model.h + * Description: Declaration of the Language Model Edge Base Class + * Author: Ahmad Abdulkader + * Created: 2007 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The LanguageModel class abstracts a State machine that is modeled as a Trie +// structure. The state machine models the language being recognized by the OCR +// Engine +// This is an abstract class that is to be inherited by any language model + +#ifndef LANG_MODEL_H +#define LANG_MODEL_H + +#include "lang_mod_edge.h" +#include "char_altlist.h" +#include "char_set.h" +#include "tuning_params.h" + +namespace tesseract { +class LangModel { + public: + LangModel() { + ood_enabled_ = true; + numeric_enabled_ = true; + word_list_enabled_ = true; + punc_enabled_ = true; + } + virtual ~LangModel() {} + + // Returns an edge pointer to the Root + virtual LangModEdge *Root() = 0; + // Returns the edges that fan-out of the specified edge and their count + virtual LangModEdge **GetEdges(CharAltList *alt_list, + LangModEdge *parent_edge, + int *edge_cnt) = 0; + // Returns is a sequence of 32-bit characters are valid within this language + // model or net. And EndOfWord flag is specified. If true, the sequence has + // to end on a valid word. The function also optionally returns the list + // of language model edges traversed to parse the string + virtual bool IsValidSequence(const char_32 *str, bool eow_flag, + LangModEdge **edge_array = NULL) = 0; + virtual bool IsLeadingPunc(char_32 ch) = 0; + virtual bool IsTrailingPunc(char_32 ch) = 0; + virtual bool IsDigit(char_32 ch) = 0; + + // accessor functions + inline bool OOD() { return ood_enabled_; } + inline bool Numeric() { return numeric_enabled_; } + inline bool WordList() { return word_list_enabled_; } + inline bool Punc() { return punc_enabled_; } + inline void SetOOD(bool ood) { ood_enabled_ = ood; } + inline void SetNumeric(bool numeric) { numeric_enabled_ = numeric; } + inline void SetWordList(bool word_list) { word_list_enabled_ = word_list; } + inline void SetPunc(bool punc_enabled) { punc_enabled_ = punc_enabled; } + + protected: + bool ood_enabled_; + bool numeric_enabled_; + bool word_list_enabled_; + bool punc_enabled_; +}; +} + +#endif // LANG_MODEL_H diff --git a/TesseractOCR/include/tesseract/language_model.h b/TesseractOCR/include/tesseract/language_model.h new file mode 100644 index 00000000..f0acfff5 --- /dev/null +++ b/TesseractOCR/include/tesseract/language_model.h @@ -0,0 +1,416 @@ +/////////////////////////////////////////////////////////////////////// +// File: language_model.h +// Description: Functions that utilize the knowledge about the properties, +// structure and statistics of the language to help segmentation +// search. +// Author: Daria Antonova +// Created: Mon Nov 11 11:26:43 PST 2009 +// +// (C) Copyright 2009, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_WORDREC_LANGUAGE_MODEL_H_ +#define TESSERACT_WORDREC_LANGUAGE_MODEL_H_ + +#include "associate.h" +#include "dawg.h" +#include "dict.h" +#include "fontinfo.h" +#include "intproto.h" +#include "lm_consistency.h" +#include "lm_pain_points.h" +#include "lm_state.h" +#include "matrix.h" +#include "params.h" +#include "pageres.h" +#include "params_model.h" + +namespace tesseract { + +// This class that contains the data structures and functions necessary +// to represent and use the knowledge about the language. +class LanguageModel { + public: + // Masks for keeping track of top choices that should not be pruned out. + static const LanguageModelFlagsType kSmallestRatingFlag = 0x1; + static const LanguageModelFlagsType kLowerCaseFlag = 0x2; + static const LanguageModelFlagsType kUpperCaseFlag = 0x4; + static const LanguageModelFlagsType kDigitFlag = 0x8; + static const LanguageModelFlagsType kXhtConsistentFlag = 0x10; + + // Denominator for normalizing per-letter ngram cost when deriving + // penalty adjustments. + static const float kMaxAvgNgramCost; + + LanguageModel(const UnicityTable *fontinfo_table, Dict *dict); + ~LanguageModel(); + + // Fills the given floats array with features extracted from path represented + // by the given ViterbiStateEntry. See ccstruct/params_training_featdef.h + // for feature information. + // Note: the function assumes that features points to an array of size + // PTRAIN_NUM_FEATURE_TYPES. + static void ExtractFeaturesFromPath(const ViterbiStateEntry &vse, + float features[]); + + // Updates data structures that are used for the duration of the segmentation + // search on the current word; + void InitForWord(const WERD_CHOICE *prev_word, + bool fixed_pitch, float max_char_wh_ratio, + float rating_cert_scale); + + // Updates language model state of the given BLOB_CHOICE_LIST (from + // the ratings matrix) a its parent. Updates pain_points if new + // problematic points are found in the segmentation graph. + // + // At most language_model_viterbi_list_size are kept in each + // LanguageModelState.viterbi_state_entries list. + // At most language_model_viterbi_list_max_num_prunable of those are prunable + // (non-dictionary) paths. + // The entries that represent dictionary word paths are kept at the front + // of the list. + // The list ordered by cost that is computed collectively by several + // language model components (currently dawg and ngram components). + bool UpdateState( + bool just_classified, + int curr_col, int curr_row, + BLOB_CHOICE_LIST *curr_list, + LanguageModelState *parent_node, + LMPainPoints *pain_points, + WERD_RES *word_res, + BestChoiceBundle *best_choice_bundle, + BlamerBundle *blamer_bundle); + + // Returns true if an acceptable best choice was discovered. + inline bool AcceptableChoiceFound() { return acceptable_choice_found_; } + inline void SetAcceptableChoiceFound(bool val) { + acceptable_choice_found_ = val; + } + // Returns the reference to ParamsModel. + inline ParamsModel &getParamsModel() { return params_model_; } + + protected: + + inline float CertaintyScore(float cert) { + if (language_model_use_sigmoidal_certainty) { + // cert is assumed to be between 0 and -dict_->certainty_scale. + // If you enable language_model_use_sigmoidal_certainty, you + // need to adjust language_model_ngram_nonmatch_score as well. + cert = -cert / dict_->certainty_scale; + return 1.0f / (1.0f + exp(10.0f * cert)); + } else { + return (-1.0f / cert); + } + } + + inline float ComputeAdjustment(int num_problems, float penalty) { + if (num_problems == 0) return 0.0f; + if (num_problems == 1) return penalty; + return (penalty + (language_model_penalty_increment * + static_cast(num_problems-1))); + } + + // Computes the adjustment to the ratings sum based on the given + // consistency_info. The paths with invalid punctuation, inconsistent + // case and character type are penalized proportionally to the number + // of inconsistencies on the path. + inline float ComputeConsistencyAdjustment( + const LanguageModelDawgInfo *dawg_info, + const LMConsistencyInfo &consistency_info) { + if (dawg_info != NULL) { + return ComputeAdjustment(consistency_info.NumInconsistentCase(), + language_model_penalty_case); + } + return (ComputeAdjustment(consistency_info.NumInconsistentPunc(), + language_model_penalty_punc) + + ComputeAdjustment(consistency_info.NumInconsistentCase(), + language_model_penalty_case) + + ComputeAdjustment(consistency_info.NumInconsistentChartype(), + language_model_penalty_chartype) + + ComputeAdjustment(consistency_info.NumInconsistentSpaces(), + language_model_penalty_spacing) + + (consistency_info.inconsistent_script ? + language_model_penalty_script : 0.0f) + + (consistency_info.inconsistent_font ? + language_model_penalty_font : 0.0f)); + } + + // Returns an adjusted ratings sum that includes inconsistency penalties, + // penalties for non-dictionary paths and paths with dips in ngram + // probability. + float ComputeAdjustedPathCost(ViterbiStateEntry *vse); + + // Finds the first lower and upper case letter and first digit in curr_list. + // Uses the first character in the list in place of empty results. + // Returns true if both alpha and digits are found. + bool GetTopLowerUpperDigit(BLOB_CHOICE_LIST *curr_list, + BLOB_CHOICE **first_lower, + BLOB_CHOICE **first_upper, + BLOB_CHOICE **first_digit) const; + // Forces there to be at least one entry in the overall set of the + // viterbi_state_entries of each element of parent_node that has the + // top_choice_flag set for lower, upper and digit using the same rules as + // GetTopLowerUpperDigit, setting the flag on the first found suitable + // candidate, whether or not the flag is set on some other parent. + // Returns 1 if both alpha and digits are found among the parents, -1 if no + // parents are found at all (a legitimate case), and 0 otherwise. + int SetTopParentLowerUpperDigit(LanguageModelState *parent_node) const; + + // Finds the next ViterbiStateEntry with which the given unichar_id can + // combine sensibly, taking into account any mixed alnum/mixed case + // situation, and whether this combination has been inspected before. + ViterbiStateEntry* GetNextParentVSE( + bool just_classified, bool mixed_alnum, + const BLOB_CHOICE* bc, LanguageModelFlagsType blob_choice_flags, + const UNICHARSET& unicharset, WERD_RES* word_res, + ViterbiStateEntry_IT* vse_it, + LanguageModelFlagsType* top_choice_flags) const; + // Helper function that computes the cost of the path composed of the + // path in the given parent ViterbiStateEntry and the given BLOB_CHOICE. + // If the new path looks good enough, adds a new ViterbiStateEntry to the + // list of viterbi entries in the given BLOB_CHOICE and returns true. + bool AddViterbiStateEntry( + LanguageModelFlagsType top_choice_flags, float denom, bool word_end, + int curr_col, int curr_row, BLOB_CHOICE *b, + LanguageModelState *curr_state, ViterbiStateEntry *parent_vse, + LMPainPoints *pain_points, WERD_RES *word_res, + BestChoiceBundle *best_choice_bundle, BlamerBundle *blamer_bundle); + + // Determines whether a potential entry is a true top choice and + // updates changed accordingly. + // + // Note: The function assumes that b, top_choice_flags and changed + // are not NULL. + void GenerateTopChoiceInfo(ViterbiStateEntry *new_vse, + const ViterbiStateEntry *parent_vse, + LanguageModelState *lms); + + // Calls dict_->LetterIsOk() with DawgArgs initialized from parent_vse and + // unichar from b.unichar_id(). Constructs and returns LanguageModelDawgInfo + // with updated active dawgs, constraints and permuter. + // + // Note: the caller is responsible for deleting the returned pointer. + LanguageModelDawgInfo *GenerateDawgInfo(bool word_end, + int curr_col, int curr_row, + const BLOB_CHOICE &b, + const ViterbiStateEntry *parent_vse); + + // Computes p(unichar | parent context) and records it in ngram_cost. + // If b.unichar_id() is an unlikely continuation of the parent context + // sets found_small_prob to true and returns NULL. + // Otherwise creates a new LanguageModelNgramInfo entry containing the + // updated context (that includes b.unichar_id() at the end) and returns it. + // + // Note: the caller is responsible for deleting the returned pointer. + LanguageModelNgramInfo *GenerateNgramInfo( + const char *unichar, float certainty, float denom, + int curr_col, int curr_row, float outline_length, + const ViterbiStateEntry *parent_vse); + + // Computes -(log(prob(classifier)) + log(prob(ngram model))) + // for the given unichar in the given context. If there are multiple + // unichars at one position - takes the average of their probabilities. + // UNICHAR::utf8_step() is used to separate out individual UTF8 characters, + // since probability_in_context() can only handle one at a time (while + // unicharset might contain ngrams and glyphs composed from multiple UTF8 + // characters). + float ComputeNgramCost(const char *unichar, float certainty, float denom, + const char *context, int *unichar_step_len, + bool *found_small_prob, float *ngram_prob); + + // Computes the normalization factors for the classifier confidences + // (used by ComputeNgramCost()). + float ComputeDenom(BLOB_CHOICE_LIST *curr_list); + + // Fills the given consistenty_info based on parent_vse.consistency_info + // and on the consistency of the given unichar_id with parent_vse. + void FillConsistencyInfo( + int curr_col, bool word_end, BLOB_CHOICE *b, + ViterbiStateEntry *parent_vse, + WERD_RES *word_res, + LMConsistencyInfo *consistency_info); + + // Constructs WERD_CHOICE by recording unichar_ids of the BLOB_CHOICEs + // on the path represented by the given BLOB_CHOICE and language model + // state entries (lmse, dse). The path is re-constructed by following + // the parent pointers in the the lang model state entries). If the + // constructed WERD_CHOICE is better than the best/raw choice recorded + // in the best_choice_bundle, this function updates the corresponding + // fields and sets best_choice_bunldle->updated to true. + void UpdateBestChoice(ViterbiStateEntry *vse, + LMPainPoints *pain_points, + WERD_RES *word_res, + BestChoiceBundle *best_choice_bundle, + BlamerBundle *blamer_bundle); + + // Constructs a WERD_CHOICE by tracing parent pointers starting with + // the given LanguageModelStateEntry. Returns the constructed word. + // Updates best_char_choices, certainties and state if they are not + // NULL (best_char_choices and certainties are assumed to have the + // length equal to lmse->length). + // The caller is responsible for freeing memory associated with the + // returned WERD_CHOICE. + WERD_CHOICE *ConstructWord(ViterbiStateEntry *vse, + WERD_RES *word_res, + DANGERR *fixpt, + BlamerBundle *blamer_bundle, + bool *truth_path); + + // Wrapper around AssociateUtils::ComputeStats(). + inline void ComputeAssociateStats(int col, int row, + float max_char_wh_ratio, + ViterbiStateEntry *parent_vse, + WERD_RES *word_res, + AssociateStats *associate_stats) { + AssociateUtils::ComputeStats( + col, row, + (parent_vse != NULL) ? &(parent_vse->associate_stats) : NULL, + (parent_vse != NULL) ? parent_vse->length : 0, + fixed_pitch_, max_char_wh_ratio, + word_res, language_model_debug_level > 2, associate_stats); + } + + // Returns true if the path with such top_choice_flags and dawg_info + // could be pruned out (i.e. is neither a system/user/frequent dictionary + // nor a top choice path). + // In non-space delimited languages all paths can be "somewhat" dictionary + // words. In such languages we can not do dictionary-driven path pruning, + // so paths with non-empty dawg_info are considered prunable. + inline bool PrunablePath(const ViterbiStateEntry &vse) { + if (vse.top_choice_flags) return false; + if (vse.dawg_info != NULL && + (vse.dawg_info->permuter == SYSTEM_DAWG_PERM || + vse.dawg_info->permuter == USER_DAWG_PERM || + vse.dawg_info->permuter == FREQ_DAWG_PERM)) return false; + return true; + } + + // Returns true if the given ViterbiStateEntry represents an acceptable path. + inline bool AcceptablePath(const ViterbiStateEntry &vse) { + return (vse.dawg_info != NULL || vse.Consistent() || + (vse.ngram_info != NULL && !vse.ngram_info->pruned)); + } + + public: + // Parameters. + INT_VAR_H(language_model_debug_level, 0, "Language model debug level"); + BOOL_VAR_H(language_model_ngram_on, false, + "Turn on/off the use of character ngram model"); + INT_VAR_H(language_model_ngram_order, 8, + "Maximum order of the character ngram model"); + INT_VAR_H(language_model_viterbi_list_max_num_prunable, 10, + "Maximum number of prunable (those for which PrunablePath() is" + " true) entries in each viterbi list recorded in BLOB_CHOICEs"); + INT_VAR_H(language_model_viterbi_list_max_size, 500, + "Maximum size of viterbi lists recorded in BLOB_CHOICEs"); + double_VAR_H(language_model_ngram_small_prob, 0.000001, + "To avoid overly small denominators use this as the floor" + " of the probability returned by the ngram model"); + double_VAR_H(language_model_ngram_nonmatch_score, -40.0, + "Average classifier score of a non-matching unichar"); + BOOL_VAR_H(language_model_ngram_use_only_first_uft8_step, false, + "Use only the first UTF8 step of the given string" + " when computing log probabilities"); + double_VAR_H(language_model_ngram_scale_factor, 0.03, + "Strength of the character ngram model relative to the" + " character classifier "); + double_VAR_H(language_model_ngram_rating_factor, 16.0, + "Factor to bring log-probs into the same range as ratings" + " when multiplied by outline length "); + BOOL_VAR_H(language_model_ngram_space_delimited_language, true, + "Words are delimited by space"); + INT_VAR_H(language_model_min_compound_length, 3, + "Minimum length of compound words"); + // Penalties used for adjusting path costs and final word rating. + double_VAR_H(language_model_penalty_non_freq_dict_word, 0.1, + "Penalty for words not in the frequent word dictionary"); + double_VAR_H(language_model_penalty_non_dict_word, 0.15, + "Penalty for non-dictionary words"); + double_VAR_H(language_model_penalty_punc, 0.2, + "Penalty for inconsistent punctuation"); + double_VAR_H(language_model_penalty_case, 0.1, + "Penalty for inconsistent case"); + double_VAR_H(language_model_penalty_script, 0.5, + "Penalty for inconsistent script"); + double_VAR_H(language_model_penalty_chartype, 0.3, + "Penalty for inconsistent character type"); + double_VAR_H(language_model_penalty_font, 0.00, + "Penalty for inconsistent font"); + double_VAR_H(language_model_penalty_spacing, 0.05, + "Penalty for inconsistent spacing"); + double_VAR_H(language_model_penalty_increment, 0.01, "Penalty increment"); + INT_VAR_H(wordrec_display_segmentations, 0, "Display Segmentations"); + BOOL_VAR_H(language_model_use_sigmoidal_certainty, false, + "Use sigmoidal score for certainty"); + + + protected: + // Member Variables. + + // Temporary DawgArgs struct that is re-used across different words to + // avoid dynamic memory re-allocation (should be cleared before each use). + DawgArgs *dawg_args_; + // Scaling for recovering blob outline length from rating and certainty. + float rating_cert_scale_; + + // The following variables are set at construction time. + + // Pointer to fontinfo table (not owned by LanguageModel). + const UnicityTable *fontinfo_table_; + + // Pointer to Dict class, that is used for querying the dictionaries + // (the pointer is not owned by LanguageModel). + Dict *dict_; + + // TODO(daria): the following variables should become LanguageModel params + // when the old code in bestfirst.cpp and heuristic.cpp is deprecated. + // + // Set to true if we are dealing with fixed pitch text + // (set to assume_fixed_pitch_char_segment). + bool fixed_pitch_; + // Max char width-to-height ratio allowed + // (set to segsearch_max_char_wh_ratio). + float max_char_wh_ratio_; + + // The following variables are initialized with InitForWord(). + + // String representation of the classification of the previous word + // (since this is only used by the character ngram model component, + // only the last language_model_ngram_order of the word are stored). + STRING prev_word_str_; + int prev_word_unichar_step_len_; + // Active dawg vector. + DawgPositionVector *very_beginning_active_dawgs_; // includes continuation + DawgPositionVector *beginning_active_dawgs_; + // Set to true if acceptable choice was discovered. + // Note: it would be nice to use this to terminate the search once an + // acceptable choices is found. However we do not do that and once an + // acceptable choice is found we finish looking for alternative choices + // in the current segmentation graph and then exit the search (no more + // classifications are done after an acceptable choice is found). + // This is needed in order to let the search find the words very close to + // the best choice in rating (e.g. what/What, Cat/cat, etc) and log these + // choices. This way the stopper will know that the best choice is not + // ambiguous (i.e. there are best choices in the best choice list that have + // ratings close to the very best one) and will be less likely to mis-adapt. + bool acceptable_choice_found_; + // Set to true if a choice representing correct segmentation was explored. + bool correct_segmentation_explored_; + + // Params models containing weights for for computing ViterbiStateEntry costs. + ParamsModel params_model_; +}; + +} // namespace tesseract + +#endif // TESSERACT_WORDREC_LANGUAGE_MODEL_H_ diff --git a/TesseractOCR/include/tesseract/ligature_table.h b/TesseractOCR/include/tesseract/ligature_table.h new file mode 100644 index 00000000..ecae7943 --- /dev/null +++ b/TesseractOCR/include/tesseract/ligature_table.h @@ -0,0 +1,79 @@ +/********************************************************************** + * File: ligature_table.h + * Description: Class for adding and removing optional latin ligatures, + * conditional on codepoint support by a specified font + * (if specified). + * Author: Ranjith Unnikrishnan + * Created: Mon Nov 18 2013 + * + * (C) Copyright 2013, Google Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + **********************************************************************/ + +#ifndef TRAININGDATA_LIGATURE_TABLE_H_ +#define TRAININGDATA_LIGATURE_TABLE_H_ + +#include + +#include "hashfn.h" +#include "util.h" + +namespace tesseract { + +class PangoFontInfo; // defined in pango_font_info.h + +// Map to substitute strings for ligatures. +typedef hash_map LigHash; + +class LigatureTable { + public: + // Get a static instance of this class. + static LigatureTable* Get(); + + // Convert the utf8 string so that ligaturizable sequences, such as "fi" get + // replaced by the (utf8 code for) appropriate ligature characters. Only do so + // if the corresponding ligature character is renderable in the current font. + string AddLigatures(const string& str, const PangoFontInfo* font) const; + // Remove all ligatures. + string RemoveLigatures(const string& str) const; + // Remove only custom ligatures (eg. "ct") encoded in the private-use-area. + string RemoveCustomLigatures(const string& str) const; + + const LigHash& norm_to_lig_table() const { + return norm_to_lig_table_; + } + const LigHash& lig_to_norm_table() const { + return lig_to_norm_table_; + } + + protected: + LigatureTable(); + // Initialize the hash tables mapping between ligature strings and the + // corresponding ligature characters. + void Init(); + + static SmartPtr instance_; + LigHash norm_to_lig_table_; + LigHash lig_to_norm_table_; + int min_lig_length_; + int max_lig_length_; + int min_norm_length_; + int max_norm_length_; + + private: + LigatureTable(const LigatureTable&); + void operator=(const LigatureTable&); +}; + +} // namespace tesseract + +#endif // OCR_TRAININGDATA_TYPESETTING_LIGATURE_TABLE_H_ diff --git a/TesseractOCR/include/tesseract/linefind.h b/TesseractOCR/include/tesseract/linefind.h new file mode 100644 index 00000000..abbd7cdd --- /dev/null +++ b/TesseractOCR/include/tesseract/linefind.h @@ -0,0 +1,150 @@ +/////////////////////////////////////////////////////////////////////// +// File: linefind.h +// Description: Class to find vertical lines in an image and create +// a corresponding list of empty blobs. +// Author: Ray Smith +// Created: Thu Mar 20 09:49:01 PDT 2008 +// +// (C) Copyright 2008, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_LINEFIND_H__ +#define TESSERACT_TEXTORD_LINEFIND_H__ + +struct Boxa; +struct Pix; +struct Pixa; +class C_BLOB_LIST; +class BLOBNBOX_LIST; +class ICOORD; + +namespace tesseract { + +class TabVector_LIST; + +/** + * The LineFinder class is a simple static function wrapper class that mainly + * exposes the FindVerticalLines function. + */ +class LineFinder { + public: + /** + * Finds vertical and horizontal line objects in the given pix and removes + * them. + * + * Uses the given resolution to determine size thresholds instead of any + * that may be present in the pix. + * + * The output vertical_x and vertical_y contain a sum of the output vectors, + * thereby giving the mean vertical direction. + * + * If pix_music_mask != NULL, and music is detected, a mask of the staves + * and anything that is connected (bars, notes etc.) will be returned in + * pix_music_mask, the mask subtracted from pix, and the lines will not + * appear in v_lines or h_lines. + * + * The output vectors are owned by the list and Frozen (cannot refit) by + * having no boxes, as there is no need to refit or merge separator lines. + * + * The detected lines are removed from the pix. + */ + static void FindAndRemoveLines(int resolution, bool debug, Pix* pix, + int* vertical_x, int* vertical_y, + Pix** pix_music_mask, + TabVector_LIST* v_lines, + TabVector_LIST* h_lines); + + /** + * Converts the Boxa array to a list of C_BLOB, getting rid of severely + * overlapping outlines and those that are children of a bigger one. + * + * The output is a list of C_BLOBs that are owned by the list. + * + * The C_OUTLINEs in the C_BLOBs contain no outline data - just empty + * bounding boxes. The Boxa is consumed and destroyed. + */ + static void ConvertBoxaToBlobs(int image_width, int image_height, + Boxa** boxes, C_BLOB_LIST* blobs); + + private: + // Finds vertical line objects in pix_vline and removes them from src_pix. + // Uses the given resolution to determine size thresholds instead of any + // that may be present in the pix. + // The output vertical_x and vertical_y contain a sum of the output vectors, + // thereby giving the mean vertical direction. + // The output vectors are owned by the list and Frozen (cannot refit) by + // having no boxes, as there is no need to refit or merge separator lines. + // If no good lines are found, pix_vline is destroyed. + static void FindAndRemoveVLines(int resolution, + Pix* pix_intersections, + int* vertical_x, int* vertical_y, + Pix** pix_vline, Pix* pix_non_vline, + Pix* src_pix, TabVector_LIST* vectors); + + + // Finds horizontal line objects in pix_vline and removes them from src_pix. + // Uses the given resolution to determine size thresholds instead of any + // that may be present in the pix. + // The output vertical_x and vertical_y contain a sum of the output vectors, + // thereby giving the mean vertical direction. + // The output vectors are owned by the list and Frozen (cannot refit) by + // having no boxes, as there is no need to refit or merge separator lines. + // If no good lines are found, pix_hline is destroyed. + static void FindAndRemoveHLines(int resolution, + Pix* pix_intersections, + int vertical_x, int vertical_y, + Pix** pix_hline, Pix* pix_non_hline, + Pix* src_pix, TabVector_LIST* vectors); + + // Finds vertical lines in the given list of BLOBNBOXes. bleft and tright + // are the bounds of the image on which the input line_bblobs were found. + // The input line_bblobs list is const really. + // The output vertical_x and vertical_y are the total of all the vectors. + // The output list of TabVector makes no reference to the input BLOBNBOXes. + static void FindLineVectors(const ICOORD& bleft, const ICOORD& tright, + BLOBNBOX_LIST* line_bblobs, + int* vertical_x, int* vertical_y, + TabVector_LIST* vectors); + + // Most of the heavy lifting of line finding. Given src_pix and its separate + // resolution, returns image masks: + // Returns image masks: + // pix_vline candidate vertical lines. + // pix_non_vline pixels that didn't look like vertical lines. + // pix_hline candidate horizontal lines. + // pix_non_hline pixels that didn't look like horizontal lines. + // pix_intersections pixels where vertical and horizontal lines meet. + // pix_music_mask candidate music staves. + // This function promises to initialize all the output (2nd level) pointers, + // but any of the returns that are empty will be NULL on output. + // None of the input (1st level) pointers may be NULL except pix_music_mask, + // which will disable music detection, and pixa_display, which is for debug. + static void GetLineMasks(int resolution, Pix* src_pix, + Pix** pix_vline, Pix** pix_non_vline, + Pix** pix_hline, Pix** pix_non_hline, + Pix** pix_intersections, Pix** pix_music_mask, + Pixa* pixa_display); + + // Returns a list of boxes corresponding to the candidate line segments. Sets + // the line_crossings member of the boxes so we can later determin the number + // of intersections touched by a full line. + static void GetLineBoxes(bool horizontal_lines, + Pix* pix_lines, Pix* pix_intersections, + C_BLOB_LIST* line_cblobs, + BLOBNBOX_LIST* line_bblobs); +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_LINEFIND_H__ + diff --git a/TesseractOCR/include/tesseract/linlsq.h b/TesseractOCR/include/tesseract/linlsq.h old mode 100755 new mode 100644 index 47de42d7..d1cea80e --- a/TesseractOCR/include/tesseract/linlsq.h +++ b/TesseractOCR/include/tesseract/linlsq.h @@ -49,13 +49,26 @@ class LLSQ { // Returns the x,y means as an FCOORD. FCOORD mean_point() const; + + // Returns the average sum of squared perpendicular error from a line + // through mean_point() in the direction dir. + double rms_orth(const FCOORD &dir) const; + // Returns the direction of the fitted line as a unit vector, using the // least mean squared perpendicular distance. The line runs through the // mean_point, i.e. a point p on the line is given by: // p = mean_point() + lambda * vector_fit() for some real number lambda. // Note that the result (0<=x<=1, -1<=y<=-1) is directionally ambiguous - // and may be negated without changing its meaning. + // and may be negated without changing its meaning, since a line is only + // unique to a range of pi radians. + // Modernists prefer to think of this as an Eigenvalue problem, but + // Pearson had the simple solution in 1901. + // + // Note that this is equivalent to returning the Principal Component in PCA, + // or the eigenvector corresponding to the largest eigenvalue in the + // covariance matrix. FCOORD vector_fit() const; + // Returns the covariance. double covariance() const { if (total_weight > 0.0) @@ -85,4 +98,37 @@ class LLSQ { double sigyy; // sum y squared }; + +// Returns the median value of the vector, given that the values are +// circular, with the given modulus. Values may be signed or unsigned, +// eg range from -pi to pi (modulus 2pi) or from 0 to 2pi (modulus 2pi). +// NOTE that the array is shuffled, but the time taken is linear. +// An assumption is made that most of the values are spread over no more than +// half the range, but wrap-around is accounted for if the median is near +// the wrap-around point. +// Cannot be a member of GenericVector, as it makes heavy used of LLSQ. +// T must be an integer or float/double type. +template T MedianOfCircularValues(T modulus, GenericVector* v) { + LLSQ stats; + T halfrange = static_cast(modulus / 2); + int num_elements = v->size(); + for (int i = 0; i < num_elements; ++i) { + stats.add((*v)[i], (*v)[i] + halfrange); + } + bool offset_needed = stats.y_variance() < stats.x_variance(); + if (offset_needed) { + for (int i = 0; i < num_elements; ++i) { + (*v)[i] += halfrange; + } + } + int median_index = v->choose_nth_item(num_elements / 2); + if (offset_needed) { + for (int i = 0; i < num_elements; ++i) { + (*v)[i] -= halfrange; + } + } + return (*v)[median_index]; +} + + #endif // TESSERACT_CCSTRUCT_LINLSQ_H_ diff --git a/TesseractOCR/include/tesseract/listio.h b/TesseractOCR/include/tesseract/listio.h new file mode 100644 index 00000000..e758c9bc --- /dev/null +++ b/TesseractOCR/include/tesseract/listio.h @@ -0,0 +1,43 @@ +/* -*-C-*- +################################################################################ +# +# File: listio.h +# Description: List I/O processing procedures. +# Author: Mark Seaman, Software Productivity +# Created: Thu Jul 23 13:24:09 1987 +# Modified: Mon Oct 16 11:38:52 1989 (Mark Seaman) marks@hpgrlt +# Language: C +# Package: N/A +# Status: Reusable Software Component +# +# (c) Copyright 1987, Hewlett-Packard Company. +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** http://www.apache.org/licenses/LICENSE-2.0 +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +# +################################################################################ + * Revision 1.5 89/06/27 11:56:00 11:56:00 marks (Mark Seaman) + * Fixed MAC_OR_DOS bug + * + + This file contains the interface definitions to a set of general purpose + list I/O routines. + +***********************************************************************/ +#ifndef LISTIO_H +#define LISTIO_H + +#include +#include "oldlist.h" + +/*---------------------------------------------------------------------------- + Public Funtion Prototypes +--------------------------------------------------------------------------*/ +LIST read_list(const char *filename); +#endif diff --git a/TesseractOCR/include/tesseract/lm_consistency.h b/TesseractOCR/include/tesseract/lm_consistency.h new file mode 100644 index 00000000..1d452157 --- /dev/null +++ b/TesseractOCR/include/tesseract/lm_consistency.h @@ -0,0 +1,143 @@ +/////////////////////////////////////////////////////////////////////// +// File: lm_consistency.h +// Description: Struct for recording consistency of the paths representing +// OCR hypotheses. +// Author: Rika Antonova +// Created: Mon Jun 20 11:26:43 PST 2012 +// +// (C) Copyright 2012, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////// + +#include "dawg.h" +#include "dict.h" +#include "host.h" +#include "ratngs.h" + +#ifndef TESSERACT_WORDREC_CONSISTENCY_H_ +#define TESSERACT_WORDREC_CONSISTENCY_H_ + +namespace tesseract { + +static const char * const XHeightConsistencyEnumName[] = { + "XH_GOOD", + "XH_SUBNORMAL", + "XH_INCONSISTENT", +}; + +// Struct for keeping track of the consistency of the path. +struct LMConsistencyInfo { + enum ChartypeEnum { CT_NONE, CT_ALPHA, CT_DIGIT, CT_OTHER}; + + // How much do characters have to be shifted away from normal parameters + // before we say they're not normal? + static const int kShiftThresh = 1; + + // How much shifting from subscript to superscript and back + // before we declare shenanigans? + static const int kMaxEntropy = 1; + + // Script positions - order important for entropy calculation. + static const int kSUB = 0, kNORM = 1, kSUP = 2; + static const int kNumPos = 3; + + explicit LMConsistencyInfo(const LMConsistencyInfo* parent_info) { + if (parent_info == NULL) { + // Initialize from scratch. + num_alphas = 0; + num_digits = 0; + num_punc = 0; + num_other = 0; + chartype = CT_NONE; + punc_ref = NO_EDGE; + invalid_punc = false; + num_non_first_upper = 0; + num_lower = 0; + script_id = 0; + inconsistent_script = false; + num_inconsistent_spaces = 0; + inconsistent_font = false; + // Initialize XHeight stats. + for (int i = 0; i < kNumPos; i++) { + xht_count[i] = 0; + xht_count_punc[i] = 0; + xht_lo[i] = 0; + xht_hi[i] = 256; // kBlnCellHeight + } + xht_sp = -1; // This invalid value indicates that there was no parent. + xpos_entropy = 0; + xht_decision = XH_GOOD; + } else { + // Copy parent info + *this = *parent_info; + } + } + inline int NumInconsistentPunc() const { + return invalid_punc ? num_punc : 0; + } + inline int NumInconsistentCase() const { + return (num_non_first_upper > num_lower) ? num_lower : num_non_first_upper; + } + inline int NumInconsistentChartype() const { + return (NumInconsistentPunc() + num_other + + ((num_alphas > num_digits) ? num_digits : num_alphas)); + } + inline bool Consistent() const { + return (NumInconsistentPunc() == 0 && NumInconsistentCase() == 0 && + NumInconsistentChartype() == 0 && !inconsistent_script && + !inconsistent_font && !InconsistentXHeight()); + } + inline int NumInconsistentSpaces() const { + return num_inconsistent_spaces; + } + inline int InconsistentXHeight() const { + return xht_decision == XH_INCONSISTENT; + } + void ComputeXheightConsistency(const BLOB_CHOICE *b, bool is_punc); + float BodyMinXHeight() const { + if (InconsistentXHeight()) + return 0.0f; + return xht_lo[kNORM]; + } + float BodyMaxXHeight() const { + if (InconsistentXHeight()) + return static_cast(MAX_INT16); + return xht_hi[kNORM]; + } + + int num_alphas; + int num_digits; + int num_punc; + int num_other; + ChartypeEnum chartype; + EDGE_REF punc_ref; + bool invalid_punc; + int num_non_first_upper; + int num_lower; + int script_id; + bool inconsistent_script; + int num_inconsistent_spaces; + bool inconsistent_font; + // Metrics clumped by position. + float xht_lo[kNumPos]; + float xht_hi[kNumPos]; + inT16 xht_count[kNumPos]; + inT16 xht_count_punc[kNumPos]; + inT16 xht_sp; + inT16 xpos_entropy; + XHeightConsistencyEnum xht_decision; +}; + + +} // namespace tesseract + +#endif // TESSERACT_WORDREC_CONSISTENCY_H_ diff --git a/TesseractOCR/include/tesseract/lm_pain_points.h b/TesseractOCR/include/tesseract/lm_pain_points.h new file mode 100644 index 00000000..0f47b1dd --- /dev/null +++ b/TesseractOCR/include/tesseract/lm_pain_points.h @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////// +// File: lm_pain_points.h +// Description: Functions that utilize the knowledge about the properties +// of the paths explored by the segmentation search in order +// to generate "pain points" - the locations in the ratings +// matrix which should be classified next. +// Author: Rika Antonova +// Created: Mon Jun 20 11:26:43 PST 2012 +// +// (C) Copyright 2012, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_WORDREC_PAIN_POINTS_H_ +#define TESSERACT_WORDREC_PAIN_POINTS_H_ + +#include "associate.h" +#include "dict.h" +#include "genericheap.h" +#include "lm_state.h" + +namespace tesseract { + +// Heap of pain points used for determining where to chop/join. +typedef GenericHeap PainPointHeap; + +// Types of pain points (ordered in the decreasing level of importance). +enum LMPainPointsType { + LM_PPTYPE_BLAMER, + LM_PPTYPE_AMBIG, + LM_PPTYPE_PATH, + LM_PPTYPE_SHAPE, + + LM_PPTYPE_NUM +}; + +static const char * const LMPainPointsTypeName[] = { + "LM_PPTYPE_BLAMER", + "LM_PPTYPE_AMBIGS", + "LM_PPTYPE_PATH", + "LM_PPTYPE_SHAPE", +}; + +class LMPainPoints { + public: + + static const float kDefaultPainPointPriorityAdjustment; + // If there is a significant drop in character ngram probability or a + // dangerous ambiguity make the thresholds on what blob combinations + // can be classified looser. + static const float kLooseMaxCharWhRatio; + // Returns a description of the type of a pain point. + static const char* PainPointDescription(LMPainPointsType type) { + return LMPainPointsTypeName[type]; + } + + LMPainPoints(int max, float rat, bool fp, const Dict *d, int deb) : + max_heap_size_(max), max_char_wh_ratio_(rat), fixed_pitch_(fp), + dict_(d), debug_level_(deb) {} + ~LMPainPoints() {} + + // Returns true if the heap of pain points of pp_type is not empty(). + inline bool HasPainPoints(LMPainPointsType pp_type) const { + return !pain_points_heaps_[pp_type].empty(); + } + + // Dequeues the next pain point from the pain points queue and copies + // its contents and priority to *pp and *priority. + // Returns LM_PPTYPE_NUM if pain points queue is empty, otherwise the type. + LMPainPointsType Deque(MATRIX_COORD *pp, float *priority); + + // Clears pain points heap. + void Clear() { + for (int h = 0; h < LM_PPTYPE_NUM; ++h) pain_points_heaps_[h].clear(); + } + + // For each cell, generate a "pain point" if the cell is not classified + // and has a left or right neighbor that was classified. + void GenerateInitial(WERD_RES *word_res); + + // Generate pain points from the given path. + void GenerateFromPath(float rating_cert_scale, ViterbiStateEntry *vse, + WERD_RES *word_res); + + // Generate pain points from dangerous ambiguities in best choice. + void GenerateFromAmbigs(const DANGERR &fixpt, ViterbiStateEntry *vse, + WERD_RES *word_res); + + // Generate a pain point for the blamer. + bool GenerateForBlamer(double max_char_wh_ratio, WERD_RES *word_res, + int col, int row) { + return GeneratePainPoint(col, row, LM_PPTYPE_BLAMER, 0.0, false, + max_char_wh_ratio, word_res); + } + + // Adds a pain point to classify chunks_record->ratings(col, row). + // Returns true if a new pain point was added to an appropriate heap. + // Pain point priority is set to special_priority for pain points of + // LM_PPTYPE_AMBIG or LM_PPTYPE_PATH, for other pain points + // AssociateStats::gap_sum is used. + bool GeneratePainPoint(int col, int row, LMPainPointsType pp_type, + float special_priority, bool ok_to_extend, + float max_char_wh_ratio, + WERD_RES *word_res); + + // Adjusts the pain point coordinates to cope with expansion of the ratings + // matrix due to a split of the blob with the given index. + void RemapForSplit(int index); + + private: + // Priority queues containing pain points generated by the language model + // The priority is set by the language model components, adjustments like + // seam cost and width priority are factored into the priority. + PainPointHeap pain_points_heaps_[LM_PPTYPE_NUM]; + // Maximum number of points to keep in the heap. + int max_heap_size_; + // Maximum character width/height ratio. + float max_char_wh_ratio_; + // Set to true if fixed pitch should be assumed. + bool fixed_pitch_; + // Cached pointer to dictionary. + const Dict *dict_; + // Debug level for print statements. + int debug_level_; +}; + +} // namespace tesseract + +#endif // TESSERACT_WORDREC_PAIN_POINTS_H_ diff --git a/TesseractOCR/include/tesseract/lm_state.h b/TesseractOCR/include/tesseract/lm_state.h new file mode 100644 index 00000000..06179019 --- /dev/null +++ b/TesseractOCR/include/tesseract/lm_state.h @@ -0,0 +1,239 @@ +/////////////////////////////////////////////////////////////////////// +// File: lm_state.h +// Description: Structures and functionality for capturing the state of +// segmentation search guided by the language model. +// +// Author: Rika Antonova +// Created: Mon Jun 20 11:26:43 PST 2012 +// +// (C) Copyright 2012, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_WORDREC_LANGUAGE_MODEL_DEFS_H_ +#define TESSERACT_WORDREC_LANGUAGE_MODEL_DEFS_H_ + +#include "associate.h" +#include "elst.h" +#include "dawg.h" +#include "lm_consistency.h" +#include "matrix.h" +#include "ratngs.h" +#include "stopper.h" +#include "strngs.h" + +namespace tesseract { + +// Used for expressing various language model flags. +typedef unsigned char LanguageModelFlagsType; + +// The following structs are used for storing the state of the language model +// in the segmentation search graph. In this graph the nodes are BLOB_CHOICEs +// and the links are the relationships between the underlying blobs (see +// segsearch.h for a more detailed description). +// Each of the BLOB_CHOICEs contains LanguageModelState struct, which has +// a list of N best paths (list of ViterbiStateEntry) explored by the Viterbi +// search leading up to and including this BLOB_CHOICE. +// Each ViterbiStateEntry contains information from various components of the +// language model: dawgs in which the path is found, character ngram model +// probability of the path, script/chartype/font consistency info, state for +// language-specific heuristics (e.g. hyphenated and compound words, lower/upper +// case preferences, etc). +// Each ViterbiStateEntry also contains the parent pointer, so that the path +// that it represents (WERD_CHOICE) can be constructed by following these +// parent pointers. + +// Struct for storing additional information used by Dawg language model +// component. It stores the set of active dawgs in which the sequence of +// letters on a path can be found. +struct LanguageModelDawgInfo { + LanguageModelDawgInfo(DawgPositionVector *a, PermuterType pt) : permuter(pt) { + active_dawgs = new DawgPositionVector(*a); + } + ~LanguageModelDawgInfo() { + delete active_dawgs; + } + DawgPositionVector *active_dawgs; + PermuterType permuter; +}; + +// Struct for storing additional information used by Ngram language model +// component. +struct LanguageModelNgramInfo { + LanguageModelNgramInfo(const char *c, int l, bool p, float nc, float ncc) + : context(c), context_unichar_step_len(l), pruned(p), ngram_cost(nc), + ngram_and_classifier_cost(ncc) {} + STRING context; // context string + // Length of the context measured by advancing using UNICHAR::utf8_step() + // (should be at most the order of the character ngram model used). + int context_unichar_step_len; + // The paths with pruned set are pruned out from the perspective of the + // character ngram model. They are explored further because they represent + // a dictionary match or a top choice. Thus ngram_info is still computed + // for them in order to calculate the combined cost. + bool pruned; + // -ln(P_ngram_model(path)) + float ngram_cost; + // -[ ln(P_classifier(path)) + scale_factor * ln(P_ngram_model(path)) ] + float ngram_and_classifier_cost; +}; + +// Struct for storing the information about a path in the segmentation graph +// explored by Viterbi search. +struct ViterbiStateEntry : public ELIST_LINK { + ViterbiStateEntry(ViterbiStateEntry *pe, + BLOB_CHOICE *b, float c, float ol, + const LMConsistencyInfo &ci, + const AssociateStats &as, + LanguageModelFlagsType tcf, + LanguageModelDawgInfo *d, + LanguageModelNgramInfo *n, + const char *debug_uch) + : cost(c), curr_b(b), parent_vse(pe), competing_vse(NULL), + ratings_sum(b->rating()), + min_certainty(b->certainty()), adapted(b->IsAdapted()), length(1), + outline_length(ol), consistency_info(ci), associate_stats(as), + top_choice_flags(tcf), dawg_info(d), ngram_info(n), + updated(true) { + debug_str = (debug_uch == NULL) ? NULL : new STRING(); + if (pe != NULL) { + ratings_sum += pe->ratings_sum; + if (pe->min_certainty < min_certainty) { + min_certainty = pe->min_certainty; + } + adapted += pe->adapted; + length += pe->length; + outline_length += pe->outline_length; + if (debug_uch != NULL) *debug_str += *(pe->debug_str); + } + if (debug_str != NULL && debug_uch != NULL) *debug_str += debug_uch; + } + ~ViterbiStateEntry() { + delete dawg_info; + delete ngram_info; + delete debug_str; + } + // Comparator function for sorting ViterbiStateEntry_LISTs in + // non-increasing order of costs. + static int Compare(const void *e1, const void *e2) { + const ViterbiStateEntry *ve1 = + *reinterpret_cast(e1); + const ViterbiStateEntry *ve2 = + *reinterpret_cast(e2); + return (ve1->cost < ve2->cost) ? -1 : 1; + } + inline bool Consistent() const { + if (dawg_info != NULL && consistency_info.NumInconsistentCase() == 0) { + return true; + } + return consistency_info.Consistent(); + } + // Returns true if this VSE has an alphanumeric character as its classifier + // result. + bool HasAlnumChoice(const UNICHARSET& unicharset) { + if (curr_b == NULL) return false; + UNICHAR_ID unichar_id = curr_b->unichar_id(); + if (unicharset.get_isalpha(unichar_id) || + unicharset.get_isdigit(unichar_id)) + return true; + return false; + } + void Print(const char *msg) const; + + // The cost is an adjusted ratings sum, that is adjusted by all the language + // model components that use Viterbi search. + float cost; + + // Pointers to BLOB_CHOICE and parent ViterbiStateEntry (not owned by this). + BLOB_CHOICE *curr_b; + ViterbiStateEntry *parent_vse; + // Pointer to a case-competing ViterbiStateEntry in the same list that + // represents a path ending in the same letter of the opposite case. + ViterbiStateEntry *competing_vse; + + // Various information about the characters on the path represented + // by this ViterbiStateEntry. + float ratings_sum; // sum of ratings of character on the path + float min_certainty; // minimum certainty on the path + int adapted; // number of BLOB_CHOICES from adapted templates + int length; // number of characters on the path + float outline_length; // length of the outline so far + LMConsistencyInfo consistency_info; // path consistency info + AssociateStats associate_stats; // character widths/gaps/seams + + // Flags for marking the entry as a top choice path with + // the smallest rating or lower/upper case letters). + LanguageModelFlagsType top_choice_flags; + + // Extra information maintained by Dawg laguage model component + // (owned by ViterbiStateEntry). + LanguageModelDawgInfo *dawg_info; + + // Extra information maintained by Ngram laguage model component + // (owned by ViterbiStateEntry). + LanguageModelNgramInfo *ngram_info; + + bool updated; // set to true if the entry has just been created/updated + // UTF8 string representing the path corresponding to this vse. + // Populated only in when language_model_debug_level > 0. + STRING *debug_str; +}; + +ELISTIZEH(ViterbiStateEntry); + +// Struct to store information maintained by various language model components. +struct LanguageModelState { + LanguageModelState() : + viterbi_state_entries_prunable_length(0), + viterbi_state_entries_prunable_max_cost(MAX_FLOAT32), + viterbi_state_entries_length(0) {} + ~LanguageModelState() {} + + // Clears the viterbi search state back to its initial conditions. + void Clear(); + + void Print(const char *msg); + + // Storage for the Viterbi state. + ViterbiStateEntry_LIST viterbi_state_entries; + // Number and max cost of prunable paths in viterbi_state_entries. + int viterbi_state_entries_prunable_length; + float viterbi_state_entries_prunable_max_cost; + // Total number of entries in viterbi_state_entries. + int viterbi_state_entries_length; +}; + +// Bundle together all the things pertaining to the best choice/state. +struct BestChoiceBundle { + explicit BestChoiceBundle(int matrix_dimension) + : updated(false), best_vse(NULL) { + beam.reserve(matrix_dimension); + for (int i = 0; i < matrix_dimension; ++i) + beam.push_back(new LanguageModelState); + } + ~BestChoiceBundle() {} + + // Flag to indicate whether anything was changed. + bool updated; + // Places to try to fix the word suggested by ambiguity checking. + DANGERR fixpt; + // The beam. One LanguageModelState containing a list of ViterbiStateEntry per + // row in the ratings matrix containing all VSEs whose BLOB_CHOICE is + // somewhere in the corresponding row. + PointerVector beam; + // Best ViterbiStateEntry and BLOB_CHOICE. + ViterbiStateEntry *best_vse; +}; + +} // namespace tesseract + +#endif // TESSERACT_WORDREC_LANGUAGE_MODEL_DEFS_H_ diff --git a/TesseractOCR/include/tesseract/lsterr.h b/TesseractOCR/include/tesseract/lsterr.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/ltrresultiterator.h b/TesseractOCR/include/tesseract/ltrresultiterator.h old mode 100755 new mode 100644 index 9464aaed..89b3c496 --- a/TesseractOCR/include/tesseract/ltrresultiterator.h +++ b/TesseractOCR/include/tesseract/ltrresultiterator.h @@ -23,7 +23,7 @@ #include "platform.h" #include "pageiterator.h" -#include "unicharset.h" +#include "unichar.h" class BLOB_CHOICE_IT; class WERD_RES; @@ -128,7 +128,7 @@ class TESS_API LTRResultIterator : public PageIterator { // Returns the pointer to ParamsTrainingBundle stored in the BlamerBundle // of the current word. - void *GetParamsTrainingBundle() const; + const void *GetParamsTrainingBundle() const; // Returns a pointer to the string with blamer information for this word. // Assumes that the word's blamer_bundle is not NULL. @@ -138,10 +138,21 @@ class TESS_API LTRResultIterator : public PageIterator { // Assumes that the word's blamer_bundle is not NULL. const char *GetBlamerMisadaptionDebug() const; + // Returns true if a truth string was recorded for the current word. + bool HasTruthString() const; + + // Returns true if the given string is equivalent to the truth string for + // the current word. + bool EquivalentToTruth(const char *str) const; + // Returns a null terminated UTF-8 encoded truth string for the current word. // Use delete [] to free after use. char* WordTruthUTF8Text() const; + // Returns a null terminated UTF-8 encoded normalized OCR string for the + // current word. Use delete [] to free after use. + char* WordNormedUTF8Text() const; + // Returns a pointer to serialized choice lattice. // Fills lattice_size with the number of bytes in lattice data. const char *WordLattice(int *lattice_size) const; diff --git a/TesseractOCR/include/tesseract/makechop.h b/TesseractOCR/include/tesseract/makechop.h new file mode 100644 index 00000000..1f2639cd --- /dev/null +++ b/TesseractOCR/include/tesseract/makechop.h @@ -0,0 +1,71 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: makechop.h (Formerly makechop.h) + * Description: + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Mon Jul 29 13:33:23 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ +#ifndef MAKECHOP_H +#define MAKECHOP_H + +/*---------------------------------------------------------------------- + I n c l u d e s +----------------------------------------------------------------------*/ +#include "chop.h" +#include "olutil.h" + +/*---------------------------------------------------------------------- + M a c r o s +---------------------------------------------------------------------*/ +/********************************************************************** + * is_split_outline + * + * Check to see if both sides of the split fall within the bounding + * box of this outline. + **********************************************************************/ + +#define is_split_outline(outline,split) \ +(outline->Contains(split->point1->pos) && \ + outline->Contains(split->point2->pos)) \ + + +/*---------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------*/ +void apply_seam(TBLOB *blob, TBLOB *other_blob, bool italic_blob, SEAM *seam); + +void form_two_blobs(TBLOB *blob, TBLOB *other_blob, bool italic_blob, + const TPOINT& location); + +void make_double_split(TBLOB *blob, TBLOB *other_blob, bool italic_blob, + SEAM *seam); + +void make_single_split(TESSLINE *outlines, SPLIT *split); + +void make_split_blobs(TBLOB *blob, TBLOB *other_blob, bool italic_blob, + SEAM *seam); + +void make_triple_split(TBLOB *blob, TBLOB *other_blob, bool italic_blob, + SEAM *seam); + +void undo_seam(TBLOB *blob, TBLOB *other_blob, SEAM *seam); + +void undo_single_split(TBLOB *blob, SPLIT *split); +#endif diff --git a/TesseractOCR/include/tesseract/makerow.h b/TesseractOCR/include/tesseract/makerow.h new file mode 100644 index 00000000..508ae6f9 --- /dev/null +++ b/TesseractOCR/include/tesseract/makerow.h @@ -0,0 +1,287 @@ +/********************************************************************** + * File: makerow.h (Formerly makerows.h) + * Description: Code to arrange blobs into rows of text. + * Author: Ray Smith + * Created: Mon Sep 21 14:34:48 BST 1992 + * + * (C) Copyright 1992, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef MAKEROW_H +#define MAKEROW_H + +#include "params.h" +#include "ocrblock.h" +#include "blobs.h" +#include "blobbox.h" +#include "statistc.h" + +enum OVERLAP_STATE +{ + ASSIGN, //assign it to row + REJECT, //reject it - dual overlap + NEW_ROW +}; + +enum ROW_CATEGORY { + ROW_ASCENDERS_FOUND, + ROW_DESCENDERS_FOUND, + ROW_UNKNOWN, + ROW_INVALID, +}; + +extern BOOL_VAR_H(textord_heavy_nr, FALSE, "Vigorously remove noise"); +extern BOOL_VAR_H (textord_show_initial_rows, FALSE, +"Display row accumulation"); +extern BOOL_VAR_H (textord_show_parallel_rows, FALSE, +"Display page correlated rows"); +extern BOOL_VAR_H (textord_show_expanded_rows, FALSE, +"Display rows after expanding"); +extern BOOL_VAR_H (textord_show_final_rows, FALSE, +"Display rows after final fitting"); +extern BOOL_VAR_H (textord_show_final_blobs, FALSE, +"Display blob bounds after pre-ass"); +extern BOOL_VAR_H (textord_test_landscape, FALSE, "Tests refer to land/port"); +extern BOOL_VAR_H (textord_parallel_baselines, TRUE, +"Force parallel baselines"); +extern BOOL_VAR_H (textord_straight_baselines, FALSE, +"Force straight baselines"); +extern BOOL_VAR_H (textord_quadratic_baselines, FALSE, +"Use quadratic splines"); +extern BOOL_VAR_H (textord_old_baselines, TRUE, "Use old baseline algorithm"); +extern BOOL_VAR_H (textord_old_xheight, TRUE, "Use old xheight algorithm"); +extern BOOL_VAR_H (textord_fix_xheight_bug, TRUE, "Use spline baseline"); +extern BOOL_VAR_H (textord_fix_makerow_bug, TRUE, +"Prevent multiple baselines"); +extern BOOL_VAR_H (textord_cblob_blockocc, TRUE, +"Use new projection for underlines"); +extern BOOL_VAR_H (textord_debug_xheights, FALSE, "Test xheight algorithms"); +extern INT_VAR_H (textord_test_x, -MAX_INT32, "coord of test pt"); +extern INT_VAR_H (textord_test_y, -MAX_INT32, "coord of test pt"); +extern INT_VAR_H (textord_min_blobs_in_row, 4, +"Min blobs before gradient counted"); +extern INT_VAR_H (textord_spline_minblobs, 8, +"Min blobs in each spline segment"); +extern INT_VAR_H (textord_spline_medianwin, 6, +"Size of window for spline segmentation"); +extern INT_VAR_H (textord_min_xheight, 10, "Min credible pixel xheight"); +extern double_VAR_H (textord_spline_shift_fraction, 0.02, +"Fraction of line spacing for quad"); +extern double_VAR_H (textord_spline_outlier_fraction, 0.1, +"Fraction of line spacing for outlier"); +extern double_VAR_H (textord_skew_ile, 0.5, "Ile of gradients for page skew"); +extern double_VAR_H (textord_skew_lag, 0.75, +"Lag for skew on row accumulation"); +extern double_VAR_H (textord_linespace_iqrlimit, 0.2, +"Max iqr/median for linespace"); +extern double_VAR_H (textord_width_limit, 8, +"Max width of blobs to make rows"); +extern double_VAR_H (textord_chop_width, 1.5, "Max width before chopping"); +extern double_VAR_H (textord_minxh, 0.25, +"fraction of linesize for min xheight"); +extern double_VAR_H (textord_min_linesize, 1.25, +"* blob height for initial linesize"); +extern double_VAR_H (textord_excess_blobsize, 1.3, +"New row made if blob makes row this big"); +extern double_VAR_H (textord_occupancy_threshold, 0.4, +"Fraction of neighbourhood"); +extern double_VAR_H (textord_underline_width, 2.0, +"Multiple of line_size for underline"); +extern double_VAR_H(textord_min_blob_height_fraction, 0.75, +"Min blob height/top to include blob top into xheight stats"); +extern double_VAR_H (textord_xheight_mode_fraction, 0.4, +"Min pile height to make xheight"); +extern double_VAR_H (textord_ascheight_mode_fraction, 0.15, +"Min pile height to make ascheight"); +extern double_VAR_H (textord_ascx_ratio_min, 1.2, "Min cap/xheight"); +extern double_VAR_H (textord_ascx_ratio_max, 1.7, "Max cap/xheight"); +extern double_VAR_H (textord_descx_ratio_min, 0.15, "Min desc/xheight"); +extern double_VAR_H (textord_descx_ratio_max, 0.6, "Max desc/xheight"); +extern double_VAR_H (textord_xheight_error_margin, 0.1, "Accepted variation"); +extern INT_VAR_H (textord_lms_line_trials, 12, "Number of linew fits to do"); +extern BOOL_VAR_H (textord_new_initial_xheight, TRUE, +"Use test xheight mechanism"); +extern BOOL_VAR_H(textord_debug_blob, FALSE, "Print test blob information"); + +inline void get_min_max_xheight(int block_linesize, + int *min_height, int *max_height) { + *min_height = static_cast(floor(block_linesize * textord_minxh)); + if (*min_height < textord_min_xheight) *min_height = textord_min_xheight; + *max_height = static_cast(ceil(block_linesize * 3.0)); +} + +inline ROW_CATEGORY get_row_category(const TO_ROW *row) { + if (row->xheight <= 0) return ROW_INVALID; + return (row->ascrise > 0) ? ROW_ASCENDERS_FOUND : + (row->descdrop != 0) ? ROW_DESCENDERS_FOUND : ROW_UNKNOWN; +} + +inline bool within_error_margin(float test, float num, float margin) { + return (test >= num * (1 - margin) && test <= num * (1 + margin)); +} + +void fill_heights(TO_ROW *row, float gradient, int min_height, + int max_height, STATS *heights, STATS *floating_heights); + +float make_single_row(ICOORD page_tr, TO_BLOCK* block, + TO_BLOCK_LIST* blocks); +float make_rows(ICOORD page_tr, // top right + TO_BLOCK_LIST *port_blocks); +void make_initial_textrows(ICOORD page_tr, + TO_BLOCK *block, // block to do + FCOORD rotation, // for drawing + BOOL8 testing_on); // correct orientation +void fit_lms_line(TO_ROW *row); +void compute_page_skew(TO_BLOCK_LIST *blocks, // list of blocks + float &page_m, // average gradient + float &page_err); // average error +void vigorous_noise_removal(TO_BLOCK* block); +void cleanup_rows_making(ICOORD page_tr, // top right + TO_BLOCK *block, // block to do + float gradient, // gradient to fit + FCOORD rotation, // for drawing + inT32 block_edge, // edge of block + BOOL8 testing_on); // correct orientation +void delete_non_dropout_rows( //find lines + TO_BLOCK *block, //block to do + float gradient, //global skew + FCOORD rotation, //deskew vector + inT32 block_edge, //left edge + BOOL8 testing_on //correct orientation + ); +BOOL8 find_best_dropout_row( //find neighbours + TO_ROW *row, //row to test + inT32 distance, //dropout dist + float dist_limit, //threshold distance + inT32 line_index, //index of row + TO_ROW_IT *row_it, //current position + BOOL8 testing_on //correct orientation + ); +TBOX deskew_block_coords( //block box + TO_BLOCK *block, //block to do + float gradient //global skew + ); +void compute_line_occupation( //project blobs + TO_BLOCK *block, //block to do + float gradient, //global skew + inT32 min_y, //min coord in block + inT32 max_y, //in block + inT32 *occupation, //output projection + inT32 *deltas //derivative + ); +void compute_occupation_threshold( //project blobs + inT32 low_window, //below result point + inT32 high_window, //above result point + inT32 line_count, //array sizes + inT32 *occupation, //input projection + inT32 *thresholds //output thresholds + ); +void compute_dropout_distances( //project blobs + inT32 *occupation, //input projection + inT32 *thresholds, //output thresholds + inT32 line_count //array sizes + ); +void expand_rows( //find lines + ICOORD page_tr, //top right + TO_BLOCK *block, //block to do + float gradient, //gradient to fit + FCOORD rotation, //for drawing + inT32 block_edge, //edge of block + BOOL8 testing_on //correct orientation + ); +void adjust_row_limits( //tidy limits + TO_BLOCK *block //block to do + ); +void compute_row_stats( //find lines + TO_BLOCK *block, //block to do + BOOL8 testing_on //correct orientation + ); +float median_block_xheight( //find lines + TO_BLOCK *block, //block to do + float gradient //global skew + ); + +int compute_xheight_from_modes( + STATS *heights, STATS *floating_heights, bool cap_only, int min_height, + int max_height, float *xheight, float *ascrise); + +inT32 compute_row_descdrop(TO_ROW *row, // row to do + float gradient, // global skew + int xheight_blob_count, + STATS *heights); +inT32 compute_height_modes(STATS *heights, // stats to search + inT32 min_height, // bottom of range + inT32 max_height, // top of range + inT32 *modes, // output array + inT32 maxmodes); // size of modes +void correct_row_xheight(TO_ROW *row, // row to fix + float xheight, // average values + float ascrise, + float descdrop); +void separate_underlines(TO_BLOCK *block, // block to do + float gradient, // skew angle + FCOORD rotation, // inverse landscape + BOOL8 testing_on); // correct orientation +void pre_associate_blobs( ICOORD page_tr, // top right + TO_BLOCK *block, // block to do + FCOORD rotation, // inverse landscape + BOOL8 testing_on); // correct orientation +void fit_parallel_rows(TO_BLOCK *block, // block to do + float gradient, // gradient to fit + FCOORD rotation, // for drawing + inT32 block_edge, // edge of block + BOOL8 testing_on); // correct orientation +void fit_parallel_lms(float gradient, // forced gradient + TO_ROW *row); // row to fit +void make_baseline_spline(TO_ROW *row, // row to fit + TO_BLOCK *block); // block it came from +BOOL8 segment_baseline ( //split baseline +TO_ROW * row, //row to fit +TO_BLOCK * block, //block it came from +inT32 & segments, //no fo segments +inT32 xstarts[] //coords of segments +); +double *linear_spline_baseline ( //split baseline +TO_ROW * row, //row to fit +TO_BLOCK * block, //block it came from +inT32 & segments, //no fo segments +inT32 xstarts[] //coords of segments +); +void assign_blobs_to_rows( //find lines + TO_BLOCK *block, //block to do + float *gradient, //block skew + int pass, //identification + BOOL8 reject_misses, //chuck big ones out + BOOL8 make_new_rows, //add rows for unmatched + BOOL8 drawing_skew //draw smoothed skew + ); + //find best row +OVERLAP_STATE most_overlapping_row(TO_ROW_IT *row_it, //iterator + TO_ROW *&best_row, //output row + float top, //top of blob + float bottom, //bottom of blob + float rowsize, //max row size + BOOL8 testing_blob //test stuff + ); +int blob_x_order( //sort function + const void *item1, //items to compare + const void *item2); +int row_y_order( //sort function + const void *item1, //items to compare + const void *item2); +int row_spacing_order( //sort function + const void *item1, //items to compare + const void *item2); + +void mark_repeated_chars(TO_ROW *row); +#endif diff --git a/TesseractOCR/include/tesseract/mastertrainer.h b/TesseractOCR/include/tesseract/mastertrainer.h new file mode 100644 index 00000000..8cc7158a --- /dev/null +++ b/TesseractOCR/include/tesseract/mastertrainer.h @@ -0,0 +1,312 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +/////////////////////////////////////////////////////////////////////// +// File: mastertrainer.h +// Description: Trainer to build the MasterClassifier. +// Author: Ray Smith +// Created: Wed Nov 03 18:07:01 PDT 2010 +// +// (C) Copyright 2010, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TRAINING_MASTERTRAINER_H__ +#define TESSERACT_TRAINING_MASTERTRAINER_H__ + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "classify.h" +#include "cluster.h" +#include "intfx.h" +#include "elst.h" +#include "errorcounter.h" +#include "featdefs.h" +#include "fontinfo.h" +#include "indexmapbidi.h" +#include "intfeaturespace.h" +#include "intfeaturemap.h" +#include "intmatcher.h" +#include "params.h" +#include "shapetable.h" +#include "trainingsample.h" +#include "trainingsampleset.h" +#include "unicharset.h" + +namespace tesseract { + +class ShapeClassifier; + +// Simple struct to hold the distance between two shapes during clustering. +struct ShapeDist { + ShapeDist() : shape1(0), shape2(0), distance(0.0f) {} + ShapeDist(int s1, int s2, float dist) + : shape1(s1), shape2(s2), distance(dist) {} + + // Sort operator to sort in ascending order of distance. + bool operator<(const ShapeDist& other) const { + return distance < other.distance; + } + + int shape1; + int shape2; + float distance; +}; + +// Class to encapsulate training processes that use the TrainingSampleSet. +// Initially supports shape clustering and mftrainining. +// Other important features of the MasterTrainer are conditioning the data +// by outlier elimination, replication with perturbation, and serialization. +class MasterTrainer { + public: + MasterTrainer(NormalizationMode norm_mode, bool shape_analysis, + bool replicate_samples, int debug_level); + ~MasterTrainer(); + + // Writes to the given file. Returns false in case of error. + bool Serialize(FILE* fp) const; + // Reads from the given file. Returns false in case of error. + // If swap is true, assumes a big/little-endian swap is needed. + bool DeSerialize(bool swap, FILE* fp); + + // Loads an initial unicharset, or sets one up if the file cannot be read. + void LoadUnicharset(const char* filename); + + // Sets the feature space definition. + void SetFeatureSpace(const IntFeatureSpace& fs) { + feature_space_ = fs; + feature_map_.Init(fs); + } + + // Reads the samples and their features from the given file, + // adding them to the trainer with the font_id from the content of the file. + // If verification, then these are verification samples, not training. + void ReadTrainingSamples(const char* page_name, + const FEATURE_DEFS_STRUCT& feature_defs, + bool verification); + + // Adds the given single sample to the trainer, setting the classid + // appropriately from the given unichar_str. + void AddSample(bool verification, const char* unichar_str, + TrainingSample* sample); + + // Loads all pages from the given tif filename and append to page_images_. + // Must be called after ReadTrainingSamples, as the current number of images + // is used as an offset for page numbers in the samples. + void LoadPageImages(const char* filename); + + // Cleans up the samples after initial load from the tr files, and prior to + // saving the MasterTrainer: + // Remaps fragmented chars if running shape anaylsis. + // Sets up the samples appropriately for class/fontwise access. + // Deletes outlier samples. + void PostLoadCleanup(); + + // Gets the samples ready for training. Use after both + // ReadTrainingSamples+PostLoadCleanup or DeSerialize. + // Re-indexes the features and computes canonical and cloud features. + void PreTrainingSetup(); + + // Sets up the master_shapes_ table, which tells which fonts should stay + // together until they get to a leaf node classifier. + void SetupMasterShapes(); + + // Adds the junk_samples_ to the main samples_ set. Junk samples are initially + // fragments and n-grams (all incorrectly segmented characters). + // Various training functions may result in incorrectly segmented characters + // being added to the unicharset of the main samples, perhaps because they + // form a "radical" decomposition of some (Indic) grapheme, or because they + // just look the same as a real character (like rn/m) + // This function moves all the junk samples, to the main samples_ set, but + // desirable junk, being any sample for which the unichar already exists in + // the samples_ unicharset gets the unichar-ids re-indexed to match, but + // anything else gets re-marked as unichar_id 0 (space character) to identify + // it as junk to the error counter. + void IncludeJunk(); + + // Replicates the samples and perturbs them if the enable_replication_ flag + // is set. MUST be used after the last call to OrganizeByFontAndClass on + // the training samples, ie after IncludeJunk if it is going to be used, as + // OrganizeByFontAndClass will eat the replicated samples into the regular + // samples. + void ReplicateAndRandomizeSamplesIfRequired(); + + // Loads the basic font properties file into fontinfo_table_. + // Returns false on failure. + bool LoadFontInfo(const char* filename); + + // Loads the xheight font properties file into xheights_. + // Returns false on failure. + bool LoadXHeights(const char* filename); + + // Reads spacing stats from filename and adds them to fontinfo_table. + // Returns false on failure. + bool AddSpacingInfo(const char *filename); + + // Returns the font id corresponding to the given font name. + // Returns -1 if the font cannot be found. + int GetFontInfoId(const char* font_name); + // Returns the font_id of the closest matching font name to the given + // filename. It is assumed that a substring of the filename will match + // one of the fonts. If more than one is matched, the longest is returned. + int GetBestMatchingFontInfoId(const char* filename); + + // Returns the filename of the tr file corresponding to the command-line + // argument with the given index. + const STRING& GetTRFileName(int index) const { + return tr_filenames_[index]; + } + + // Sets up a flat shapetable with one shape per class/font combination. + void SetupFlatShapeTable(ShapeTable* shape_table); + + // Sets up a Clusterer for mftraining on a single shape_id. + // Call FreeClusterer on the return value after use. + CLUSTERER* SetupForClustering(const ShapeTable& shape_table, + const FEATURE_DEFS_STRUCT& feature_defs, + int shape_id, int* num_samples); + + // Writes the given float_classes (produced by SetupForFloat2Int) as inttemp + // to the given inttemp_file, and the corresponding pffmtable. + // The unicharset is the original encoding of graphemes, and shape_set should + // match the size of the shape_table, and may possibly be totally fake. + void WriteInttempAndPFFMTable(const UNICHARSET& unicharset, + const UNICHARSET& shape_set, + const ShapeTable& shape_table, + CLASS_STRUCT* float_classes, + const char* inttemp_file, + const char* pffmtable_file); + + const UNICHARSET& unicharset() const { + return samples_.unicharset(); + } + TrainingSampleSet* GetSamples() { + return &samples_; + } + const ShapeTable& master_shapes() const { + return master_shapes_; + } + + // Generates debug output relating to the canonical distance between the + // two given UTF8 grapheme strings. + void DebugCanonical(const char* unichar_str1, const char* unichar_str2); + #ifndef GRAPHICS_DISABLED + // Debugging for cloud/canonical features. + // Displays a Features window containing: + // If unichar_str2 is in the unicharset, and canonical_font is non-negative, + // displays the canonical features of the char/font combination in red. + // If unichar_str1 is in the unicharset, and cloud_font is non-negative, + // displays the cloud feature of the char/font combination in green. + // The canonical features are drawn first to show which ones have no + // matches in the cloud features. + // Until the features window is destroyed, each click in the features window + // will display the samples that have that feature in a separate window. + void DisplaySamples(const char* unichar_str1, int cloud_font, + const char* unichar_str2, int canonical_font); + #endif // GRAPHICS_DISABLED + + void TestClassifierVOld(bool replicate_samples, + ShapeClassifier* test_classifier, + ShapeClassifier* old_classifier); + + // Tests the given test_classifier on the internal samples. + // See TestClassifier for details. + void TestClassifierOnSamples(CountTypes error_mode, + int report_level, + bool replicate_samples, + ShapeClassifier* test_classifier, + STRING* report_string); + // Tests the given test_classifier on the given samples + // error_mode indicates what counts as an error. + // report_levels: + // 0 = no output. + // 1 = bottom-line error rate. + // 2 = bottom-line error rate + time. + // 3 = font-level error rate + time. + // 4 = list of all errors + short classifier debug output on 16 errors. + // 5 = list of all errors + short classifier debug output on 25 errors. + // If replicate_samples is true, then the test is run on an extended test + // sample including replicated and systematically perturbed samples. + // If report_string is non-NULL, a summary of the results for each font + // is appended to the report_string. + double TestClassifier(CountTypes error_mode, + int report_level, + bool replicate_samples, + TrainingSampleSet* samples, + ShapeClassifier* test_classifier, + STRING* report_string); + + // Returns the average (in some sense) distance between the two given + // shapes, which may contain multiple fonts and/or unichars. + // This function is public to facilitate testing. + float ShapeDistance(const ShapeTable& shapes, int s1, int s2); + + private: + // Replaces samples that are always fragmented with the corresponding + // fragment samples. + void ReplaceFragmentedSamples(); + + // Runs a hierarchical agglomerative clustering to merge shapes in the given + // shape_table, while satisfying the given constraints: + // * End with at least min_shapes left in shape_table, + // * No shape shall have more than max_shape_unichars in it, + // * Don't merge shapes where the distance between them exceeds max_dist. + void ClusterShapes(int min_shapes, int max_shape_unichars, + float max_dist, ShapeTable* shape_table); + + private: + NormalizationMode norm_mode_; + // Character set we are training for. + UNICHARSET unicharset_; + // Original feature space. Subspace mapping is contained in feature_map_. + IntFeatureSpace feature_space_; + TrainingSampleSet samples_; + TrainingSampleSet junk_samples_; + TrainingSampleSet verify_samples_; + // Master shape table defines what fonts stay together until the leaves. + ShapeTable master_shapes_; + // Flat shape table has each unichar/font id pair in a separate shape. + ShapeTable flat_shapes_; + // Font metrics gathered from multiple files. + FontInfoTable fontinfo_table_; + // Array of xheights indexed by font ids in fontinfo_table_; + GenericVector xheights_; + + // Non-serialized data initialized by other means or used temporarily + // during loading of training samples. + // Number of different class labels in unicharset_. + int charsetsize_; + // Flag to indicate that we are running shape analysis and need fragments + // fixing. + bool enable_shape_anaylsis_; + // Flag to indicate that sample replication is required. + bool enable_replication_; + // Array of classids of fragments that replace the correctly segmented chars. + int* fragments_; + // Classid of previous correctly segmented sample that was added. + int prev_unichar_id_; + // Debug output control. + int debug_level_; + // Feature map used to construct reduced feature spaces for compact + // classifiers. + IntFeatureMap feature_map_; + // Vector of Pix pointers used for classifiers that need the image. + // Indexed by page_num_ in the samples. + // These images are owned by the trainer and need to be pixDestroyed. + GenericVector page_images_; + // Vector of filenames of loaded tr files. + GenericVector tr_filenames_; +}; + +} // namespace tesseract. + +#endif diff --git a/TesseractOCR/include/tesseract/matchdefs.h b/TesseractOCR/include/tesseract/matchdefs.h new file mode 100644 index 00000000..f0782792 --- /dev/null +++ b/TesseractOCR/include/tesseract/matchdefs.h @@ -0,0 +1,113 @@ +/****************************************************************************** + ** Filename: matchdefs.h + ** Purpose: Generic interface definitions for feature matchers. + ** Author: Dan Johnson + ** History: Fri Jan 19 09:21:25 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef MATCHDEFS_H +#define MATCHDEFS_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "host.h" +#include +#include "unichar.h" + +/* define the maximum number of classes defined for any matcher + and the maximum class id for any matcher. This must be changed + if more different classes need to be classified */ +#define MAX_NUM_CLASSES MAX_INT16 +#define MAX_CLASS_ID (MAX_NUM_CLASSES - 1) + +/** a CLASS_ID is the ascii character to be associated with a class */ +typedef UNICHAR_ID CLASS_ID; +#define NO_CLASS (0) + +/** a PROTO_ID is the index of a prototype within it's class. Valid proto + id's are 0 to N-1 where N is the number of prototypes that make up the + class. */ +typedef inT16 PROTO_ID; +#define NO_PROTO (-1) + +/** FEATURE_ID is the index of a feature within a character description + The feature id ranges from 0 to N-1 where N is the number + of features in a character description. */ +typedef uinT8 FEATURE_ID; +#define NO_FEATURE 255 +#define NOISE_FEATURE 254 +#define MISSING_PROTO 254 +#define MAX_NUM_FEAT 40 +#define MAX_FEATURE_ID 250 + +/** a RATING is the match rating returned by a classifier. + Higher is better. */ +typedef FLOAT32 RATING; + +/** a CERTAINTY is an indication of the degree of confidence of the + classifier. Higher is better. 0 means the match is as good as the + mean of the matches seen in training. -1 means the match was one + standard deviation worse than the training matches, etc. */ +typedef FLOAT32 CERTAINTY; + +/** define a data structure to hold a single match result */ +typedef struct +{ + CLASS_ID Class; + RATING Rating; + CERTAINTY Certainty; +} + + +MATCH_RESULT; + +/** define a data structure for holding an array of match results */ +typedef MATCH_RESULT SORTED_CLASSES[MAX_CLASS_ID + 1]; + +/*---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------*/ +/** + all feature matchers that are to be used with the high level + classifier must support the following interface. The names will, of + course, be unique for each different matcher. Note also that + FEATURE_STRUCT is a data structure that is defined specifically for + each feature extractor/matcher pair. +*/ + +/* misc test functions for proto id's and feature id's */ +#define IsValidFeature(Fid) ((Fid) < MAX_FEATURE_ID) +#define IsValidProto(Pid) ((Pid) >= 0) + +#if defined(__STDC__) || defined(__cplusplus) +# define _ARGS(s) s +#else +# define _ARGS(s) () +#endif + +/* matchdefs.c */ +int CompareMatchResults +_ARGS ((MATCH_RESULT * Result1, MATCH_RESULT * Result2)); + +void PrintMatchResult _ARGS ((FILE * File, MATCH_RESULT * MatchResult)); + +void PrintMatchResults +_ARGS ((FILE * File, int N, MATCH_RESULT MatchResults[])); + +#undef _ARGS + +/*---------------------------------------------------------------------------- + Global Data Definitions and Declarations +----------------------------------------------------------------------------*/ +#endif diff --git a/TesseractOCR/include/tesseract/mathfix.h b/TesseractOCR/include/tesseract/mathfix.h new file mode 100644 index 00000000..b0e7dd37 --- /dev/null +++ b/TesseractOCR/include/tesseract/mathfix.h @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////// +// File: mathfix.h +// Description: Implement missing math functions +// Author: zdenop +// Created: Fri Feb 03 06:45:06 CET 2012 +// +// (C) Copyright 2012, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef VS2008_INCLUDE_MATHFIX_H_ +#define VS2008_INCLUDE_MATHFIXT_H_ + +#ifndef _MSC_VER +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif + +#include +#include // for _isnan(), _finite() on VC++ +#define isnan(x) _isnan(x) +#define isinf(x) (!_finite(x)) +#define fmax max //VC++ does not implement all the provisions of C99 Standard +#define round(x) roundf(x) +inline float roundf(float num) { return num > 0 ? floorf(num + 0.5f) : ceilf(num - 0.5f); } + +#endif // VS2008_INCLUDE_MATHFIXT_H_ diff --git a/TesseractOCR/include/tesseract/matrix.h b/TesseractOCR/include/tesseract/matrix.h old mode 100755 new mode 100644 index 8b34711c..af240b07 --- a/TesseractOCR/include/tesseract/matrix.h +++ b/TesseractOCR/include/tesseract/matrix.h @@ -1,5 +1,5 @@ /* -*-C-*- - ******************************************************************************** + ****************************************************************************** * * File: matrix.h (Formerly matrix.h) * Description: Ratings matrix code. (Used by associator) @@ -25,18 +25,28 @@ #ifndef TESSERACT_CCSTRUCT_MATRIX_H__ #define TESSERACT_CCSTRUCT_MATRIX_H__ -#include "ratngs.h" +#include "kdpair.h" #include "unicharset.h" +class BLOB_CHOICE_LIST; + #define NOT_CLASSIFIED reinterpret_cast(NULL) -// A generic class to store a matrix with entries of type T. +// A generic class to hold a 2-D matrix with entries of type T, but can also +// act as a base class for other implementations, such as a triangular or +// banded matrix. template class GENERIC_2D_ARRAY { public: - // Allocate a piece of memory to hold a 2d-array of the given dimension. - // Initialize all the elements of the array to empty instead of assuming - // that a default constructor can be used. + // Initializes the array size, and empty element, but cannot allocate memory + // for the subclasses or initialize because calls to the num_elements + // member will be routed to the base class implementation. Subclasses can + // either pass the memory in, or allocate after by calling Resize(). + GENERIC_2D_ARRAY(int dim1, int dim2, const T& empty, T* array) + : empty_(empty), dim1_(dim1), dim2_(dim2), array_(array) { + } + // Original constructor for a full rectangular matrix DOES allocate memory + // and initialize it to empty. GENERIC_2D_ARRAY(int dim1, int dim2, const T& empty) : empty_(empty), dim1_(dim1), dim2_(dim2) { array_ = new T[dim1_ * dim2_]; @@ -44,26 +54,67 @@ class GENERIC_2D_ARRAY { for (int y = 0; y < dim2_; y++) this->put(x, y, empty_); } - ~GENERIC_2D_ARRAY() { delete[] array_; } + virtual ~GENERIC_2D_ARRAY() { delete[] array_; } + + // Reallocate the array to the given size. Does not keep old data. + void Resize(int size1, int size2, const T& empty) { + empty_ = empty; + if (size1 != dim1_ || size2 != dim2_) { + dim1_ = size1; + dim2_ = size2; + delete [] array_; + array_ = new T[dim1_ * dim2_]; + } + Clear(); + } + + // Reallocate the array to the given size, keeping old data. + void ResizeWithCopy(int size1, int size2) { + if (size1 != dim1_ || size2 != dim2_) { + T* new_array = new T[size1 * size2]; + for (int col = 0; col < size1; ++col) { + for (int row = 0; row < size2; ++row) { + int old_index = col * dim2() + row; + int new_index = col * size2 + row; + if (col < dim1_ && row < dim2_) { + new_array[new_index] = array_[old_index]; + } else { + new_array[new_index] = empty_; + } + } + } + delete[] array_; + array_ = new_array; + dim1_ = size1; + dim2_ = size2; + } + } + + // Sets all the elements of the array to the empty value. + void Clear() { + int total_size = num_elements(); + for (int i = 0; i < total_size; ++i) + array_[i] = empty_; + } // Writes to the given file. Returns false in case of error. // Only works with bitwise-serializeable types! bool Serialize(FILE* fp) const { if (!SerializeSize(fp)) return false; if (fwrite(&empty_, sizeof(empty_), 1, fp) != 1) return false; - int size = dim1_ * dim2_; + int size = num_elements(); if (fwrite(array_, sizeof(*array_), size, fp) != size) return false; return true; } // Reads from the given file. Returns false in case of error. - // Only works with bitwise-serializeable types! + // Only works with bitwise-serializeable typ // If swap is true, assumes a big/little-endian swap is needed. bool DeSerialize(bool swap, FILE* fp) { if (!DeSerializeSize(swap, fp)) return false; if (fread(&empty_, sizeof(empty_), 1, fp) != 1) return false; if (swap) ReverseN(&empty_, sizeof(empty_)); - int size = dim1_ * dim2_; + int size = num_elements(); if (fread(array_, sizeof(*array_), size, fp) != size) return false; if (swap) { for (int i = 0; i < size; ++i) @@ -77,7 +128,7 @@ class GENERIC_2D_ARRAY { bool SerializeClasses(FILE* fp) const { if (!SerializeSize(fp)) return false; if (!empty_.Serialize(fp)) return false; - int size = dim1_ * dim2_; + int size = num_elements(); for (int i = 0; i < size; ++i) { if (!array_[i].Serialize(fp)) return false; } @@ -90,7 +141,7 @@ class GENERIC_2D_ARRAY { bool DeSerializeClasses(bool swap, FILE* fp) { if (!DeSerializeSize(swap, fp)) return false; if (!empty_.DeSerialize(swap, fp)) return false; - int size = dim1_ * dim2_; + int size = num_elements(); for (int i = 0; i < size; ++i) { if (!array_[i].DeSerialize(swap, fp)) return false; } @@ -100,11 +151,14 @@ class GENERIC_2D_ARRAY { // Provide the dimensions of this rectangular matrix. int dim1() const { return dim1_; } int dim2() const { return dim2_; } + // Returns the number of elements in the array. + // Banded/triangular matrices may override. + virtual int num_elements() const { return dim1_ * dim2_; } // Expression to select a specific location in the matrix. The matrix is // stored COLUMN-major, so the left-most index is the most significant. // This allows [][] access to use indices in the same order as (,). - int index(int column, int row) const { + virtual int index(int column, int row) const { return (column * dim2_ + row); } @@ -129,19 +183,21 @@ class GENERIC_2D_ARRAY { T* operator[](int column) { return &array_[this->index(column, 0)]; } + const T* operator[](int column) const { + return &array_[this->index(column, 0)]; + } // Delete objects pointed to by array_[i]. void delete_matrix_pointers() { - for (int x = 0; x < dim1_; x++) { - for (int y = 0; y < dim2_; y++) { - T matrix_cell = this->get(x, y); - if (matrix_cell != empty_) - delete matrix_cell; - } + int size = num_elements(); + for (int i = 0; i < size; ++i) { + T matrix_cell = array_[i]; + if (matrix_cell != empty_) + delete matrix_cell; } } - private: + protected: // Factored helper to serialize the size. bool SerializeSize(FILE* fp) const { inT32 size = dim1_; @@ -160,12 +216,7 @@ class GENERIC_2D_ARRAY { ReverseN(&size1, sizeof(size1)); ReverseN(&size2, sizeof(size2)); } - if (size1 != dim1_ || size2 != dim2_) { - dim1_ = size1; - dim2_ = size2; - delete [] array_; - array_ = new T[dim1_ * dim2_]; - } + Resize(size1, size2, empty_); return true; } @@ -175,25 +226,90 @@ class GENERIC_2D_ARRAY { int dim2_; // Size of the 2nd dimension in indexing functions. }; -// A generic class to store a square matrix with entries of type T. +// A generic class to store a banded triangular matrix with entries of type T. +// In this array, the nominally square matrix is dim1_ x dim1_, and dim2_ is +// the number of bands, INCLUDING the diagonal. The storage is thus of size +// dim1_ * dim2_ and index(col, row) = col * dim2_ + row - col, and an +// assert will fail if row < col or row - col >= dim2. template -class GENERIC_MATRIX : public GENERIC_2D_ARRAY { +class BandTriMatrix : public GENERIC_2D_ARRAY { public: - // Allocate a piece of memory to hold a matrix of the given dimension. - // Initialize all the elements of the matrix to empty instead of assuming + // Allocate a piece of memory to hold a 2d-array of the given dimension. + // Initialize all the elements of the array to empty instead of assuming // that a default constructor can be used. - GENERIC_MATRIX(int dimension, const T& empty) - : GENERIC_2D_ARRAY(dimension, dimension, empty) { + BandTriMatrix(int dim1, int dim2, const T& empty) + : GENERIC_2D_ARRAY(dim1, dim2, empty) { + } + // The default destructor will do. + + // Provide the dimensions of this matrix. + // dimension is the size of the nominally square matrix. + int dimension() const { return this->dim1_; } + // bandwidth is the number of bands in the matrix, INCLUDING the diagonal. + int bandwidth() const { return this->dim2_; } + + // Expression to select a specific location in the matrix. The matrix is + // stored COLUMN-major, so the left-most index is the most significant. + // This allows [][] access to use indices in the same order as (,). + virtual int index(int column, int row) const { + ASSERT_HOST(row >= column); + ASSERT_HOST(row - column < this->dim2_); + return column * this->dim2_ + row - column; } - // Provide the dimension of this square matrix. - int dimension() const { return this->dim1(); } + // Appends array2 corner-to-corner to *this, making an array of dimension + // equal to the sum of the individual dimensions. + // array2 is not destroyed, but is left empty, as all elements are moved + // to *this. + void AttachOnCorner(BandTriMatrix* array2) { + int new_dim1 = this->dim1_ + array2->dim1_; + int new_dim2 = MAX(this->dim2_, array2->dim2_); + T* new_array = new T[new_dim1 * new_dim2]; + for (int col = 0; col < new_dim1; ++col) { + for (int j = 0; j < new_dim2; ++j) { + int new_index = col * new_dim2 + j; + if (col < this->dim1_ && j < this->dim2_) { + new_array[new_index] = this->get(col, col + j); + } else if (col >= this->dim1_ && j < array2->dim2_) { + new_array[new_index] = array2->get(col - this->dim1_, + col - this->dim1_ + j); + array2->put(col - this->dim1_, col - this->dim1_ + j, NULL); + } else { + new_array[new_index] = this->empty_; + } + } + } + delete[] this->array_; + this->array_ = new_array; + this->dim1_ = new_dim1; + this->dim2_ = new_dim2; + } }; -class MATRIX : public GENERIC_MATRIX { +class MATRIX : public BandTriMatrix { public: - MATRIX(int dimension) : GENERIC_MATRIX(dimension, - NOT_CLASSIFIED) {} + MATRIX(int dimension, int bandwidth) + : BandTriMatrix(dimension, bandwidth, NOT_CLASSIFIED) {} + + // Returns true if there are any real classification results. + bool Classified(int col, int row, int wildcard_id) const; + + // Expands the existing matrix in-place to make the band wider, without + // losing any existing data. + void IncreaseBandSize(int bandwidth); + + // Returns a bigger MATRIX with a new column and row in the matrix in order + // to split the blob at the given (ind,ind) diagonal location. + // Entries are relocated to the new MATRIX using the transformation defined + // by MATRIX_COORD::MapForSplit. + // Transfers the pointer data to the new MATRIX and deletes *this. + MATRIX* ConsumeAndMakeBigger(int ind); + + // Makes and returns a deep copy of *this, including all the BLOB_CHOICEs + // on the lists, but not any LanguageModelState that may be attached to the + // BLOB_CHOICEs. + MATRIX* DeepCopy() const; + // Print a shortened version of the contents of the matrix. void print(const UNICHARSET &unicharset) const; }; @@ -203,14 +319,34 @@ struct MATRIX_COORD { MATRIX_COORD *c = static_cast(arg); delete c; } + // Default constructor required by GenericHeap. + MATRIX_COORD() : col(0), row(0) {} MATRIX_COORD(int c, int r): col(c), row(r) {} ~MATRIX_COORD() {} + bool Valid(const MATRIX &m) const { - return (col >= 0 && row >= 0 && - col < m.dimension() && row < m.dimension()); + return 0 <= col && col < m.dimension() && + col <= row && row < col + m.bandwidth() && row < m.dimension(); + } + + // Remaps the col,row pair to split the blob at the given (ind,ind) diagonal + // location. + // Entries at (i,j) for i in [0,ind] and j in [ind,dim) move to (i,j+1), + // making a new row at ind. + // Entries at (i,j) for i in [ind+1,dim) and j in [i,dim) move to (i+i,j+1), + // making a new column at ind+1. + void MapForSplit(int ind) { + ASSERT_HOST(row >= col); + if (col > ind) ++col; + if (row >= ind) ++row; + ASSERT_HOST(row >= col); } + int col; int row; }; +// The MatrixCoordPair contains a MATRIX_COORD and its priority. +typedef tesseract::KDPairInc MatrixCoordPair; + #endif // TESSERACT_CCSTRUCT_MATRIX_H__ diff --git a/TesseractOCR/include/tesseract/measure.h b/TesseractOCR/include/tesseract/measure.h new file mode 100644 index 00000000..978932ae --- /dev/null +++ b/TesseractOCR/include/tesseract/measure.h @@ -0,0 +1,135 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: measure.h (Formerly measure.h) + * Description: Statistics for a group of single measurements + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Mon Apr 8 09:42:28 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + ******************************************************************************** + */ + +#ifndef MEASURE_H +#define MEASURE_H + +/* +---------------------------------------------------------------------- + I n c l u d e s +---------------------------------------------------------------------- +*/ + +#include + +/* +---------------------------------------------------------------------- + T y p e s +---------------------------------------------------------------------- +*/ + +typedef struct +{ + long num_samples; + float sum_of_samples; + float sum_of_squares; +} MEASUREMENT; + +/* +---------------------------------------------------------------------- + M a c r o s +---------------------------------------------------------------------- +*/ + +/********************************************************************** + * add_sample + * + * Add one more sample to a measurement. + **********************************************************************/ + +#define ADD_SAMPLE(m,s) \ +(m.sum_of_samples += (float) (s), \ + m.sum_of_squares += (float) (s) * (float) (s), \ + ++m.num_samples) + +/********************************************************************** + * mean + * + * Return the mean value of the measurement. + **********************************************************************/ + +#define MEAN(m) \ +((m).num_samples ? \ + ((float) ((m).sum_of_samples / (m).num_samples)) : \ + 0) + +/********************************************************************** + * new_measurement + * + * Initalize a record to hold a measurement of a group of individual + * samples. + **********************************************************************/ + +#define new_measurement(m) \ +((m).num_samples = 0, \ + (m).sum_of_samples = 0, \ + (m).sum_of_squares = 0) + +/********************************************************************** + * number_of_samples + * + * Return the number of samples in a measurement. + **********************************************************************/ + +#define number_of_samples(m) \ +((m).num_samples) + +/********************************************************************** + * standard_deviation + * + * Return the standard deviation of the measurement. + **********************************************************************/ + +#define standard_deviation(m) \ +((float) sqrt (VARIANCE (m))) + +/********************************************************************** + * variance + * + * Return the variance of the measurement. + **********************************************************************/ + +#define VARIANCE(m) \ +(((m).num_samples > 1) ? \ + ((float) \ + (((m).num_samples * (m).sum_of_squares - \ + (m).sum_of_samples * (m).sum_of_samples) / \ + (((m).num_samples - 1) * (m).num_samples))) : \ + 0) + +/********************************************************************** + * print_summary + * + * Summarize a MEASUREMENT record. + **********************************************************************/ + +#define print_summary(string,measure) \ +cprintf ("\t%-20s \tn = %d, \tm = %4.2f, \ts = %4.2f\n ", \ + string, \ + number_of_samples (measure), \ + MEAN (measure), \ + standard_deviation (measure)) +#endif diff --git a/TesseractOCR/include/tesseract/memry.h b/TesseractOCR/include/tesseract/memry.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/mergenf.h b/TesseractOCR/include/tesseract/mergenf.h new file mode 100644 index 00000000..d0920a63 --- /dev/null +++ b/TesseractOCR/include/tesseract/mergenf.h @@ -0,0 +1,97 @@ +/****************************************************************************** +** Filename: MergeNF.c +** Purpose: Program for merging similar nano-feature protos +** Author: Dan Johnson +** History: Wed Nov 21 09:55:23 1990, DSJ, Created. +** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. +******************************************************************************/ +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "protos.h" +#include "cluster.h" +#include "ocrfeatures.h" +#include "callcpp.h" +#include "picofeat.h" + + +#define WORST_MATCH_ALLOWED (0.9) +#define WORST_EVIDENCE (1.0) +#define MAX_LENGTH_MISMATCH (2.0 * GetPicoFeatureLength ()) + + +#define PROTO_SUFFIX ".mf.p" +#define CONFIG_SUFFIX ".cl" +#define NO_PROTO (-1) +#define XPOSITION 0 +#define YPOSITION 1 +#define MFLENGTH 2 +#define ORIENTATION 3 + +typedef struct +{ + FLOAT32 MinX, MaxX, MinY, MaxY; +} FRECT; + +/**---------------------------------------------------------------------------- + Public Macros +----------------------------------------------------------------------------**/ +#define CenterX(M) ( (M)[XPOSITION] ) +#define CenterY(M) ( (M)[YPOSITION] ) +#define LengthOf(M) ( (M)[MFLENGTH] ) +#define OrientationOf(M) ( (M)[ORIENTATION] ) + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +FLOAT32 CompareProtos ( + PROTO p1, + PROTO p2); + +void ComputeMergedProto ( + PROTO p1, + PROTO p2, + FLOAT32 w1, + FLOAT32 w2, + PROTO MergedProto); + +int FindClosestExistingProto ( + CLASS_TYPE Class, + int NumMerged[], + PROTOTYPE *Prototype); + +void MakeNewFromOld ( + PROTO New, + PROTOTYPE *Old); + +FLOAT32 SubfeatureEvidence ( + FEATURE Feature, + PROTO Proto); + +double EvidenceOf ( + register double Similarity); + +BOOL8 DummyFastMatch ( + FEATURE Feature, + PROTO Proto); + +void ComputePaddedBoundingBox ( + PROTO Proto, + FLOAT32 TangentPad, + FLOAT32 OrthogonalPad, + FRECT *BoundingBox); + +BOOL8 PointInside ( + FRECT *Rectangle, + FLOAT32 X, + FLOAT32 Y); diff --git a/TesseractOCR/include/tesseract/mf.h b/TesseractOCR/include/tesseract/mf.h new file mode 100644 index 00000000..716f5b8c --- /dev/null +++ b/TesseractOCR/include/tesseract/mf.h @@ -0,0 +1,41 @@ +/****************************************************************************** + ** Filename: mf.h + ** Purpose: Micro-feature interface to flexible feature extractor. + ** Author: Dan Johnson + ** History: Thu May 24 09:39:56 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef MF_H +#define MF_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "ocrfeatures.h" +#include "blobs.h" + +typedef enum { + MFXPosition, MFYPosition, + MFLength, MFDirection, MFBulge1, MFBulge2, + MFCount // For array sizes. +} MF_PARAM_NAME; + +typedef float MicroFeature[MFCount]; +/*---------------------------------------------------------------------------- + Private Function Prototypes +-----------------------------------------------------------------------------*/ +FEATURE_SET ExtractMicros(TBLOB *Blob, const DENORM& bl_denorm, + const DENORM& cn_denorm, + const INT_FX_RESULT_STRUCT& fx_info); + +#endif diff --git a/TesseractOCR/include/tesseract/mfcpch.h b/TesseractOCR/include/tesseract/mfcpch.h deleted file mode 100755 index 52cccd83..00000000 --- a/TesseractOCR/include/tesseract/mfcpch.h +++ /dev/null @@ -1,37 +0,0 @@ -// mfcpch.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// -// For Unix and mac the file does nothing. It needs to be included in all cpp -// files for compatibility with the PC pre-compiled header mechanism. -#ifdef _WIN32 -#ifndef _AFXDLL -#define WIN32_LEAN_AND_MEAN -#define STRICT 1 -//#include -#include -#else -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers - -#include // mfc core and standard components -#include // mfc extensions - -#ifndef _AFX_NO_OLE_SUPPORT -#include // mfc ole classes -#include // mfc ole dialog classes -#include // mfc ole automation classes -#endif // _AFX_NO_OLE_SUPPORT - -#ifndef _AFX_NO_DB_SUPPORT -#include // mfc odbc database classes -#endif // _AFX_NO_DB_SUPPORT - -#ifndef _AFX_NO_DAO_SUPPORT -#include // mfc dao database classes -#endif // _AFX_NO_DAO_SUPPORT - -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // mfc support for windows 95 common controls -#endif // _AFX_NO_AFXCMN_SUPPORT -#endif -#endif diff --git a/TesseractOCR/include/tesseract/mfdefs.h b/TesseractOCR/include/tesseract/mfdefs.h new file mode 100644 index 00000000..6202a174 --- /dev/null +++ b/TesseractOCR/include/tesseract/mfdefs.h @@ -0,0 +1,57 @@ +/****************************************************************************** + ** Filename: mfdefs.h + ** Purpose: Definition of micro-features + ** Author: Dan Johnson + ** History: Mon Jan 22 08:42:13 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef MFDEFS_H +#define MFDEFS_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "oldlist.h" +#include "matchdefs.h" +#include "xform2d.h" + +/* definition of a list of micro-features */ +typedef LIST MICROFEATURES; + +/* definition of structure of micro-features */ +#define MFSIZE 6 +typedef FLOAT32 MFBLOCK[MFSIZE]; +typedef FLOAT32 *MICROFEATURE; + +/* definitions of individual micro-feature parameters */ +#define XPOSITION 0 +#define YPOSITION 1 +#define MFLENGTH 2 +#define ORIENTATION 3 +#define FIRSTBULGE 4 +#define SECONDBULGE 5 + +/**---------------------------------------------------------------------------- + Macros +----------------------------------------------------------------------------**/ + +/* macros for accessing micro-feature lists */ +#define NextFeatureOf(L) ( (MICROFEATURE) first_node ( L ) ) + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +MICROFEATURE NewMicroFeature(); + +void FreeMicroFeatures(MICROFEATURES MicroFeatures); +#endif diff --git a/TesseractOCR/include/tesseract/mfoutline.h b/TesseractOCR/include/tesseract/mfoutline.h new file mode 100644 index 00000000..bdf20f37 --- /dev/null +++ b/TesseractOCR/include/tesseract/mfoutline.h @@ -0,0 +1,142 @@ +/****************************************************************************** + ** Filename: mfoutline.h + ** Purpose: Interface spec for fx outline structures + ** Author: Dan Johnson + ** History: Thu May 17 08:55:32 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef MFOUTLINE_H +#define MFOUTLINE_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "blobs.h" +#include "host.h" +#include "oldlist.h" +#include "fpoint.h" +#include "params.h" + +#define NORMAL_X_HEIGHT (0.5) +#define NORMAL_BASELINE (0.0) + +typedef LIST MFOUTLINE; + +typedef enum { + north, south, east, west, northeast, northwest, southeast, southwest +} DIRECTION; + +typedef struct { + FPOINT Point; + FLOAT32 Slope; + unsigned Padding:20; + BOOL8 Hidden:TRUE; + BOOL8 ExtremityMark:TRUE; + DIRECTION Direction:4; + DIRECTION PreviousDirection:4; +} MFEDGEPT; + +typedef enum { + outer, hole +} OUTLINETYPE; + +typedef struct { + FLOAT64 Mx, My; /* first moment of all outlines */ + FLOAT64 L; /* total length of all outlines */ + FLOAT64 x, y; /* center of mass of all outlines */ + FLOAT64 Ix, Iy; /* second moments about center of mass axes */ + FLOAT64 Rx, Ry; /* radius of gyration about center of mass axes */ +} OUTLINE_STATS; + +typedef enum { + baseline, character +} NORM_METHOD; + +/**---------------------------------------------------------------------------- + Macros +----------------------------------------------------------------------------**/ +#define AverageOf(A,B) (((A) + (B)) / 2) + +/* macro for computing the scale factor to use to normalize characters */ +#define MF_SCALE_FACTOR (NORMAL_X_HEIGHT / kBlnXHeight) + +/* macros for manipulating micro-feature outlines */ +#define DegenerateOutline(O) (((O) == NIL_LIST) || ((O) == list_rest(O))) +#define PointAt(O) ((MFEDGEPT *) first_node (O)) +#define NextPointAfter(E) (list_rest (E)) +#define MakeOutlineCircular(O) (set_rest (last (O), (O))) + +/* macros for manipulating micro-feature outline edge points */ +#define ClearMark(P) ((P)->ExtremityMark = FALSE) +#define MarkPoint(P) ((P)->ExtremityMark = TRUE) + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +void ComputeBlobCenter(TBLOB *Blob, TPOINT *BlobCenter); + +LIST ConvertBlob(TBLOB *Blob); + +MFOUTLINE ConvertOutline(TESSLINE *Outline); + +LIST ConvertOutlines(TESSLINE *Outline, + LIST ConvertedOutlines, + OUTLINETYPE OutlineType); + +void FilterEdgeNoise(MFOUTLINE Outline, FLOAT32 NoiseSegmentLength); + +void FindDirectionChanges(MFOUTLINE Outline, + FLOAT32 MinSlope, + FLOAT32 MaxSlope); + +void FreeMFOutline(void *agr); //MFOUTLINE Outline); + +void FreeOutlines(LIST Outlines); + +void MarkDirectionChanges(MFOUTLINE Outline); + +MFEDGEPT *NewEdgePoint(); + +MFOUTLINE NextExtremity(MFOUTLINE EdgePoint); + +void NormalizeOutline(MFOUTLINE Outline, + FLOAT32 XOrigin); + +/*---------------------------------------------------------------------------- + Private Function Prototypes +-----------------------------------------------------------------------------*/ +void ChangeDirection(MFOUTLINE Start, MFOUTLINE End, DIRECTION Direction); + +// Normalizes the Outline in-place using cn_denorm's local transformation, +// then converts from the integer feature range [0,255] to the clusterer +// feature range of [-0.5, 0.5]. +void CharNormalizeOutline(MFOUTLINE Outline, const DENORM& cn_denorm); + +void ComputeDirection(MFEDGEPT *Start, + MFEDGEPT *Finish, + FLOAT32 MinSlope, + FLOAT32 MaxSlope); + +void FinishOutlineStats(register OUTLINE_STATS *OutlineStats); + +void InitOutlineStats(OUTLINE_STATS *OutlineStats); + +MFOUTLINE NextDirectionChange(MFOUTLINE EdgePoint); + +void UpdateOutlineStats(register OUTLINE_STATS *OutlineStats, + register FLOAT32 x1, + register FLOAT32 x2, + register FLOAT32 y1, + register FLOAT32 y2); + +#endif diff --git a/TesseractOCR/include/tesseract/mfx.h b/TesseractOCR/include/tesseract/mfx.h new file mode 100644 index 00000000..7e7fe1cf --- /dev/null +++ b/TesseractOCR/include/tesseract/mfx.h @@ -0,0 +1,42 @@ +/****************************************************************************** + ** Filename: mfx.h + ** Purpose: Definition of micro-feature extraction routines + ** Author: Dan Johnson + ** History: 5/29/89, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef MFX_H +#define MFX_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "params.h" +/**---------------------------------------------------------------------------- + Variables +----------------------------------------------------------------------------**/ + +/* old numbers corresponded to 10.0 degrees and 80.0 degrees */ +extern double_VAR_H(classify_min_slope, 0.414213562, + "Slope below which lines are called horizontal"); +extern double_VAR_H(classify_max_slope, 2.414213562, + "Slope above which lines are called vertical"); + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +CHAR_FEATURES BlobMicroFeatures(TBLOB *Blob, const DENORM& bl_denorm, + const DENORM& cn_denorm, + const INT_FX_RESULT_STRUCT& fx_info); + +#endif diff --git a/TesseractOCR/include/tesseract/mod128.h b/TesseractOCR/include/tesseract/mod128.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/mutableiterator.h b/TesseractOCR/include/tesseract/mutableiterator.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/ndminx.h b/TesseractOCR/include/tesseract/ndminx.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/neural_net.h b/TesseractOCR/include/tesseract/neural_net.h new file mode 100644 index 00000000..91d0d68a --- /dev/null +++ b/TesseractOCR/include/tesseract/neural_net.h @@ -0,0 +1,246 @@ +// Copyright 2008 Google Inc. +// All Rights Reserved. +// Author: ahmadab@google.com (Ahmad Abdulkader) +// +// neural_net.h: Declarations of a class for an object that +// represents an arbitrary network of neurons +// + +#ifndef NEURAL_NET_H +#define NEURAL_NET_H + +#include +#include +#include "neuron.h" +#include "input_file_buffer.h" + +namespace tesseract { + +// Minimum input range below which we set the input weight to zero +static const float kMinInputRange = 1e-6f; + +class NeuralNet { + public: + NeuralNet(); + virtual ~NeuralNet(); + // create a net object from a file. Uses stdio + static NeuralNet *FromFile(const string file_name); + // create a net object from an input buffer + static NeuralNet *FromInputBuffer(InputFileBuffer *ib); + // Different flavors of feed forward function + template bool FeedForward(const Type *inputs, + Type *outputs); + // Compute the output of a specific output node. + // This function is useful for application that are interested in a single + // output of the net and do not want to waste time on the rest + template bool GetNetOutput(const Type *inputs, + int output_id, + Type *output); + // Accessor functions + int in_cnt() const { return in_cnt_; } + int out_cnt() const { return out_cnt_; } + + protected: + struct Node; + // A node-weight pair + struct WeightedNode { + Node *input_node; + float input_weight; + }; + // node struct used for fast feedforward in + // Read only nets + struct Node { + float out; + float bias; + int fan_in_cnt; + WeightedNode *inputs; + }; + // Read-Only flag (no training: On by default) + // will presumeably be set to false by + // the inherting TrainableNeuralNet class + bool read_only_; + // input count + int in_cnt_; + // output count + int out_cnt_; + // Total neuron count (including inputs) + int neuron_cnt_; + // count of unique weights + int wts_cnt_; + // Neuron vector + Neuron *neurons_; + // size of allocated weight chunk (in weights) + // This is basically the size of the biggest network + // that I have trained. However, the class will allow + // a bigger sized net if desired + static const int kWgtChunkSize = 0x10000; + // Magic number expected at the beginning of the NN + // binary file + static const unsigned int kNetSignature = 0xFEFEABD0; + // count of allocated wgts in the last chunk + int alloc_wgt_cnt_; + // vector of weights buffers + vector *>wts_vec_; + // Is the net an auto-encoder type + bool auto_encoder_; + // vector of input max values + vector inputs_max_; + // vector of input min values + vector inputs_min_; + // vector of input mean values + vector inputs_mean_; + // vector of input standard deviation values + vector inputs_std_dev_; + // vector of input offsets used by fast read-only + // feedforward function + vector fast_nodes_; + // Network Initialization function + void Init(); + // Clears all neurons + void Clear() { + for (int node = 0; node < neuron_cnt_; node++) { + neurons_[node].Clear(); + } + } + // Reads the net from an input buffer + template bool ReadBinary(ReadBuffType *input_buff) { + // Init vars + Init(); + // is this an autoencoder + unsigned int read_val; + unsigned int auto_encode; + // read and verify signature + if (input_buff->Read(&read_val, sizeof(read_val)) != sizeof(read_val)) { + return false; + } + if (read_val != kNetSignature) { + return false; + } + if (input_buff->Read(&auto_encode, sizeof(auto_encode)) != + sizeof(auto_encode)) { + return false; + } + auto_encoder_ = auto_encode; + // read and validate total # of nodes + if (input_buff->Read(&read_val, sizeof(read_val)) != sizeof(read_val)) { + return false; + } + neuron_cnt_ = read_val; + if (neuron_cnt_ <= 0) { + return false; + } + // set the size of the neurons vector + neurons_ = new Neuron[neuron_cnt_]; + if (neurons_ == NULL) { + return false; + } + // read & validate inputs + if (input_buff->Read(&read_val, sizeof(read_val)) != sizeof(read_val)) { + return false; + } + in_cnt_ = read_val; + if (in_cnt_ <= 0) { + return false; + } + // read outputs + if (input_buff->Read(&read_val, sizeof(read_val)) != sizeof(read_val)) { + return false; + } + out_cnt_ = read_val; + if (out_cnt_ <= 0) { + return false; + } + // set neuron ids and types + for (int idx = 0; idx < neuron_cnt_; idx++) { + neurons_[idx].set_id(idx); + // input type + if (idx < in_cnt_) { + neurons_[idx].set_node_type(Neuron::Input); + } else if (idx >= (neuron_cnt_ - out_cnt_)) { + neurons_[idx].set_node_type(Neuron::Output); + } else { + neurons_[idx].set_node_type(Neuron::Hidden); + } + } + // read the connections + for (int node_idx = 0; node_idx < neuron_cnt_; node_idx++) { + // read fanout + if (input_buff->Read(&read_val, sizeof(read_val)) != sizeof(read_val)) { + return false; + } + // read the neuron's info + int fan_out_cnt = read_val; + for (int fan_out_idx = 0; fan_out_idx < fan_out_cnt; fan_out_idx++) { + // read the neuron id + if (input_buff->Read(&read_val, sizeof(read_val)) != sizeof(read_val)) { + return false; + } + // create the connection + if (!SetConnection(node_idx, read_val)) { + return false; + } + } + } + // read all the neurons' fan-in connections + for (int node_idx = 0; node_idx < neuron_cnt_; node_idx++) { + // read + if (!neurons_[node_idx].ReadBinary(input_buff)) { + return false; + } + } + // size input stats vector to expected input size + inputs_mean_.resize(in_cnt_); + inputs_std_dev_.resize(in_cnt_); + inputs_min_.resize(in_cnt_); + inputs_max_.resize(in_cnt_); + // read stats + if (input_buff->Read(&(inputs_mean_.front()), + sizeof(inputs_mean_[0]) * in_cnt_) != + sizeof(inputs_mean_[0]) * in_cnt_) { + return false; + } + if (input_buff->Read(&(inputs_std_dev_.front()), + sizeof(inputs_std_dev_[0]) * in_cnt_) != + sizeof(inputs_std_dev_[0]) * in_cnt_) { + return false; + } + if (input_buff->Read(&(inputs_min_.front()), + sizeof(inputs_min_[0]) * in_cnt_) != + sizeof(inputs_min_[0]) * in_cnt_) { + return false; + } + if (input_buff->Read(&(inputs_max_.front()), + sizeof(inputs_max_[0]) * in_cnt_) != + sizeof(inputs_max_[0]) * in_cnt_) { + return false; + } + // create a readonly version for fast feedforward + if (read_only_) { + return CreateFastNet(); + } + return true; + } + + // creates a connection between two nodes + bool SetConnection(int from, int to); + // Create a read only version of the net that + // has faster feedforward performance + bool CreateFastNet(); + // internal function to allocate a new set of weights + // Centralized weight allocation attempts to increase + // weights locality of reference making it more cache friendly + float *AllocWgt(int wgt_cnt); + // different flavors read-only feedforward function + template bool FastFeedForward(const Type *inputs, + Type *outputs); + // Compute the output of a specific output node. + // This function is useful for application that are interested in a single + // output of the net and do not want to waste time on the rest + // This is the fast-read-only version of this function + template bool FastGetNetOutput(const Type *inputs, + int output_id, + Type *output); +}; +} + +#endif // NEURAL_NET_H__ diff --git a/TesseractOCR/include/tesseract/neuron.h b/TesseractOCR/include/tesseract/neuron.h new file mode 100644 index 00000000..a13d4a2e --- /dev/null +++ b/TesseractOCR/include/tesseract/neuron.h @@ -0,0 +1,147 @@ +// Copyright 2008 Google Inc. +// All Rights Reserved. +// Author: ahmadab@google.com (Ahmad Abdulkader) +// +// neuron.h: Declarations of a class for an object that +// represents a single neuron in a neural network +// + +#ifndef NEURON_H +#define NEURON_H + +#include +#include + +#ifdef USE_STD_NAMESPACE +using std::vector; +#endif + +namespace tesseract { + +// Input Node bias values +static const float kInputNodeBias = 0.0f; + +class Neuron { + public: + // Types of nodes + enum NeuronTypes { + Unknown = 0, + Input, + Hidden, + Output + }; + Neuron(); + ~Neuron(); + // set the forward dirty flag indicating that the + // activation of the net is not fresh + void Clear() { + frwd_dirty_ = true; + } + // Read a binary representation of the neuron info from + // an input buffer. + template bool ReadBinary(BuffType *input_buff) { + float val; + if (input_buff->Read(&val, sizeof(val)) != sizeof(val)) { + return false; + } + // input nodes should have no biases + if (node_type_ == Input) { + bias_ = kInputNodeBias; + } else { + bias_ = val; + } + // read fanin count + int fan_in_cnt; + if (input_buff->Read(&fan_in_cnt, sizeof(fan_in_cnt)) != + sizeof(fan_in_cnt)) { + return false; + } + // validate fan-in cnt + if (fan_in_cnt != fan_in_.size()) { + return false; + } + // read the weights + for (int in = 0; in < fan_in_cnt; in++) { + if (input_buff->Read(&val, sizeof(val)) != sizeof(val)) { + return false; + } + *(fan_in_weights_[in]) = val; + } + return true; + } + + // Add a new connection from this neuron *From* + // a target neuron using specfied params + // Note that what is actually copied in this function are pointers to the + // specified Neurons and weights and not the actualt values. This is by + // design to centralize the alloction of neurons and weights and so + // increase the locality of reference and improve cache-hits resulting + // in a faster net. This technique resulted in a 2X-10X speedup + // (depending on network size and processor) + void AddFromConnection(Neuron *neuron_vec, + float *wts_offset, + int from_cnt); + // Set the type of a neuron + void set_node_type(NeuronTypes type); + // Computes the output of the node by + // "pulling" the output of the fan-in nodes + void FeedForward(); + // fast computation of sigmoid function using a lookup table + // defined in sigmoid_table.cpp + static float Sigmoid(float activation); + // Accessor functions + float output() const { + return output_; + } + void set_output(float out_val) { + output_ = out_val; + } + int id() const { + return id_; + } + int fan_in_cnt() const { + return fan_in_.size(); + } + Neuron * fan_in(int idx) const { + return fan_in_[idx]; + } + float fan_in_wts(int idx) const { + return *(fan_in_weights_[idx]); + } + void set_id(int id) { + id_ = id; + } + float bias() const { + return bias_; + } + Neuron::NeuronTypes node_type() const { + return node_type_; + } + + protected: + // Type of Neuron + NeuronTypes node_type_; + // unqique id of the neuron + int id_; + // node bias + float bias_; + // node net activation + float activation_; + // node output + float output_; + // pointers to fanin nodes + vector fan_in_; + // pointers to fanin weights + vector fan_in_weights_; + // Sigmoid function lookup table used for fast computation + // of sigmoid function + static const float kSigmoidTable[]; + // flag determining if the activation of the node + // is fresh or not (dirty) + bool frwd_dirty_; + // Initializer + void Init(); +}; +} + +#endif // NEURON_H__ diff --git a/TesseractOCR/include/tesseract/normalis.h b/TesseractOCR/include/tesseract/normalis.h old mode 100755 new mode 100644 index 9af193b6..c8ce7cd2 --- a/TesseractOCR/include/tesseract/normalis.h +++ b/TesseractOCR/include/tesseract/normalis.h @@ -21,6 +21,7 @@ #define NORMALIS_H #include +#include "genericvector.h" #include "host.h" const int kBlnCellHeight = 256; // Full-height for baseline normalization. @@ -31,12 +32,13 @@ struct Pix; class ROW; // Forward decl class BLOCK; class FCOORD; -class TBLOB; +struct TBLOB; class TBOX; -class TPOINT; +struct TPOINT; class UNICHARSET; namespace tesseract { + // Possible normalization methods. Use NEGATIVE values as these also // double up as markers for the last sub-classifier. enum NormalizationMode { @@ -47,39 +49,15 @@ enum NormalizationMode { } // namespace tesseract. -class DENORM_SEG { - public: - DENORM_SEG() {} - - inT32 xstart; // start of segment - inT32 ycoord; // y at segment - float scale_factor; // normalized_x/scale_factor + x_center == original_x -}; - class DENORM { public: DENORM(); - DENORM(float x, float scaling, ROW *src); - DENORM(float x, // from same pieces - float scaling, - double line_m, // default line: y = mx + c - double line_c, - inT16 seg_count, // no of segments - DENORM_SEG *seg_pts, // actual segments - BOOL8 using_row, // as baseline - ROW *src); + // Copying a DENORM is allowed. DENORM(const DENORM &); DENORM& operator=(const DENORM&); ~DENORM(); - // Setup for a baseline normalization. If there are segs, then they - // are used, otherwise, if there is a row, that is used, otherwise the - // bottom of the word_box is used for the baseline. - void SetupBLNormalize(const BLOCK* block, const ROW* row, float x_height, - const TBOX& word_box, - int num_segs, const DENORM_SEG* segs); - // Setup the normalization transformation parameters. // The normalizations applied to a blob are as follows: // 1. An optional block layout rotation that was applied during layout @@ -120,18 +98,12 @@ class DENORM { // block: if not NULL, then this is the first transformation, and // block->re_rotation() needs to be used after the Denorm // transformation to get back to the image coords. - // row: if not NULL, then row->baseline(x) is added to the y_origin, unless - // segs is not NULL and num_segs > 0, in which case they are used. // rotation: if not NULL, apply this rotation after translation to the // origin and scaling. (Usually a classify rotation.) // predecessor: if not NULL, then predecessor has been applied to the // input space and needs to be undone to complete the inverse. - // segs: if not NULL and num_segs > 0, then the segs provide the y_origin - // and the y_scale at a given source x. - // num_segs: the number of segs. // The above pointers are not owned by this DENORM and are assumed to live - // longer than this denorm, except rotation and segs, which are deep - // copied on input. + // longer than this denorm, except rotation, which is deep copied on input. // // x_origin: The x origin which will be mapped to final_xshift in the result. // y_origin: The y origin which will be mapped to final_yshift in the result. @@ -148,21 +120,23 @@ class DENORM { // // In theory, any of the commonly used normalizations can be setup here: // * Traditional baseline normalization on a word: - // SetupNormalization(block, row, NULL, NULL, NULL, 0, - // box.x_middle(), 0.0f, + // SetupNormalization(block, NULL, NULL, + // box.x_middle(), baseline, // kBlnXHeight / x_height, kBlnXHeight / x_height, // 0, kBlnBaselineOffset); - // * Numeric mode baseline normalization on a word: - // SetupNormalization(block, NULL, NULL, NULL, segs, num_segs, - // box.x_middle(), 0.0f, + // * "Numeric mode" baseline normalization on a word, in which the blobs + // are positioned with the bottom as the baseline is achieved by making + // a separate DENORM for each blob. + // SetupNormalization(block, NULL, NULL, + // box.x_middle(), box.bottom(), // kBlnXHeight / x_height, kBlnXHeight / x_height, // 0, kBlnBaselineOffset); // * Anisotropic character normalization used by IntFx. - // SetupNormalization(NULL, NULL, NULL, denorm, NULL, 0, + // SetupNormalization(NULL, NULL, denorm, // centroid_x, centroid_y, // 51.2 / ry, 51.2 / rx, 128, 128); // * Normalize blob height to x-height (current OSD): - // SetupNormalization(NULL, NULL, &rotation, NULL, NULL, 0, + // SetupNormalization(NULL, &rotation, NULL, // box.rotational_x_middle(rotation), // box.rotational_y_middle(rotation), // kBlnXHeight / box.rotational_height(rotation), @@ -171,7 +145,7 @@ class DENORM { // * Secondary normalization for classification rotation (current): // FCOORD rotation = block->classify_rotation(); // float target_height = kBlnXHeight / CCStruct::kXHeightCapRatio; - // SetupNormalization(NULL, NULL, &rotation, denorm, NULL, 0, + // SetupNormalization(NULL, &rotation, denorm, // box.rotational_x_middle(rotation), // box.rotational_y_middle(rotation), // target_height / box.rotational_height(rotation), @@ -183,7 +157,7 @@ class DENORM { // Scales height and width independently so that modal height and pitch // fill the cell respectively. // float cap_height = x_height / CCStruct::kXHeightCapRatio; - // SetupNormalization(block, row, NULL, NULL, NULL, 0, + // SetupNormalization(block, NULL, NULL, // box.x_middle(), cap_height / 2.0f, // kBlnCellHeight / fixed_pitch, // kBlnCellHeight / cap_height, @@ -193,30 +167,52 @@ class DENORM { // cell, no further scaling and a simple rotation (or nothing) about the // cell center. // FCOORD rotation = block->classify_rotation(); - // SetupNormalization(NULL, NULL, &rotation, denorm, NULL, 0, + // SetupNormalization(NULL, &rotation, denorm, // fixed_pitch_cell_center, // 0.0f, // 1.0f, // 1.0f, // 0, 0); void SetupNormalization(const BLOCK* block, - const ROW* row, const FCOORD* rotation, const DENORM* predecessor, - const DENORM_SEG* segs, int num_segs, float x_origin, float y_origin, float x_scale, float y_scale, float final_xshift, float final_yshift); + // Sets up the DENORM to execute a non-linear transformation based on + // preserving an even distribution of stroke edges. The transformation + // operates only within the given box, scaling input coords within the box + // non-linearly to a box of target_width by target_height, with all other + // coords being clipped to the box edge. As with SetupNormalization above, + // final_xshift and final_yshift are applied after scaling, and the bottom- + // left of box is used as a pre-scaling origin. + // x_coords is a collection of the x-coords of vertical edges for each + // y-coord starting at box.bottom(). + // y_coords is a collection of the y-coords of horizontal edges for each + // x-coord starting at box.left(). + // Eg x_coords[0] is a collection of the x-coords of edges at y=bottom. + // Eg x_coords[1] is a collection of the x-coords of edges at y=bottom + 1. + // The second-level vectors must all be sorted in ascending order. + void SetupNonLinear(const DENORM* predecessor, const TBOX& box, + float target_width, float target_height, + float final_xshift, float final_yshift, + const GenericVector >& x_coords, + const GenericVector >& y_coords); + // Transforms the given coords one step forward to normalized space, without // using any block rotation or predecessor. void LocalNormTransform(const TPOINT& pt, TPOINT* transformed) const; void LocalNormTransform(const FCOORD& pt, FCOORD* transformed) const; // Transforms the given coords forward to normalized space using the // full transformation sequence defined by the block rotation, the - // predecessors, deepest first, and finally this. - void NormTransform(const TPOINT& pt, TPOINT* transformed) const; - void NormTransform(const FCOORD& pt, FCOORD* transformed) const; + // predecessors, deepest first, and finally this. If first_norm is not NULL, + // then the first and deepest transformation used is first_norm, ending + // with this, and the block rotation will not be applied. + void NormTransform(const DENORM* first_norm, const TPOINT& pt, + TPOINT* transformed) const; + void NormTransform(const DENORM* first_norm, const FCOORD& pt, + FCOORD* transformed) const; // Transforms the given coords one step back to source space, without // using to any block rotation or predecessor. void LocalDenormTransform(const TPOINT& pt, TPOINT* original) const; @@ -224,21 +220,30 @@ class DENORM { // Transforms the given coords all the way back to source image space using // the full transformation sequence defined by this and its predecesors // recursively, shallowest first, and finally any block re_rotation. - void DenormTransform(const TPOINT& pt, TPOINT* original) const; - void DenormTransform(const FCOORD& pt, FCOORD* original) const; + // If last_denorm is not NULL, then the last transformation used will + // be last_denorm, and the block re_rotation will never be executed. + void DenormTransform(const DENORM* last_denorm, const TPOINT& pt, + TPOINT* original) const; + void DenormTransform(const DENORM* last_denorm, const FCOORD& pt, + FCOORD* original) const; // Normalize a blob using blob transformations. Less accurate, but // more accurately copies the old way. void LocalNormBlob(TBLOB* blob) const; - // Fills in the x-height range accepted by the given unichar_id, given its - // bounding box in the usual baseline-normalized coordinates, with some - // initial crude x-height estimate (such as word size) and this denoting the - // transformation that was used. Returns false, and an empty range if the - // bottom is a mis-fit. Returns true and empty [0, 0] range if the bottom - // fits, but the top is impossible. - bool XHeightRange(int unichar_id, const UNICHARSET& unicharset, - const TBOX& bbox, inT16* min_xht, inT16* max_xht) const; + // Fills in the x-height range accepted by the given unichar_id in blob + // coordinates, given its bounding box in the usual baseline-normalized + // coordinates, with some initial crude x-height estimate (such as word + // size) and this denoting the transformation that was used. + // Also returns the amount the character must have shifted up or down. + void XHeightRange(int unichar_id, const UNICHARSET& unicharset, + const TBOX& bbox, + float* min_xht, + float* max_xht, + float* yshift) const; + + // Prints the content of the DENORM for debug purposes. + void Print() const; Pix* pix() const { return pix_; @@ -267,12 +272,6 @@ class DENORM { float y_scale() const { return y_scale_; } - const ROW *row() const { - return row_; - } - void set_row(ROW* row) { - row_ = row; - } const BLOCK* block() const { return block_; } @@ -286,36 +285,24 @@ class DENORM { // Setup default values. void Init(); - // Returns the y-origin at the original (un-normalized) x. - float YOriginAtOrigX(float orig_x) const; - - // Returns the y-scale at the original (un-normalized) x. - float YScaleAtOrigX(float orig_x) const; - - // Deep copy the array of segments for use as a y_origin and y_scale. - void SetSegments(const DENORM_SEG* new_segs, int seg_count); - - // Finds the appropriate segment for a given original x-coord - const DENORM_SEG* BinarySearchSegment(float orig_x) const; - // Best available image. Pix* pix_; // True if the source image is white-on-black. bool inverse_; // Block the word came from. If not null, block->re_rotation() takes the // "untransformed" coordinates even further back to the original image. + // Used only on the first DENORM in a chain. const BLOCK* block_; - // Row the word came from. If not null, row->baseline() is added to y_origin_. - const ROW* row_; // Rotation to apply between translation to the origin and scaling. const FCOORD* rotation_; // Previous transformation in a chain. const DENORM* predecessor_; - // Array of segments used to specify local y_origin_ and y_scale_. - // Owned by the DENORM. - DENORM_SEG *segs_; - // Size of the segs_ array. - int num_segs_; + // Non-linear transformation maps directly from each integer offset from the + // origin to the corresponding x-coord. Owned by the DENORM. + GenericVector* x_map_; + // Non-linear transformation maps directly from each integer offset from the + // origin to the corresponding y-coord. Owned by the DENORM. + GenericVector* y_map_; // x-coordinate to be mapped to final_xshift_ in the result. float x_origin_; // y-coordinate to be mapped to final_yshift_ in the result. diff --git a/TesseractOCR/include/tesseract/normfeat.h b/TesseractOCR/include/tesseract/normfeat.h new file mode 100644 index 00000000..59703a51 --- /dev/null +++ b/TesseractOCR/include/tesseract/normfeat.h @@ -0,0 +1,41 @@ +/****************************************************************************** + ** Filename: normfeat.h + ** Purpose: Definition of character normalization features. + ** Author: Dan Johnson + ** History: 12/14/90, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef NORMFEAT_H +#define NORMFEAT_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "ocrfeatures.h" + +#define LENGTH_COMPRESSION (10.0) + +typedef enum { + CharNormY, CharNormLength, CharNormRx, CharNormRy +} NORM_PARAM_NAME; + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +FLOAT32 ActualOutlineLength(FEATURE Feature); + +FEATURE_SET ExtractCharNormFeatures(TBLOB *Blob, const DENORM& bl_denorm, + const DENORM& cn_denorm, + const INT_FX_RESULT_STRUCT& fx_info); + +#endif diff --git a/TesseractOCR/include/tesseract/normmatch.h b/TesseractOCR/include/tesseract/normmatch.h new file mode 100644 index 00000000..cdec0fd9 --- /dev/null +++ b/TesseractOCR/include/tesseract/normmatch.h @@ -0,0 +1,37 @@ +/****************************************************************************** + ** Filename: normmatch.h + ** Purpose: Simple matcher based on character normalization features. + ** Author: Dan Johnson + ** History: Thu Dec 20 08:55:05 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef NORMMATCH_H +#define NORMMATCH_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "matchdefs.h" +#include "ocrfeatures.h" +#include "params.h" + +/**---------------------------------------------------------------------------- + Variables +----------------------------------------------------------------------------**/ + +/* control knobs used to control the normalization adjustment process */ +extern double_VAR_H(classify_norm_adj_midpoint, 32.0, + "Norm adjust midpoint ..."); +extern double_VAR_H(classify_norm_adj_curl, 2.0, "Norm adjust curl ..."); + +#endif diff --git a/TesseractOCR/include/tesseract/normstrngs.h b/TesseractOCR/include/tesseract/normstrngs.h new file mode 100644 index 00000000..71e7b8da --- /dev/null +++ b/TesseractOCR/include/tesseract/normstrngs.h @@ -0,0 +1,82 @@ +/********************************************************************** + * File: normstrngs.h + * Description: Utilities to normalize and manipulate UTF-32 and + * UTF-8 strings. + * Author: Ranjith Unnikrishnan + * Created: Thu July 4 2013 + * + * (C) Copyright 2013, Google Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + **********************************************************************/ + +#ifndef TESSERACT_CCUTIL_NORMSTRNGS_H_ +#define TESSERACT_CCUTIL_NORMSTRNGS_H_ + +#include "genericvector.h" +#include "strngs.h" + +typedef signed int char32; + +namespace tesseract { + +// UTF-8 to UTF-32 conversion function. +void UTF8ToUTF32(const char* utf8_str, GenericVector* str32); + +// UTF-32 to UTF-8 convesion function. +void UTF32ToUTF8(const GenericVector& str32, STRING* utf8_str); + +// Normalize a single char32 using NFKC + OCR-specific transformations. +// NOTE that proper NFKC may require multiple characters as input. The +// assumption of this function is that the input is already as fully composed +// as it can be, but may require some compatibility normalizations or just +// OCR evaluation related normalizations. +void NormalizeChar32(char32 ch, GenericVector* str); + +// Normalize a UTF8 string. Same as above, but for UTF8-encoded strings, that +// can contain multiple UTF32 code points. +STRING NormalizeUTF8String(const char* str8); + +// Apply just the OCR-specific normalizations and return the normalized char. +char32 OCRNormalize(char32 ch); + +// Returns true if the OCRNormalized ch1 and ch2 are the same. +bool IsOCREquivalent(char32 ch1, char32 ch2); + +// Returns true if the value lies in the range of valid unicodes. +bool IsValidCodepoint(const char32 ch); + +// Returns true a code point has the White_Space Unicode property. +bool IsWhitespace(const char32 ch); +// Returns true if every char in the given (null-terminated) string has the +// White_Space Unicode property. +bool IsUTF8Whitespace(const char* text); + +// Returns the length of bytes of the prefix of 'text' that have the White_Space +// unicode property. +int SpanUTF8Whitespace(const char* text); + +// Returns the length of bytes of the prefix of 'text' that DO NOT have the +// White_Space unicode property. +int SpanUTF8NotWhitespace(const char* text); + +// Returns true if the char is interchange valid i.e. no C0 or C1 control codes +// (other than CR LF HT FF) and no non-characters. +bool IsInterchangeValid(const char32 ch); +// Same as above but restricted to 7-bit ASCII. +bool IsInterchangeValid7BitAscii(const char32 ch); + +// Convert a full-width UTF-8 string to half-width. +char32 FullwidthToHalfwidth(const char32 ch); + +} // namespace tesseract + +#endif // TESSERACT_CCUTIL_NORMSTRNGS_H_ diff --git a/TesseractOCR/include/tesseract/nwmain.h b/TesseractOCR/include/tesseract/nwmain.h old mode 100755 new mode 100644 index 409cd6e0..a9b1926a --- a/TesseractOCR/include/tesseract/nwmain.h +++ b/TesseractOCR/include/tesseract/nwmain.h @@ -22,7 +22,6 @@ #include "host.h" #include "params.h" -#include "notdll.h" //must be last include #define DECLARE_MAIN(ARGC,ARGV)\ STRING_VAR(init_config_file,"config","Config file to read on startup");\ diff --git a/TesseractOCR/include/tesseract/object_cache.h b/TesseractOCR/include/tesseract/object_cache.h new file mode 100644 index 00000000..c8c3167c --- /dev/null +++ b/TesseractOCR/include/tesseract/object_cache.h @@ -0,0 +1,125 @@ +/////////////////////////////////////////////////////////////////////// +// File: object_cache.h +// Description: A string indexed object cache. +// Author: David Eger +// Created: Fri Jan 27 12:08:00 PST 2012 +// +// (C) Copyright 2012, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_CCUTIL_OBJECT_CACHE_H_ +#define TESSERACT_CCUTIL_OBJECT_CACHE_H_ + +#include "ccutil.h" +#include "errcode.h" +#include "genericvector.h" +#include "tesscallback.h" + +namespace tesseract { + +// A simple object cache which maps a string to an object of type T. +// Usually, these are expensive objects that are loaded from disk. +// Reference counting is performed, so every Get() needs to be followed later +// by a Free(). Actual deletion is accomplished by DeleteUnusedObjects(). +template +class ObjectCache { + public: + ObjectCache() {} + ~ObjectCache() { + mu_.Lock(); + for (int i = 0; i < cache_.size(); i++) { + if (cache_[i].count > 0) { + tprintf("ObjectCache(%p)::~ObjectCache(): WARNING! LEAK! object %p " + "still has count %d (id %s)\n", + this, cache_[i].object, cache_[i].count, + cache_[i].id.string()); + } else { + delete cache_[i].object; + cache_[i].object = NULL; + } + } + mu_.Unlock(); + } + + // Return a pointer to the object identified by id. + // If we haven't yet loaded the object, use loader to load it. + // If loader fails to load it, record a NULL entry in the cache + // and return NULL -- further attempts to load will fail (even + // with a different loader) until DeleteUnusedObjects() is called. + // We delete the given loader. + T *Get(STRING id, + TessResultCallback *loader) { + T *retval = NULL; + mu_.Lock(); + for (int i = 0; i < cache_.size(); i++) { + if (id == cache_[i].id) { + retval = cache_[i].object; + if (cache_[i].object != NULL) { + cache_[i].count++; + } + mu_.Unlock(); + delete loader; + return retval; + } + } + cache_.push_back(ReferenceCount()); + ReferenceCount &rc = cache_.back(); + rc.id = id; + retval = rc.object = loader->Run(); + rc.count = (retval != NULL) ? 1 : 0; + mu_.Unlock(); + return retval; + } + + // Decrement the count for t. + // Return whether we knew about the given pointer. + bool Free(T *t) { + if (t == NULL) return false; + mu_.Lock(); + for (int i = 0; i < cache_.size(); i++) { + if (cache_[i].object == t) { + --cache_[i].count; + mu_.Unlock(); + return true; + } + } + mu_.Unlock(); + return false; + } + + void DeleteUnusedObjects() { + mu_.Lock(); + for (int i = cache_.size() - 1; i >= 0; i--) { + if (cache_[i].count <= 0) { + delete cache_[i].object; + cache_.remove(i); + } + } + mu_.Unlock(); + } + + private: + struct ReferenceCount { + STRING id; // A unique ID to identify the object (think path on disk) + T *object; // A copy of the object in memory. Can be delete'd. + int count; // A count of the number of active users of this object. + }; + + CCUtilMutex mu_; + GenericVector cache_; +}; + +} // namespace tesseract + + +#endif // TESSERACT_CCUTIL_OBJECT_CACHE_H_ diff --git a/TesseractOCR/include/tesseract/oclkernels.h b/TesseractOCR/include/tesseract/oclkernels.h new file mode 100644 index 00000000..3998e025 --- /dev/null +++ b/TesseractOCR/include/tesseract/oclkernels.h @@ -0,0 +1,1229 @@ + +#ifndef _OCL_KERNEL_H_ +#define _OCL_KERNEL_H_ +#ifndef USE_EXTERNAL_KERNEL +#define KERNEL( ... )# __VA_ARGS__ "\n" +// Double precision is a default of spreadsheets +// cl_khr_fp64: Khronos extension +// cl_amd_fp64: AMD extension +// use build option outside to define fp_t +///////////////////////////////////////////// +const char *kernel_src = KERNEL( +\n#ifdef KHR_DP_EXTENSION\n +\n#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n +\n#elif AMD_DP_EXTENSION\n +\n#pragma OPENCL EXTENSION cl_amd_fp64 : enable\n +\n#else\n +\n#endif\n +__kernel void composeRGBPixel(__global uint *tiffdata, int w, int h,int wpl, __global uint *output) +{ + int i = get_global_id(1); + int j = get_global_id(0); + int tiffword,rval,gval,bval; + + //Ignore the excess + if ((i >= h) || (j >= w)) + return; + + tiffword = tiffdata[i * w + j]; + rval = ((tiffword) & 0xff); + gval = (((tiffword) >> 8) & 0xff); + bval = (((tiffword) >> 16) & 0xff); + output[i*wpl+j] = (rval << (8 * (sizeof(uint) - 1 - 0))) | (gval << (8 * (sizeof(uint) - 1 - 1))) | (bval << (8 * (sizeof(uint) - 1 - 2))); +} +) + +KERNEL( +\n__kernel void pixSubtract_inplace(__global int *dword, __global int *sword, + const int wpl, const int h) +{ + const unsigned int row = get_global_id(1); + const unsigned int col = get_global_id(0); + const unsigned int pos = row * wpl + col; + + //Ignore the execss + if (row >= h || col >= wpl) + return; + + *(dword + pos) &= ~(*(sword + pos)); +}\n +) + +KERNEL( +\n__kernel void pixSubtract(__global int *dword, __global int *sword, + const int wpl, const int h, __global int *outword) +{ + const unsigned int row = get_global_id(1); + const unsigned int col = get_global_id(0); + const unsigned int pos = row * wpl + col; + + //Ignore the execss + if (row >= h || col >= wpl) + return; + + *(outword + pos) = *(dword + pos) & ~(*(sword + pos)); +}\n +) + +KERNEL( +\n__kernel void pixAND(__global int *dword, __global int *sword, __global int *outword, + const int wpl, const int h) +{ + const unsigned int row = get_global_id(1); + const unsigned int col = get_global_id(0); + const unsigned int pos = row * wpl + col; + + //Ignore the execss + if (row >= h || col >= wpl) + return; + + *(outword + pos) = *(dword + pos) & (*(sword + pos)); +}\n +) + +KERNEL( +\n__kernel void pixOR(__global int *dword, __global int *sword, __global int *outword, + const int wpl, const int h) +{ + const unsigned int row = get_global_id(1); + const unsigned int col = get_global_id(0); + const unsigned int pos = row * wpl + col; + + //Ignore the execss + if (row >= h || col >= wpl) + return; + + *(outword + pos) = *(dword + pos) | (*(sword + pos)); +}\n +) + +KERNEL( +\n__kernel void morphoDilateHor_5x5(__global int *sword,__global int *dword, + const int wpl, const int h) +{ + const unsigned int pos = get_global_id(0); + unsigned int prevword, nextword, currword,tempword; + unsigned int destword; + const int col = pos % wpl; + + //Ignore the execss + if (pos >= (wpl * h)) + return; + + + currword = *(sword + pos); + destword = currword; + + //Handle boundary conditions + if(col==0) + prevword=0; + else + prevword = *(sword + pos - 1); + + if(col==(wpl - 1)) + nextword=0; + else + nextword = *(sword + pos + 1); + + //Loop unrolled + + //1 bit to left and 1 bit to right + //Get the max value on LHS of every pixel + tempword = (prevword << (31)) | ((currword >> 1)); + destword |= tempword; + //Get max value on RHS of every pixel + tempword = (currword << 1) | (nextword >> (31)); + destword |= tempword; + + //2 bit to left and 2 bit to right + //Get the max value on LHS of every pixel + tempword = (prevword << (30)) | ((currword >> 2)); + destword |= tempword; + //Get max value on RHS of every pixel + tempword = (currword << 2) | (nextword >> (30)); + destword |= tempword; + + + *(dword + pos) = destword; + +}\n +) + +KERNEL( +\n__kernel void morphoDilateVer_5x5(__global int *sword,__global int *dword, + const int wpl, const int h) +{ + const int col = get_global_id(0); + const int row = get_global_id(1); + const unsigned int pos = row * wpl + col; + unsigned int tempword; + unsigned int destword; + int i; + + //Ignore the execss + if (row >= h || col >= wpl) + return; + + destword = *(sword + pos); + + //2 words above + i = (row - 2) < 0 ? row : (row - 2); + tempword = *(sword + i*wpl + col); + destword |= tempword; + + //1 word above + i = (row - 1) < 0 ? row : (row - 1); + tempword = *(sword + i*wpl + col); + destword |= tempword; + + //1 word below + i = (row >= (h - 1)) ? row : (row + 1); + tempword = *(sword + i*wpl + col); + destword |= tempword; + + //2 words below + i = (row >= (h - 2)) ? row : (row + 2); + tempword = *(sword + i*wpl + col); + destword |= tempword; + + *(dword + pos) = destword; +}\n +) + +KERNEL( +\n__kernel void morphoDilateHor(__global int *sword,__global int *dword,const int xp, const int xn, const int wpl, const int h) +{ + const int col = get_global_id(0); + const int row = get_global_id(1); + const unsigned int pos = row * wpl + col; + unsigned int parbitsxp, parbitsxn, nwords; + unsigned int destword, tempword, lastword, currword; + unsigned int lnextword, lprevword, rnextword, rprevword, firstword, secondword; + int i, j, siter, eiter; + + //Ignore the execss + if (pos >= (wpl*h) || (xn < 1 && xp < 1)) + return; + + currword = *(sword + pos); + destword = currword; + + parbitsxp = xp & 31; + parbitsxn = xn & 31; + nwords = xp >> 5; + + if (parbitsxp > 0) + nwords += 1; + else + parbitsxp = 31; + + siter = (col - nwords); + eiter = (col + nwords); + + //Get prev word + if (col==0) + firstword = 0x0; + else + firstword = *(sword + pos - 1); + + //Get next word + if (col == (wpl - 1)) + secondword = 0x0; + else + secondword = *(sword + pos + 1); + + //Last partial bits on either side + for (i = 1; i <= parbitsxp; i++) + { + //Get the max value on LHS of every pixel + tempword = ((i == parbitsxp) && (parbitsxp != parbitsxn)) ? 0x0 : (firstword << (32-i)) | ((currword >> i)); + + destword |= tempword; + + //Get max value on RHS of every pixel + tempword = (currword << i) | (secondword >> (32 - i)); + destword |= tempword; + } + + //Return if halfwidth <= 1 word + if (nwords == 1) + { + if (xn == 32) + { + destword |= firstword; + } + if (xp == 32) + { + destword |= secondword; + } + + *(dword + pos) = destword; + return; + } + + if (siter < 0) + firstword = 0x0; + else + firstword = *(sword + row*wpl + siter); + + if (eiter >= wpl) + lastword = 0x0; + else + lastword = *(sword + row*wpl + eiter); + + for ( i = 1; i < nwords; i++) + { + //Gets LHS words + if ((siter + i) < 0) + secondword = 0x0; + else + secondword = *(sword + row*wpl + siter + i); + + lprevword = firstword << (32 - parbitsxn) | secondword >> parbitsxn; + + firstword = secondword; + + if ((siter + i + 1) < 0) + secondword = 0x0; + else + secondword = *(sword + row*wpl + siter + i + 1); + + lnextword = firstword << (32 - parbitsxn) | secondword >> parbitsxn; + + //Gets RHS words + if ((eiter - i) >= wpl) + firstword = 0x0; + else + firstword = *(sword + row*wpl + eiter - i); + + rnextword = firstword << parbitsxp | lastword >> (32 - parbitsxp); + + lastword = firstword; + if ((eiter - i - 1) >= wpl) + firstword = 0x0; + else + firstword = *(sword + row*wpl + eiter - i - 1); + + rprevword = firstword << parbitsxp | lastword >> (32 - parbitsxp); + + for (j = 1; j < 32; j++) + { + //OR LHS full words + tempword = (lprevword << j) | (lnextword >> (32 - j)); + destword |= tempword; + + //OR RHS full words + tempword = (rprevword << j) | (rnextword >> (32 - j)); + destword |= tempword; + } + + destword |= lprevword; + destword |= lnextword; + destword |= rprevword; + destword |= rnextword; + + lastword = firstword; + firstword = secondword; + } + + *(dword + pos) = destword; +}\n +) + +KERNEL( +\n__kernel void morphoDilateHor_32word(__global int *sword,__global int *dword, + const int halfwidth, + const int wpl, const int h, + const char isEven) +{ + const int col = get_global_id(0); + const int row = get_global_id(1); + const unsigned int pos = row * wpl + col; + unsigned int prevword, nextword, currword,tempword; + unsigned int destword; + int i; + + //Ignore the execss + if (pos >= (wpl * h)) + return; + + currword = *(sword + pos); + destword = currword; + + //Handle boundary conditions + if(col==0) + prevword=0; + else + prevword = *(sword + pos - 1); + + if(col==(wpl - 1)) + nextword=0; + else + nextword = *(sword + pos + 1); + + for (i = 1; i <= halfwidth; i++) + { + //Get the max value on LHS of every pixel + if (i == halfwidth && isEven) + { + tempword = 0x0; + } + else + { + tempword = (prevword << (32-i)) | ((currword >> i)); + } + + destword |= tempword; + + //Get max value on RHS of every pixel + tempword = (currword << i) | (nextword >> (32 - i)); + + destword |= tempword; + } + + *(dword + pos) = destword; +}\n +) + +KERNEL( +\n__kernel void morphoDilateVer(__global int *sword,__global int *dword, + const int yp, + const int wpl, const int h, + const int yn) +{ + const int col = get_global_id(0); + const int row = get_global_id(1); + const unsigned int pos = row * wpl + col; + unsigned int tempword; + unsigned int destword; + int i, siter, eiter; + + //Ignore the execss + if (row >= h || col >= wpl) + return; + + destword = *(sword + pos); + + //Set start position and end position considering the boundary conditions + siter = (row - yn) < 0 ? 0 : (row - yn); + eiter = (row >= (h - yp)) ? (h - 1) : (row + yp); + + for (i = siter; i <= eiter; i++) + { + tempword = *(sword + i*wpl + col); + + destword |= tempword; + } + + *(dword + pos) = destword; +}\n +) + +KERNEL( +\n__kernel void morphoErodeHor_5x5(__global int *sword,__global int *dword, + const int wpl, const int h) +{ + const unsigned int pos = get_global_id(0); + unsigned int prevword, nextword, currword,tempword; + unsigned int destword; + const int col = pos % wpl; + + //Ignore the execss + if (pos >= (wpl * h)) + return; + + currword = *(sword + pos); + destword = currword; + + //Handle boundary conditions + if(col==0) + prevword=0xffffffff; + else + prevword = *(sword + pos - 1); + + if(col==(wpl - 1)) + nextword=0xffffffff; + else + nextword = *(sword + pos + 1); + + //Loop unrolled + + //1 bit to left and 1 bit to right + //Get the min value on LHS of every pixel + tempword = (prevword << (31)) | ((currword >> 1)); + destword &= tempword; + //Get min value on RHS of every pixel + tempword = (currword << 1) | (nextword >> (31)); + destword &= tempword; + + //2 bit to left and 2 bit to right + //Get the min value on LHS of every pixel + tempword = (prevword << (30)) | ((currword >> 2)); + destword &= tempword; + //Get min value on RHS of every pixel + tempword = (currword << 2) | (nextword >> (30)); + destword &= tempword; + + + *(dword + pos) = destword; + +}\n +) + +KERNEL( +\n__kernel void morphoErodeVer_5x5(__global int *sword,__global int *dword, + const int wpl, const int h, + const int fwmask, const int lwmask) +{ + const int col = get_global_id(0); + const int row = get_global_id(1); + const unsigned int pos = row * wpl + col; + unsigned int tempword; + unsigned int destword; + int i; + + //Ignore the execss + if (row >= h || col >= wpl) + return; + + destword = *(sword + pos); + + if (row < 2 || row >= (h - 2)) + { + destword = 0x0; + } + else + { + //2 words above + //i = (row - 2) < 0 ? row : (row - 2); + i = (row - 2); + tempword = *(sword + i*wpl + col); + destword &= tempword; + + //1 word above + //i = (row - 1) < 0 ? row : (row - 1); + i = (row - 1); + tempword = *(sword + i*wpl + col); + destword &= tempword; + + //1 word below + //i = (row >= (h - 1)) ? row : (row + 1); + i = (row + 1); + tempword = *(sword + i*wpl + col); + destword &= tempword; + + //2 words below + //i = (row >= (h - 2)) ? row : (row + 2); + i = (row + 2); + tempword = *(sword + i*wpl + col); + destword &= tempword; + + if (col == 0) + { + destword &= fwmask; + } + if (col == (wpl - 1)) + { + destword &= lwmask; + } + } + + + *(dword + pos) = destword; +}\n +) + +KERNEL( +\n__kernel void morphoErodeHor(__global int *sword,__global int *dword, const int xp, const int xn, const int wpl, + const int h, const char isAsymmetric, const int rwmask, const int lwmask) +{ + const int col = get_global_id(0); + const int row = get_global_id(1); + const unsigned int pos = row * wpl + col; + unsigned int parbitsxp, parbitsxn, nwords; + unsigned int destword, tempword, lastword, currword; + unsigned int lnextword, lprevword, rnextword, rprevword, firstword, secondword; + int i, j, siter, eiter; + + //Ignore the execss + if (pos >= (wpl*h) || (xn < 1 && xp < 1)) + return; + + currword = *(sword + pos); + destword = currword; + + parbitsxp = xp & 31; + parbitsxn = xn & 31; + nwords = xp >> 5; + + if (parbitsxp > 0) + nwords += 1; + else + parbitsxp = 31; + + siter = (col - nwords); + eiter = (col + nwords); + + //Get prev word + if (col==0) + firstword = 0xffffffff; + else + firstword = *(sword + pos - 1); + + //Get next word + if (col == (wpl - 1)) + secondword = 0xffffffff; + else + secondword = *(sword + pos + 1); + + //Last partial bits on either side + for (i = 1; i <= parbitsxp; i++) + { + //Get the max value on LHS of every pixel + tempword = (firstword << (32-i)) | ((currword >> i)); + destword &= tempword; + + //Get max value on RHS of every pixel + tempword = ((i == parbitsxp) && (parbitsxp != parbitsxn)) ? 0xffffffff : (currword << i) | (secondword >> (32 - i)); + + //tempword = (currword << i) | (secondword >> (32 - i)); + destword &= tempword; + } + + //Return if halfwidth <= 1 word + if (nwords == 1) + { + if (xp == 32) + { + destword &= firstword; + } + if (xn == 32) + { + destword &= secondword; + } + + //Clear boundary pixels + if (isAsymmetric) + { + if (col == 0) + destword &= rwmask; + if (col == (wpl - 1)) + destword &= lwmask; + } + + *(dword + pos) = destword; + return; + } + + if (siter < 0) + firstword = 0xffffffff; + else + firstword = *(sword + row*wpl + siter); + + if (eiter >= wpl) + lastword = 0xffffffff; + else + lastword = *(sword + row*wpl + eiter); + + + for ( i = 1; i < nwords; i++) + { + //Gets LHS words + if ((siter + i) < 0) + secondword = 0xffffffff; + else + secondword = *(sword + row*wpl + siter + i); + + lprevword = firstword << (32 - parbitsxp) | secondword >> (parbitsxp); + + firstword = secondword; + + if ((siter + i + 1) < 0) + secondword = 0xffffffff; + else + secondword = *(sword + row*wpl + siter + i + 1); + + lnextword = firstword << (32 - parbitsxp) | secondword >> (parbitsxp); + + //Gets RHS words + if ((eiter - i) >= wpl) + firstword = 0xffffffff; + else + firstword = *(sword + row*wpl + eiter - i); + + rnextword = firstword << parbitsxn | lastword >> (32 - parbitsxn); + + lastword = firstword; + if ((eiter - i - 1) >= wpl) + firstword = 0xffffffff; + else + firstword = *(sword + row*wpl + eiter - i - 1); + + rprevword = firstword << parbitsxn | lastword >> (32 - parbitsxn); + + for (j = 0; j < 32; j++) + { + //OR LHS full words + tempword = (lprevword << j) | (lnextword >> (32 - j)); + destword &= tempword; + + //OR RHS full words + tempword = (rprevword << j) | (rnextword >> (32 - j)); + destword &= tempword; + } + + destword &= lprevword; + destword &= lnextword; + destword &= rprevword; + destword &= rnextword; + + lastword = firstword; + firstword = secondword; + } + + if (isAsymmetric) + { + //Clear boundary pixels + if (col < (nwords - 1)) + destword = 0x0; + else if (col == (nwords - 1)) + destword &= rwmask; + else if (col > (wpl - nwords)) + destword = 0x0; + else if (col == (wpl - nwords)) + destword &= lwmask; + } + + *(dword + pos) = destword; +}\n +) + +KERNEL( +\n__kernel void morphoErodeHor_32word(__global int *sword,__global int *dword, + const int halfwidth, const int wpl, + const int h, const char clearBoundPixH, + const int rwmask, const int lwmask, + const char isEven) +{ + const int col = get_global_id(0); + const int row = get_global_id(1); + const unsigned int pos = row * wpl + col; + unsigned int prevword, nextword, currword,tempword, destword; + int i; + + //Ignore the execss + if (pos >= (wpl * h)) + return; + + currword = *(sword + pos); + destword = currword; + + //Handle boundary conditions + if(col==0) + prevword=0xffffffff; + else + prevword = *(sword + pos - 1); + + if(col==(wpl - 1)) + nextword=0xffffffff; + else + nextword = *(sword + pos + 1); + + for (i = 1; i <= halfwidth; i++) + { + //Get the min value on LHS of every pixel + tempword = (prevword << (32-i)) | ((currword >> i)); + + destword &= tempword; + + //Get min value on RHS of every pixel + if (i == halfwidth && isEven) + { + tempword = 0xffffffff; + } + else + { + tempword = (currword << i) | (nextword >> (32 - i)); + } + + destword &= tempword; + } + + if (clearBoundPixH) + { + if (col == 0) + { + destword &= rwmask; + } + else if (col == (wpl - 1)) + { + destword &= lwmask; + } + } + + *(dword + pos) = destword; +}\n +) + +KERNEL( +\n__kernel void morphoErodeVer(__global int *sword,__global int *dword, + const int yp, + const int wpl, const int h, + const char clearBoundPixV, const int yn) +{ + const int col = get_global_id(0); + const int row = get_global_id(1); + const unsigned int pos = row * wpl + col; + unsigned int tempword, destword; + int i, siter, eiter; + + //Ignore the execss + if (row >= h || col >= wpl) + return; + + destword = *(sword + pos); + + //Set start position and end position considering the boundary conditions + siter = (row - yp) < 0 ? 0 : (row - yp); + eiter = (row >= (h - yn)) ? (h - 1) : (row + yn); + + for (i = siter; i <= eiter; i++) + { + tempword = *(sword + i*wpl + col); + + destword &= tempword; + } + + //Clear boundary pixels + if (clearBoundPixV && ((row < yp) || ((h - row) <= yn))) + { + destword = 0x0; + } + + *(dword + pos) = destword; +}\n +) + +// HistogramRect Kernel: Accumulate +// assumes 4 channels, i.e., bytes_per_pixel = 4 +// assumes number of pixels is multiple of 8 +// data is layed out as +// ch0 ch1 ... +// bin0 bin1 bin2... bin0... +// rpt0,1,2...256 rpt0,1,2... +KERNEL( +\n#define HIST_REDUNDANCY 256\n +\n#define GROUP_SIZE 256\n +\n#define HIST_SIZE 256\n +\n#define NUM_CHANNELS 4\n +\n#define HR_UNROLL_SIZE 8 \n +\n#define HR_UNROLL_TYPE uchar8 \n + +__attribute__((reqd_work_group_size(256, 1, 1))) +__kernel +void kernel_HistogramRectAllChannels( + __global const uchar8 *data, + uint numPixels, + __global uint *histBuffer) { + + // declare variables + uchar8 pixels; + int threadOffset = get_global_id(0)%HIST_REDUNDANCY; + + // for each pixel/channel, accumulate in global memory + for ( uint pc = get_global_id(0); pc < numPixels*NUM_CHANNELS/HR_UNROLL_SIZE; pc += get_global_size(0) ) { + pixels = data[pc]; + // channel bin thread + atomic_inc( &histBuffer[ 0*HIST_SIZE*HIST_REDUNDANCY + pixels.s0*HIST_REDUNDANCY + threadOffset ]); // ch0 + atomic_inc( &histBuffer[ 0*HIST_SIZE*HIST_REDUNDANCY + pixels.s4*HIST_REDUNDANCY + threadOffset ]); // ch0 + atomic_inc( &histBuffer[ 1*HIST_SIZE*HIST_REDUNDANCY + pixels.s1*HIST_REDUNDANCY + threadOffset ]); // ch1 + atomic_inc( &histBuffer[ 1*HIST_SIZE*HIST_REDUNDANCY + pixels.s5*HIST_REDUNDANCY + threadOffset ]); // ch1 + atomic_inc( &histBuffer[ 2*HIST_SIZE*HIST_REDUNDANCY + pixels.s2*HIST_REDUNDANCY + threadOffset ]); // ch2 + atomic_inc( &histBuffer[ 2*HIST_SIZE*HIST_REDUNDANCY + pixels.s6*HIST_REDUNDANCY + threadOffset ]); // ch2 + atomic_inc( &histBuffer[ 3*HIST_SIZE*HIST_REDUNDANCY + pixels.s3*HIST_REDUNDANCY + threadOffset ]); // ch3 + atomic_inc( &histBuffer[ 3*HIST_SIZE*HIST_REDUNDANCY + pixels.s7*HIST_REDUNDANCY + threadOffset ]); // ch3 + } +} +) + +KERNEL( +// NUM_CHANNELS = 1 +__attribute__((reqd_work_group_size(256, 1, 1))) +__kernel +void kernel_HistogramRectOneChannel( + __global const uchar8 *data, + uint numPixels, + __global uint *histBuffer) { + + // declare variables + uchar8 pixels; + int threadOffset = get_global_id(0)%HIST_REDUNDANCY; + + // for each pixel/channel, accumulate in global memory + for ( uint pc = get_global_id(0); pc < numPixels/HR_UNROLL_SIZE; pc += get_global_size(0) ) { + pixels = data[pc]; + // bin thread + atomic_inc( &histBuffer[ pixels.s0*HIST_REDUNDANCY + threadOffset ]); + atomic_inc( &histBuffer[ pixels.s1*HIST_REDUNDANCY + threadOffset ]); + atomic_inc( &histBuffer[ pixels.s2*HIST_REDUNDANCY + threadOffset ]); + atomic_inc( &histBuffer[ pixels.s3*HIST_REDUNDANCY + threadOffset ]); + atomic_inc( &histBuffer[ pixels.s4*HIST_REDUNDANCY + threadOffset ]); + atomic_inc( &histBuffer[ pixels.s5*HIST_REDUNDANCY + threadOffset ]); + atomic_inc( &histBuffer[ pixels.s6*HIST_REDUNDANCY + threadOffset ]); + atomic_inc( &histBuffer[ pixels.s7*HIST_REDUNDANCY + threadOffset ]); + } +} +) + + +KERNEL( +// unused +\n __attribute__((reqd_work_group_size(256, 1, 1))) +\n __kernel +\n void kernel_HistogramRectAllChannels_Grey( +\n __global const uchar* data, +\n uint numPixels, +\n __global uint *histBuffer) { // each wg will write HIST_SIZE*NUM_CHANNELS into this result; cpu will accumulate across wg's +\n +\n /* declare variables */ +\n +\n // work indices +\n size_t groupId = get_group_id(0); +\n size_t localId = get_local_id(0); // 0 -> 256-1 +\n size_t globalId = get_global_id(0); // 0 -> 8*10*256-1=20480-1 +\n uint numThreads = get_global_size(0); +\n +\n /* accumulate in global memory */ +\n for ( uint pc = get_global_id(0); pc < numPixels; pc += get_global_size(0) ) { +\n uchar value = data[ pc ]; +\n int idx = value * get_global_size(0) + get_global_id(0); +\n histBuffer[ idx ]++; +\n +\n } +\n +\n } // kernel_HistogramRectAllChannels_Grey + +) + +// HistogramRect Kernel: Reduction +// only supports 4 channels +// each work group handles a single channel of a single histogram bin +KERNEL( +__attribute__((reqd_work_group_size(256, 1, 1))) +__kernel +void kernel_HistogramRectAllChannelsReduction( + int n, // unused pixel redundancy + __global uint *histBuffer, + __global int* histResult) { + + // declare variables + int channel = get_group_id(0)/HIST_SIZE; + int bin = get_group_id(0)%HIST_SIZE; + int value = 0; + + // accumulate in register + for ( uint i = get_local_id(0); i < HIST_REDUNDANCY; i+=GROUP_SIZE) { + value += histBuffer[ channel*HIST_SIZE*HIST_REDUNDANCY+bin*HIST_REDUNDANCY+i]; + } + + // reduction in local memory + __local int localHist[GROUP_SIZE]; + localHist[get_local_id(0)] = value; + barrier(CLK_LOCAL_MEM_FENCE); + for (int stride = GROUP_SIZE/2; stride >= 1; stride /= 2) { + if (get_local_id(0) < stride) { + value = localHist[ get_local_id(0)+stride]; + } + barrier(CLK_LOCAL_MEM_FENCE); + if (get_local_id(0) < stride) { + localHist[ get_local_id(0)] += value; + } + barrier(CLK_LOCAL_MEM_FENCE); + } + + // write reduction to final result + if (get_local_id(0) == 0) { + histResult[get_group_id(0)] = localHist[0]; + } +} // kernel_HistogramRectAllChannels +) + + +KERNEL( +// NUM_CHANNELS = 1 +__attribute__((reqd_work_group_size(256, 1, 1))) +__kernel +void kernel_HistogramRectOneChannelReduction( + int n, // unused pixel redundancy + __global uint *histBuffer, + __global int* histResult) { + + // declare variables + // int channel = get_group_id(0)/HIST_SIZE; + int bin = get_group_id(0)%HIST_SIZE; + int value = 0; + + // accumulate in register + for ( int i = get_local_id(0); i < HIST_REDUNDANCY; i+=GROUP_SIZE) { + value += histBuffer[ bin*HIST_REDUNDANCY+i]; + } + + // reduction in local memory + __local int localHist[GROUP_SIZE]; + localHist[get_local_id(0)] = value; + barrier(CLK_LOCAL_MEM_FENCE); + for (int stride = GROUP_SIZE/2; stride >= 1; stride /= 2) { + if (get_local_id(0) < stride) { + value = localHist[ get_local_id(0)+stride]; + } + barrier(CLK_LOCAL_MEM_FENCE); + if (get_local_id(0) < stride) { + localHist[ get_local_id(0)] += value; + } + barrier(CLK_LOCAL_MEM_FENCE); + } + + // write reduction to final result + if (get_local_id(0) == 0) { + histResult[get_group_id(0)] = localHist[0]; + } +} // kernel_HistogramRectOneChannelReduction +) + + +KERNEL( +// unused + // each work group (x256) handles a histogram bin +\n __attribute__((reqd_work_group_size(256, 1, 1))) +\n __kernel +\n void kernel_HistogramRectAllChannelsReduction_Grey( +\n int n, // pixel redundancy that needs to be accumulated +\n __global uint *histBuffer, +\n __global uint* histResult) { // each wg accumulates 1 bin +\n +\n /* declare variables */ +\n +\n // work indices +\n size_t groupId = get_group_id(0); +\n size_t localId = get_local_id(0); // 0 -> 256-1 +\n size_t globalId = get_global_id(0); // 0 -> 8*10*256-1=20480-1 +\n uint numThreads = get_global_size(0); +\n unsigned int hist = 0; +\n +\n /* accumulate in global memory */ +\n for ( uint p = 0; p < n; p+=GROUP_SIZE) { +\n hist += histBuffer[ (get_group_id(0)*n + p)]; +\n } +\n +\n /* reduction in local memory */ +\n // populate local memory +\n __local unsigned int localHist[GROUP_SIZE]; + +\n localHist[localId] = hist; +\n barrier(CLK_LOCAL_MEM_FENCE); +\n +\n for (int stride = GROUP_SIZE/2; stride >= 1; stride /= 2) { +\n if (localId < stride) { +\n hist = localHist[ (localId+stride)]; +\n } +\n barrier(CLK_LOCAL_MEM_FENCE); +\n if (localId < stride) { +\n localHist[ localId] += hist; +\n } +\n barrier(CLK_LOCAL_MEM_FENCE); +\n } +\n +\n if (localId == 0) +\n histResult[get_group_id(0)] = localHist[0]; +\n +\n } // kernel_HistogramRectAllChannelsReduction_Grey + +) + +// ThresholdRectToPix Kernel +// only supports 4 channels +// imageData is input image (24-bits/pixel) +// pix is output image (1-bit/pixel) +KERNEL( +\n#define CHAR_VEC_WIDTH 8 \n +\n#define PIXELS_PER_WORD 32 \n +\n#define PIXELS_PER_BURST 8 \n +\n#define BURSTS_PER_WORD (PIXELS_PER_WORD/PIXELS_PER_BURST) \n + typedef union { + uchar s[PIXELS_PER_BURST*NUM_CHANNELS]; + uchar8 v[(PIXELS_PER_BURST*NUM_CHANNELS)/CHAR_VEC_WIDTH]; + } charVec; + +__attribute__((reqd_work_group_size(256, 1, 1))) +__kernel +void kernel_ThresholdRectToPix( + __global const uchar8 *imageData, + int height, + int width, + int wpl, // words per line + __global int *thresholds, + __global int *hi_values, + __global int *pix) { + + // declare variables + int pThresholds[NUM_CHANNELS]; + int pHi_Values[NUM_CHANNELS]; + for ( int i = 0; i < NUM_CHANNELS; i++) { + pThresholds[i] = thresholds[i]; + pHi_Values[i] = hi_values[i]; + } + + // for each word (32 pixels) in output image + for ( uint w = get_global_id(0); w < wpl*height; w += get_global_size(0) ) { + unsigned int word = 0; // all bits start at zero + + // for each burst in word + for ( int b = 0; b < BURSTS_PER_WORD; b++) { + + // load burst + charVec pixels; + for ( int i = 0; i < (PIXELS_PER_BURST*NUM_CHANNELS)/CHAR_VEC_WIDTH; i++ ) { + pixels.v[i] = imageData[w*(BURSTS_PER_WORD*(PIXELS_PER_BURST*NUM_CHANNELS)/CHAR_VEC_WIDTH) + b*((PIXELS_PER_BURST*NUM_CHANNELS)/CHAR_VEC_WIDTH) + i]; + } + + // for each pixel in burst + for ( int p = 0; p < PIXELS_PER_BURST; p++) { + for ( int c = 0; c < NUM_CHANNELS; c++) { + unsigned char pixChan = pixels.s[p*NUM_CHANNELS + c]; + if (pHi_Values[c] >= 0 && (pixChan > pThresholds[c]) == (pHi_Values[c] == 0)) { + word |= (0x80000000 >> ((b*PIXELS_PER_BURST+p)&31)); + } + } + } + } + pix[w] = word; + } +} + +// only supports 1 channel + typedef union { + uchar s[PIXELS_PER_BURST]; + uchar8 v[(PIXELS_PER_BURST)/CHAR_VEC_WIDTH]; + } charVec1; + +__attribute__((reqd_work_group_size(256, 1, 1))) +__kernel +void kernel_ThresholdRectToPix_OneChan( + __global const uchar8 *imageData, + int height, + int width, + int wpl, // words per line + __global int *thresholds, + __global int *hi_values, + __global int *pix) { + + // declare variables + int pThresholds[1]; + int pHi_Values[1]; + for ( int i = 0; i < 1; i++) { + pThresholds[i] = thresholds[i]; + pHi_Values[i] = hi_values[i]; + } + + // for each word (32 pixels) in output image + for ( uint w = get_global_id(0); w < wpl*height; w += get_global_size(0) ) { + unsigned int word = 0; // all bits start at zero + + // for each burst in word + for ( int b = 0; b < BURSTS_PER_WORD; b++) { + + // load burst + charVec1 pixels; + for ( int i = 0; i < (PIXELS_PER_BURST)/CHAR_VEC_WIDTH; i++ ) { + pixels.v[i] = imageData[w*(BURSTS_PER_WORD*(PIXELS_PER_BURST)/CHAR_VEC_WIDTH) + b*((PIXELS_PER_BURST)/CHAR_VEC_WIDTH) + i]; + } + + // for each pixel in burst + for ( int p = 0; p < PIXELS_PER_BURST; p++) { + for ( int c = 0; c < 1; c++) { + unsigned char pixChan = pixels.s[p + c]; + if (pHi_Values[c] >= 0 && (pixChan > pThresholds[c]) == (pHi_Values[c] == 0)) { + word |= (0x80000000 >> ((b*PIXELS_PER_BURST+p)&31)); + } + } + } + } + pix[w] = word; + } +} +) + + ; // close char* + +#endif // USE_EXTERNAL_KERNEL +#endif //_OCL_KERNEL_H_ +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + +// Alternative histogram kernel written to use uchar and different global memory scattered write +// was a little better for intel platforms but still not faster then native serial code +#if 0 +/* data layed out as + bin0 bin1 bin2... + r,g,b,a,r,g,b,a,r,g,b,a nthreads/4 copies +*/ +\n__attribute__((reqd_work_group_size(256, 1, 1))) +\n __kernel +\n void kernel_HistogramRectAllChannels_uchar( +\n volatile __global const uchar *data, +\n uint numPixels, +\n volatile __global uint *histBuffer) { +\n +\n // for each pixel/channel, accumulate in global memory +\n for ( uint pc = get_global_id(0); pc < numPixels*NUM_CHANNELS; pc += get_global_size(0) ) { +\n uchar value = data[pc]; +\n int idx = value*get_global_size(0) + get_global_id(0); +\n histBuffer[ idx ]++; // coalesced if same value +\n } +\n } // kernel_HistogramRectAllChannels +\n +\n __attribute__((reqd_work_group_size(256, 1, 1))) +\n __kernel +\n void kernel_HistogramRectAllChannelsReduction_uchar( +\n int n, // pixel redundancy that needs to be accumulated = nthreads/4 +\n __global uint4 *histBuffer, +\n __global uint* histResult) { // each wg accumulates 1 bin (all channels within it +\n +\n // declare variables +\n int binIdx = get_group_id(0); +\n size_t groupId = get_group_id(0); +\n size_t localId = get_local_id(0); // 0 -> 256-1 +\n size_t globalId = get_global_id(0); // 0 -> 8*10*256-1=20480-1 +\n uint numThreads = get_global_size(0); +\n uint4 hist = {0, 0, 0, 0}; +\n +\n // accumulate in register +\n for ( uint p = get_local_id(0); p < n; p+=GROUP_SIZE) { +\n hist += histBuffer[binIdx*n+p]; +\n } +\n +\n // reduction in local memory +\n __local uint4 localHist[GROUP_SIZE]; +\n localHist[localId] = hist; +\n barrier(CLK_LOCAL_MEM_FENCE); +\n +\n for (int stride = GROUP_SIZE/2; stride >= 1; stride /= 2) { +\n if (localId < stride) { +\n hist = localHist[ localId+stride]; +\n } +\n barrier(CLK_LOCAL_MEM_FENCE); +\n if (localId < stride) { +\n localHist[ localId] += hist; +\n } +\n barrier(CLK_LOCAL_MEM_FENCE); +\n } +\n +\n // write reduction to final result +\n if (localId == 0) { +\n histResult[0*HIST_SIZE+binIdx] = localHist[0].s0; +\n histResult[1*HIST_SIZE+binIdx] = localHist[0].s1; +\n histResult[2*HIST_SIZE+binIdx] = localHist[0].s2; +\n histResult[3*HIST_SIZE+binIdx] = localHist[0].s3; +\n } +\n +\n } // kernel_HistogramRectAllChannels +#endif diff --git a/TesseractOCR/include/tesseract/ocrblock.h b/TesseractOCR/include/tesseract/ocrblock.h old mode 100755 new mode 100644 index 9e6fa0d1..207c1e85 --- a/TesseractOCR/include/tesseract/ocrblock.h +++ b/TesseractOCR/include/tesseract/ocrblock.h @@ -20,7 +20,6 @@ #ifndef OCRBLOCK_H #define OCRBLOCK_H -#include "img.h" #include "ocrpara.h" #include "ocrrow.h" #include "pdblock.h" diff --git a/TesseractOCR/include/tesseract/ocrclass.h b/TesseractOCR/include/tesseract/ocrclass.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/ocrfeatures.h b/TesseractOCR/include/tesseract/ocrfeatures.h new file mode 100644 index 00000000..734b4ff0 --- /dev/null +++ b/TesseractOCR/include/tesseract/ocrfeatures.h @@ -0,0 +1,134 @@ +/****************************************************************************** + ** Filename: features.h + ** Purpose: Generic definition of a feature. + ** Author: Dan Johnson + ** History: Sun May 20 10:28:30 1990, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef FEATURES_H +#define FEATURES_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "blobs.h" + +#include + +class DENORM; +struct INT_FX_RESULT_STRUCT; + +#undef Min +#undef Max +#define FEAT_NAME_SIZE 80 + +// define trap errors which can be caused by this module +#define ILLEGAL_FEATURE_PARAM 1000 +#define ILLEGAL_NUM_FEATURES 1001 + +// A character is described by multiple sets of extracted features. Each +// set contains a number of features of a particular type, for example, a +// set of bays, or a set of closures, or a set of microfeatures. Each +// feature consists of a number of parameters. All features within a +// feature set contain the same number of parameters. All circular +// parameters are required to be the first parameters in the feature. + +struct PARAM_DESC { + inT8 Circular; // TRUE if dimension wraps around + inT8 NonEssential; // TRUE if dimension not used in searches + FLOAT32 Min; // low end of range for circular dimensions + FLOAT32 Max; // high end of range for circular dimensions + FLOAT32 Range; // Max - Min + FLOAT32 HalfRange; // (Max - Min)/2 + FLOAT32 MidRange; // (Max + Min)/2 +}; + +struct FEATURE_DESC_STRUCT { + uinT16 NumParams; // total # of params + const char *ShortName; // short name for feature + const PARAM_DESC *ParamDesc; // array - one per param +}; +typedef FEATURE_DESC_STRUCT *FEATURE_DESC; + +struct FEATURE_STRUCT { + const FEATURE_DESC_STRUCT *Type; // points to description of feature type + FLOAT32 Params[1]; // variable size array - params for feature +}; +typedef FEATURE_STRUCT *FEATURE; + +struct FEATURE_SET_STRUCT { + uinT16 NumFeatures; // number of features in set + uinT16 MaxNumFeatures; // maximum size of feature set + FEATURE Features[1]; // variable size array of features +}; +typedef FEATURE_SET_STRUCT *FEATURE_SET; + +// A generic character description as a char pointer. In reality, it will be +// a pointer to some data structure. Paired feature extractors/matchers need +// to agree on the data structure to be used, however, the high level +// classifier does not need to know the details of this data structure. +typedef char *CHAR_FEATURES; + +typedef FEATURE_SET (*FX_FUNC)(TBLOB *, const DENORM&, const DENORM&, + const INT_FX_RESULT_STRUCT&); + +struct FEATURE_EXT_STRUCT { + FX_FUNC Extractor; // func to extract features +}; + +/*---------------------------------------------------------------------- + Macros for defining the parameters of a new features +----------------------------------------------------------------------*/ +#define StartParamDesc(Name) \ +const PARAM_DESC Name[] = { + +#define DefineParam(Circular, NonEssential, Min, Max) \ + {Circular, NonEssential, Min, Max, \ + (Max) - (Min), (((Max) - (Min))/2.0), (((Max) + (Min))/2.0)}, + +#define EndParamDesc }; + +/*---------------------------------------------------------------------- +Macro for describing a new feature. The parameters of the macro +are as follows: + +DefineFeature (Name, NumLinear, NumCircular, ShortName, ParamName) +----------------------------------------------------------------------*/ +#define DefineFeature(Name, NL, NC, SN, PN) \ +const FEATURE_DESC_STRUCT Name = { \ + ((NL) + (NC)), SN, PN}; + +/*---------------------------------------------------------------------- + Generic routines that work for all feature types +----------------------------------------------------------------------*/ +BOOL8 AddFeature(FEATURE_SET FeatureSet, FEATURE Feature); + +void FreeFeature(FEATURE Feature); + +void FreeFeatureSet(FEATURE_SET FeatureSet); + +FEATURE NewFeature(const FEATURE_DESC_STRUCT *FeatureDesc); + +FEATURE_SET NewFeatureSet(int NumFeatures); + +FEATURE ReadFeature(FILE *File, const FEATURE_DESC_STRUCT *FeatureDesc); + +FEATURE_SET ReadFeatureSet(FILE *File, const FEATURE_DESC_STRUCT *FeatureDesc); + +void WriteFeature(FILE *File, FEATURE Feature); + +void WriteFeatureSet(FILE *File, FEATURE_SET FeatureSet); + +void WriteOldParamDesc(FILE *File, const FEATURE_DESC_STRUCT *FeatureDesc); + +#endif diff --git a/TesseractOCR/include/tesseract/ocrpara.h b/TesseractOCR/include/tesseract/ocrpara.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/ocrrow.h b/TesseractOCR/include/tesseract/ocrrow.h old mode 100755 new mode 100644 index f55692ad..1a238892 --- a/TesseractOCR/include/tesseract/ocrrow.h +++ b/TesseractOCR/include/tesseract/ocrrow.h @@ -27,7 +27,7 @@ class TO_ROW; -class PARA; +struct PARA; class ROW:public ELIST_LINK { diff --git a/TesseractOCR/include/tesseract/oldbasel.h b/TesseractOCR/include/tesseract/oldbasel.h new file mode 100644 index 00000000..c8f884ff --- /dev/null +++ b/TesseractOCR/include/tesseract/oldbasel.h @@ -0,0 +1,175 @@ +/********************************************************************** + * File: oldbasel.h (Formerly oldbl.h) + * Description: A re-implementation of the old baseline algorithm. + * Author: Ray Smith + * Created: Wed Oct 6 09:41:48 BST 1993 + * + * (C) Copyright 1993, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef OLDBASEL_H +#define OLDBASEL_H + +#include "params.h" +#include "blobbox.h" + +extern BOOL_VAR_H (textord_really_old_xheight, FALSE, +"Use original wiseowl xheight"); +extern BOOL_VAR_H (textord_oldbl_debug, FALSE, +"Debug old baseline generation"); +extern BOOL_VAR_H (textord_debug_baselines, FALSE, +"Debug baseline generation"); +extern BOOL_VAR_H (textord_oldbl_paradef, TRUE, "Use para default mechanism"); +extern BOOL_VAR_H (textord_oldbl_split_splines, TRUE, +"Split stepped splines"); +extern BOOL_VAR_H (textord_oldbl_merge_parts, TRUE, +"Merge suspect partitions"); +extern BOOL_VAR_H (oldbl_xhfix, FALSE, +"Fix bug in modes threshold for xheights"); +extern INT_VAR_H (oldbl_holed_losscount, 10, +"Max lost before fallback line used"); +extern double_VAR_H (oldbl_dot_error_size, 1.26, "Max aspect ratio of a dot"); +extern double_VAR_H (textord_oldbl_jumplimit, 0.15, +"X fraction for new partition"); +int get_blob_coords( //get boxes + TO_ROW *row, //row to use + inT32 lineheight, //block level + TBOX *blobcoords, //ouput boxes + BOOL8 &holed_line, //lost a lot of blobs + int &outcount //no of real blobs + ); +void make_first_baseline ( //initial approximation +TBOX blobcoords[], /*blob bounding boxes */ +int blobcount, /*no of blobcoords */ +int xcoords[], /*coords for spline */ +int ycoords[], /*approximator */ +QSPLINE * spline, /*initial spline */ +QSPLINE * baseline, /*output spline */ +float jumplimit /*guess half descenders */ +); +void make_holed_baseline ( //initial approximation +TBOX blobcoords[], /*blob bounding boxes */ +int blobcount, /*no of blobcoords */ +QSPLINE * spline, /*initial spline */ +QSPLINE * baseline, /*output spline */ +float gradient //of line +); +int partition_line ( //partition blobs +TBOX blobcoords[], //bounding boxes +int blobcount, /*no of blobs on row */ +int *numparts, /*number of partitions */ +char partids[], /*partition no of each blob */ +int partsizes[], /*no in each partition */ +QSPLINE * spline, /*curve to fit to */ +float jumplimit, /*allowed delta change */ +float ydiffs[] /*diff from spline */ +); +void merge_oldbl_parts ( //partition blobs +TBOX blobcoords[], //bounding boxes +int blobcount, /*no of blobs on row */ +char partids[], /*partition no of each blob */ +int partsizes[], /*no in each partition */ +int biggestpart, //major partition +float jumplimit /*allowed delta change */ +); +int get_ydiffs ( //evaluate differences +TBOX blobcoords[], //bounding boxes +int blobcount, /*no of blobs */ +QSPLINE * spline, /*approximating spline */ +float ydiffs[] /*output */ +); +int choose_partition ( //select partition +register float diff, /*diff from spline */ +float partdiffs[], /*diff on all parts */ +int lastpart, /*last assigned partition */ +float jumplimit, /*new part threshold */ +float* drift, +float* last_delta, +int *partcount /*no of partitions */ +); +int partition_coords ( //find relevant coords +TBOX blobcoords[], //bounding boxes +int blobcount, /*no of blobs in row */ +char partids[], /*partition no of each blob */ +int bestpart, /*best new partition */ +int xcoords[], /*points to work on */ +int ycoords[] /*points to work on */ +); +int segment_spline ( //make xstarts +TBOX blobcoords[], //boundign boxes +int blobcount, /*no of blobs in row */ +int xcoords[], /*points to work on */ +int ycoords[], /*points to work on */ +int degree, int pointcount, /*no of points */ +int xstarts[] //result +); +BOOL8 split_stepped_spline ( //make xstarts +QSPLINE * baseline, //current shot +float jumplimit, //max step fuction +int xcoords[], /*points to work on */ +int xstarts[], //result +int &segments //no of segments +); +void insert_spline_point ( //get descenders +int xstarts[], //starts to shuffle +int segment, //insertion pt +int coord1, //coords to add +int coord2, int &segments //total segments +); +void find_lesser_parts ( //get descenders +TO_ROW * row, //row to process +TBOX blobcoords[], //bounding boxes +int blobcount, /*no of blobs */ +char partids[], /*partition of each blob */ +int partsizes[], /*size of each part */ +int partcount, /*no of partitions */ +int bestpart /*biggest partition */ +); + +void old_first_xheight ( //the wiseowl way +TO_ROW * row, /*current row */ +TBOX blobcoords[], /*blob bounding boxes */ +int initialheight, //initial guess +int blobcount, /*blobs in blobcoords */ +QSPLINE * baseline, /*established */ +float jumplimit /*min ascender height */ +); + +void make_first_xheight ( //find xheight +TO_ROW * row, /*current row */ +TBOX blobcoords[], /*blob bounding boxes */ +int lineheight, //initial guess +int init_lineheight, //block level guess +int blobcount, /*blobs in blobcoords */ +QSPLINE * baseline, /*established */ +float jumplimit /*min ascender height */ +); + +int *make_height_array ( //get array of heights +TBOX blobcoords[], /*blob bounding boxes */ +int blobcount, /*blobs in blobcoords */ +QSPLINE * baseline /*established */ +); + +void find_top_modes ( //get modes +STATS * stats, //stats to hack +int statnum, //no of piles +int modelist[], int modenum //no of modes to get +); + +void pick_x_height(TO_ROW * row, //row to do +int modelist[], +int lefts[], int rights[], +STATS * heightstat, +int mode_threshold); +#endif diff --git a/TesseractOCR/include/tesseract/oldlist.h b/TesseractOCR/include/tesseract/oldlist.h new file mode 100644 index 00000000..103dd725 --- /dev/null +++ b/TesseractOCR/include/tesseract/oldlist.h @@ -0,0 +1,356 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: list.h (Formerly list.h) + * Description: List processing procedures declarations. + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Wed Dec 5 15:43:17 1990 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + ******************************************************************************** + * + * This file contains the interface for a set of general purpose list + * manipulation routines. For the implementation of these routines see + * the file "list.c". + * + ******************************************************************************** + * + * INDEX + * ======= + * + * BASICS: + * ------- + * first_node - Macro to return the first list node (not the cell). + * list_rest - Macro the return the second list cell + * pop - Destroy one list cell + * push - Create one list cell and set the node and next fields + * + * ITERATION: + * ----------------- + * iterate - Macro to create a for loop to visit each cell. + * iterate_list - Macro to visit each cell using a local variable. + * for_each - Applies a function to each node. + * + * LIST CELL COUNTS: + * ----------------- + * count - Returns the number of list cells in the list. + * second_node - Returns the second node. + * third - Returns the third node. + * fourth - Returns the fourth node. + * fifth - Returns the fifth node. + * last - Returns the last list cell. + * pair - Creates a list of two elements. + * + * COPYING: + * ----------------- + * copy_first - Pushes the first element from list 1 onto list 2. + * copy - Create a copy of a list. + * concat - Creates a new list that is a copy of both input lists. + * delete_n - Creates a new list without the chosen elements. + * reverse - Creates a backwards copy of the input list. + * sort - Use quick sort to construct a new list. + * transform - Creates a new list by transforming each of the nodes. + * + * TRANFORMS: (Note: These functions all modify the input list.) + * ---------- + * join - Concatenates list 1 and list 2. + * delete_d - Removes the requested elements from the list. + * transform_d - Modifies the list by applying a function to each node. + * insert - Add a new element into this spot in a list. (not NIL_LIST) + * push_last - Add a new element onto the end of a list. + * reverse_d - Reverse a list and destroy the old one. + * + * ASSOCIATED LISTS: + * ----------------- + * adelete - Remove a particular entry from an associated list. + * assoc - Find an entry in an associated list that matches a key. + * match - Return the data element of an a-list entry. + * + * DISPLAY: + * ----------------- + * print_cell - Print a hex dump of a list cell. + * show - Displays a string and a list (using lprint). + * + * SETS: + * ----- + * adjoin - Add a new element to list if it does not exist already. + * intersection - Create a new list that is the set intersection. + * set_union - Create a new list that is the set intersection. + * set_difference - Create a new list that is the set difference. + * s_adjoin - Add an element to a sort list if it is not there. + * s_intersection - Set intersection on a sorted list. Modifies old list. + * s_union - Set intersection on a sorted list. Modifies old list. + * search - Return the pointer to the list cell whose node matches. + * + * COMPARISONS: + * ----------------- + * is_same - Compares each node to the key. + * is_not_same - Compares each node to the key. + * is_key - Compares first of each node to the key. + * is_not_key - Compares first of each node to the key. + * + * CELL OPERATIONS: + * ----------------- + * new_cell - Obtain a new list cell from the free list. Allocate. + * free_cell - Return a list cell to the free list. + * destroy - Return all list cells in a list. + * destroy_nodes - Apply a function to each list cell and destroy the list. + * set_node - Assign the node field in a list cell. + * set_rest - Assign the next field in a list cell. + * + ***********************************************************************/ + +#ifndef LIST_H +#define LIST_H + +#include "cutil.h" +#include "tesscallback.h" + +/*---------------------------------------------------------------------- + T y p e s +----------------------------------------------------------------------*/ +#define NIL_LIST (LIST) 0 +struct list_rec +{ + struct list_rec *node; + struct list_rec *next; +}; +typedef list_rec *LIST; + +/*---------------------------------------------------------------------- + M a c r o s +----------------------------------------------------------------------*/ +/* Predefinitions */ +#define list_rest(l) ((l) ? (l)->next : NIL_LIST) +#define first_node(l) ((l) ? (l)->node : NIL_LIST) + +/********************************************************************** + * c o p y f i r s t + * + * Do the appropriate kind a push operation to copy the first node from + * one list to another. + * + **********************************************************************/ + +#define copy_first(l1,l2) \ +(l2=push(l2, first_node(l1))) + +/********************************************************************** + * i t e r a t e + * + * Visit each node in the list. Replace the old list with the list + * minus the head. Continue until the list is NIL_LIST. + **********************************************************************/ + +#define iterate(l) \ +for (; (l) != NIL_LIST; (l) = list_rest (l)) + +/********************************************************************** + * i t e r a t e l i s t + * + * Visit each node in the list (l). Use a local variable (x) to iterate + * through all of the list cells. This macro is identical to iterate + * except that it does not lose the original list. + **********************************************************************/ + +#define iterate_list(x,l) \ +for ((x)=(l); (x)!=0; (x)=list_rest(x)) + +/********************************************************************** + * j o i n o n + * + * Add another list onto the tail of this one. The list given as an input + * parameter is modified. + **********************************************************************/ + +#define JOIN_ON(list1,list2) \ +((list1) = join ((list1), (list2))) + +/********************************************************************** + * p o p o f f + * + * Add a cell onto the front of a list. The list given as an input + * parameter is modified. + **********************************************************************/ + +#define pop_off(list) \ +((list) = pop (list)) + +/********************************************************************** + * p u s h o n + * + * Add a cell onto the front of a list. The list given as an input + * parameter is modified. + **********************************************************************/ + +#define push_on(list,thing) \ +((list) = push (list, (LIST) (thing))) + +/********************************************************************** + * s e c o n d + * + * Return the contents of the second list element. + * + * #define second_node(l) first_node (list_rest (l)) + **********************************************************************/ + +#define second_node(l) \ +first_node (list_rest (l)) + +/********************************************************************** + * s e t r e s t + * + * Change the "next" field of a list element to point to a desired place. + * + * #define set_rest(l,node) l->next = node; + **********************************************************************/ + +#define set_rest(l,cell)\ +((l)->next = (cell)) + +/********************************************************************** + * t h i r d + * + * Return the contents of the third list element. + * + * #define third(l) first_node (list_rest (list_rest (l))) + **********************************************************************/ + +#define third(l) \ +first_node (list_rest (list_rest (l))) + +/*---------------------------------------------------------------------- + Public Funtion Prototypes +----------------------------------------------------------------------*/ +int count(LIST var_list); + +LIST delete_d(LIST list, void *key, int_compare is_equal); + +LIST delete_d(LIST list, void *key, + TessResultCallback2* is_equal); + +LIST destroy(LIST list); + +void destroy_nodes(LIST list, void_dest destructor); + +void insert(LIST list, void *node); + +int is_same_node(void *item1, void *item2); + +int is_same(void *item1, void *item2); + +LIST join(LIST list1, LIST list2); + +LIST last(LIST var_list); + +void *nth_cell(LIST var_list, int item_num); + +LIST pop(LIST list); + +LIST push(LIST list, void *element); + +LIST push_last(LIST list, void *item); + +LIST reverse(LIST list); + +LIST reverse_d(LIST list); + +LIST s_adjoin(LIST var_list, void *variable, int_compare compare); + +LIST search(LIST list, void *key, int_compare is_equal); + +LIST search(LIST list, void *key, TessResultCallback2*); + +/* +#if defined(__STDC__) || defined(__cplusplus) +# define _ARGS(s) s +#else +# define _ARGS(s) () +#endif + +typedef void (*destructor) _ARGS((LIST l)); + +typedef LIST (*list_proc) _ARGS((LIST a)); + +int count +_ARGS((LIST var_list)); + +LIST delete_d +_ARGS((LIST list, + LIST key, + int_compare is_equal)); + +LIST destroy +_ARGS((LIST list)); + +LIST destroy_nodes +_ARGS((LIST list, + void_dest destructor)); + +void insert +_ARGS((LIST list, + LIST node)); + +int is_same_node +_ARGS((LIST s1, + LIST s2)); + +int is_same +_ARGS((LIST s1, + LIST s2)); + +LIST join +_ARGS((LIST list1, + LIST list2)); + +LIST last +_ARGS((LIST var_list)); + +LIST nth_cell +_ARGS((LIST var_list, + int item_num)); + +LIST pop +_ARGS((LIST list)); + +LIST push +_ARGS((LIST list, + LIST element)); + +LIST push_last +_ARGS((LIST list, + LIST item)); + +LIST reverse +_ARGS((LIST list)); + +LIST reverse_d +_ARGS((LIST list)); + +LIST s_adjoin +_ARGS((LIST var_list, + LIST variable, + int_compare compare)); + +LIST search +_ARGS((LIST list, + LIST key, + int_compare is_equal)); + +#undef _ARGS +*/ +#endif diff --git a/TesseractOCR/include/tesseract/olutil.h b/TesseractOCR/include/tesseract/olutil.h new file mode 100644 index 00000000..c7eeecd2 --- /dev/null +++ b/TesseractOCR/include/tesseract/olutil.h @@ -0,0 +1,82 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: olutil.h (Formerly olutil.h) + * Description: + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Wed Jul 10 14:21:55 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ +#ifndef OLUTIL_H +#define OLUTIL_H + +/*---------------------------------------------------------------------- + I n c l u d e s +----------------------------------------------------------------------*/ +#include "blobs.h" + +/*---------------------------------------------------------------------- + M a c r o s +----------------------------------------------------------------------*/ +/********************************************************************** + * is_inside_angle + * + * Return true if the edgept supplied as input is an inside angle. This + * is determined by the angular change of the vectors from point to + * point. + + **********************************************************************/ + +#define is_inside_angle(pt) \ +(angle_change ((pt)->prev, (pt), (pt)->next) < chop_inside_angle) + +/********************************************************************** + * same_outline_bounds + * + * Return TRUE if these two outlines have the same bounds. + **********************************************************************/ + +#define same_outline_bounds(outline,other_outline) \ +(outline->topleft.x == other_outline->topleft.x && \ + outline->topleft.y == other_outline->topleft.y && \ + outline->botright.x == other_outline->botright.x && \ + outline->botright.y == other_outline->botright.y) \ + + +/********************************************************************** + * weighted_edgept_dist + * + * Return the distance (squared) between the two edge points. + **********************************************************************/ + +#define weighted_edgept_dist(p1,p2,chop_x_y_weight) \ +(((p1)->pos.x - (p2)->pos.x) * \ + ((p1)->pos.x - (p2)->pos.x) * chop_x_y_weight + \ + ((p1)->pos.y - (p2)->pos.y) * \ + ((p1)->pos.y - (p2)->pos.y)) + +/*---------------------------------------------------------------------- + F u n c t i o n s +----------------------------------------------------------------------*/ +void correct_blob_order(TBLOB *blob1, TBLOB *blob2); + +void eliminate_duplicate_outlines(TBLOB *blob); + +void setup_blob_outlines(TBLOB *blob); + +#endif diff --git a/TesseractOCR/include/tesseract/opencl_device_selection.h b/TesseractOCR/include/tesseract/opencl_device_selection.h new file mode 100644 index 00000000..ba45b5de --- /dev/null +++ b/TesseractOCR/include/tesseract/opencl_device_selection.h @@ -0,0 +1,594 @@ +#ifdef USE_OPENCL +#ifndef DEVICE_SELECTION_H +#define DEVICE_SELECTION_H + + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#define DS_DEVICE_NAME_LENGTH 256 + +typedef enum { + DS_SUCCESS = 0, + DS_INVALID_PROFILE = 1000, + DS_MEMORY_ERROR, + DS_INVALID_PERF_EVALUATOR_TYPE, + DS_INVALID_PERF_EVALUATOR, + DS_PERF_EVALUATOR_ERROR, + DS_FILE_ERROR, + DS_UNKNOWN_DEVICE_TYPE, + DS_PROFILE_FILE_ERROR, + DS_SCORE_SERIALIZER_ERROR, + DS_SCORE_DESERIALIZER_ERROR +} ds_status; + +// device type +typedef enum { + DS_DEVICE_NATIVE_CPU = 0, + DS_DEVICE_OPENCL_DEVICE +} ds_device_type; + + +typedef struct { + ds_device_type type; + cl_device_id oclDeviceID; + char* oclDeviceName; + char* oclDriverVersion; + // a pointer to the score data, the content/format is application defined. + void* score; +} ds_device; + +typedef struct { + unsigned int numDevices; + ds_device* devices; + const char* version; +} ds_profile; + +// deallocate memory used by score +typedef ds_status (*ds_score_release)(void* score); +static ds_status releaseDSProfile(ds_profile* profile, ds_score_release sr) { + ds_status status = DS_SUCCESS; + if (profile!=NULL) { + if (profile->devices!=NULL && sr!=NULL) { + unsigned int i; + for (i = 0; i < profile->numDevices; i++) { + status = sr(profile->devices[i].score); + if (status != DS_SUCCESS) + break; + } + free(profile->devices); + } + free(profile); + } + return status; +} + + +static ds_status initDSProfile(ds_profile** p, const char* version) { + int numDevices; + cl_uint numPlatforms; + cl_platform_id* platforms = NULL; + cl_device_id* devices = NULL; + ds_status status = DS_SUCCESS; + ds_profile* profile = NULL; + unsigned int next; + unsigned int i; + + if (p == NULL) + return DS_INVALID_PROFILE; + + profile = (ds_profile*)malloc(sizeof(ds_profile)); + if (profile == NULL) + return DS_MEMORY_ERROR; + + memset(profile, 0, sizeof(ds_profile)); + + clGetPlatformIDs(0, NULL, &numPlatforms); + if (numPlatforms == 0) + goto cleanup; + + platforms = (cl_platform_id*)malloc(numPlatforms*sizeof(cl_platform_id)); + if (platforms == NULL) { + status = DS_MEMORY_ERROR; + goto cleanup; + } + clGetPlatformIDs(numPlatforms, platforms, NULL); + + numDevices = 0; + for (i = 0; i < (unsigned int)numPlatforms; i++) { + cl_uint num; + clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, 0, NULL, &num); + numDevices+=num; + } + if (numDevices == 0) + goto cleanup; + + devices = (cl_device_id*)malloc(numDevices*sizeof(cl_device_id)); + if (devices == NULL) { + status = DS_MEMORY_ERROR; + goto cleanup; + } + + profile->numDevices = numDevices+1; // +1 to numDevices to include the native CPU + profile->devices = (ds_device*)malloc(profile->numDevices*sizeof(ds_device)); + if (profile->devices == NULL) { + profile->numDevices = 0; + status = DS_MEMORY_ERROR; + goto cleanup; + } + memset(profile->devices, 0, profile->numDevices*sizeof(ds_device)); + + next = 0; + for (i = 0; i < (unsigned int)numPlatforms; i++) { + cl_uint num; + unsigned j; + clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, numDevices, devices, &num); + for (j = 0; j < num; j++, next++) { + char buffer[DS_DEVICE_NAME_LENGTH]; + size_t length; + + profile->devices[next].type = DS_DEVICE_OPENCL_DEVICE; + profile->devices[next].oclDeviceID = devices[j]; + + clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_NAME + , DS_DEVICE_NAME_LENGTH, &buffer, NULL); + length = strlen(buffer); + profile->devices[next].oclDeviceName = (char*)malloc(length+1); + memcpy(profile->devices[next].oclDeviceName, buffer, length+1); + + clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DRIVER_VERSION + , DS_DEVICE_NAME_LENGTH, &buffer, NULL); + length = strlen(buffer); + profile->devices[next].oclDriverVersion = (char*)malloc(length+1); + memcpy(profile->devices[next].oclDriverVersion, buffer, length+1); + } + } + profile->devices[next].type = DS_DEVICE_NATIVE_CPU; + profile->version = version; + +cleanup: + if (platforms) free(platforms); + if (devices) free(devices); + if (status == DS_SUCCESS) { + *p = profile; + } + else { + if (profile) { + if (profile->devices) + free(profile->devices); + free(profile); + } + } + return status; +} + +// Pointer to a function that calculates the score of a device (ex: +// device->score) update the data size of score. The encoding and the format +// of the score data is implementation defined. The function should return +// DS_SUCCESS if there's no error to be reported. +typedef ds_status (*ds_perf_evaluator)(ds_device* device, void* data); + +typedef enum { + DS_EVALUATE_ALL + ,DS_EVALUATE_NEW_ONLY +} ds_evaluation_type; + +static ds_status profileDevices(ds_profile* profile, + const ds_evaluation_type type, + ds_perf_evaluator evaluator, + void* evaluatorData, unsigned int* numUpdates) { + ds_status status = DS_SUCCESS; + unsigned int i; + unsigned int updates = 0; + + if (profile == NULL) { + return DS_INVALID_PROFILE; + } + if (evaluator == NULL) { + return DS_INVALID_PERF_EVALUATOR; + } + + for (i = 0; i < profile->numDevices; i++) { + ds_status evaluatorStatus; + + switch (type) { + case DS_EVALUATE_NEW_ONLY: + if (profile->devices[i].score != NULL) + break; + // else fall through + case DS_EVALUATE_ALL: + evaluatorStatus = evaluator(profile->devices+i, evaluatorData); + if (evaluatorStatus != DS_SUCCESS) { + status = evaluatorStatus; + return status; + } + updates++; + break; + default: + return DS_INVALID_PERF_EVALUATOR_TYPE; + break; + }; + } + if (numUpdates) + *numUpdates = updates; + return status; +} + + +#define DS_TAG_VERSION "" +#define DS_TAG_VERSION_END "" +#define DS_TAG_DEVICE "" +#define DS_TAG_DEVICE_END "" +#define DS_TAG_SCORE "" +#define DS_TAG_SCORE_END "" +#define DS_TAG_DEVICE_TYPE "" +#define DS_TAG_DEVICE_TYPE_END "" +#define DS_TAG_DEVICE_NAME "" +#define DS_TAG_DEVICE_NAME_END "" +#define DS_TAG_DEVICE_DRIVER_VERSION "" +#define DS_TAG_DEVICE_DRIVER_VERSION_END "" + +#define DS_DEVICE_NATIVE_CPU_STRING "native_cpu" + + + +typedef ds_status (*ds_score_serializer)(ds_device* device, + void** serializedScore, + unsigned int* serializedScoreSize); +static ds_status writeProfileToFile(ds_profile* profile, + ds_score_serializer serializer, + const char* file) { + ds_status status = DS_SUCCESS; + FILE* profileFile = NULL; + + + if (profile == NULL) + return DS_INVALID_PROFILE; + + profileFile = fopen(file, "wb"); + if (profileFile==NULL) { + status = DS_FILE_ERROR; + } + else { + unsigned int i; + + // write version string + fwrite(DS_TAG_VERSION, sizeof(char), strlen(DS_TAG_VERSION), profileFile); + fwrite(profile->version, sizeof(char), strlen(profile->version), profileFile); + fwrite(DS_TAG_VERSION_END, sizeof(char), strlen(DS_TAG_VERSION_END), profileFile); + fwrite("\n", sizeof(char), 1, profileFile); + + for (i = 0; i < profile->numDevices && status == DS_SUCCESS; i++) { + void* serializedScore; + unsigned int serializedScoreSize; + + fwrite(DS_TAG_DEVICE, sizeof(char), strlen(DS_TAG_DEVICE), profileFile); + + fwrite(DS_TAG_DEVICE_TYPE, sizeof(char), strlen(DS_TAG_DEVICE_TYPE), + profileFile); + fwrite(&profile->devices[i].type,sizeof(ds_device_type),1, profileFile); + fwrite(DS_TAG_DEVICE_TYPE_END, sizeof(char), + strlen(DS_TAG_DEVICE_TYPE_END), profileFile); + + switch(profile->devices[i].type) { + case DS_DEVICE_NATIVE_CPU: + { + // There's no need to emit a device name for the native CPU device. + /* + fwrite(DS_TAG_DEVICE_NAME, sizeof(char), strlen(DS_TAG_DEVICE_NAME), + profileFile); + fwrite(DS_DEVICE_NATIVE_CPU_STRING,sizeof(char), + strlen(DS_DEVICE_NATIVE_CPU_STRING), profileFile); + fwrite(DS_TAG_DEVICE_NAME_END, sizeof(char), + strlen(DS_TAG_DEVICE_NAME_END), profileFile); + */ + } + break; + case DS_DEVICE_OPENCL_DEVICE: + { + fwrite(DS_TAG_DEVICE_NAME, sizeof(char), strlen(DS_TAG_DEVICE_NAME), + profileFile); + fwrite(profile->devices[i].oclDeviceName, + sizeof(char),strlen(profile->devices[i].oclDeviceName), profileFile); + fwrite(DS_TAG_DEVICE_NAME_END, sizeof(char), + strlen(DS_TAG_DEVICE_NAME_END), profileFile); + + fwrite(DS_TAG_DEVICE_DRIVER_VERSION, sizeof(char), + strlen(DS_TAG_DEVICE_DRIVER_VERSION), profileFile); + fwrite(profile->devices[i].oclDriverVersion, sizeof(char), + strlen(profile->devices[i].oclDriverVersion), profileFile); + fwrite(DS_TAG_DEVICE_DRIVER_VERSION_END, sizeof(char), + strlen(DS_TAG_DEVICE_DRIVER_VERSION_END), profileFile); + } + break; + default: + status = DS_UNKNOWN_DEVICE_TYPE; + break; + }; + + fwrite(DS_TAG_SCORE, sizeof(char), strlen(DS_TAG_SCORE), profileFile); + status = serializer(profile->devices+i, &serializedScore, + &serializedScoreSize); + if (status == DS_SUCCESS && serializedScore!=NULL && serializedScoreSize > 0) { + fwrite(serializedScore, sizeof(char), serializedScoreSize, profileFile); + free(serializedScore); + } + fwrite(DS_TAG_SCORE_END, sizeof(char), strlen(DS_TAG_SCORE_END), profileFile); + fwrite(DS_TAG_DEVICE_END, sizeof(char), strlen(DS_TAG_DEVICE_END), profileFile); + fwrite("\n",sizeof(char),1,profileFile); + } + fclose(profileFile); + } + return status; +} + + +static ds_status readProFile(const char* fileName, char** content, + size_t* contentSize) { + FILE * input = NULL; + size_t size = 0; + char* binary = NULL; + + *contentSize = 0; + *content = NULL; + + input = fopen(fileName, "rb"); + if(input == NULL) { + return DS_FILE_ERROR; + } + + fseek(input, 0L, SEEK_END); + size = ftell(input); + rewind(input); + binary = (char*)malloc(size); + if(binary == NULL) { + fclose(input); + return DS_FILE_ERROR; + } + fread(binary, sizeof(char), size, input); + fclose(input); + + *contentSize = size; + *content = binary; + return DS_SUCCESS; +} + + +static const char* findString(const char* contentStart, const char* contentEnd, + const char* string) { + size_t stringLength; + const char* currentPosition; + const char* found; + found = NULL; + stringLength = strlen(string); + currentPosition = contentStart; + for(currentPosition = contentStart; currentPosition < contentEnd; currentPosition++) { + if (*currentPosition == string[0]) { + if (currentPosition+stringLength < contentEnd) { + if (strncmp(currentPosition, string, stringLength) == 0) { + found = currentPosition; + break; + } + } + } + } + return found; +} + + +typedef ds_status (*ds_score_deserializer)(ds_device* device, + const unsigned char* serializedScore, + unsigned int serializedScoreSize); +static ds_status readProfileFromFile(ds_profile* profile, + ds_score_deserializer deserializer, + const char* file) { + + ds_status status = DS_SUCCESS; + char* contentStart = NULL; + const char* contentEnd = NULL; + size_t contentSize; + + if (profile==NULL) + return DS_INVALID_PROFILE; + + status = readProFile(file, &contentStart, &contentSize); + if (status == DS_SUCCESS) { + const char* currentPosition; + const char* dataStart; + const char* dataEnd; + size_t versionStringLength; + + contentEnd = contentStart + contentSize; + currentPosition = contentStart; + + + // parse the version string + dataStart = findString(currentPosition, contentEnd, DS_TAG_VERSION); + if (dataStart == NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + dataStart += strlen(DS_TAG_VERSION); + + dataEnd = findString(dataStart, contentEnd, DS_TAG_VERSION_END); + if (dataEnd==NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + + versionStringLength = strlen(profile->version); + if (versionStringLength!=(dataEnd-dataStart) + || strncmp(profile->version, dataStart, versionStringLength)!=0) { + // version mismatch + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + currentPosition = dataEnd+strlen(DS_TAG_VERSION_END); + + // parse the device information + while (1) { + unsigned int i; + + const char* deviceTypeStart; + const char* deviceTypeEnd; + ds_device_type deviceType; + + const char* deviceNameStart; + const char* deviceNameEnd; + + const char* deviceScoreStart; + const char* deviceScoreEnd; + + const char* deviceDriverStart; + const char* deviceDriverEnd; + + dataStart = findString(currentPosition, contentEnd, DS_TAG_DEVICE); + if (dataStart==NULL) { + // nothing useful remain, quit... + break; + } + dataStart+=strlen(DS_TAG_DEVICE); + dataEnd = findString(dataStart, contentEnd, DS_TAG_DEVICE_END); + if (dataEnd==NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + + // parse the device type + deviceTypeStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_TYPE); + if (deviceTypeStart==NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + deviceTypeStart+=strlen(DS_TAG_DEVICE_TYPE); + deviceTypeEnd = findString(deviceTypeStart, contentEnd, + DS_TAG_DEVICE_TYPE_END); + if (deviceTypeEnd==NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + memcpy(&deviceType, deviceTypeStart, sizeof(ds_device_type)); + + + // parse the device name + if (deviceType == DS_DEVICE_OPENCL_DEVICE) { + + deviceNameStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_NAME); + if (deviceNameStart==NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + deviceNameStart+=strlen(DS_TAG_DEVICE_NAME); + deviceNameEnd = findString(deviceNameStart, contentEnd, + DS_TAG_DEVICE_NAME_END); + if (deviceNameEnd==NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + + + deviceDriverStart = findString(dataStart, contentEnd, + DS_TAG_DEVICE_DRIVER_VERSION); + if (deviceDriverStart==NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + deviceDriverStart+=strlen(DS_TAG_DEVICE_DRIVER_VERSION); + deviceDriverEnd = findString(deviceDriverStart, contentEnd, + DS_TAG_DEVICE_DRIVER_VERSION_END); + if (deviceDriverEnd ==NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + + + // check if this device is on the system + for (i = 0; i < profile->numDevices; i++) { + if (profile->devices[i].type == DS_DEVICE_OPENCL_DEVICE) { + size_t actualDeviceNameLength; + size_t driverVersionLength; + + actualDeviceNameLength = strlen(profile->devices[i].oclDeviceName); + driverVersionLength = strlen(profile->devices[i].oclDriverVersion); + if (actualDeviceNameLength == (deviceNameEnd - deviceNameStart) + && driverVersionLength == (deviceDriverEnd - deviceDriverStart) + && strncmp(profile->devices[i].oclDeviceName, deviceNameStart, + actualDeviceNameLength)==0 + && strncmp(profile->devices[i].oclDriverVersion, deviceDriverStart, + driverVersionLength)==0) { + deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE); + if (deviceNameStart==NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + deviceScoreStart+=strlen(DS_TAG_SCORE); + deviceScoreEnd = findString(deviceScoreStart, contentEnd, + DS_TAG_SCORE_END); + status = deserializer(profile->devices+i, + (const unsigned char*)deviceScoreStart, + deviceScoreEnd-deviceScoreStart); + if (status != DS_SUCCESS) { + goto cleanup; + } + } + } + } + + } + else if (deviceType == DS_DEVICE_NATIVE_CPU) { + for (i = 0; i < profile->numDevices; i++) { + if (profile->devices[i].type == DS_DEVICE_NATIVE_CPU) { + deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE); + if (deviceScoreStart==NULL) { + status = DS_PROFILE_FILE_ERROR; + goto cleanup; + } + deviceScoreStart+=strlen(DS_TAG_SCORE); + deviceScoreEnd = findString(deviceScoreStart, contentEnd, + DS_TAG_SCORE_END); + status = deserializer(profile->devices+i, + (const unsigned char*)deviceScoreStart, + deviceScoreEnd-deviceScoreStart); + if (status != DS_SUCCESS) { + goto cleanup; + } + } + } + } + + // skip over the current one to find the next device + currentPosition = dataEnd+strlen(DS_TAG_DEVICE_END); + } + } +cleanup: + if (contentStart!=NULL) free(contentStart); + return status; +} + +static ds_status getNumDeviceWithEmptyScore(ds_profile* profile, + unsigned int* num) { + unsigned int i; + if (profile == NULL || num==NULL) + return DS_MEMORY_ERROR; + *num=0; + for (i = 0; i < profile->numDevices; i++) { + if (profile->devices[i].score == NULL) { + *num++; + } + } + return DS_SUCCESS; +} + +#endif +#endif diff --git a/TesseractOCR/include/tesseract/openclwrapper.h b/TesseractOCR/include/tesseract/openclwrapper.h new file mode 100644 index 00000000..d94c45ee --- /dev/null +++ b/TesseractOCR/include/tesseract/openclwrapper.h @@ -0,0 +1,345 @@ +#include +#include "allheaders.h" +#include "pix.h" +#ifdef USE_OPENCL +#include "tiff.h" +#include "tiffio.h" +#endif +#include "tprintf.h" + +// including CL/cl.h doesn't occur until USE_OPENCL defined below + +// platform preprocessor commands +#if defined( WIN32 ) || defined( __WIN32__ ) || defined( _WIN32 ) || defined( __CYGWIN32__ ) || defined( __MINGW32__ ) +#define ON_WINDOWS 1 +#define ON_LINUX 0 +#define ON_APPLE 0 +#define ON_OTHER 0 +#define IF_WINDOWS(X) X +#define IF_LINUX(X) +#define IF_APPLE(X) +#define IF_OTHER(X) +#define NOT_WINDOWS(X) +#elif defined( __linux__ ) +#define ON_WINDOWS 0 +#define ON_LINUX 1 +#define ON_APPLE 0 +#define ON_OTHER 0 +#define IF_WINDOWS(X) +#define IF_LINUX(X) X +#define IF_APPLE(X) +#define IF_OTHER(X) +#define NOT_WINDOWS(X) X +#elif defined( __APPLE__ ) +#define ON_WINDOWS 0 +#define ON_LINUX 0 +#define ON_APPLE 1 +#define ON_OTHER 0 +#define IF_WINDOWS(X) +#define IF_LINUX(X) +#define IF_APPLE(X) X +#define IF_OTHER(X) +#define NOT_WINDOWS(X) X +#else +#define ON_WINDOWS 0 +#define ON_LINUX 0 +#define ON_APPLE 0 +#define ON_OTHER 1 +#define IF_WINDOWS(X) +#define IF_LINUX(X) +#define IF_APPLE(X) +#define IF_OTHER(X) X +#define NOT_WINDOWS(X) X +#endif + +#if ON_LINUX +#include +#endif + +/************************************************************************************ + * enable/disable reporting of performance + * PERF_REPORT_LEVEL + * 0 - no reporting + * 1 - no reporting + * 2 - report total function call time for functions we're tracking + * 3 - optionally report breakdown of function calls (kernel launch, kernel time, data copies) + ************************************************************************************/ +#define PERF_COUNT_VERBOSE 1 +#define PERF_COUNT_REPORT_STR "[%36s], %24s, %11.6f\n" + + +#if ON_WINDOWS + +#if PERF_COUNT_VERBOSE >= 2 +#define PERF_COUNT_START(FUNCT_NAME) \ + char *funct_name = FUNCT_NAME; \ + double elapsed_time_sec; \ + LARGE_INTEGER freq, time_funct_start, time_funct_end, time_sub_start, time_sub_end; \ + QueryPerformanceFrequency(&freq); \ + QueryPerformanceCounter(&time_funct_start); \ + time_sub_start = time_funct_start; \ + time_sub_end = time_funct_start; + +#define PERF_COUNT_END \ + QueryPerformanceCounter(&time_funct_end); \ + elapsed_time_sec = (time_funct_end.QuadPart-time_funct_start.QuadPart)/(double)(freq.QuadPart); \ + tprintf(PERF_COUNT_REPORT_STR, funct_name, "total", elapsed_time_sec); +#else +#define PERF_COUNT_START(FUNCT_NAME) +#define PERF_COUNT_END +#endif + +#if PERF_COUNT_VERBOSE >= 3 +#define PERF_COUNT_SUB(SUB) \ + QueryPerformanceCounter(&time_sub_end); \ + elapsed_time_sec = (time_sub_end.QuadPart-time_sub_start.QuadPart)/(double)(freq.QuadPart); \ + tprintf(PERF_COUNT_REPORT_STR, funct_name, SUB, elapsed_time_sec); \ + time_sub_start = time_sub_end; +#else +#define PERF_COUNT_SUB(SUB) +#endif + + +// not on windows +#else + +#if PERF_COUNT_VERBOSE >= 2 +#define PERF_COUNT_START(FUNCT_NAME) \ + char *funct_name = FUNCT_NAME; \ + double elapsed_time_sec; \ + timespec time_funct_start, time_funct_end, time_sub_start, time_sub_end; \ + clock_gettime( CLOCK_MONOTONIC, &time_funct_start ); \ + time_sub_start = time_funct_start; \ + time_sub_end = time_funct_start; + +#define PERF_COUNT_END \ + clock_gettime( CLOCK_MONOTONIC, &time_funct_end ); \ + elapsed_time_sec = (time_funct_end.tv_sec - time_funct_start.tv_sec)*1.0 + (time_funct_end.tv_nsec - time_funct_start.tv_nsec)/1000000000.0; \ + tprintf(PERF_COUNT_REPORT_STR, funct_name, "total", elapsed_time_sec); +#else +#define PERF_COUNT_START(FUNCT_NAME) +#define PERF_COUNT_END +#endif + +#if PERF_COUNT_VERBOSE >= 3 +#define PERF_COUNT_SUB(SUB) \ + clock_gettime( CLOCK_MONOTONIC, &time_sub_end ); \ + elapsed_time_sec = (time_sub_end.tv_sec - time_sub_start.tv_sec)*1.0 + (time_sub_end.tv_nsec - time_sub_start.tv_nsec)/1000000000.0; \ + tprintf(PERF_COUNT_REPORT_STR, funct_name, SUB, elapsed_time_sec); \ + time_sub_start = time_sub_end; +#else +#define PERF_COUNT_SUB(SUB) +#endif + +#endif +/************************************************************************** + * enable/disable use of OpenCL + **************************************************************************/ + +#ifdef USE_OPENCL + +#define USE_DEVICE_SELECTION 1 + +#include "opencl_device_selection.h" + +#ifndef strcasecmp +#define strcasecmp strcmp +#endif + +#define MAX_KERNEL_STRING_LEN 64 +#define MAX_CLFILE_NUM 50 +#define MAX_CLKERNEL_NUM 200 +#define MAX_KERNEL_NAME_LEN 64 +#define CL_QUEUE_THREAD_HANDLE_AMD 0x403E +#define GROUPSIZE_X 16 +#define GROUPSIZE_Y 16 +#define GROUPSIZE_HMORX 256 +#define GROUPSIZE_HMORY 1 + +typedef struct _KernelEnv +{ + cl_context mpkContext; + cl_command_queue mpkCmdQueue; + cl_program mpkProgram; + cl_kernel mpkKernel; + char mckKernelName[150]; +} KernelEnv; + +typedef struct _OpenCLEnv +{ + cl_platform_id mpOclPlatformID; + cl_context mpOclContext; + cl_device_id mpOclDevsID; + cl_command_queue mpOclCmdQueue; +} OpenCLEnv; +typedef int ( *cl_kernel_function )( void **userdata, KernelEnv *kenv ); + + +static l_int32 MORPH_BC = ASYMMETRIC_MORPH_BC; + +static const l_uint32 lmask32[] = {0x0, + 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, + 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, + 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, + 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, + 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, + 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, + 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, + 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff}; + +static const l_uint32 rmask32[] = {0x0, + 0x00000001, 0x00000003, 0x00000007, 0x0000000f, + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, + 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, + 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, + 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, + 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, + 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, + 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff}; + +#define CHECK_OPENCL(status,name) \ +if( status != CL_SUCCESS ) \ +{ \ + printf ("OpenCL error code is %d at when %s .\n", status, name); \ +} + + +typedef struct _GPUEnv +{ + //share vb in all modules in hb library + cl_platform_id mpPlatformID; + cl_device_type mDevType; + cl_context mpContext; + cl_device_id *mpArryDevsID; + cl_device_id mpDevID; + cl_command_queue mpCmdQueue; + cl_kernel mpArryKernels[MAX_CLFILE_NUM]; + cl_program mpArryPrograms[MAX_CLFILE_NUM]; //one program object maps one kernel source file + char mArryKnelSrcFile[MAX_CLFILE_NUM][256], //the max len of kernel file name is 256 + mArrykernelNames[MAX_CLKERNEL_NUM][MAX_KERNEL_STRING_LEN + 1]; + cl_kernel_function mpArryKnelFuncs[MAX_CLKERNEL_NUM]; + int mnKernelCount, mnFileCount, // only one kernel file + mnIsUserCreated; // 1: created , 0:no create and needed to create by opencl wrapper + int mnKhrFp64Flag; + int mnAmdFp64Flag; + +} GPUEnv; + + +class OpenclDevice +{ + +public: + static GPUEnv gpuEnv; + static int isInited; + OpenclDevice(); + ~OpenclDevice(); + static int InitEnv(); // load dll, call InitOpenclRunEnv(0) + static int InitOpenclRunEnv( int argc ); // RegistOpenclKernel, double flags, compile kernels + static int InitOpenclRunEnv_DeviceSelection( int argc ); // RegistOpenclKernel, double flags, compile kernels + static int InitOpenclRunEnv( GPUEnv *gpu ); // select device by env_CPU or selector + static int RegistOpenclKernel(); + static int ReleaseOpenclRunEnv(); + static int ReleaseOpenclEnv( GPUEnv *gpuInfo ); + static int CompileKernelFile( GPUEnv *gpuInfo, const char *buildOption ); + static int CachedOfKernerPrg( const GPUEnv *gpuEnvCached, const char * clFileName ); + static int GeneratBinFromKernelSource( cl_program program, const char * clFileName ); + static int WriteBinaryToFile( const char* fileName, const char* birary, size_t numBytes ); + static int BinaryGenerated( const char * clFileName, FILE ** fhandle ); + //static int CompileKernelFile( const char *filename, GPUEnv *gpuInfo, const char *buildOption ); + static l_uint32* pixReadFromTiffKernel(l_uint32 *tiffdata,l_int32 w,l_int32 h,l_int32 wpl, l_uint32 *line); + static Pix* pixReadTiffCl( const char *filename, l_int32 n ); + static PIX * pixReadStreamTiffCl ( FILE *fp, l_int32 n ); + static PIX* pixReadFromTiffStreamCl(TIFF *tif); + static int composeRGBPixelCl(int *tiffdata,int *line,int h,int w); + static l_int32 getTiffStreamResolutionCl(TIFF *tif,l_int32 *pxres,l_int32 *pyres); + static TIFF* fopenTiffCl(FILE *fp,const char *modestring); + +/* OpenCL implementations of Morphological operations*/ + + //Initialiation of OCL buffers used in Morph operations + static int initMorphCLAllocations(l_int32 wpl, l_int32 h, PIX* pixs); + static void releaseMorphCLBuffers(); + + // OpenCL implementation of Morphology Dilate + static PIX* pixDilateBrickCL(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize, bool reqDataCopy); + + // OpenCL implementation of Morphology Erode + static PIX* pixErodeBrickCL(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize, bool reqDataCopy); + + // OpenCL implementation of Morphology Close + static PIX* pixCloseBrickCL(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize, bool reqDataCopy); + + // OpenCL implementation of Morphology Open + static PIX* pixOpenBrickCL(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize, bool reqDataCopy); + + // OpenCL implementation of Morphology Open + static PIX* pixSubtractCL(PIX *pixd, PIX *pixs1, PIX *pixs2, bool reqDataCopy); + + // OpenCL implementation of Morphology (Hollow = Closed - Open) + static PIX* pixHollowCL(PIX *pixd, PIX *pixs, l_int32 close_hsize, l_int32 close_vsize, l_int32 open_hsize, l_int32 open_vsize, bool reqDataCopy); + + static void pixGetLinesCL(PIX *pixd, PIX *pixs, + PIX** pix_vline, PIX** pix_hline, + PIX** pixClosed, bool getpixClosed, + l_int32 close_hsize, l_int32 close_vsize, + l_int32 open_hsize, l_int32 open_vsize, + l_int32 line_hsize, l_int32 line_vsize); + + //int InitOpenclAttr( OpenCLEnv * env ); + //int ReleaseKernel( KernelEnv * env ); + static int SetKernelEnv( KernelEnv *envInfo ); + //int CreateKernel( char * kernelname, KernelEnv * env ); + //int RunKernel( const char *kernelName, void **userdata ); + //int ConvertToString( const char *filename, char **source ); + //int CheckKernelName( KernelEnv *envInfo, const char *kernelName ); + //int RegisterKernelWrapper( const char *kernelName, cl_kernel_function function ); + //int RunKernelWrapper( cl_kernel_function function, const char * kernelName, void **usrdata ); + //int GetKernelEnvAndFunc( const char *kernelName, KernelEnv *env, cl_kernel_function *function ); + // static cl_device_id performDeviceSelection( ); + //static bool thresholdRectToPixMicroBench( TessScoreEvaluationInputData input, ds_device_type type); + + static int LoadOpencl(); +#ifdef WIN32 + //static int OpenclInite(); + static void FreeOpenclDll(); +#endif + + //int GetOpenclState(); + //void SetOpenclState( int state ); + inline static int AddKernelConfig( int kCount, const char *kName ); + + /* for binarization */ + static void HistogramRectOCL( + const unsigned char *imagedata, + int bytes_per_pixel, + int bytes_per_line, + int left, + int top, + int width, + int height, + int kHistogramSize, + int *histogramAllChannels); + static void ThresholdRectToPixOCL( + const unsigned char* imagedata, + int bytes_per_pixel, + int bytes_per_line, + const int* thresholds, + const int* hi_values, + Pix** pix, + int rect_height, + int rect_width, + int rect_top, + int rect_left); +#if USE_DEVICE_SELECTION + static ds_device getDeviceSelection(); + static ds_device selectedDevice; + static bool deviceIsSelected; +#endif + static bool selectedDeviceIsOpenCL(); + static bool selectedDeviceIsNativeCPU(); + +}; + + +#endif diff --git a/TesseractOCR/include/tesseract/osdetect.h b/TesseractOCR/include/tesseract/osdetect.h old mode 100755 new mode 100644 index 97bf599b..dec07d58 --- a/TesseractOCR/include/tesseract/osdetect.h +++ b/TesseractOCR/include/tesseract/osdetect.h @@ -59,7 +59,7 @@ struct OSResults { // orientation id. void update_best_script(int orientation_id); // Return the index of the script with the highest score for this orientation. - int get_best_script(int orientation_id) const; + TESS_API int get_best_script(int orientation_id) const; // Accumulate scores with given OSResults instance and update the best script. void accumulate(const OSResults& osr); @@ -81,18 +81,21 @@ struct OSResults { class OrientationDetector { public: - OrientationDetector(OSResults*); + OrientationDetector(const GenericVector* allowed_scripts, + OSResults* results); bool detect_blob(BLOB_CHOICE_LIST* scores); int get_orientation(); private: OSResults* osr_; + tesseract::Tesseract* tess_; + const GenericVector* allowed_scripts_; }; class ScriptDetector { public: - ScriptDetector(OSResults*, tesseract::Tesseract* tess); + ScriptDetector(const GenericVector* allowed_scripts, + OSResults* osr, tesseract::Tesseract* tess); void detect_blob(BLOB_CHOICE_LIST* scores); - void get_script() ; bool must_stop(int orientation); private: OSResults* osr_; @@ -108,6 +111,7 @@ class ScriptDetector { int latin_id_; int fraktur_id_; tesseract::Tesseract* tess_; + const GenericVector* allowed_scripts_; }; int orientation_and_script_detection(STRING& filename, @@ -118,7 +122,8 @@ int os_detect(TO_BLOCK_LIST* port_blocks, OSResults* osr, tesseract::Tesseract* tess); -int os_detect_blobs(BLOBNBOX_CLIST* blob_list, +int os_detect_blobs(const GenericVector* allowed_scripts, + BLOBNBOX_CLIST* blob_list, OSResults* osr, tesseract::Tesseract* tess); @@ -129,6 +134,6 @@ bool os_detect_blob(BLOBNBOX* bbox, OrientationDetector* o, // Helper method to convert an orientation index to its value in degrees. // The value represents the amount of clockwise rotation in degrees that must be // applied for the text to be upright (readable). -const int OrientationIdToValue(const int& id); +TESS_API const int OrientationIdToValue(const int& id); #endif // TESSERACT_CCMAIN_OSDETECT_H__ diff --git a/TesseractOCR/include/tesseract/otsuthr.h b/TesseractOCR/include/tesseract/otsuthr.h old mode 100755 new mode 100644 index 59eaf806..7e7d2817 --- a/TesseractOCR/include/tesseract/otsuthr.h +++ b/TesseractOCR/include/tesseract/otsuthr.h @@ -20,35 +20,33 @@ #ifndef TESSERACT_CCMAIN_OTSUTHR_H__ #define TESSERACT_CCMAIN_OTSUTHR_H__ +struct Pix; + namespace tesseract { const int kHistogramSize = 256; // The size of a histogram of pixel values. -// Compute the Otsu threshold(s) for the given image rectangle, making one +// Computes the Otsu threshold(s) for the given image rectangle, making one // for each channel. Each channel is always one byte per pixel. // Returns an array of threshold values and an array of hi_values, such // that a pixel value >threshold[channel] is considered foreground if // hi_values[channel] is 0 or background if 1. A hi_value of -1 indicates // that there is no apparent foreground. At least one hi_value will not be -1. // Delete thresholds and hi_values with delete [] after use. -void OtsuThreshold(const unsigned char* imagedata, - int bytes_per_pixel, int bytes_per_line, - int left, int top, int width, int height, - int** thresholds, int** hi_values); - -// Compute the histogram for the given image rectangle, and the given -// channel. (Channel pointed to by imagedata.) Each channel is always -// one byte per pixel. -// Bytes per pixel is used to skip channels not being -// counted with this call in a multi-channel (pixel-major) image. -// Histogram is always a 256 element array to count occurrences of -// each pixel value. -void HistogramRect(const unsigned char* imagedata, - int bytes_per_pixel, int bytes_per_line, +// The return value is the number of channels in the input image, being +// the size of the output thresholds and hi_values arrays. +int OtsuThreshold(Pix* src_pix, int left, int top, int width, int height, + int** thresholds, int** hi_values); + +// Computes the histogram for the given image rectangle, and the given +// single channel. Each channel is always one byte per pixel. +// Histogram is always a kHistogramSize(256) element array to count +// occurrences of each pixel value. +void HistogramRect(Pix* src_pix, int channel, int left, int top, int width, int height, int* histogram); -// Compute the Otsu threshold(s) for the given histogram. +// Computes the Otsu threshold(s) for the given histogram. // Also returns H = total count in histogram, and // omega0 = count of histogram below threshold. int OtsuStats(const int* histogram, int* H_out, int* omega0_out); diff --git a/TesseractOCR/include/tesseract/outfeat.h b/TesseractOCR/include/tesseract/outfeat.h new file mode 100644 index 00000000..e7a36476 --- /dev/null +++ b/TesseractOCR/include/tesseract/outfeat.h @@ -0,0 +1,48 @@ +/****************************************************************************** + ** Filename: outfeat.h + ** Purpose: Definition of outline features. + ** Author: Dan Johnson + ** History: 11/13/90, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef OUTFEAT_H +#define OUTFEAT_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "ocrfeatures.h" +#include "fpoint.h" +#include "mfoutline.h" + +typedef enum { + OutlineFeatX, + OutlineFeatY, + OutlineFeatLength, + OutlineFeatDir +} OUTLINE_FEAT_PARAM_NAME; + +#define MAX_OUTLINE_FEATURES (100) + +/*--------------------------------------------------------------------------- + Privat Function Prototypes +----------------------------------------------------------------------------*/ +void AddOutlineFeatureToSet(FPOINT *Start, + FPOINT *End, + FEATURE_SET FeatureSet); + +void ConvertToOutlineFeatures(MFOUTLINE Outline, FEATURE_SET FeatureSet); + +void NormalizeOutlineX(FEATURE_SET FeatureSet); + +#endif diff --git a/TesseractOCR/include/tesseract/outlines.h b/TesseractOCR/include/tesseract/outlines.h new file mode 100644 index 00000000..bcb675e5 --- /dev/null +++ b/TesseractOCR/include/tesseract/outlines.h @@ -0,0 +1,134 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: outlines.h (Formerly outlines.h) + * Description: Combinatorial Splitter + * Author: Mark Seaman, OCR Technology + * Created: Thu Jul 27 11:27:55 1989 + * Modified: Wed May 15 17:28:47 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Experimental (Do Not Distribute) + * + * (c) Copyright 1989, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ +#ifndef OUTLINES_H +#define OUTLINES_H + +#include "blobs.h" +#include "chop.h" + +#include + +/*---------------------------------------------------------------------- + C o n s t a n t s +----------------------------------------------------------------------*/ +#define LARGE_DISTANCE 100000 /* Used for closest dist */ +#define MIN_BLOB_SIZE 10 /* Big units */ +#define MAX_ASPECT_RATIO 2.5 /* Widest character */ + +/*---------------------------------------------------------------------- + M a c r o s +----------------------------------------------------------------------*/ +/********************************************************************** + * same_point + * + * Return TRUE if the point values are the same. The parameters must + * be of type POINT. + **********************************************************************/ +#define same_point(p1,p2) \ + ((abs (p1.x - p2.x) < chop_same_distance) && \ + (abs (p1.y - p2.y) < chop_same_distance)) + +/********************************************************************** + * dist_square + * + * Return the square of the distance between these two points. The + * parameters must be of type POINT. + **********************************************************************/ + +#define dist_square(p1,p2) \ + ((p2.x - p1.x) * (p2.x - p1.x) + \ + (p2.y - p1.y) * (p2.y - p1.y)) + +/********************************************************************** + * closest + * + * The expression provides the EDGEPT that is closest to the point in + * question. All three parameters must be of type EDGEPT. + **********************************************************************/ + +#define closest(test_p,p1,p2) \ +(p1 ? \ + (p2 ? \ + ((dist_square (test_p->pos, p1->pos) < \ + dist_square (test_p->pos, p2->pos)) ? \ + p1 : \ + p2) : \ + p1) : \ + p2) + +/********************************************************************** + * edgept_dist + * + * Return the distance (squared) between the two edge points. + **********************************************************************/ + +#define edgept_dist(p1,p2) \ +(dist_square ((p1)->pos, (p2)->pos)) + +/********************************************************************** + * is_exterior_point + * + * Return TRUE if the point supplied is an exterior projection from the + * outline. + **********************************************************************/ + +#define is_exterior_point(edge,point) \ +(same_point (edge->prev->pos, point->pos) || \ + same_point (edge->next->pos, point->pos) || \ + (angle_change (edge->prev, edge, edge->next) - \ + angle_change (edge->prev, edge, point) > 20)) + +/********************************************************************** + * is_equal + * + * Return TRUE if the POINTs are equal. + **********************************************************************/ + +#define is_equal(p1,p2) \ +(((p1).x == (p2).x) && ((p1).y == (p2).y)) + +/********************************************************************** + * is_on_line + * + * Return TRUE if the point is on the line segment between the two end + * points. The two end points are included as part of the line. The + * parameters must be of type POINT. + **********************************************************************/ + +#define is_on_line(p,p0,p1) \ + (within_range ((p).x, (p0).x, (p1).x) && \ + within_range ((p).y, (p0).y, (p1).y)) + +/********************************************************************** + * within_range + * + * Return TRUE if the first number is in between the second two numbers. + * Return FALSE otherwise. + **********************************************************************/ + +#define within_range(x,x0,x1) \ + (((x0 <= x) && (x <= x1)) || ((x1 <= x) && (x <= x0))) + +#endif diff --git a/TesseractOCR/include/tesseract/output.h b/TesseractOCR/include/tesseract/output.h old mode 100755 new mode 100644 index 9e9bfd51..7f297c93 --- a/TesseractOCR/include/tesseract/output.h +++ b/TesseractOCR/include/tesseract/output.h @@ -23,7 +23,6 @@ #include "params.h" //#include "epapconv.h" #include "pageres.h" -#include "notdll.h" /** test line ends */ char determine_newline_type(WERD *word, ///< word to do diff --git a/TesseractOCR/include/tesseract/pageiterator.h b/TesseractOCR/include/tesseract/pageiterator.h old mode 100755 new mode 100644 index 0d6084f9..ce5fa7fd --- a/TesseractOCR/include/tesseract/pageiterator.h +++ b/TesseractOCR/include/tesseract/pageiterator.h @@ -24,12 +24,13 @@ #include "publictypes.h" #include "platform.h" +struct BlamerBundle; class C_BLOB_IT; -class PBLOB_IT; class PAGE_RES; class PAGE_RES_IT; class WERD; struct Pix; +struct Pta; namespace tesseract { @@ -189,6 +190,8 @@ class TESS_API PageIterator { */ bool BoundingBox(PageIteratorLevel level, int* left, int* top, int* right, int* bottom) const; + bool BoundingBox(PageIteratorLevel level, const int padding, + int* left, int* top, int* right, int* bottom) const; /** * Returns the bounding rectangle of the object in a coordinate system of the * working image rectangle having its origin at (rect_left_, rect_top_) with @@ -201,11 +204,20 @@ class TESS_API PageIterator { bool Empty(PageIteratorLevel level) const; /** - * Returns the type of the current block. See apitypes.h for + * Returns the type of the current block. See apitypes.h for * PolyBlockType. */ PolyBlockType BlockType() const; + /** + * Returns the polygon outline of the current block. The returned Pta must + * be ptaDestroy-ed after use. Note that the returned Pta lists the vertices + * of the polygon, and the last edge is the line segment between the last + * point and the first point. NULL will be returned if the iterator is + * at the end of the document or layout analysis was not used. + */ + Pta* BlockPolygon() const; + /** * Returns a binary image of the current object at the given level. * The position and size match the return from BoundingBoxInternal, and so @@ -282,6 +294,12 @@ class TESS_API PageIterator { bool *is_crown, int *first_line_indent) const; + // If the current WERD_RES (it_->word()) is not NULL, sets the BlamerBundle + // of the current word to the given pointer (takes ownership of the pointer) + // and returns true. + // Can only be used when iterating on the word level. + bool SetWordBlamerBundle(BlamerBundle *blamer_bundle); + protected: /** * Sets up the internal data for iterating the blobs of a new word, then diff --git a/TesseractOCR/include/tesseract/pageres.h b/TesseractOCR/include/tesseract/pageres.h old mode 100755 new mode 100644 index bd53586b..4eb29ee4 --- a/TesseractOCR/include/tesseract/pageres.h +++ b/TesseractOCR/include/tesseract/pageres.h @@ -19,6 +19,7 @@ #ifndef PAGERES_H #define PAGERES_H +#include "blamer.h" #include "blobs.h" #include "boxword.h" #include "elst.h" @@ -38,167 +39,6 @@ class Tesseract; } using tesseract::FontInfo; -static const inT16 kBlamerBoxTolerance = 5; - -// Enum for expressing the source of error. -// Note: Please update kIncorrectResultReasonNames when modifying this enum. -enum IncorrectResultReason { - // The text recorded in best choice == truth text - IRR_CORRECT, - // Either: Top choice is incorrect and is a dictionary word (language model - // is unlikely to help correct such errors, so blame the classifier). - // Or: the correct unichar was not included in shortlist produced by the - // classifier at all. - IRR_CLASSIFIER, - // Chopper have not found one or more splits that correspond to the correct - // character bounding boxes recorded in BlamerBundle::truth_word. - IRR_CHOPPER, - // Classifier did include correct unichars for each blob in the correct - // segmentation, however its rating could have been too bad to allow the - // language model to pull out the correct choice. On the other hand the - // strength of the language model might have been too weak to favor the - // correct answer, this we call this case a classifier-language model - // tradeoff error. - IRR_CLASS_LM_TRADEOFF, - // Page layout failed to produce the correct bounding box. Blame page layout - // if the truth was not found for the word, which implies that the bounding - // box of the word was incorrect (no truth word had a similar bounding box). - IRR_PAGE_LAYOUT, - // SegSearch heuristic prevented one or more blobs from the correct - // segmentation state to be classified (e.g. the blob was too wide). - IRR_SEGSEARCH_HEUR, - // The correct segmentaiton state was not explored because of poor SegSearch - // pain point prioritization. We blame SegSearch pain point prioritization - // if the best rating of a choice constructed from correct segmentation is - // better than that of the best choice (i.e. if we got to explore the correct - // segmentation state, language model would have picked the correct choice). - IRR_SEGSEARCH_PP, - // Same as IRR_CLASS_LM_TRADEOFF, but used when we only run chopper on a word, - - // and thus use the old language model (permuters). - // TODO(antonova): integrate the new language mode with chopper - IRR_CLASS_OLD_LM_TRADEOFF, - // If there is an incorrect adaptive template match with a better score than - // a correct one (either pre-trained or adapted), mark this as adaption error. - IRR_ADAPTION, - // split_and_recog_word() failed to find a suitable split in truth. - IRR_NO_TRUTH_SPLIT, - // Truth is not available for this word (e.g. when words in corrected content - // file are turned into ~~~~ because an appropriate alignment was not found. - IRR_NO_TRUTH, - // The text recorded in best choice != truth text, but none of the above - // reasons are set. - IRR_UNKNOWN, - - IRR_NUM_REASONS -}; - -// Blamer-related information to determine the source of errors. -struct BlamerBundle { - static const char *IncorrectReasonName(IncorrectResultReason irr); - BlamerBundle() : truth_has_char_boxes(false), - incorrect_result_reason(IRR_CORRECT), - lattice_data(NULL) { ClearResults(); } - ~BlamerBundle() { delete[] lattice_data; } - void ClearResults() { - norm_truth_word.DeleteAllBoxes(); - norm_box_tolerance = 0; - if (!NoTruth()) incorrect_result_reason = IRR_CORRECT; - debug = ""; - segsearch_is_looking_for_blame = false; - best_correctly_segmented_rating = WERD_CHOICE::kBadRating; - correct_segmentation_cols.clear(); - correct_segmentation_rows.clear(); - best_choice_is_dict_and_top_choice = false; - delete[] lattice_data; - lattice_data = NULL; - lattice_size = 0; - } - void CopyTruth(const BlamerBundle &other) { - truth_has_char_boxes = other.truth_has_char_boxes; - truth_word = other.truth_word; - truth_text = other.truth_text; - incorrect_result_reason = - (other.NoTruth() ? other.incorrect_result_reason : IRR_CORRECT); - } - void CopyResults(const BlamerBundle &other) { - norm_truth_word = other.norm_truth_word; - norm_box_tolerance = other.norm_box_tolerance; - incorrect_result_reason = other.incorrect_result_reason; - segsearch_is_looking_for_blame = other.segsearch_is_looking_for_blame; - best_correctly_segmented_rating =other.best_correctly_segmented_rating; - correct_segmentation_cols = other.correct_segmentation_cols; - correct_segmentation_rows = other.correct_segmentation_rows; - best_choice_is_dict_and_top_choice = - other.best_choice_is_dict_and_top_choice; - if (other.lattice_data != NULL) { - lattice_data = new char[other.lattice_size]; - memcpy(lattice_data, other.lattice_data, other.lattice_size); - lattice_size = other.lattice_size; - } else { - lattice_data = NULL; - } - } - BlamerBundle(const BlamerBundle &other) { - this->CopyTruth(other); - this->CopyResults(other); - } - const char *IncorrectReason() const; - bool NoTruth() const { - return (incorrect_result_reason == IRR_NO_TRUTH || - incorrect_result_reason == IRR_PAGE_LAYOUT); - } - void SetBlame(IncorrectResultReason irr, - const STRING &msg, const WERD_CHOICE *choice, bool debug) { - this->incorrect_result_reason = irr; - this->debug = this->IncorrectReason(); - this->debug += " to blame: "; - this->FillDebugString(msg, choice, &(this->debug)); - if (debug) tprintf("SetBlame(): %s", this->debug.string()); - } - // Appends choice and truth details to the given debug string. - void FillDebugString(const STRING &msg, const WERD_CHOICE *choice, - STRING *debug); - - // Set to true when bounding boxes for individual unichars are recorded. - bool truth_has_char_boxes; - // The true_word (in the original image coordinate space) contains ground - // truth bounding boxes for this WERD_RES. - tesseract::BoxWord truth_word; - // Same as above, but in normalized coordinates - // (filled in by WERD_RES::SetupForRecognition()). - tesseract::BoxWord norm_truth_word; - // Tolerance for bounding box comparisons in normalized space. - int norm_box_tolerance; - // Contains ground truth unichar for each of the bounding boxes in truth_word. - GenericVector truth_text; - // The reason for incorrect OCR result. - IncorrectResultReason incorrect_result_reason; - // Debug text associated with the blame. - STRING debug; - // Misadaption debug information (filled in if this word was misadapted to). - STRING misadaption_debug; - // Variables used by the segmentation search when looking for the blame. - // Set to true while segmentation search is continued after the usual - // termination condition in order to look for the blame. - bool segsearch_is_looking_for_blame; - // Best rating for correctly segmented path - // (set and used by SegSearch when looking for blame). - float best_correctly_segmented_rating; - // Vectors populated by SegSearch to indicate column and row indices that - // correspond to blobs with correct bounding boxes. - GenericVector correct_segmentation_cols; - GenericVector correct_segmentation_rows; - // Set to true if best choice is a dictionary word and - // classifier's top choice. - bool best_choice_is_dict_and_top_choice; - // Serialized segmentation search lattice. - char *lattice_data; - int lattice_size; // size of lattice_data in bytes - // Information about hypotheses (paths) explored by the segmentation search. - tesseract::ParamsTrainingBundle params_training_bundle; -}; - /* Forward declarations */ class BLOCK_RES; @@ -341,8 +181,11 @@ class WERD_RES : public ELIST_LINK { // TODO(rays) determine if docqual does anything useful and delete bln_boxes // if it doesn't. tesseract::BoxWord* bln_boxes; // BLN input bounding boxes. + // The ROW that this word sits in. NOT owned by the WERD_RES. + ROW* blob_row; // The denorm provides the transformation to get back to the rotated image - // coords from the chopped_word/rebuild_word BLN coords. + // coords from the chopped_word/rebuild_word BLN coords, but each blob also + // has its own denorm. DENORM denorm; // For use on chopped_word. // Unicharset used by the classifier output in best_choice and raw_choice. const UNICHARSET* uch_set; // For converting back to utf8. @@ -355,13 +198,32 @@ class WERD_RES : public ELIST_LINK { // character fragments that make up the word. // The length of chopped_word matches length of seam_array + 1 (if set). TWERD* chopped_word; // BLN chopped fragments output. - SEAMS seam_array; // Seams matching chopped_word. - WERD_CHOICE *best_choice; // tess output - WERD_CHOICE *raw_choice; // top choice permuter - // Alternative paths found during chopping/segmentation search stages - // (the first entry being a slim copy of best_choice). - GenericVector alt_choices; - GenericVector > alt_states; + // Vector of SEAM* holding chopping points matching chopped_word. + GenericVector seam_array; + // Widths of blobs in chopped_word. + GenericVector blob_widths; + // Gaps between blobs in chopped_word. blob_gaps[i] is the gap between + // blob i and blob i+1. + GenericVector blob_gaps; + // Ratings matrix contains classifier choices for each classified combination + // of blobs. The dimension is the same as the number of blobs in chopped_word + // and the leading diagonal corresponds to classifier results of the blobs + // in chopped_word. The state_ members of best_choice, raw_choice and + // best_choices all correspond to this ratings matrix and allow extraction + // of the blob choices for any given WERD_CHOICE. + MATRIX* ratings; // Owned pointer. + // Pointer to the first WERD_CHOICE in best_choices. This is the result that + // will be output from Tesseract. Note that this is now a borrowed pointer + // and should NOT be deleted. + WERD_CHOICE* best_choice; // Borrowed pointer. + // The best raw_choice found during segmentation search. Differs from the + // best_choice by being the best result according to just the character + // classifier, not taking any language model information into account. + // Unlike best_choice, the pointer IS owned by this WERD_RES. + WERD_CHOICE* raw_choice; // Owned pointer. + // Alternative results found during chopping/segmentation search stages. + // Note that being an ELIST, best_choices owns the WERD_CHOICEs. + WERD_CHOICE_LIST best_choices; // Truth bounding boxes, text and incorrect choice reason. BlamerBundle *blamer_bundle; @@ -462,6 +324,8 @@ class WERD_RES : public ELIST_LINK { InitPointers(); word = the_word; } + // Deep copies everything except the ratings MATRIX. + // To get that use deep_copy below. WERD_RES(const WERD_RES &source) { InitPointers(); *this = source; // see operator= @@ -475,7 +339,8 @@ class WERD_RES : public ELIST_LINK { // characters purely based on their shape on the page, and by default produce // the corresponding unicode for a left-to-right context. const char* const BestUTF8(int blob_index, bool in_rtl_context) const { - if (blob_index < 0 || blob_index >= best_choice->length()) + if (blob_index < 0 || best_choice == NULL || + blob_index >= best_choice->length()) return NULL; UNICHAR_ID id = best_choice->unichar_id(blob_index); if (id < 0 || id >= uch_set->size() || id == INVALID_UNICHAR_ID) @@ -545,7 +410,11 @@ class WERD_RES : public ELIST_LINK { void InitPointers(); void Clear(); void ClearResults(); + void ClearWordChoices(); + void ClearRatings(); + // Deep copies everything except the ratings MATRIX. + // To get that use deep_copy below. WERD_RES& operator=(const WERD_RES& source); //from this void CopySimpleFields(const WERD_RES& source); @@ -557,24 +426,31 @@ class WERD_RES : public ELIST_LINK { void InitForRetryRecognition(const WERD_RES& source); // Sets up the members used in recognition: bln_boxes, chopped_word, - // seam_array, denorm, best_choice, raw_choice. Returns false if + // seam_array, denorm. Returns false if // the word is empty and sets up fake results. If use_body_size is // true and row->body_size is set, then body_size will be used for // blob normalization instead of xheight + ascrise. This flag is for // those languages that are using CJK pitch model and thus it has to // be true if and only if tesseract->textord_use_cjk_fp_model is // true. - bool SetupForTessRecognition(const UNICHARSET& unicharset_in, - tesseract::Tesseract* tesseract, Pix* pix, - bool numeric_mode, bool use_body_size, - ROW *row, BLOCK* block); - - // Sets up the members used in recognition: - // bln_boxes, chopped_word, seam_array, denorm. + // If allow_detailed_fx is true, the feature extractor will receive fine + // precision outline information, allowing smoother features and better + // features on low resolution images. + // The norm_mode sets the default mode for normalization in absence + // of any of the above flags. It should really be a tesseract::OcrEngineMode + // but is declared as int for ease of use with tessedit_ocr_engine_mode. // Returns false if the word is empty and sets up fake results. - bool SetupForCubeRecognition(const UNICHARSET& unicharset_in, - tesseract::Tesseract* tesseract, - const BLOCK* block); + bool SetupForRecognition(const UNICHARSET& unicharset_in, + tesseract::Tesseract* tesseract, Pix* pix, + int norm_mode, + const TBOX* norm_box, bool numeric_mode, + bool use_body_size, bool allow_detailed_fx, + ROW *row, const BLOCK* block); + + // Set up the seam array, bln_boxes, best_choice, and raw_choice to empty + // accumulators from a made chopped word. We presume the fields are already + // empty. + void SetupBasicsFromChoppedWord(const UNICHARSET &unicharset_in); // Sets up the members used in recognition for an empty recognition result: // bln_boxes, chopped_word, seam_array, denorm, best_choice, raw_choice. @@ -586,6 +462,87 @@ class WERD_RES : public ELIST_LINK { // Sets up the blamer_bundle if it is not null, using the initialized denorm. void SetupBlamerBundle(); + // Computes the blob_widths and blob_gaps from the chopped_word. + void SetupBlobWidthsAndGaps(); + + // Updates internal data to account for a new SEAM (chop) at the given + // blob_number. Fixes the ratings matrix and states in the choices, as well + // as the blob widths and gaps. + void InsertSeam(int blob_number, SEAM* seam); + + // Returns true if all the word choices except the first have adjust_factors + // worse than the given threshold. + bool AlternativeChoiceAdjustmentsWorseThan(float threshold) const; + + // Returns true if the current word is ambiguous (by number of answers or + // by dangerous ambigs.) + bool IsAmbiguous(); + + // Returns true if the ratings matrix size matches the sum of each of the + // segmentation states. + bool StatesAllValid(); + + // Prints a list of words found if debug is true or the word result matches + // the word_to_debug. + void DebugWordChoices(bool debug, const char* word_to_debug); + + // Removes from best_choices all choices which are not within a reasonable + // range of the best choice. + void FilterWordChoices(int debug_level); + + // Computes a set of distance thresholds used to control adaption. + // Compares the best choice for the current word to the best raw choice + // to determine which characters were classified incorrectly by the + // classifier. Then places a separate threshold into thresholds for each + // character in the word. If the classifier was correct, max_rating is placed + // into thresholds. If the classifier was incorrect, the mean match rating + // (error percentage) of the classifier's incorrect choice minus some margin + // is placed into thresholds. This can then be used by the caller to try to + // create a new template for the desired class that will classify the + // character with a rating better than the threshold value. The match rating + // placed into thresholds is never allowed to be below min_rating in order to + // prevent trying to make overly tight templates. + // min_rating limits how tight to make a template. + // max_rating limits how loose to make a template. + // rating_margin denotes the amount of margin to put in template. + void ComputeAdaptionThresholds(float certainty_scale, + float min_rating, + float max_rating, + float rating_margin, + float* thresholds); + + // Saves a copy of the word_choice if it has the best unadjusted rating. + // Returns true if the word_choice was the new best. + bool LogNewRawChoice(WERD_CHOICE* word_choice); + // Consumes word_choice by adding it to best_choices, (taking ownership) if + // the certainty for word_choice is some distance of the best choice in + // best_choices, or by deleting the word_choice and returning false. + // The best_choices list is kept in sorted order by rating. Duplicates are + // removed, and the list is kept no longer than max_num_choices in length. + // Returns true if the word_choice is still a valid pointer. + bool LogNewCookedChoice(int max_num_choices, bool debug, + WERD_CHOICE* word_choice); + + // Prints a brief list of all the best choices. + void PrintBestChoices() const; + + // Returns the sum of the widths of the blob between start_blob and last_blob + // inclusive. + int GetBlobsWidth(int start_blob, int last_blob); + // Returns the width of a gap between the specified blob and the next one. + int GetBlobsGap(int blob_index); + + // Returns the BLOB_CHOICE corresponding to the given index in the + // best choice word taken from the appropriate cell in the ratings MATRIX. + // Borrowed pointer, so do not delete. May return NULL if there is no + // BLOB_CHOICE matching the unichar_id at the given index. + BLOB_CHOICE* GetBlobChoice(int index) const; + + // Returns the BLOB_CHOICE_LIST corresponding to the given index in the + // best choice word taken from the appropriate cell in the ratings MATRIX. + // Borrowed pointer, so do not delete. + BLOB_CHOICE_LIST* GetBlobChoices(int index) const; + // Moves the results fields from word to this. This takes ownership of all // the data, so src can be destructed. // word1.ConsumeWordResult(word); @@ -597,10 +554,11 @@ class WERD_RES : public ELIST_LINK { void ConsumeWordResults(WERD_RES* word); // Replace the best choice and rebuild box word. - void ReplaceBestChoice(const WERD_CHOICE& choice, - const GenericVector &segmentation_state); + // choice must be from the current best_choices list. + void ReplaceBestChoice(WERD_CHOICE* choice); - // Builds the rebuild_word from the chopped_word and the best_state. + // Builds the rebuild_word and sets the best_state from the chopped_word and + // the best_choice->state. void RebuildBestState(); // Copies the chopped_word to the rebuild_word, faking a best_state as well. @@ -610,30 +568,26 @@ class WERD_RES : public ELIST_LINK { // Sets/replaces the box_word with one made from the rebuild_word. void SetupBoxWord(); - // Sets up the script positions in the output boxword using the best_choice + // Sets up the script positions in the best_choice using the best_choice // to get the unichars, and the unicharset to get the target positions. void SetScriptPositions(); - - // Returns the indices [start, end) containing the core of the word, stripped - // of any superscript digits on either side. - // (i.e., the non-footnote part of the word). - // Assumes that BoxWord is all set up for best_choice. - void WithoutFootnoteSpan(int *start, int *end) const; - - // Given an alternate word choice and segmentation state, yield the indices - // [start, end) containig the core of the word, stripped of any superscript - // digits on either side. (i.e. stripping off the footnote parts). - void WithoutFootnoteSpan( - const WERD_CHOICE &choice, const GenericVector &state, - int *start, int *end) const; + // Sets all the blobs in all the words (best choice and alternates) to be + // the given position. (When a sub/superscript is recognized as a separate + // word, it falls victim to the rule that a whole word cannot be sub or + // superscript, so this function overrides that problem.) + void SetAllScriptPositions(tesseract::ScriptPos position); // Classifies the word with some already-calculated BLOB_CHOICEs. // The choices are an array of blob_count pointers to BLOB_CHOICE, // providing a single classifier result for each blob. // The BLOB_CHOICEs are consumed and the word takes ownership. - // The number of blobs in the outword must match blob_count. + // The number of blobs in the box_word must match blob_count. void FakeClassifyWord(int blob_count, BLOB_CHOICE** choices); + // Creates a WERD_CHOICE for the word using the top choices from the leading + // diagonal of the ratings matrix. + void FakeWordFromRatings(); + // Copies the best_choice strings to the correct_text for adaption/training. void BestChoiceToCorrectText(); @@ -644,13 +598,16 @@ class WERD_RES : public ELIST_LINK { // Returns true if anything was merged. bool ConditionalBlobMerge( TessResultCallback2* class_cb, - TessResultCallback2* box_cb, - BLOB_CHOICE_LIST_CLIST *blob_choices); + TessResultCallback2* box_cb); + + // Merges 2 adjacent blobs in the result (index and index+1) and corrects + // all the data to account for the change. + void MergeAdjacentBlobs(int index); // Callback helper for fix_quotes returns a double quote if both // arguments are quote, otherwise INVALID_UNICHAR_ID. UNICHAR_ID BothQuotes(UNICHAR_ID id1, UNICHAR_ID id2); - void fix_quotes(BLOB_CHOICE_LIST_CLIST *blob_choices); + void fix_quotes(); // Callback helper for fix_hyphens returns UNICHAR_ID of - if both // arguments are hyphen, otherwise INVALID_UNICHAR_ID. @@ -658,15 +615,21 @@ class WERD_RES : public ELIST_LINK { // Callback helper for fix_hyphens returns true if box1 and box2 overlap // (assuming both on the same textline, are in order and a chopped em dash.) bool HyphenBoxesOverlap(const TBOX& box1, const TBOX& box2); - void fix_hyphens(BLOB_CHOICE_LIST_CLIST *blob_choices); + void fix_hyphens(); // Callback helper for merge_tess_fails returns a space if both // arguments are space, otherwise INVALID_UNICHAR_ID. UNICHAR_ID BothSpaces(UNICHAR_ID id1, UNICHAR_ID id2); void merge_tess_fails(); + // Returns a really deep copy of *src, including the ratings MATRIX. static WERD_RES* deep_copy(const WERD_RES* src) { - return new WERD_RES(*src); + WERD_RES* result = new WERD_RES(*src); + // That didn't copy the ratings, but we want a copy if there is one to + // begin width. + if (src->ratings != NULL) + result->ratings = src->ratings->DeepCopy(); + return result; } // Copy blobs from word_res onto this word (eliminating spaces between). diff --git a/TesseractOCR/include/tesseract/pango_font_info.h b/TesseractOCR/include/tesseract/pango_font_info.h new file mode 100644 index 00000000..56aae46f --- /dev/null +++ b/TesseractOCR/include/tesseract/pango_font_info.h @@ -0,0 +1,187 @@ +/********************************************************************** + * File: pango_font_info.h + * Description: Font-related objects and helper functions + * Author: Ranjith Unnikrishnan + * Created: Mon Nov 18 2013 + * + * (C) Copyright 2013, Google Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + **********************************************************************/ + +#ifndef TESSERACT_TRAINING_PANGO_FONT_INFO_H_ +#define TESSERACT_TRAINING_PANGO_FONT_INFO_H_ + +#include +#include +#include + +#include "hashfn.h" +#include "host.h" +#include "util.h" +#include "pango/pango-font.h" + +typedef signed int char32; + +namespace tesseract { + +// Data holder class for a font, intented to avoid having to work with Pango or +// FontConfig-specific objects directly. +class PangoFontInfo { + public: + enum FontTypeEnum { + UNKNOWN, + SERIF, + SANS_SERIF, + DECORATIVE, + }; + PangoFontInfo(); + // Initialize from parsing a font description name, defined as a string of the + // format: + // "FamilyName [FaceName] [PointSize]" + // where a missing FaceName implies the default regular face. + // eg. "Arial Italic 12", "Verdana" + // + // FaceName is a combination of: + // [StyleName] [Variant] [Weight] [Stretch] + // with (all optional) Pango-defined values of: + // StyleName: Oblique, Italic + // Variant : Small-Caps + // Weight : Ultra-Light, Light, Medium, Semi-Bold, Bold, Ultra-Bold, Heavy + // Stretch : Ultra-Condensed, Extra-Condensed, Condensed, Semi-Condensed, + // Semi-Expanded, Expanded, Extra-Expanded, Ultra-Expanded. + explicit PangoFontInfo(const string& name); + bool ParseFontDescriptionName(const string& name); + + // Returns true if the font have codepoint coverage for the specified text. + bool CoversUTF8Text(const char* utf8_text, int byte_length) const; + // Modifies string to remove unicode points that are not covered by the + // font. Returns the number of characters dropped. + int DropUncoveredChars(string* utf8_text) const; + + // Returns true if the entire string can be rendered by the font with full + // character coverage and no unknown glyph or dotted-circle glyph + // substitutions on encountering a badly formed unicode sequence. + // If true, returns individual graphemes. Any whitespace characters in the + // original string are also included in the list. + bool CanRenderString(const char* utf8_word, int len, + vector* graphemes) const; + bool CanRenderString(const char* utf8_word, int len) const; + + // Retrieves the x_bearing and x_advance for the given utf8 character in the + // font. Returns false if the glyph for the character could not be found in + // the font. + // Ref: http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-3.html + bool GetSpacingProperties(const string& utf8_char, + int* x_bearing, int* x_advance) const; + + // Accessors + string DescriptionName() const; + // Font Family name eg. "Arial" + const string& family_name() const { return family_name_; } + // Size in points (1/72"), rounded to the nearest integer. + const int font_size() const { return font_size_; } + const bool is_bold() const { return is_bold_; } + const bool is_italic() const { return is_italic_; } + const bool is_smallcaps() const { return is_smallcaps_; } + const bool is_monospace() const { return is_monospace_; } + const bool is_fraktur() const { return is_fraktur_; } + const FontTypeEnum font_type() const { return font_type_; } + + const int resolution() const { return resolution_; } + void set_resolution(const int resolution) { + resolution_ = resolution; + } + + private: + friend class FontUtils; + void Clear(); + bool ParseFontDescription(const PangoFontDescription* desc); + // Returns the PangoFont structure corresponding to the closest available font + // in the font map. + PangoFont* ToPangoFont() const; + + // Font properties set automatically from parsing the font description name. + string family_name_; + int font_size_; + bool is_bold_; + bool is_italic_; + bool is_smallcaps_; + bool is_monospace_; + bool is_fraktur_; + FontTypeEnum font_type_; + // The Pango description that was used to initialize the instance. + PangoFontDescription* desc_; + // Default output resolution to assume for GetSpacingProperties() and any + // other methods that returns pixel values. + int resolution_; + + private: + PangoFontInfo(const PangoFontInfo&); + void operator=(const PangoFontInfo&); +}; + +// Static utility methods for querying font availability and font-selection +// based on codepoint coverage. +class FontUtils { + public: + // Returns true if the font of the given description name is available in the + // target directory specified by --fonts_dir + static bool IsAvailableFont(const char* font_desc); + // Outputs description names of available fonts. + static const vector& ListAvailableFonts(); + + // Picks font among available fonts that covers and can render the given word, + // and returns the font description name and the decomposition of the word to + // graphemes. Returns false if no suitable font was found. + static bool SelectFont(const char* utf8_word, const int utf8_len, + string* font_name, vector* graphemes); + + // Picks font among all_fonts that covers and can render the given word, + // and returns the font description name and the decomposition of the word to + // graphemes. Returns false if no suitable font was found. + static bool SelectFont(const char* utf8_word, const int utf8_len, + const vector& all_fonts, + string* font_name, vector* graphemes); + + // Returns a bitmask where the value of true at index 'n' implies that unicode + // value 'n' is renderable by at least one available font. + static void GetAllRenderableCharacters(vector* unichar_bitmap); + // Variant of the above function that inspects only the provided font names. + static void GetAllRenderableCharacters(const vector& font_names, + vector* unichar_bitmap); + static void GetAllRenderableCharacters(const string& font_name, + vector* unichar_bitmap); + + // NOTE: The following utilities were written to be backward compatible with + // StringRender. + + // BestFonts returns a font name and a bit vector of the characters it + // can render for the fonts that score within some fraction of the best + // font on the characters in the given hash map. + // In the flags vector, each flag is set according to whether the + // corresponding character (in order of iterating ch_map) can be rendered. + // The return string is a list of the acceptable fonts that were used. + static string BestFonts(const unordered_map& ch_map, + vector > >* font_flag); + + // FontScore returns the weighted renderability score of the given + // hash map character table in the given font. The unweighted score + // is also returned in raw_score. + // The values in the bool vector ch_flags correspond to whether the + // corresponding character (in order of iterating ch_map) can be rendered. + static int FontScore(const unordered_map& ch_map, + const string& fontname, int* raw_score, + vector* ch_flags); +}; +} // namespace tesseract + +#endif // TESSERACT_TRAINING_PANGO_FONT_INFO_H_ diff --git a/TesseractOCR/include/tesseract/paragraphs.h b/TesseractOCR/include/tesseract/paragraphs.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/paragraphs_internal.h b/TesseractOCR/include/tesseract/paragraphs_internal.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/params.h b/TesseractOCR/include/tesseract/params.h old mode 100755 new mode 100644 index f95ac631..d49ce3ff --- a/TesseractOCR/include/tesseract/params.h +++ b/TesseractOCR/include/tesseract/params.h @@ -104,6 +104,9 @@ class ParamUtils { // Print parameters to the given file. static void PrintParams(FILE *fp, const ParamsVectors *member_params); + + // Resets all parameters back to default values; + static void ResetToDefaults(ParamsVectors* member_params); }; // Definition of various parameter types. @@ -142,15 +145,21 @@ class IntParam : public Param { IntParam(inT32 value, const char *name, const char *comment, bool init, ParamsVectors *vec) : Param(name, comment, init) { value_ = value; + default_ = value; params_vec_ = &(vec->int_params); vec->int_params.push_back(this); } ~IntParam() { ParamUtils::RemoveParam(this, params_vec_); } operator inT32() const { return value_; } + void operator=(inT32 value) { value_ = value; } void set_value(inT32 value) { value_ = value; } + void ResetToDefault() { + value_ = default_; + } private: inT32 value_; + inT32 default_; // Pointer to the vector that contains this param (not owened by this class). GenericVector *params_vec_; }; @@ -160,15 +169,21 @@ class BoolParam : public Param { BoolParam(bool value, const char *name, const char *comment, bool init, ParamsVectors *vec) : Param(name, comment, init) { value_ = value; + default_ = value; params_vec_ = &(vec->bool_params); vec->bool_params.push_back(this); } ~BoolParam() { ParamUtils::RemoveParam(this, params_vec_); } operator BOOL8() const { return value_; } + void operator=(BOOL8 value) { value_ = value; } void set_value(BOOL8 value) { value_ = value; } + void ResetToDefault() { + value_ = default_; + } private: BOOL8 value_; + BOOL8 default_; // Pointer to the vector that contains this param (not owned by this class). GenericVector *params_vec_; }; @@ -179,17 +194,25 @@ class StringParam : public Param { const char *comment, bool init, ParamsVectors *vec) : Param(name, comment, init) { value_ = value; + default_ = value; params_vec_ = &(vec->string_params); vec->string_params.push_back(this); } ~StringParam() { ParamUtils::RemoveParam(this, params_vec_); } operator STRING &() { return value_; } const char *string() const { return value_.string(); } + const char *c_str() const { return value_.string(); } bool empty() { return value_.length() <= 0; } - void set_value(const STRING &value) { value_ = value; } + bool operator==(const STRING& other) { return value_ == other; } + void operator=(const STRING& value) { value_ = value; } + void set_value(const STRING& value) { value_ = value; } + void ResetToDefault() { + value_ = default_; + } private: STRING value_; + STRING default_; // Pointer to the vector that contains this param (not owened by this class). GenericVector *params_vec_; }; @@ -199,15 +222,21 @@ class DoubleParam : public Param { DoubleParam(double value, const char *name, const char *comment, bool init, ParamsVectors *vec) : Param(name, comment, init) { value_ = value; + default_ = value; params_vec_ = &(vec->double_params); vec->double_params.push_back(this); } ~DoubleParam() { ParamUtils::RemoveParam(this, params_vec_); } operator double() const { return value_; } + void operator=(double value) { value_ = value; } void set_value(double value) { value_ = value; } + void ResetToDefault() { + value_ = default_; + } private: double value_; + double default_; // Pointer to the vector that contains this param (not owned by this class). GenericVector *params_vec_; }; diff --git a/TesseractOCR/include/tesseract/params_model.h b/TesseractOCR/include/tesseract/params_model.h new file mode 100644 index 00000000..a66e4450 --- /dev/null +++ b/TesseractOCR/include/tesseract/params_model.h @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////// +// File: params_model.h +// Description: Trained feature serialization for language parameter training. +// Author: David Eger +// Created: Mon Jun 11 11:26:42 PDT 2012 +// +// (C) Copyright 2011, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_WORDREC_PARAMS_MODEL_H_ +#define TESSERACT_WORDREC_PARAMS_MODEL_H_ + +#include "params_training_featdef.h" +#include "ratngs.h" +#include "strngs.h" + +namespace tesseract { + +// Represents the learned weights for a given language. +class ParamsModel { + public: + // Enum for expressing OCR pass. + enum PassEnum { + PTRAIN_PASS1, + PTRAIN_PASS2, + + PTRAIN_NUM_PASSES + }; + + ParamsModel() : pass_(PTRAIN_PASS1) {} + ParamsModel(const char *lang, const GenericVector &weights) : + lang_(lang), pass_(PTRAIN_PASS1) { weights_vec_[pass_] = weights; } + inline bool Initialized() { + return weights_vec_[pass_].size() == PTRAIN_NUM_FEATURE_TYPES; + } + // Prints out feature weights. + void Print(); + // Clears weights for all passes. + void Clear() { + for (int p = 0; p < PTRAIN_NUM_PASSES; ++p) weights_vec_[p].clear(); + } + // Copies the weights of the given params model. + void Copy(const ParamsModel &other_model); + // Applies params model weights to the given features. + // Assumes that features is an array of size PTRAIN_NUM_FEATURE_TYPES. + float ComputeCost(const float features[]) const; + bool Equivalent(const ParamsModel &that) const; + + // Returns true on success. + bool SaveToFile(const char *full_path) const; + + // Returns true on success. + bool LoadFromFile(const char *lang, const char *full_path); + bool LoadFromFp(const char *lang, FILE *fp, inT64 end_offset); + + const GenericVector& weights() const { + return weights_vec_[pass_]; + } + const GenericVector& weights_for_pass(PassEnum pass) const { + return weights_vec_[pass]; + } + void SetPass(PassEnum pass) { pass_ = pass; } + + private: + bool ParseLine(char *line, char **key, float *val); + + STRING lang_; + // Set to the current pass type and used to determine which set of weights + // should be used for ComputeCost() and other functions. + PassEnum pass_; + // Several sets of weights for various OCR passes (e.g. pass1 with adaption, + // pass2 without adaption, etc). + GenericVector weights_vec_[PTRAIN_NUM_PASSES]; +}; + +} // namespace tesseract + +#endif // TESSERACT_WORDREC_PARAMS_MODEL_H_ + diff --git a/TesseractOCR/include/tesseract/params_training_featdef.h b/TesseractOCR/include/tesseract/params_training_featdef.h old mode 100755 new mode 100644 index ce795687..ff76480b --- a/TesseractOCR/include/tesseract/params_training_featdef.h +++ b/TesseractOCR/include/tesseract/params_training_featdef.h @@ -25,67 +25,97 @@ namespace tesseract { +// Maximum number of unichars in the small and medium sized words +static const int kMaxSmallWordUnichars = 3; +static const int kMaxMediumWordUnichars = 6; + // Raw features extracted from a single OCR hypothesis. -// The features are non-normalized real-valued quantities with -// unbounded range and unknown distribution. +// The features are normalized (by outline length or number of unichars as +// appropriate) real-valued quantities with unbounded range and +// unknown distribution. // Normalization / binarization of these features is done at a later stage. // Note: when adding new fields to this enum make sure to modify -// kParamsTrainingRawFeatureTypeName enum accordingly. -enum ParamsTrainingRawFeatureType { - // What dictionary (if any) was this hypothesis found in. - // See PermuterType enum in ccstruct/ratngs.h for interpretation. - PTRAIN_RAW_FEATURE_DICT_MATCH_TYPE, // 0 - // Boolean indicator of whether this hypothesis is ambiguous to a known - // dictionary word (or a valid number pattern). - PTRAIN_RAW_FEATURE_UNAMBIG_DICT_MATCH, // 1 - // Shape cost of the segmentation path for this hypothesis. - PTRAIN_RAW_FEATURE_SHAPE_COST, // 2 - // Character ngram probability of the string of unichars of this hypothesis. - PTRAIN_RAW_FEATURE_NGRAM_PROB, // 3 - // Number of bad/inconsistent spots in this hypothesis. - PTRAIN_RAW_FEATURE_NUM_BAD_PUNC, // 4 - PTRAIN_RAW_FEATURE_NUM_BAD_CASE, // 5 - PTRAIN_RAW_FEATURE_NUM_BAD_CHAR_TYPE, // 6 - PTRAIN_RAW_FEATURE_NUM_BAD_SPACING, // 7 - PTRAIN_RAW_FEATURE_NUM_BAD_SCRIPT, // 8 - PTRAIN_RAW_FEATURE_NUM_BAD_FONT, // 9 - // Classifier-related features. - PTRAIN_RAW_FEATURE_WORST_CERT, // 10 - PTRAIN_RAW_FEATURE_RATING, // 11 - // Number of classifier results that came from adapted templates. - PTRAIN_RAW_FEATURE_ADAPTED, // 12 - // Features potentially useful for normalization. - PTRAIN_RAW_FEATURE_NUM_UNICHARS, // 13 - PTRAIN_RAW_FEATURE_OUTLINE_LEN, // 14 +// kParamsTrainingFeatureTypeName +enum kParamsTrainingFeatureType { + // Digits + PTRAIN_DIGITS_SHORT, // 0 + PTRAIN_DIGITS_MED, // 1 + PTRAIN_DIGITS_LONG, // 2 + // Number or pattern (NUMBER_PERM, USER_PATTERN_PERM) + PTRAIN_NUM_SHORT, // 3 + PTRAIN_NUM_MED, // 4 + PTRAIN_NUM_LONG, // 5 + // Document word (DOC_DAWG_PERM) + PTRAIN_DOC_SHORT, // 6 + PTRAIN_DOC_MED, // 7 + PTRAIN_DOC_LONG, // 8 + // Word (SYSTEM_DAWG_PERM, USER_DAWG_PERM, COMPOUND_PERM) + PTRAIN_DICT_SHORT, // 9 + PTRAIN_DICT_MED, // 10 + PTRAIN_DICT_LONG, // 11 + // Frequent word (FREQ_DAWG_PERM) + PTRAIN_FREQ_SHORT, // 12 + PTRAIN_FREQ_MED, // 13 + PTRAIN_FREQ_LONG, // 14 + PTRAIN_SHAPE_COST_PER_CHAR, // 15 + PTRAIN_NGRAM_COST_PER_CHAR, // 16 + PTRAIN_NUM_BAD_PUNC, // 17 + PTRAIN_NUM_BAD_CASE, // 18 + PTRAIN_XHEIGHT_CONSISTENCY, // 19 + PTRAIN_NUM_BAD_CHAR_TYPE, // 20 + PTRAIN_NUM_BAD_SPACING, // 21 + PTRAIN_NUM_BAD_FONT, // 22 + PTRAIN_RATING_PER_CHAR, // 23 - PTRAIN_NUM_RAW_FEATURE_TYPES + PTRAIN_NUM_FEATURE_TYPES }; -static const char * const kParamsTrainingRawFeatureTypeName[] = { - "DICT_MATCH_TYPE", // 0 - "UNAMBIG_DICT_MATCH", // 1 - "SHAPE_COST", // 2 - "NGRAM_PROB", // 3 - "NUM_BAD_PUNC", // 4 - "NUM_BAD_CASE", // 5 - "NUM_BAD_CHAR_TYPE", // 6 - "NUM_BAD_SPACING", // 7 - "NUM_BAD_SCRIPT", // 8 - "NUM_BAD_FONT", // 9 - "WORST_CERT", // 10 - "RATING", // 11 - "ADAPTED", // 12 - "NUM_UNICHARS", // 13 - "OUTLINE_LEN", // 14 +static const char * const kParamsTrainingFeatureTypeName[] = { + "PTRAIN_DIGITS_SHORT", // 0 + "PTRAIN_DIGITS_MED", // 1 + "PTRAIN_DIGITS_LONG", // 2 + "PTRAIN_NUM_SHORT", // 3 + "PTRAIN_NUM_MED", // 4 + "PTRAIN_NUM_LONG", // 5 + "PTRAIN_DOC_SHORT", // 6 + "PTRAIN_DOC_MED", // 7 + "PTRAIN_DOC_LONG", // 8 + "PTRAIN_DICT_SHORT", // 9 + "PTRAIN_DICT_MED", // 10 + "PTRAIN_DICT_LONG", // 11 + "PTRAIN_FREQ_SHORT", // 12 + "PTRAIN_FREQ_MED", // 13 + "PTRAIN_FREQ_LONG", // 14 + "PTRAIN_SHAPE_COST_PER_CHAR", // 15 + "PTRAIN_NGRAM_COST_PER_CHAR", // 16 + "PTRAIN_NUM_BAD_PUNC", // 17 + "PTRAIN_NUM_BAD_CASE", // 18 + "PTRAIN_XHEIGHT_CONSISTENCY", // 19 + "PTRAIN_NUM_BAD_CHAR_TYPE", // 20 + "PTRAIN_NUM_BAD_SPACING", // 21 + "PTRAIN_NUM_BAD_FONT", // 22 + "PTRAIN_RATING_PER_CHAR", // 23 }; +// Returns the index of the given feature (by name), +// or -1 meaning the feature is unknown. +int ParamsTrainingFeatureByName(const char *name); + + // Entry with features extracted from a single OCR hypothesis for a word. struct ParamsTrainingHypothesis { - ParamsTrainingHypothesis() { - for (int i = 0; i < PTRAIN_NUM_RAW_FEATURE_TYPES; ++i) features[i] = 0.0; + ParamsTrainingHypothesis() : cost(0.0) { + memset(features, 0, sizeof(float) * PTRAIN_NUM_FEATURE_TYPES); + } + ParamsTrainingHypothesis(const ParamsTrainingHypothesis &other) { + memcpy(features, other.features, + sizeof(float) * PTRAIN_NUM_FEATURE_TYPES); + str = other.str; + cost = other.cost; } - float features[PTRAIN_NUM_RAW_FEATURE_TYPES]; + float features[PTRAIN_NUM_FEATURE_TYPES]; STRING str; // string corresponding to word hypothesis (for debugging) + float cost; // path cost computed by segsearch }; // A list of hypotheses explored during one run of segmentation search. @@ -104,9 +134,10 @@ class ParamsTrainingBundle { } // Adds a new ParamsTrainingHypothesis to the current hypothesis list // and returns the reference to the newly added entry. - ParamsTrainingHypothesis &AddHypothesis() { + ParamsTrainingHypothesis &AddHypothesis( + const ParamsTrainingHypothesis &other) { if (hyp_list_vec.empty()) StartHypothesisList(); - hyp_list_vec.back().push_back(ParamsTrainingHypothesis()); + hyp_list_vec.back().push_back(ParamsTrainingHypothesis(other)); return hyp_list_vec.back().back(); } diff --git a/TesseractOCR/include/tesseract/paramsd.h b/TesseractOCR/include/tesseract/paramsd.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/pdblock.h b/TesseractOCR/include/tesseract/pdblock.h old mode 100755 new mode 100644 index 08262fd0..34f5518e --- a/TesseractOCR/include/tesseract/pdblock.h +++ b/TesseractOCR/include/tesseract/pdblock.h @@ -21,12 +21,9 @@ #define PDBLOCK_H #include "clst.h" -#include "img.h" #include "strngs.h" #include "polyblk.h" -#include "hpddef.h" //must be last (handpd.dll) - class DLLSYM PDBLK; //forward decl struct Pix; @@ -103,11 +100,6 @@ class PDBLK inT32 serial, ScrollView::Color colour); #endif // GRAPHICS_DISABLED - ///show image - ///@param image image to show - ///@param window window to show in - void show(IMAGE *image, - ScrollView* window); ///assignment ///@param source from this diff --git a/TesseractOCR/include/tesseract/pgedit.h b/TesseractOCR/include/tesseract/pgedit.h old mode 100755 new mode 100644 index 667be1bb..e9fc6936 --- a/TesseractOCR/include/tesseract/pgedit.h +++ b/TesseractOCR/include/tesseract/pgedit.h @@ -25,7 +25,6 @@ #include "werd.h" #include "rect.h" #include "params.h" -#include "notdll.h" #include "tesseractclass.h" class ScrollView; diff --git a/TesseractOCR/include/tesseract/picofeat.h b/TesseractOCR/include/tesseract/picofeat.h new file mode 100644 index 00000000..ab37ba03 --- /dev/null +++ b/TesseractOCR/include/tesseract/picofeat.h @@ -0,0 +1,72 @@ +/****************************************************************************** + ** Filename: picofeat.h + ** Purpose: Definition of pico features. + ** Author: Dan Johnson + ** History: 9/4/90, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef PICOFEAT_H +#define PICOFEAT_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "ocrfeatures.h" +#include "params.h" + +// Enum for the order/type of params in IntFeatDesc. +enum IntParams { + IntX, // x-position (0-255). + IntY, // y-position (0-255). + IntDir // Direction (0-255, circular). +}; + +// Enum for the order/type of params in GeoFeatDesc. +enum GeoParams { + GeoBottom, // Bounding box bottom in baseline space (0-255). + GeoTop, // Bounding box top in baseline space (0-255). + GeoWidth, // Bounding box width in baseline space (0-255). + + GeoCount // Number of geo features. +}; + +typedef enum +{ PicoFeatY, PicoFeatDir, PicoFeatX } +PICO_FEAT_PARAM_NAME; + +#define MAX_PICO_FEATURES (1000) + +/*--------------------------------------------------------------------------- + Variables +----------------------------------------------------------------------------*/ + +extern double_VAR_H(classify_pico_feature_length, 0.05, "Pico Feature Length"); + + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ +#define GetPicoFeatureLength() (PicoFeatureLength) + +FEATURE_SET ExtractIntCNFeatures(TBLOB *Blob, const DENORM& bl_denorm, + const DENORM& cn_denorm, + const INT_FX_RESULT_STRUCT& fx_info); +FEATURE_SET ExtractIntGeoFeatures(TBLOB *Blob, const DENORM& bl_denorm, + const DENORM& cn_denorm, + const INT_FX_RESULT_STRUCT& fx_info); + +/**---------------------------------------------------------------------------- + Global Data Definitions and Declarations +----------------------------------------------------------------------------**/ +extern FLOAT32 PicoFeatureLength; +#endif diff --git a/TesseractOCR/include/tesseract/pithsync.h b/TesseractOCR/include/tesseract/pithsync.h new file mode 100644 index 00000000..c7f5e16d --- /dev/null +++ b/TesseractOCR/include/tesseract/pithsync.h @@ -0,0 +1,133 @@ +/********************************************************************** + * File: pithsync.h (Formerly pitsync2.h) + * Description: Code to find the optimum fixed pitch segmentation of some blobs. + * Author: Ray Smith + * Created: Thu Nov 19 11:48:05 GMT 1992 + * + * (C) Copyright 1992, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef PITHSYNC_H +#define PITHSYNC_H + +#include "blobbox.h" +#include "params.h" +#include "statistc.h" + +class FPSEGPT_LIST; + +class FPCUTPT +{ + public: + FPCUTPT() { //empty + } + void setup ( //start of cut + FPCUTPT cutpts[], //predecessors + inT16 array_origin, //start coord + STATS * projection, //occupation + inT16 zero_count, //official zero + inT16 pitch, //proposed pitch + inT16 x, //position + inT16 offset); //dist to gap + + void assign ( //evaluate cut + FPCUTPT cutpts[], //predecessors + inT16 array_origin, //start coord + inT16 x, //position + BOOL8 faking, //faking this one + BOOL8 mid_cut, //doing free cut + inT16 offset, //extra cost dist + STATS * projection, //occupation + float projection_scale, //scaling + inT16 zero_count, //official zero + inT16 pitch, //proposed pitch + inT16 pitch_error); //allowed tolerance + + void assign_cheap ( //evaluate cut + FPCUTPT cutpts[], //predecessors + inT16 array_origin, //start coord + inT16 x, //position + BOOL8 faking, //faking this one + BOOL8 mid_cut, //doing free cut + inT16 offset, //extra cost dist + STATS * projection, //occupation + float projection_scale, //scaling + inT16 zero_count, //official zero + inT16 pitch, //proposed pitch + inT16 pitch_error); //allowed tolerance + + inT32 position() { //acces func + return xpos; + } + double cost_function() { + return cost; + } + double squares() { + return sq_sum; + } + double sum() { + return mean_sum; + } + FPCUTPT *previous() { + return pred; + } + inT16 cheap_cuts() const { //no of mi cuts + return mid_cuts; + } + inT16 index() const { + return region_index; + } + + BOOL8 faked; //faked split point + BOOL8 terminal; //successful end + inT16 fake_count; //total fakes to here + + private: + inT16 region_index; //cut serial number + inT16 mid_cuts; //no of cheap cuts + inT32 xpos; //location + uinT32 back_balance; //proj backwards + uinT32 fwd_balance; //proj forwards + FPCUTPT *pred; //optimal previous + double mean_sum; //mean so far + double sq_sum; //summed distsances + double cost; //cost function +}; +double check_pitch_sync2( //find segmentation + BLOBNBOX_IT *blob_it, //blobs to do + inT16 blob_count, //no of blobs + inT16 pitch, //pitch estimate + inT16 pitch_error, //tolerance + STATS *projection, //vertical + inT16 projection_left, //edges //scale factor + inT16 projection_right, + float projection_scale, + inT16 &occupation_count, //no of occupied cells + FPSEGPT_LIST *seg_list, //output list + inT16 start, //start of good range + inT16 end //end of good range + ); +double check_pitch_sync3( //find segmentation + inT16 projection_left, //edges //to be considered 0 + inT16 projection_right, + inT16 zero_count, + inT16 pitch, //pitch estimate + inT16 pitch_error, //tolerance + STATS *projection, //vertical + float projection_scale, //scale factor + inT16 &occupation_count, //no of occupied cells + FPSEGPT_LIST *seg_list, //output list + inT16 start, //start of good range + inT16 end //end of good range + ); +#endif diff --git a/TesseractOCR/include/tesseract/pitsync1.h b/TesseractOCR/include/tesseract/pitsync1.h new file mode 100644 index 00000000..41947a8b --- /dev/null +++ b/TesseractOCR/include/tesseract/pitsync1.h @@ -0,0 +1,122 @@ +/********************************************************************** + * File: pitsync1.h (Formerly pitsync.h) + * Description: Code to find the optimum fixed pitch segmentation of some blobs. + * Author: Ray Smith + * Created: Thu Nov 19 11:48:05 GMT 1992 + * + * (C) Copyright 1992, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef PITSYNC1_H +#define PITSYNC1_H + +#include "elst.h" +#include "clst.h" +#include "blobbox.h" +#include "params.h" +#include "statistc.h" +#include "pithsync.h" + +class FPSEGPT_LIST; + +class FPSEGPT:public ELIST_LINK +{ + public: + FPSEGPT() { //empty + } + FPSEGPT( //constructor + inT16 x); //position + FPSEGPT( //constructor + inT16 x, //position + BOOL8 faking, //faking this one + inT16 offset, //extra cost dist + inT16 region_index, //segment number + inT16 pitch, //proposed pitch + inT16 pitch_error, //allowed tolerance + FPSEGPT_LIST *prev_list); //previous segment + FPSEGPT(FPCUTPT *cutpt); //build from new type + + inT32 position() { //acces func + return xpos; + } + double cost_function() { + return cost; + } + double squares() { + return sq_sum; + } + double sum() { + return mean_sum; + } + FPSEGPT *previous() { + return pred; + } + inT16 cheap_cuts() const { //no of cheap cuts + return mid_cuts; + } + + //faked split point + BOOL8 faked; + BOOL8 terminal; //successful end + inT16 fake_count; //total fakes to here + + private: + inT16 mid_cuts; //no of cheap cuts + inT32 xpos; //location + FPSEGPT *pred; //optimal previous + double mean_sum; //mean so far + double sq_sum; //summed distsances + double cost; //cost function +}; + +ELISTIZEH (FPSEGPT) CLISTIZEH (FPSEGPT_LIST) +extern +INT_VAR_H (pitsync_linear_version, 0, "Use new fast algorithm"); +extern +double_VAR_H (pitsync_joined_edge, 0.75, +"Dist inside big blob for chopping"); +extern +double_VAR_H (pitsync_offset_freecut_fraction, 0.25, +"Fraction of cut for free cuts"); +extern +INT_VAR_H (pitsync_fake_depth, 1, "Max advance fake generation"); +double check_pitch_sync( //find segmentation + BLOBNBOX_IT *blob_it, //blobs to do + inT16 blob_count, //no of blobs + inT16 pitch, //pitch estimate + inT16 pitch_error, //tolerance + STATS *projection, //vertical + FPSEGPT_LIST *seg_list //output list + ); +void make_illegal_segment( //find segmentation + FPSEGPT_LIST *prev_list, //previous segments + TBOX blob_box, //bounding box + BLOBNBOX_IT blob_it, //iterator + inT16 region_index, //number of segment + inT16 pitch, //pitch estimate + inT16 pitch_error, //tolerance + FPSEGPT_LIST *seg_list //output list + ); +inT16 vertical_torow_projection( //project whole row + TO_ROW *row, //row to do + STATS *projection //output + ); +void vertical_cblob_projection( //project outlines + C_BLOB *blob, //blob to project + STATS *stats //output + ); +void vertical_coutline_projection( //project outlines + C_OUTLINE *outline, //outline to project + STATS *stats //output + ); +#endif diff --git a/TesseractOCR/include/tesseract/platform.h b/TesseractOCR/include/tesseract/platform.h old mode 100755 new mode 100644 index 4f8a8164..4f611df4 --- a/TesseractOCR/include/tesseract/platform.h +++ b/TesseractOCR/include/tesseract/platform.h @@ -20,14 +20,12 @@ #ifndef TESSERACT_CCUTIL_PLATFORM_H__ #define TESSERACT_CCUTIL_PLATFORM_H__ +#include + #define DLLSYM #ifdef _WIN32 #ifdef __GNUC__ #define ultoa _ultoa -typedef struct _BLOB { - unsigned int cbSize; - char *pBlobData; -} BLOB, *LPBLOB; #endif /* __GNUC__ */ #define SIGNED #define snprintf _snprintf @@ -45,6 +43,12 @@ typedef struct _BLOB { #define SIGNED signed #endif +#ifdef _WIN32 +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#endif + #if defined(_WIN32) || defined(__CYGWIN__) #if defined(TESS_EXPORTS) #define TESS_API __declspec(dllexport) @@ -69,4 +73,12 @@ typedef struct _BLOB { #endif #endif +#if defined(_WIN32) || defined(__CYGWIN__) + #define _TESS_FILE_BASENAME_ \ + (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) +#else // Unices + #define _TESS_FILE_BASENAME_ \ + (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) +#endif + #endif // TESSERACT_CCUTIL_PLATFORM_H__ diff --git a/TesseractOCR/include/tesseract/plotedges.h b/TesseractOCR/include/tesseract/plotedges.h new file mode 100644 index 00000000..d0ca40be --- /dev/null +++ b/TesseractOCR/include/tesseract/plotedges.h @@ -0,0 +1,71 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: plotedges.h (Formerly plotedges.h) + * Description: Convert the various data type into line lists + * Author: Mark Seaman, OCR Technology + * Created: Fri Jul 28 13:14:48 1989 + * Modified: Mon May 13 09:34:51 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Experimental (Do Not Distribute) + * + * (c) Copyright 1989, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ +#ifndef PLOTEDGES_H +#define PLOTEDGES_H + +#include "callcpp.h" +#include "oldlist.h" +#include "blobs.h" +#include "split.h" + +/*---------------------------------------------------------------------- + V a r i a b l e s +----------------------------------------------------------------------*/ +extern ScrollView *edge_window; /* Window for edges */ + +/*---------------------------------------------------------------------- + Macros +----------------------------------------------------------------------*/ +/********************************************************************** + * update_edge_window + * + * Refresh the display of the edge window. + **********************************************************************/ +#define update_edge_window() \ +if (wordrec_display_splits) { \ + c_make_current (edge_window); \ +} \ + + +/********************************************************************** + * edge_window_wait + * + * Wait for someone to click in the edges window. + **********************************************************************/ + +#define edge_window_wait() \ +if (wordrec_display_splits) window_wait (edge_window) + +/*---------------------------------------------------------------------- + F u n c t i o n s +---------------------------------------------------------------------*/ +void display_edgepts(LIST outlines); + +void draw_blob_edges(TBLOB *blob); + +void mark_outline(EDGEPT *edgept); + +void mark_split(SPLIT *split); +#endif diff --git a/TesseractOCR/include/tesseract/points.h b/TesseractOCR/include/tesseract/points.h old mode 100755 new mode 100644 index 7f50fd15..33e07328 --- a/TesseractOCR/include/tesseract/points.h +++ b/TesseractOCR/include/tesseract/points.h @@ -249,6 +249,25 @@ class DLLSYM FCOORD float angle() const { return (float) atan2 (ycoord, xcoord); } + // Returns the standard feature direction corresponding to this. + // See binary_angle_plus_pi below for a description of the direction. + uinT8 to_direction() const; + // Sets this with a unit vector in the given standard feature direction. + void from_direction(uinT8 direction); + + // Converts an angle in radians (from ICOORD::angle or FCOORD::angle) to a + // standard feature direction as an unsigned angle in 256ths of a circle + // measured anticlockwise from (-1, 0). + static uinT8 binary_angle_plus_pi(double angle); + // Inverse of binary_angle_plus_pi returns an angle in radians for the + // given standard feature direction. + static double angle_from_direction(uinT8 direction); + // Returns the point on the given line nearest to this, ie the point such + // that the vector point->this is perpendicular to the line. + // The line is defined as a line_point and a dir_vector for its direction. + // dir_vector need not be a unit vector. + FCOORD nearest_pt_on_line(const FCOORD& line_point, + const FCOORD& dir_vector) const; ///Convert to unit vec bool normalise(); diff --git a/TesseractOCR/include/tesseract/polyaprx.h b/TesseractOCR/include/tesseract/polyaprx.h old mode 100755 new mode 100644 index 7e5eff90..45e3c755 --- a/TesseractOCR/include/tesseract/polyaprx.h +++ b/TesseractOCR/include/tesseract/polyaprx.h @@ -24,7 +24,7 @@ #include "coutln.h" // convert a chain-coded input to the old OUTLINE approximation -TESSLINE* ApproximateOutline(C_OUTLINE *c_outline); +TESSLINE* ApproximateOutline(bool allow_detailed_fx, C_OUTLINE *c_outline); EDGEPT *edgesteps_to_edgepts ( //convert outline C_OUTLINE * c_outline, //input EDGEPT edgepts[] //output is array diff --git a/TesseractOCR/include/tesseract/polyblk.h b/TesseractOCR/include/tesseract/polyblk.h old mode 100755 new mode 100644 index f5546bba..edfaac78 --- a/TesseractOCR/include/tesseract/polyblk.h +++ b/TesseractOCR/include/tesseract/polyblk.h @@ -25,8 +25,6 @@ #include "rect.h" #include "scrollview.h" -#include "hpddef.h" // must be last (handpd.dll) - class DLLSYM POLY_BLOCK { public: POLY_BLOCK() { diff --git a/TesseractOCR/include/tesseract/protos.h b/TesseractOCR/include/tesseract/protos.h new file mode 100644 index 00000000..bb2f56b5 --- /dev/null +++ b/TesseractOCR/include/tesseract/protos.h @@ -0,0 +1,179 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: protos.h (Formerly protos.h) + * Description: + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Fri Jul 12 10:06:55 1991 (Dan Johnson) danj@hpgrlj + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ +#ifndef PROTOS_H +#define PROTOS_H + +/*---------------------------------------------------------------------- + I n c l u d e s +----------------------------------------------------------------------*/ +#include "bitvec.h" +#include "cutil.h" +#include "unichar.h" +#include "unicity_table.h" +#include "params.h" + +/*---------------------------------------------------------------------- + T y p e s +----------------------------------------------------------------------*/ +typedef BIT_VECTOR *CONFIGS; + +typedef struct +{ + FLOAT32 A; + FLOAT32 B; + FLOAT32 C; + FLOAT32 X; + FLOAT32 Y; + FLOAT32 Angle; + FLOAT32 Length; +} PROTO_STRUCT; +typedef PROTO_STRUCT *PROTO; + +struct CLASS_STRUCT { + CLASS_STRUCT() + : NumProtos(0), MaxNumProtos(0), Prototypes(NULL), + NumConfigs(0), MaxNumConfigs(0), Configurations(NULL) { + } + inT16 NumProtos; + inT16 MaxNumProtos; + PROTO Prototypes; + inT16 NumConfigs; + inT16 MaxNumConfigs; + CONFIGS Configurations; + UnicityTableEqEq font_set; +}; +typedef CLASS_STRUCT *CLASS_TYPE; +typedef CLASS_STRUCT *CLASSES; + +/*---------------------------------------------------------------------- + C o n s t a n t s +----------------------------------------------------------------------*/ +#define NUMBER_OF_CLASSES MAX_NUM_CLASSES +#define Y_OFFSET -40.0 +#define FEATURE_SCALE 100.0 + +/*---------------------------------------------------------------------- + V a r i a b l e s +----------------------------------------------------------------------*/ +extern CLASS_STRUCT TrainingData[]; + +extern STRING_VAR_H(classify_training_file, "MicroFeatures", "Training file"); + +/*---------------------------------------------------------------------- + M a c r o s +----------------------------------------------------------------------*/ +/** + * AddProtoToConfig + * + * Set a single proto bit in the specified configuration. + */ + +#define AddProtoToConfig(Pid,Config) \ +(SET_BIT (Config, Pid)) + +/** + * RemoveProtoFromConfig + * + * Clear a single proto bit in the specified configuration. + */ + +#define RemoveProtoFromConfig(Pid,Config) \ +(reset_bit (Config, Pid)) + +/** + * ClassOfChar + * + * Return the class of a particular ASCII character value. + */ + +#define ClassOfChar(Char) \ +((TrainingData [Char].NumProtos) ? \ + (& TrainingData [Char]) : \ + NO_CLASS) + +/** + * ProtoIn + * + * Choose the selected prototype in this class record. Return the + * pointer to it (type PROTO). + */ + +#define ProtoIn(Class,Pid) \ +(& (Class)->Prototypes [Pid]) + +/** + * PrintProto + * + * Print out the contents of a prototype. The 'Proto' argument is of + * type 'PROTO'. + */ + +#define PrintProto(Proto) \ +(tprintf("X=%4.2f, Y=%4.2f, Length=%4.2f, Angle=%4.2f", \ + Proto->X, \ + Proto->Y, \ + Proto->Length, \ + Proto->Angle)) \ + + +/** + * PrintProtoLine + * + * Print out the contents of a prototype. The 'Proto' argument is of + * type 'PROTO'. + */ + +#define PrintProtoLine(Proto) \ +(cprintf ("A=%4.2f, B=%4.2f, C=%4.2f", \ + Proto->A, \ + Proto->B, \ + Proto->C)) \ + +/*---------------------------------------------------------------------- + F u n c t i o n s +----------------------------------------------------------------------*/ +int AddConfigToClass(CLASS_TYPE Class); + +int AddProtoToClass(CLASS_TYPE Class); + +FLOAT32 ClassConfigLength(CLASS_TYPE Class, BIT_VECTOR Config); + +FLOAT32 ClassProtoLength(CLASS_TYPE Class); + +void CopyProto(PROTO Src, PROTO Dest); + +void FillABC(PROTO Proto); + +void FreeClass(CLASS_TYPE Class); + +void FreeClassFields(CLASS_TYPE Class); + +void InitPrototypes(); + +CLASS_TYPE NewClass(int NumProtos, int NumConfigs); + +void PrintProtos(CLASS_TYPE Class); + +#endif diff --git a/TesseractOCR/include/tesseract/publictypes.h b/TesseractOCR/include/tesseract/publictypes.h old mode 100755 new mode 100644 index 3640d54f..5ab8bf39 --- a/TesseractOCR/include/tesseract/publictypes.h +++ b/TesseractOCR/include/tesseract/publictypes.h @@ -73,6 +73,10 @@ inline bool PTIsTextType(PolyBlockType type) { type == PT_VERTICAL_TEXT || type == PT_CAPTION_TEXT || type == PT_INLINE_EQUATION; } +// Returns true if PolyBlockType is of pullout(inter-column) type +inline bool PTIsPulloutType(PolyBlockType type) { + return type == PT_PULLOUT_IMAGE || type == PT_PULLOUT_TEXT; +} /** String name for each block type. Keep in sync with PolyBlockType. */ extern const char* kPolyBlockNames[]; @@ -158,6 +162,8 @@ enum PageSegMode { PSM_SINGLE_WORD, ///< Treat the image as a single word. PSM_CIRCLE_WORD, ///< Treat the image as a single word in a circle. PSM_SINGLE_CHAR, ///< Treat the image as a single character. + PSM_SPARSE_TEXT, ///< Find as much text as possible in no particular order. + PSM_SPARSE_TEXT_OSD, ///< Sparse text with orientation and script det. PSM_COUNT ///< Number of enum entries. }; @@ -167,15 +173,19 @@ enum PageSegMode { * layout analysis are enabled. * *Depend critically on the order of elements of PageSegMode.* */ -#define PSM_OSD_ENABLED(pageseg_mode) ((pageseg_mode) <= PSM_AUTO_OSD) +#define PSM_OSD_ENABLED(pageseg_mode) ((pageseg_mode) <= PSM_AUTO_OSD || \ + (pageseg_mode) == PSM_SPARSE_TEXT_OSD) #define PSM_COL_FIND_ENABLED(pageseg_mode) \ ((pageseg_mode) >= PSM_AUTO_OSD && (pageseg_mode) <= PSM_AUTO) +#define PSM_SPARSE(pageseg_mode) \ + ((pageseg_mode) == PSM_SPARSE_TEXT || (pageseg_mode) == PSM_SPARSE_TEXT_OSD) #define PSM_BLOCK_FIND_ENABLED(pageseg_mode) \ ((pageseg_mode) >= PSM_AUTO_OSD && (pageseg_mode) <= PSM_SINGLE_COLUMN) #define PSM_LINE_FIND_ENABLED(pageseg_mode) \ ((pageseg_mode) >= PSM_AUTO_OSD && (pageseg_mode) <= PSM_SINGLE_BLOCK) #define PSM_WORD_FIND_ENABLED(pageseg_mode) \ - ((pageseg_mode) >= PSM_AUTO_OSD && (pageseg_mode) <= PSM_SINGLE_LINE) + (((pageseg_mode) >= PSM_AUTO_OSD && (pageseg_mode) <= PSM_SINGLE_LINE) || \ + (pageseg_mode) == PSM_SPARSE_TEXT || (pageseg_mode) == PSM_SPARSE_TEXT_OSD) /** * enum of the elements of the page hierarchy, used in ResultIterator diff --git a/TesseractOCR/include/tesseract/qrsequence.h b/TesseractOCR/include/tesseract/qrsequence.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/quadlsq.h b/TesseractOCR/include/tesseract/quadlsq.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/quadratc.h b/TesseractOCR/include/tesseract/quadratc.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/quspline.h b/TesseractOCR/include/tesseract/quspline.h old mode 100755 new mode 100644 index 51a01367..f9e8145b --- a/TesseractOCR/include/tesseract/quspline.h +++ b/TesseractOCR/include/tesseract/quspline.h @@ -26,6 +26,7 @@ #include "rect.h" class ROW; +struct Pix; class QSPLINE { @@ -80,6 +81,10 @@ class QSPLINE ScrollView::Color colour) const; //in colour #endif + // Paint the baseline over pix. If pix has depth of 32, then the line will + // be painted in red. Otherwise it will be painted in black. + void plot(Pix* pix) const; + QSPLINE & operator= ( const QSPLINE & source); //from this diff --git a/TesseractOCR/include/tesseract/ratngs.h b/TesseractOCR/include/tesseract/ratngs.h old mode 100755 new mode 100644 index 4e9e07bc..e776859e --- a/TesseractOCR/include/tesseract/ratngs.h +++ b/TesseractOCR/include/tesseract/ratngs.h @@ -23,12 +23,27 @@ #include #include "clst.h" +#include "elst.h" #include "genericvector.h" -#include "notdll.h" +#include "matrix.h" #include "unichar.h" #include "unicharset.h" #include "werd.h" +class MATRIX; +struct TBLOB; +struct TWERD; + +// Enum to describe the source of a BLOB_CHOICE to make it possible to determine +// whether a blob has been classified by inspecting the BLOB_CHOICEs. +enum BlobChoiceClassifier { + BCC_STATIC_CLASSIFIER, // From the char_norm classifier. + BCC_ADAPTED_CLASSIFIER, // From the adaptive classifier. + BCC_SPECKLE_CLASSIFIER, // Backup for failed classification. + BCC_AMBIG, // Generated by ambiguity detection. + BCC_FAKE, // From some other process. +}; + class BLOB_CHOICE: public ELIST_LINK { public: @@ -39,20 +54,23 @@ class BLOB_CHOICE: public ELIST_LINK rating_ = MAX_FLOAT32; certainty_ = -MAX_FLOAT32; script_id_ = -1; - language_model_state_ = NULL; - min_xheight_ = 0; - max_xheight_ = 0; - adapted_ = false; + xgap_before_ = 0; + xgap_after_ = 0; + min_xheight_ = 0.0f; + max_xheight_ = 0.0f; + yshift_ = 0.0f; + classifier_ = BCC_FAKE; } BLOB_CHOICE(UNICHAR_ID src_unichar_id, // character id float src_rating, // rating float src_cert, // certainty - inT16 src_fontinfo_id, // font - inT16 src_fontinfo_id2, // 2nd choice font + inT16 src_fontinfo_id, // font + inT16 src_fontinfo_id2, // 2nd choice font int script_id, // script - inT16 min_xheight, // min xheight in image pixel units - inT16 max_xheight, // max xheight allowed by this char - bool adapted); // adapted match or not + float min_xheight, // min xheight in image pixel units + float max_xheight, // max xheight allowed by this char + float yshift, // the larger of y shift (top or bottom) + BlobChoiceClassifier c); // adapted match or other BLOB_CHOICE(const BLOB_CHOICE &other); ~BLOB_CHOICE() {} @@ -74,8 +92,8 @@ class BLOB_CHOICE: public ELIST_LINK int script_id() const { return script_id_; } - void *language_model_state() { - return language_model_state_; + const MATRIX_COORD& matrix_cell() { + return matrix_cell_; } inT16 xgap_before() const { return xgap_before_; @@ -83,14 +101,25 @@ class BLOB_CHOICE: public ELIST_LINK inT16 xgap_after() const { return xgap_after_; } - inT16 min_xheight() const { + float min_xheight() const { return min_xheight_; } - inT16 max_xheight() const { + float max_xheight() const { return max_xheight_; } - bool adapted() const { - return adapted_; + float yshift() const { + return yshift_; + } + BlobChoiceClassifier classifier() const { + return classifier_; + } + bool IsAdapted() const { + return classifier_ == BCC_ADAPTED_CLASSIFIER; + } + bool IsClassified() const { + return classifier_ == BCC_STATIC_CLASSIFIER || + classifier_ == BCC_ADAPTED_CLASSIFIER || + classifier_ == BCC_SPECKLE_CLASSIFIER; } void set_unichar_id(UNICHAR_ID newunichar_id) { @@ -111,8 +140,9 @@ class BLOB_CHOICE: public ELIST_LINK void set_script(int newscript_id) { script_id_ = newscript_id; } - void set_language_model_state(void *language_model_state) { - language_model_state_ = language_model_state; + void set_matrix_cell(int col, int row) { + matrix_cell_.col = col; + matrix_cell_.row = row; } void set_xgap_before(inT16 gap) { xgap_before_ = gap; @@ -120,19 +150,39 @@ class BLOB_CHOICE: public ELIST_LINK void set_xgap_after(inT16 gap) { xgap_after_ = gap; } - void set_adapted(bool adapted) { - adapted_ = adapted; + void set_classifier(BlobChoiceClassifier classifier) { + classifier_ = classifier; } static BLOB_CHOICE* deep_copy(const BLOB_CHOICE* src) { BLOB_CHOICE* choice = new BLOB_CHOICE; *choice = *src; return choice; } - void print(const UNICHARSET *unicharset) { - tprintf("r%.2f c%.2f : %d %s", rating_, certainty_, unichar_id_, + // Returns true if *this and other agree on the baseline and x-height + // to within some tolerance based on a given estimate of the x-height. + bool PosAndSizeAgree(const BLOB_CHOICE& other, float x_height, + bool debug) const; + + void print(const UNICHARSET *unicharset) const { + tprintf("r%.2f c%.2f x[%g,%g]: %d %s", + rating_, certainty_, + min_xheight_, max_xheight_, unichar_id_, (unicharset == NULL) ? "" : unicharset->debug_str(unichar_id_).string()); } + void print_full() const { + print(NULL); + tprintf(" script=%d, font1=%d, font2=%d, yshift=%g, classifier=%d\n", + script_id_, fontinfo_id_, fontinfo_id2_, yshift_, classifier_); + } + // Sort function for sorting BLOB_CHOICEs in increasing order of rating. + static int SortByRating(const void *p1, const void *p2) { + const BLOB_CHOICE *bc1 = + *reinterpret_cast(p1); + const BLOB_CHOICE *bc2 = + *reinterpret_cast(p2); + return (bc1->rating_ < bc2->rating_) ? -1 : 1; + } private: UNICHAR_ID unichar_id_; // unichar id @@ -150,21 +200,26 @@ class BLOB_CHOICE: public ELIST_LINK // k is defined as above to normalize -klog p to the range [0, 1]. float certainty_; // absolute int script_id_; - // Stores language model information about this BLOB_CHOICE. Used during - // the segmentation search for BLOB_CHOICEs in BLOB_CHOICE_LISTs that are - // recorded in the ratings matrix. - // The pointer is owned/managed by the segmentation search. - void *language_model_state_; + // Holds the position of this choice in the ratings matrix. + // Used to location position in the matrix during path backtracking. + MATRIX_COORD matrix_cell_; inT16 xgap_before_; inT16 xgap_after_; // X-height range (in image pixels) that this classification supports. - inT16 min_xheight_; - inT16 max_xheight_; - bool adapted_; // true if this is a match from adapted templates + float min_xheight_; + float max_xheight_; + // yshift_ - The vertical distance (in image pixels) the character is + // shifted (up or down) from an acceptable y position. + float yshift_; + BlobChoiceClassifier classifier_; // What generated *this. }; // Make BLOB_CHOICE listable. -ELISTIZEH (BLOB_CHOICE) CLISTIZEH (BLOB_CHOICE_LIST) +ELISTIZEH(BLOB_CHOICE) + +// Return the BLOB_CHOICE in bc_list matching a given unichar_id, +// or NULL if there is no match. +BLOB_CHOICE *FindMatchingChoice(UNICHAR_ID char_id, BLOB_CHOICE_LIST *bc_list); // Permuter codes used in WERD_CHOICEs. enum PermuterType { @@ -181,11 +236,27 @@ enum PermuterType { USER_DAWG_PERM, // 10 FREQ_DAWG_PERM, // 11 COMPOUND_PERM, // 12 + + NUM_PERMUTER_TYPES }; -class WERD_CHOICE { +namespace tesseract { +// ScriptPos tells whether a character is subscript, superscript or normal. +enum ScriptPos { + SP_NORMAL, + SP_SUBSCRIPT, + SP_SUPERSCRIPT, + SP_DROPCAP +}; + +const char *ScriptPosToString(tesseract::ScriptPos script_pos); + +} // namespace tesseract. + +class WERD_CHOICE : public ELIST_LINK { public: static const float kBadRating; + static const char *permuter_name(uinT8 permuter); WERD_CHOICE(const UNICHARSET *unicharset) : unicharset_(unicharset) { this->init(8); } @@ -214,6 +285,12 @@ class WERD_CHOICE { inline int length() const { return length_; } + float adjust_factor() const { + return adjust_factor_; + } + void set_adjust_factor(float factor) { + adjust_factor_ = factor; + } inline const UNICHAR_ID *unichar_ids() const { return unichar_ids_; } @@ -221,12 +298,13 @@ class WERD_CHOICE { assert(index < length_); return unichar_ids_[index]; } - inline const char *fragment_lengths() const { - return fragment_lengths_; + inline int state(int index) const { + return state_[index]; } - inline const char fragment_length(int index) const { - assert(index < length_); - return fragment_lengths_[index]; + tesseract::ScriptPos BlobPosition(int index) const { + if (index < 0 || index >= length_) + return tesseract::SP_NORMAL; + return script_pos_[index]; } inline float rating() const { return rating_; @@ -234,23 +312,41 @@ class WERD_CHOICE { inline float certainty() const { return certainty_; } + inline float certainty(int index) const { + return certainties_[index]; + } + inline float min_x_height() const { + return min_x_height_; + } + inline float max_x_height() const { + return max_x_height_; + } + inline void set_x_heights(float min_height, float max_height) { + min_x_height_ = min_height; + max_x_height_ = max_height; + } inline uinT8 permuter() const { return permuter_; } const char *permuter_name() const; - inline bool fragment_mark() const { - return fragment_mark_; - } - inline BLOB_CHOICE_LIST_CLIST* blob_choices() { - return blob_choices_; - } + // Returns the BLOB_CHOICE_LIST corresponding to the given index in the word, + // taken from the appropriate cell in the ratings MATRIX. + // Borrowed pointer, so do not delete. + BLOB_CHOICE_LIST* blob_choices(int index, MATRIX* ratings) const; + + // Returns the MATRIX_COORD corresponding to the location in the ratings + // MATRIX for the given index into the word. + MATRIX_COORD MatrixCoord(int index) const; + inline void set_unichar_id(UNICHAR_ID unichar_id, int index) { assert(index < length_); unichar_ids_[index] = unichar_id; } - inline void set_fragment_length(char flen, int index) { - assert(index < length_); - fragment_lengths_[index] = flen; + bool dangerous_ambig_found() const { + return dangerous_ambig_found_; + } + void set_dangerous_ambig_found_(bool value) { + dangerous_ambig_found_ = value; } inline void set_rating(float new_val) { rating_ = new_val; @@ -261,9 +357,6 @@ class WERD_CHOICE { inline void set_permuter(uinT8 perm) { permuter_ = perm; } - inline void set_fragment_mark(bool new_fragment_mark) { - fragment_mark_ = new_fragment_mark; - } // Note: this function should only be used if all the fields // are populated manually with set_* functions (rather than // (copy)constructors and append_* functions). @@ -271,19 +364,24 @@ class WERD_CHOICE { ASSERT_HOST(reserved_ >= len); length_ = len; } - void set_blob_choices(BLOB_CHOICE_LIST_CLIST *blob_choices); /// Make more space in unichar_id_ and fragment_lengths_ arrays. inline void double_the_size() { if (reserved_ > 0) { unichar_ids_ = GenericVector::double_the_size_memcpy( reserved_, unichar_ids_); - fragment_lengths_ = GenericVector::double_the_size_memcpy( - reserved_, fragment_lengths_); + script_pos_ = GenericVector::double_the_size_memcpy( + reserved_, script_pos_); + state_ = GenericVector::double_the_size_memcpy( + reserved_, state_); + certainties_ = GenericVector::double_the_size_memcpy( + reserved_, certainties_); reserved_ *= 2; } else { unichar_ids_ = new UNICHAR_ID[1]; - fragment_lengths_ = new char[1]; + script_pos_ = new tesseract::ScriptPos[1]; + state_ = new int[1]; + certainties_ = new float[1]; reserved_ = 1; } } @@ -294,18 +392,24 @@ class WERD_CHOICE { reserved_ = reserved; if (reserved > 0) { unichar_ids_ = new UNICHAR_ID[reserved]; - fragment_lengths_ = new char[reserved]; + script_pos_ = new tesseract::ScriptPos[reserved]; + state_ = new int[reserved]; + certainties_ = new float[reserved]; } else { unichar_ids_ = NULL; - fragment_lengths_ = NULL; + script_pos_ = NULL; + state_ = NULL; + certainties_ = NULL; } length_ = 0; + adjust_factor_ = 1.0f; rating_ = 0.0; certainty_ = MAX_FLOAT32; + min_x_height_ = 0.0f; + max_x_height_ = MAX_FLOAT32; permuter_ = NO_PERM; - fragment_mark_ = false; - blob_choices_ = NULL; unichars_in_script_order_ = false; // Tesseract is strict left-to-right. + dangerous_ambig_found_ = false; } /// Helper function to build a WERD_CHOICE from the given string, @@ -322,34 +426,39 @@ class WERD_CHOICE { length_ = 0; rating_ = kBadRating; certainty_ = -MAX_FLOAT32; - fragment_mark_ = false; } /// This function assumes that there is enough space reserved /// in the WERD_CHOICE for adding another unichar. /// This is an efficient alternative to append_unichar_id(). inline void append_unichar_id_space_allocated( - UNICHAR_ID unichar_id, char fragment_length, + UNICHAR_ID unichar_id, int blob_count, float rating, float certainty) { assert(reserved_ > length_); length_++; - this->set_unichar_id(unichar_id, fragment_length, + this->set_unichar_id(unichar_id, blob_count, rating, certainty, length_-1); } - void append_unichar_id(UNICHAR_ID unichar_id, char fragment_length, + void append_unichar_id(UNICHAR_ID unichar_id, int blob_count, float rating, float certainty); - inline void set_unichar_id(UNICHAR_ID unichar_id, char fragment_length, + inline void set_unichar_id(UNICHAR_ID unichar_id, int blob_count, float rating, float certainty, int index) { assert(index < length_); unichar_ids_[index] = unichar_id; - fragment_lengths_[index] = fragment_length; + state_[index] = blob_count; + certainties_[index] = certainty; + script_pos_[index] = tesseract::SP_NORMAL; rating_ += rating; if (certainty < certainty_) { certainty_ = certainty; } } + // Sets the entries for the given index from the BLOB_CHOICE, assuming + // unit fragment lengths, but setting the state for this index to blob_count. + void set_blob_choice(int index, int blob_count, + const BLOB_CHOICE* blob_choice); bool contains_unichar_id(UNICHAR_ID unichar_id) const; void remove_unichar_ids(int index, int num); @@ -365,6 +474,11 @@ class WERD_CHOICE { // punctuation from the left and right. void punct_stripped(int *start_core, int *end_core) const; + // Returns the indices [start, end) containing the core of the word, stripped + // of any superscript digits on either side. (i.e., the non-footnote part + // of the word). There is no guarantee that the output range is non-empty. + void GetNonSuperscriptSpan(int *start, int *end) const; + // Return a copy of this WERD_CHOICE with the choices [start, end). // The result is useful only for checking against a dictionary. WERD_CHOICE shallow_copy(int start, int end) const; @@ -403,8 +517,42 @@ class WERD_CHOICE { this->string_and_lengths(&unichar_string_, &unichar_lengths_); return unichar_lengths_; } - const void print() const { this->print(""); } - const void print(const char *msg) const; + + // Sets up the script_pos_ member using the blobs_list to get the bln + // bounding boxes, *this to get the unichars, and this->unicharset + // to get the target positions. If small_caps is true, sub/super are not + // considered, but dropcaps are. + // NOTE: blobs_list should be the chopped_word blobs. (Fully segemented.) + void SetScriptPositions(bool small_caps, TWERD* word); + // Sets the script_pos_ member from some source positions with a given length. + void SetScriptPositions(const tesseract::ScriptPos* positions, int length); + // Sets all the script_pos_ positions to the given position. + void SetAllScriptPositions(tesseract::ScriptPos position); + + static tesseract::ScriptPos ScriptPositionOf(bool print_debug, + const UNICHARSET& unicharset, + const TBOX& blob_box, + UNICHAR_ID unichar_id); + + // Returns the "dominant" script ID for the word. By "dominant", the script + // must account for at least half the characters. Otherwise, it returns 0. + // Note that for Japanese, Hiragana and Katakana are simply treated as Han. + int GetTopScriptID() const; + + // Fixes the state_ for a chop at the given blob_posiiton. + void UpdateStateForSplit(int blob_position); + + // Returns the sum of all the state elements, being the total number of blobs. + int TotalOfStates() const; + + void print() const { this->print(""); } + void print(const char *msg) const; + // Prints the segmentation state with an introductory message. + void print_state(const char *msg) const; + + // Displays the segmentation state of *this (if not the same as the last + // one displayed) and waits for a click in the window. + void DisplaySegmentation(TWERD* word); WERD_CHOICE& operator+= ( // concatanate const WERD_CHOICE & second);// second on first @@ -413,41 +561,55 @@ class WERD_CHOICE { private: const UNICHARSET *unicharset_; + // TODO(rays) Perhaps replace the multiple arrays with an array of structs? + // unichar_ids_ is an array of classifier "results" that make up a word. + // For each unichar_ids_[i], script_pos_[i] has the sub/super/normal position + // of each unichar_id. + // state_[i] indicates the number of blobs in WERD_RES::chopped_word that + // were put together to make the classification results in the ith position + // in unichar_ids_, and certainties_[i] is the certainty of the choice that + // was used in this word. + // == Change from before == + // Previously there was fragment_lengths_ that allowed a word to be + // artificially composed of multiple fragment results. Since the new + // segmentation search doesn't do fragments, treatment of fragments has + // been moved to a lower level, augmenting the ratings matrix with the + // combined fragments, and allowing the language-model/segmentation-search + // to deal with only the combined unichar_ids. UNICHAR_ID *unichar_ids_; // unichar ids that represent the text of the word - char *fragment_lengths_; // number of fragments in each unichar + tesseract::ScriptPos* script_pos_; // Normal/Sub/Superscript of each unichar. + int* state_; // Number of blobs in each unichar. + float* certainties_; // Certainty of each unichar. int reserved_; // size of the above arrays int length_; // word length + // Factor that was used to adjust the rating. + float adjust_factor_; // Rating is the sum of the ratings of the individual blobs in the word. float rating_; // size related // certainty is the min (worst) certainty of the individual blobs in the word. float certainty_; // absolute + // xheight computed from the result, or 0 if inconsistent. + float min_x_height_; + float max_x_height_; uinT8 permuter_; // permuter code - bool fragment_mark_; // if true, indicates that this choice - // was chosen over a better one that - // contained a fragment - BLOB_CHOICE_LIST_CLIST *blob_choices_; // best choices for each blob - // Normally, the blob_choices_ represent the recognition results in order + // Normally, the ratings_ matrix represents the recognition results in order // from left-to-right. However, some engines (say Cube) may return // recognition results in the order of the script's major reading direction // (for Arabic, that is right-to-left). bool unichars_in_script_order_; + // True if NoDangerousAmbig found an ambiguity. + bool dangerous_ambig_found_; // The following variables are populated and passed by reference any // time unichar_string() or unichar_lengths() are called. mutable STRING unichar_string_; mutable STRING unichar_lengths_; - - bool unichar_info_present; - - private: - void delete_blob_choices(); }; // Make WERD_CHOICE listable. -ELISTIZEH (WERD_CHOICE) +ELISTIZEH(WERD_CHOICE) typedef GenericVector BLOB_CHOICE_LIST_VECTOR; -typedef GenericVector WERD_CHOICE_LIST_VECTOR; // Utilities for comparing WERD_CHOICEs @@ -455,27 +617,11 @@ bool EqualIgnoringCaseAndTerminalPunct(const WERD_CHOICE &word1, const WERD_CHOICE &word2); // Utilities for debug printing. -void print_ratings_list(const char *msg, BLOB_CHOICE_LIST *ratings); void print_ratings_list( const char *msg, // intro message BLOB_CHOICE_LIST *ratings, // list of results const UNICHARSET ¤t_unicharset // unicharset that can be used // for id-to-unichar conversion ); -void print_ratings_info( - FILE *fp, // file to use - BLOB_CHOICE_LIST *ratings, // list of results - const UNICHARSET ¤t_unicharset // unicharset that can be used - // for id-to-unichar conversion - ); -void print_char_choices_list( - const char *msg, - const BLOB_CHOICE_LIST_VECTOR &char_choices, - const UNICHARSET ¤t_unicharset, - BOOL8 detailed - ); -void print_word_alternates_list( - WERD_CHOICE *word, - GenericVector *alternates); #endif diff --git a/TesseractOCR/include/tesseract/rect.h b/TesseractOCR/include/tesseract/rect.h old mode 100755 new mode 100644 index 2682ad9f..534656e0 --- a/TesseractOCR/include/tesseract/rect.h +++ b/TesseractOCR/include/tesseract/rect.h @@ -24,6 +24,7 @@ #include "points.h" #include "ndminx.h" #include "scrollview.h" +#include "strngs.h" #include "tprintf.h" class DLLSYM TBOX { // bounding box @@ -264,15 +265,8 @@ class DLLSYM TBOX { // bounding box tprintf("Bounding box=(%d,%d)->(%d,%d)\n", left(), bottom(), right(), top()); } - - // Same as print(), but appends debug information to the given string - // instead of printing it to stdout. - void append_debug(STRING *str) const { - char buffer[256]; - sprintf(buffer, "Bounding box=(%d,%d)->(%d,%d)\n", - left(), bottom(), right(), top()); - *str += buffer; - } + // Appends the bounding box as (%d,%d)->(%d,%d) to a STRING. + void print_to_str(STRING *str) const; #ifndef GRAPHICS_DISABLED void plot( // use current settings diff --git a/TesseractOCR/include/tesseract/rejctmap.h b/TesseractOCR/include/tesseract/rejctmap.h old mode 100755 new mode 100644 index 3954cf4c..4b27bab4 --- a/TesseractOCR/include/tesseract/rejctmap.h +++ b/TesseractOCR/include/tesseract/rejctmap.h @@ -47,7 +47,6 @@ OF THIS IMPLIED TEMPORAL ORDERING OF THE FLAGS!!!! #include "memry.h" #include "bits16.h" #include "params.h" -#include "notdll.h" enum REJ_FLAGS { diff --git a/TesseractOCR/include/tesseract/reject.h b/TesseractOCR/include/tesseract/reject.h old mode 100755 new mode 100644 index d3aa1ec5..cffb262c --- a/TesseractOCR/include/tesseract/reject.h +++ b/TesseractOCR/include/tesseract/reject.h @@ -22,11 +22,10 @@ #include "params.h" #include "pageres.h" -#include "notdll.h" void reject_blanks(WERD_RES *word); -void reject_poor_matches(WERD_RES *word, BLOB_CHOICE_LIST_CLIST *blob_choices); -float compute_reject_threshold(BLOB_CHOICE_LIST_CLIST *blob_choices); +void reject_poor_matches(WERD_RES *word); +float compute_reject_threshold(WERD_CHOICE* word); BOOL8 word_contains_non_1_digit(const char *word, const char *word_lengths); void dont_allow_1Il(WERD_RES *word); void flip_hyphens(WERD_RES *word); diff --git a/TesseractOCR/include/tesseract/render.h b/TesseractOCR/include/tesseract/render.h new file mode 100644 index 00000000..3faa398d --- /dev/null +++ b/TesseractOCR/include/tesseract/render.h @@ -0,0 +1,59 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: render.h (Formerly render.h) + * Description: Convert the various data type into line lists + * Author: Mark Seaman, OCR Technology + * Created: Fri Jul 28 13:14:48 1989 + * Modified: Fri Apr 26 09:59:45 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Experimental (Do Not Distribute) + * + * (c) Copyright 1989, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ +#ifndef RENDER_H +#define RENDER_H + +#include "host.h" +#include "callcpp.h" +#include "blobs.h" + +/*---------------------------------------------------------------------- + V a r i a b l e s +----------------------------------------------------------------------*/ +extern ScrollView *blob_window; /* Window for blobs */ +extern C_COL color_list[]; /* Colors for outlines */ + +extern BOOL_VAR_H(wordrec_display_all_blobs, 0, "Display Blobs"); + +extern BOOL_VAR_H(wordrec_display_all_words, 0, "Display Words"); + +extern BOOL_VAR_H(wordrec_blob_pause, 0, "Blob pause"); + +#define NUM_COLORS 6 + +/*---------------------------------------------------------------------- + F u n c t i o n s +----------------------------------------------------------------------*/ +void display_blob(TBLOB *blob, C_COL color); + +void render_blob(void *window, TBLOB *blob, C_COL color); + +void render_edgepts(void *window, EDGEPT *edgept, C_COL color); + +void render_outline(void *window, + TESSLINE *outline, + C_COL color); + +#endif diff --git a/TesseractOCR/include/tesseract/renderer.h b/TesseractOCR/include/tesseract/renderer.h new file mode 100644 index 00000000..080a603f --- /dev/null +++ b/TesseractOCR/include/tesseract/renderer.h @@ -0,0 +1,246 @@ +/////////////////////////////////////////////////////////////////////// +// File: renderer.h +// Description: Rendering interface to inject into TessBaseAPI +// +// (C) Copyright 2011, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_API_RENDERER_H__ +#define TESSERACT_API_RENDERER_H__ + +// To avoid collision with other typenames include the ABSOLUTE MINIMUM +// complexity of includes here. Use forward declarations wherever possible +// and hide includes of complex types in baseapi.cpp. +#include "genericvector.h" +#include "platform.h" +#include "publictypes.h" + +namespace tesseract { + +class TessBaseAPI; + +/** + * Interface for rendering tesseract results into a document, such as text, + * HOCR or pdf. This class is abstract. Specific classes handle individual + * formats. This interface is then used to inject the renderer class into + * tesseract when processing images. + * + * For simplicity implementing this with tesesract version 3.01, + * the renderer contains document state that is cleared from document + * to document just as the TessBaseAPI is. This way the base API can just + * delegate its rendering functionality to injected renderers, and the + * renderers can manage the associated state needed for the specific formats + * in addition to the heuristics for producing it. + */ +class TESS_API TessResultRenderer { + public: + virtual ~TessResultRenderer(); + + // Takes ownership of pointer so must be new'd instance. + // Renderers arent ordered, but appends the sequences of next parameter + // and existing next(). The renderers should be unique across both lists. + void insert(TessResultRenderer* next); + + // Returns the next renderer or NULL. + TessResultRenderer* next() { return next_; } + + /** + * Starts a new document with the given title. + * This clears the contents of the output data. + */ + bool BeginDocument(const char* title); + + /** + * Adds the recognized text from the source image to the current document. + * Invalid if BeginDocument not yet called. + * + * Note that this API is a bit weird but is designed to fit into the + * current TessBaseAPI implementation where the api has lots of state + * information that we might want to add in. + */ + bool AddImage(TessBaseAPI* api); + + /** + * Called to inform the renderer when tesseract failed on an image. + */ + bool AddError(TessBaseAPI* api); + + /** + * Finishes the document and finalizes the output data + * Invalid if BeginDocument not yet called. + */ + bool EndDocument(); + + const char* full_typename() const { return full_typename_; } + const char* file_extension() const { return file_extension_; } + const char* title() const { return title_; } + + /** + * Returns the index of the last image given to AddImage or AddError + * (i.e. images are incremented whether the image succeeded or not) + * + * This is always defined. It means either the number of the + * current image, the last image ended, or in the completed document + * depending on when in the document lifecycle you are looking at it. + * Will return -1 if a document was never started. + */ + int imagenum() const { return imagenum_; } + + /** + * The results are not defined if EndDocument has not yet been called. + * Returns the current output from the renderer. The data is owned by + * the renderer and only valid until the next call into the renderer + * that may modify document state (such as Begin/End Document + * or AddImage. + */ + virtual bool GetOutput(const char** data, int* data_len) const; + + protected: + /** + * Called by concrete classes + */ + TessResultRenderer(const char* type, const char* extension); + + // Hook for specialized handling in BeginDocument() + virtual bool BeginDocumentHandler(); + + // This must be overriden to render the OCR'd results + virtual bool AddImageHandler(TessBaseAPI* api) = 0; + + // The default handler ignores the error and just returns true + virtual bool AddErrorHandler(TessBaseAPI* api); + + // Hook for specialized handling in EndDocument() + virtual bool EndDocumentHandler(); + + // Clear output data. + void ResetData(); + + // Renderers can call this method to allocate data storage in advance, + // which can cut down on allocations and copying. This isnt required, + // and if used can still request less than will ultimately be used without + // worrying about data corruption. It's purely performance. + // Note that relative_len is in addition to what is already being used. + void ReserveAdditionalData(int relative_len); + + // Renderers can call this to append '\0' terminated strings into + // the output string returned by GetOutput. + // This method will grow the output buffer if needed. + void AppendString(const char* s); + + // Renderers can call this to append binary byte sequences into + // the output string returned by GetOutput. Note that s is not necessarily + // '\0' terminated (and can contain '\0' within it). + // This method will grow the output buffer if needed. + void AppendData(const char* s, int len); + + private: + const char* full_typename_; // name of renderer + const char* file_extension_; // standard extension for generated output + const char* title_; // title of document being renderered + int imagenum_; // index of last image added + + char* output_data_; // output bytes + int output_alloc_; // bytes allocated + int output_len_; // bytes actually used + TessResultRenderer* next_; // Can link multiple renderers together. +}; + +/** + * Renders tesseract output into a plain UTF-8 text string + */ +class TESS_API TessTextRenderer : public TessResultRenderer { + public: + TessTextRenderer(); + + protected: + virtual bool AddImageHandler(TessBaseAPI* api); +}; + +/** + * Renders tesseract output into an hocr text string + */ +class TESS_API TessHOcrRenderer : public TessResultRenderer { + public: + TessHOcrRenderer(); + +protected: + virtual bool BeginDocumentHandler(); + virtual bool AddImageHandler(TessBaseAPI* api); + virtual bool EndDocumentHandler(); +}; + +/** + * Renders tesseract output into searchable PDF + */ +class TESS_API TessPDFRenderer : public TessResultRenderer { + public: + TessPDFRenderer(const char *datadir); + +protected: + virtual bool BeginDocumentHandler(); + virtual bool AddImageHandler(TessBaseAPI* api); + virtual bool EndDocumentHandler(); + +private: + // We don't want to have every image in memory at once, + // so we store some metadata as we go along producing + // PDFs one page at a time. At the end that metadata is + // used to make everything that isn't easily handled in a + // streaming fashion. + long int obj_; // counter for PDF objects + GenericVector offsets_; // offset of every PDF object in bytes + GenericVector pages_; // object number for every /Page object + const char *datadir_; // where to find the custom font + // Bookkeeping only. DIY = Do It Yourself. + void AppendPDFObjectDIY(size_t objectsize); + // Bookkeeping + emit data. + void AppendPDFObject(const char *data); + // Create the /Contents object for an entire page. + static char* GetPDFTextObjects(TessBaseAPI* api, + double width, double height, + int page_number); + // Attempt to create PFD object from an image without transcoding. + static bool fileToPDFObj(char *filename, long int objnum, + char **pdf_object, long int *pdf_object_size); + // Turn a Pix into a the very best PDF object that we can. + static bool pixToPDFObj(Pix *pix, long int objnum, + char **pdf_object, long int *pdf_object_size); +}; + + +/** + * Renders tesseract output into a plain UTF-8 text string + */ +class TESS_API TessUnlvRenderer : public TessResultRenderer { + public: + TessUnlvRenderer(); + + protected: + virtual bool AddImageHandler(TessBaseAPI* api); +}; + +/** + * Renders tesseract output into a plain UTF-8 text string + */ +class TESS_API TessBoxTextRenderer : public TessResultRenderer { + public: + TessBoxTextRenderer(); + + protected: + virtual bool AddImageHandler(TessBaseAPI* api); +}; + +} // namespace tesseract. + +#endif // TESSERACT_API_RENDERER_H__ diff --git a/TesseractOCR/include/tesseract/resource.h b/TesseractOCR/include/tesseract/resource.h new file mode 100644 index 00000000..25e0730f --- /dev/null +++ b/TesseractOCR/include/tesseract/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by tesseract.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/TesseractOCR/include/tesseract/resultiterator.h b/TesseractOCR/include/tesseract/resultiterator.h old mode 100755 new mode 100644 index c9d880b4..cde19f08 --- a/TesseractOCR/include/tesseract/resultiterator.h +++ b/TesseractOCR/include/tesseract/resultiterator.h @@ -24,8 +24,9 @@ #include "platform.h" #include "ltrresultiterator.h" -#include "genericvector.h" +template class GenericVector; +template class GenericVectorEqEq; class BLOB_CHOICE_IT; class WERD_RES; class STRING; diff --git a/TesseractOCR/include/tesseract/sampleiterator.h b/TesseractOCR/include/tesseract/sampleiterator.h new file mode 100644 index 00000000..b64060ce --- /dev/null +++ b/TesseractOCR/include/tesseract/sampleiterator.h @@ -0,0 +1,195 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + + +#ifndef TESSERACT_CLASSIFY_SAMPLEITERATOR_H_ +#define TESSERACT_CLASSIFY_SAMPLEITERATOR_H_ + +namespace tesseract { + +class IndexMapBiDi; +class IntFeatureMap; +class ShapeTable; +class TrainingSample; +class TrainingSampleSet; +struct UnicharAndFonts; + +// Iterator class to encapsulate the complex iteration involved in getting +// all samples of all shapes needed for a classification problem. +// +// =====INPUTS TO Init FUNCTION===== +// The charset_map defines a subset of the sample_set classes (with a NULL +// shape_table, or the shape_table classes if not NULL.) +// +// The shape_table (if not NULL) defines the mapping from shapes to +// font_id/class_id pairs. Each shape is a list of unichar_id and font lists. +// +// The sample_set holds the samples and provides indexed access to samples +// of font_id/class_id pairs. +// +// If randomize is true, the samples are perturbed slightly, but the +// perturbation is guaranteed to be the same for multiple identical +// iterations. +// +// =====DIFFERENT COMBINATIONS OF INPUTS===== +// NULL shape_table: +// Without a shape_table, everything works in UNICHAR_IDs. +// +// NULL shape_table, NULL charset_map: +// Iterations simply run over the samples in the order the samples occur in the +// input files. +// GetCompactClassID and GetSparseClassID both return the sample UNICHAR_ID. +// +// NULL shape_table, non-NULL charset_map: +// When shape_table is NULL, the charset_map indexes unichar_ids directly, +// and an iteration returns all samples of all chars in the charset_map, which +// is a subset of the full unicharset. +// The iteration will be in groups of the same unichar_id, in the order +// defined by the charset_map. +// GetCompactClassID returns the charset_map index of a sample, and +// GetSparseClassID returns the sample UNICHAR_ID. +// +// Non-NULL shape_table: +// With a shape_table, samples are grouped according to the shape_table, so +// multiple UNICHAR_IDs and fonts may be grouped together, and everything +// works in shape_ids. +// +// Non-NULL shape_table, NULL charset_map. +// Iterations simply run over the samples in the order of shape_id. +// GetCompactClassID and GetSparseClassID both return the shape_id. +// (If you want the unichar_id or font_id, the sample still has them.) +// +// Non-NULL shape_table, non-NULL charset_map. +// When shape_table is not NULL, the charset_map indexes and subsets shapes in +// the shape_table, and iterations will be in shape_table order, not +// charset_map order. +// GetCompactClassID returns the charset_map index of a shape, and +// GetSparseClassID returns the shape_id. +// +// =====What is SampleIterator good for?===== +// Inside a classifier training module, the SampleIterator has abstracted away +// all the different modes above. +// Use the following iteration to train your classifier: +// for (it.Begin(); !it.AtEnd(); it.Next()) { +// const TrainingSample& sample = it.GetSample(); +// int class_id = it.GetCompactClassID(); +// Your classifier may or may not be dealing with a shape_table, and may be +// dealing with some subset of the character/shape set. It doesn't need to +// know and shouldn't care. It is just learning shapes with compact class ids +// in the range [0, it.CompactCharsetSize()). +class SampleIterator { + public: + SampleIterator(); + ~SampleIterator(); + + void Clear(); + + // See class comment for arguments. + void Init(const IndexMapBiDi* charset_map, + const ShapeTable* shape_table, + bool randomize, + TrainingSampleSet* sample_set); + + // Iterator functions designed for use with a simple for loop: + // for (it.Begin(); !it.AtEnd(); it.Next()) { + // const TrainingSample& sample = it.GetSample(); + // int class_id = it.GetCompactClassID(); + // ... + // } + void Begin(); + bool AtEnd() const; + const TrainingSample& GetSample() const; + TrainingSample* MutableSample() const; + // Returns the total index (from the original set of samples) of the current + // sample. + int GlobalSampleIndex() const; + // Returns the index of the current sample in compact charset space, so + // in a 2-class problem between x and y, the returned indices will all be + // 0 or 1, and have nothing to do with the unichar_ids. + // If the charset_map_ is NULL, then this is equal to GetSparseClassID(). + int GetCompactClassID() const; + // Returns the index of the current sample in sparse charset space, so + // in a 2-class problem between x and y, the returned indices will all be + // x or y, where x and y may be unichar_ids (no shape_table_) or shape_ids + // with a shape_table_. + int GetSparseClassID() const; + // Moves on to the next indexable sample. If the end is reached, leaves + // the state such that AtEnd() is true. + void Next(); + + // Returns the size of the compact charset space. + int CompactCharsetSize() const; + // Returns the size of the sparse charset space. + int SparseCharsetSize() const; + + const IndexMapBiDi& charset_map() const { + return *charset_map_; + } + const ShapeTable* shape_table() const { + return shape_table_; + } + // Sample set operations. + const TrainingSampleSet* sample_set() const { + return sample_set_; + } + + // A set of functions that do something to all the samples accessed by the + // iterator, as it is currently setup. + + // Apply the supplied feature_space/feature_map transform to all samples + // accessed by this iterator. + void MapSampleFeatures(const IntFeatureMap& feature_map); + + // Adjust the weights of all the samples to be uniform in the given charset. + // Returns the number of samples in the iterator. + int UniformSamples(); + + // Normalize the weights of all the samples defined by the iterator so they + // sum to 1. Returns the minimum assigned sample weight. + double NormalizeSamples(); + + private: + // Helper returns the current UnicharAndFont shape_entry. + const UnicharAndFonts* GetShapeEntry() const; + + // Map to subset the actual charset space. + const IndexMapBiDi* charset_map_; + // Shape table to recombine character classes into shapes + const ShapeTable* shape_table_; + // The samples to iterate over. + TrainingSampleSet* sample_set_; + // Flag to control randomizing the sample features. + bool randomize_; + // Shape table owned by this used to iterate character classes. + ShapeTable* owned_shape_table_; + + // Top-level iteration. Shape index in sparse charset_map space. + int shape_index_; + int num_shapes_; + // Index to the character class within a shape. + int shape_char_index_; + int num_shape_chars_; + // Index to the font within a shape/class pair. + int shape_font_index_; + int num_shape_fonts_; + // The lowest level iteration. sample_index_/num_samples_ counts samples + // in the current shape/class/font combination. + int sample_index_; + int num_samples_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_CLASSIFY_SAMPLEITERATOR_H_ diff --git a/TesseractOCR/include/tesseract/scaleimg.h b/TesseractOCR/include/tesseract/scaleimg.h deleted file mode 100755 index 4807b09e..00000000 --- a/TesseractOCR/include/tesseract/scaleimg.h +++ /dev/null @@ -1,35 +0,0 @@ -/********************************************************************** - * File: scaleimg.h (Formerly scaleim.h) - * Description: Smart scaling of images. - * Author: Phil Cheatle - * Created: Wed Nov 18 16:12:03 GMT 1992 - * - * (C) Copyright 1992, Hewlett-Packard Ltd. - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** http://www.apache.org/licenses/LICENSE-2.0 - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - * - **********************************************************************/ - -#ifndef SCALEIMG_H -#define SCALEIMG_H - -void scale_image( //scale an image - IMAGE &image, //source image - IMAGE &target_image //target image - ); -void scale_image_cop_out( //scale an image - IMAGE &image, //source image - IMAGE &target_image, //target image - float factor, //scale factor - int *hires, - int *lores, - int *oldhires, - int *oldlores); -#endif diff --git a/TesseractOCR/include/tesseract/scanedg.h b/TesseractOCR/include/tesseract/scanedg.h new file mode 100644 index 00000000..862fab24 --- /dev/null +++ b/TesseractOCR/include/tesseract/scanedg.h @@ -0,0 +1,68 @@ +/********************************************************************** + * File: scanedg.h (Formerly scanedge.h) + * Description: Raster scanning crack based edge extractor. + * Author: Ray Smith + * Created: Fri Mar 22 16:11:50 GMT 1991 + * + * (C) Copyright 1991, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef SCANEDG_H +#define SCANEDG_H + +#include "params.h" +#include "scrollview.h" +#include "pdblock.h" +#include "crakedge.h" + +class C_OUTLINE_IT; + +struct CrackPos { + CRACKEDGE** free_cracks; // Freelist for fast allocation. + int x; // Position of new edge. + int y; +}; + +struct Pix; + +void block_edges(Pix *t_image, // thresholded image + PDBLK *block, // block in image + C_OUTLINE_IT* outline_it); +void make_margins(PDBLK *block, // block in image + BLOCK_LINE_IT *line_it, // for old style + uinT8 *pixels, // pixels to strip + uinT8 margin, // white-out pixel + inT16 left, // block edges + inT16 right, + inT16 y); // line coord ); +void line_edges(inT16 x, // coord of line start + inT16 y, // coord of line + inT16 xext, // width of line + uinT8 uppercolour, // start of prev line + uinT8 * bwpos, // thresholded line + CRACKEDGE ** prevline, // edges in progress + CRACKEDGE **free_cracks, + C_OUTLINE_IT* outline_it); +CRACKEDGE *h_edge(int sign, // sign of edge + CRACKEDGE * join, // edge to join to + CrackPos* pos); +CRACKEDGE *v_edge(int sign, // sign of edge + CRACKEDGE * join, // edge to join to + CrackPos* pos); +void join_edges(CRACKEDGE *edge1, // edges to join + CRACKEDGE *edge2, // no specific order + CRACKEDGE **free_cracks, + C_OUTLINE_IT* outline_it); +void free_crackedges(CRACKEDGE *start); + +#endif diff --git a/TesseractOCR/include/tesseract/scanutils.h b/TesseractOCR/include/tesseract/scanutils.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/scrollview.h b/TesseractOCR/include/tesseract/scrollview.h new file mode 100644 index 00000000..fe099efc --- /dev/null +++ b/TesseractOCR/include/tesseract/scrollview.h @@ -0,0 +1,418 @@ +/////////////////////////////////////////////////////////////////////// +// File: scrollview.h +// Description: ScrollView +// Author: Joern Wanke +// Created: Thu Nov 29 2007 +// +// (C) Copyright 2007, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// +// +// ScrollView is designed as an UI which can be run remotely. This is the +// client code for it, the server part is written in java. The client consists +// mainly of 2 parts: +// The "core" ScrollView which sets up the remote connection, +// takes care of event handling etc. +// The other part of ScrollView consists of predefined API calls through LUA, +// which can basically be used to get a zoomable canvas in which it is possible +// to draw lines, text etc. +// Technically, thanks to LUA, its even possible to bypass the here defined LUA +// API calls at all and generate a java user interface from scratch (or +// basically generate any kind of java program, possibly even dangerous ones). + +#ifndef TESSERACT_VIEWER_SCROLLVIEW_H__ +#define TESSERACT_VIEWER_SCROLLVIEW_H__ +// TODO(rays) Move ScrollView into the tesseract namespace. +#ifndef OCR_SCROLLVIEW_H__ + +#include + +class ScrollView; +class SVNetwork; +class SVMutex; +class SVSemaphore; +struct SVPolyLineBuffer; + +enum SVEventType { + SVET_DESTROY, // Window has been destroyed by user. + SVET_EXIT, // User has destroyed the last window by clicking on the 'X'. + SVET_CLICK, // Left button pressed. + SVET_SELECTION, // Left button selection. + SVET_INPUT, // There is some input (single key or a whole string). + SVET_MOUSE, // The mouse has moved with a button pressed. + SVET_MOTION, // The mouse has moved with no button pressed. + SVET_HOVER, // The mouse has stayed still for a second. + SVET_POPUP, // A command selected through a popup menu. + SVET_MENU, // A command selected through the menubar. + SVET_ANY, // Any of the above. + + SVET_COUNT // Array sizing. +}; + +struct SVEvent { + ~SVEvent() { delete [] parameter; } + SVEvent* copy(); + SVEventType type; // What kind of event. + ScrollView* window; // Window event relates to. + int x; // Coords of click or selection. + int y; + int x_size; // Size of selection. + int y_size; + int command_id; // The ID of the possibly associated event (e.g. MENU) + char* parameter; // Any string that might have been passed as argument. + int counter; // Used to detect which kind of event to process next. + + SVEvent() { + window = NULL; + parameter = NULL; + } + + SVEvent(const SVEvent&); + SVEvent& operator=(const SVEvent&); +}; + +// The SVEventHandler class is used for Event handling: If you register your +// class as SVEventHandler to a ScrollView Window, the SVEventHandler will be +// called whenever an appropriate event occurs. +class SVEventHandler { + public: + virtual ~SVEventHandler() {} + +// Gets called by the SV Window. Does nothing on default, overwrite this +// to implement the desired behaviour + virtual void Notify(const SVEvent* sve) { } +}; + +// The ScrollView class provides the expernal API to the scrollviewer process. +// The scrollviewer process manages windows and displays images, graphics and +// text while allowing the user to zoom and scroll the windows arbitrarily. +// Each ScrollView class instance represents one window, and stuff is drawn in +// the window through method calls on the class. The constructor is used to +// create the class instance (and the window). + +class ScrollView { + public: +// Color enum for pens and brushes. + enum Color { + NONE, + BLACK, + WHITE, + RED, + YELLOW, + GREEN, + CYAN, + BLUE, + MAGENTA, + AQUAMARINE, + DARK_SLATE_BLUE, + LIGHT_BLUE, + MEDIUM_BLUE, + MIDNIGHT_BLUE, + NAVY_BLUE, + SKY_BLUE, + SLATE_BLUE, + STEEL_BLUE, + CORAL, + BROWN, + SANDY_BROWN, + GOLD, + GOLDENROD, + DARK_GREEN, + DARK_OLIVE_GREEN, + FOREST_GREEN, + LIME_GREEN, + PALE_GREEN, + YELLOW_GREEN, + LIGHT_GREY, + DARK_SLATE_GREY, + DIM_GREY, + GREY, + KHAKI, + MAROON, + ORANGE, + ORCHID, + PINK, + PLUM, + INDIAN_RED, + ORANGE_RED, + VIOLET_RED, + SALMON, + TAN, + TURQUOISE, + DARK_TURQUOISE, + VIOLET, + WHEAT, + GREEN_YELLOW // Make sure this one is last. +}; + + ~ScrollView(); + +#ifndef GRAPHICS_DISABLED + +// Create a window. The pixel size of the window may be 0,0, in which case +// a default size is selected based on the size of your canvas. +// The canvas may not be 0,0 in size! + ScrollView(const char* name, int x_pos, int y_pos, int x_size, int y_size, + int x_canvas_size, int y_canvas_size); +// With a flag whether the x axis is reversed. + ScrollView(const char* name, int x_pos, int y_pos, int x_size, int y_size, + int x_canvas_size, int y_canvas_size, bool y_axis_reversed); +// Connect to a server other than localhost. + ScrollView(const char* name, int x_pos, int y_pos, int x_size, int y_size, + int x_canvas_size, int y_canvas_size, bool y_axis_reversed, + const char* server_name); +/******************************************************************************* +* Event handling +* To register as listener, the class has to derive from the SVEventHandler +* class, which consists of a notifyMe(SVEvent*) function that should be +* overwritten to process the event the way you want. +*******************************************************************************/ + +// Add an Event Listener to this ScrollView Window. + void AddEventHandler(SVEventHandler* listener); + +// Block until an event of the given type is received. + SVEvent* AwaitEvent(SVEventType type); + +// Block until any event on any window is received. + SVEvent* AwaitEventAnyWindow(); + +/******************************************************************************* +* Getters and Setters +*******************************************************************************/ + +// Returns the title of the window. + const char* GetName() { return window_name_; } + +// Returns the unique ID of the window. + int GetId() { return window_id_; } + +/******************************************************************************* +* API functions for LUA calls +* the implementations for these can be found in svapi.cc +* (keep in mind that the window is actually created through the ScrollView +* constructor, so this is not listed here) +*******************************************************************************/ + +// Draw a Pix on (x,y). + void Image(struct Pix* image, int x_pos, int y_pos); + +// Flush buffers and update display. + static void Update(); + +// Exit the program. + static void Exit(); + +// Update the contents of a specific window. + void UpdateWindow(); + +// Erase all content from the window, but do not destroy it. + void Clear(); + +// Set pen color with an enum. + void Pen(Color color); + +// Set pen color to RGB (0-255). + void Pen(int red, int green, int blue); + +// Set pen color to RGBA (0-255). + void Pen(int red, int green, int blue, int alpha); + +// Set brush color with an enum. + void Brush(Color color); + +// Set brush color to RGB (0-255). + void Brush(int red, int green, int blue); + +// Set brush color to RGBA (0-255). + void Brush(int red, int green, int blue, int alpha); + +// Set attributes for future text, like font name (e.g. +// "Times New Roman"), font size etc.. +// Note: The underlined flag is currently not supported + void TextAttributes(const char* font, int pixel_size, + bool bold, bool italic, bool underlined); + +// Draw line from (x1,y1) to (x2,y2) with the current pencolor. + void Line(int x1, int y1, int x2, int y2); + +// Set the stroke width of the pen. + void Stroke(float width); + +// Draw a rectangle given upper left corner and lower right corner. +// The current pencolor is used as outline, the brushcolor to fill the shape. + void Rectangle(int x1, int y1, int x2, int y2); + +// Draw an ellipse centered on (x,y). +// The current pencolor is used as outline, the brushcolor to fill the shape. + void Ellipse(int x, int y, int width, int height); + +// Draw text with the current pencolor + void Text(int x, int y, const char* mystring); + +// Draw an image from a local filename. This should be faster than createImage. +// WARNING: This only works on a local machine. This also only works image +// types supported by java (like bmp,jpeg,gif,png) since the image is opened by +// the server. + void Image(const char* image, int x_pos, int y_pos); + +// Set the current position to draw from (x,y). In conjunction with... + void SetCursor(int x, int y); + +// ...this function, which draws a line from the current to (x,y) and then +// sets the new position to the new (x,y), this can be used to easily draw +// polygons using vertices + void DrawTo(int x, int y); + +// Set the SVWindow visible/invisible. + void SetVisible(bool visible); + +// Set the SVWindow always on top or not always on top. + void AlwaysOnTop(bool b); + +// Shows a modal dialog with "msg" as question and returns 'y' or 'n'. + int ShowYesNoDialog(const char* msg); + +// Shows a modal dialog with "msg" as question and returns a char* string. +// Constraint: As return, only words (e.g. no whitespaces etc.) are allowed. + char* ShowInputDialog(const char* msg); + +// Adds a messagebox to the SVWindow. This way, it can show the messages... + void AddMessageBox(); + +// ...which can be added by this command. +// This is intended as an "debug" output window. + void AddMessage(const char* format, ...); + +// Zoom the window to the rectangle given upper left corner and +// lower right corner. + void ZoomToRectangle(int x1, int y1, int x2, int y2); + +// Custom messages (manipulating java code directly) can be send through this. +// Send a message to the server and attach the Id of the corresponding window. +// Note: This should only be called if you are know what you are doing, since +// you are fiddling with the Java objects on the server directly. Calling +// this just for fun will likely break your application! +// It is public so you can actually take use of the LUA functionalities, but +// be careful! + void SendMsg(const char* msg, ...); + +// Custom messages (manipulating java code directly) can be send through this. +// Send a message to the server without adding the +// window id. Used for global events like Exit(). +// Note: This should only be called if you are know what you are doing, since +// you are fiddling with the Java objects on the server directly. Calling +// this just for fun will likely break your application! +// It is public so you can actually take use of the LUA functionalities, but +// be careful! + static void SendRawMessage(const char* msg); + +/******************************************************************************* +* Add new menu entries to parent. If parent is "", the entry gets added to the +* main menubar (toplevel). +*******************************************************************************/ +// This adds a new submenu to the menubar. + void MenuItem(const char* parent, const char* name); + +// This adds a new (normal) menu entry with an associated eventID, which should +// be unique among menubar eventIDs. + void MenuItem(const char* parent, const char* name, int cmdEvent); + +// This adds a new checkbox entry, which might initally be flagged. + void MenuItem(const char* parent, const char* name, + int cmdEvent, bool flagged); + +// This adds a new popup submenu to the popup menu. If parent is "", the entry +// gets added at "toplevel" popupmenu. + void PopupItem(const char* parent, const char* name); + +// This adds a new popup entry with the associated eventID, which should be +// unique among popup eventIDs. +// If value and desc are given, on a click the server will ask you to modify +// the value and return the new value. + void PopupItem(const char* parent, const char* name, + int cmdEvent, const char* value, const char* desc); + +// Returns the correct Y coordinate for a window, depending on whether it might +// have to be flipped (by ySize). + int TranslateYCoordinate(int y); + + private: +// Transfers a binary Image. + void TransferBinaryImage(struct Pix* image); +// Transfers a gray scale Image. + void TransferGrayImage(struct Pix* image); +// Transfers a 32-Bit Image. + void Transfer32bppImage(struct Pix* image); + +// Sets up ScrollView, depending on the variables from the constructor. + void Initialize(const char* name, int x_pos, int y_pos, int x_size, + int y_size, int x_canvas_size, int y_canvas_size, + bool y_axis_reversed, const char* server_name); + +// Send the current buffered polygon (if any) and clear it. + void SendPolygon(); + +// Start the message receiving thread. + static void* MessageReceiver(void* a); + +// Place an event into the event_table (synchronized). + void SetEvent(SVEvent* svevent); + +// Wake up the semaphore. + void Signal(); + +// Returns the unique, shared network stream. + static SVNetwork* GetStream() { return stream_; } + +// Starts a new event handler. Called whenever a new window is created. + static void* StartEventHandler(void* sv); + +// Escapes the ' character with a \, so it can be processed by LUA. + char* AddEscapeChars(const char* input); + + // The event handler for this window. + SVEventHandler* event_handler_; + // The name of the window. + const char* window_name_; + // The id of the window. + int window_id_; + // The points of the currently under-construction polyline. + SVPolyLineBuffer* points_; + // Whether the axis is reversed. + bool y_axis_is_reversed_; + // Set to true only after the event handler has terminated. + bool event_handler_ended_; + // If the y axis is reversed, flip all y values by ySize. + int y_size_; + // # of created windows (used to assign an id to each ScrollView* for svmap). + static int nr_created_windows_; + // Serial number of sent images to ensure that the viewer knows they + // are distinct. + static int image_index_; + + // The stream through which the c++ client is connected to the server. + static SVNetwork* stream_; + + // Table of all the currently queued events. + SVEvent* event_table_[SVET_COUNT]; + + // Mutex to access the event_table_ in a synchronized fashion. + SVMutex* mutex_; + + // Semaphore to the thread belonging to this window. + SVSemaphore* semaphore_; +#endif // GRAPHICS_DISABLED +}; + +#endif // OCR_SCROLLVIEW_H__ +#endif // TESSERACT_VIEWER_SCROLLVIEW_H__ diff --git a/TesseractOCR/include/tesseract/seam.h b/TesseractOCR/include/tesseract/seam.h old mode 100755 new mode 100644 index 2bef37fc..23b7bc71 --- a/TesseractOCR/include/tesseract/seam.h +++ b/TesseractOCR/include/tesseract/seam.h @@ -30,15 +30,36 @@ ----------------------------------------------------------------------*/ #include "blobs.h" #include "split.h" -#include "tessarray.h" /*---------------------------------------------------------------------- T y p e s ----------------------------------------------------------------------*/ typedef float PRIORITY; /* PRIORITY */ -typedef struct seam_record -{ /* SEAM */ +struct SEAM { + // Constructor that was formerly new_seam. + SEAM(PRIORITY priority0, const TPOINT& location0, + SPLIT *splita, SPLIT *splitb, SPLIT *splitc) + : priority(priority0), widthp(0), widthn(0), location(location0), + split1(splita), split2(splitb), split3(splitc) {} + // Copy constructor that was formerly clone_seam. + SEAM(const SEAM& src) + : priority(src.priority), widthp(src.widthp), widthn(src.widthn), + location(src.location) { + clone_split(split1, src.split1); + clone_split(split2, src.split2); + clone_split(split3, src.split3); + } + // Destructor was delete_seam. + ~SEAM() { + if (split1) + delete_split(split1); + if (split2) + delete_split(split2); + if (split3) + delete_split(split3); + } + PRIORITY priority; inT8 widthp; inT8 widthn; @@ -46,36 +67,7 @@ typedef struct seam_record SPLIT *split1; SPLIT *split2; SPLIT *split3; -} SEAM; - -typedef ARRAY SEAMS; /* SEAMS */ - -extern SEAM *newseam(); - -/*---------------------------------------------------------------------- - M a c r o s -----------------------------------------------------------------------*/ -/** - * @name clone_seam - * - * Create a new seam record and copy the contents of this seam into it. - */ - -#define clone_seam(dest,source) \ -if (source) { \ - (dest) = newseam (); \ - (dest)->location = (source)->location; \ - (dest)->widthp = (source)->widthp; \ - (dest)->widthn = (source)->widthn; \ - (dest)->priority = (source)->priority; \ - clone_split ((dest)->split1, (source)->split1); \ - clone_split ((dest)->split2, (source)->split2); \ - clone_split ((dest)->split3, (source)->split3); \ -} \ -else { \ - (dest) = (SEAM*) NULL; \ -} \ - +}; /** * exact_point @@ -92,61 +84,40 @@ else { \ ----------------------------------------------------------------------*/ bool point_in_split(SPLIT *split, EDGEPT *point1, EDGEPT *point2); -bool point_in_seam(SEAM *seam, SPLIT *split); +bool point_in_seam(const SEAM *seam, SPLIT *split); bool point_used_by_split(SPLIT *split, EDGEPT *point); bool point_used_by_seam(SEAM *seam, EDGEPT *point); -SEAMS add_seam(SEAMS seam_list, SEAM *seam); - void combine_seams(SEAM *dest_seam, SEAM *source_seam); -void delete_seam(void *arg); //SEAM *seam); - -SEAMS start_seam_list(TBLOB *blobs); - -void free_seam_list(SEAMS seam_list); +void start_seam_list(TWERD *word, GenericVector* seam_array); -bool test_insert_seam(SEAMS seam_list, - int index, - TBLOB *left_blob, - TBLOB *first_blob); +bool test_insert_seam(const GenericVector& seam_array, + TWERD *word, int index); -SEAMS insert_seam(SEAMS seam_list, - int index, - SEAM *seam, - TBLOB *left_blob, - TBLOB *first_blob); +void insert_seam(const TWERD *word, int index, SEAM *seam, + GenericVector* seam_array); -int account_splits_right(SEAM *seam, TBLOB *blob); - -int account_splits_left(SEAM *seam, TBLOB *blob, TBLOB *end_blob); - -void account_splits_left_helper(SEAM *seam, TBLOB *blob, TBLOB *end_blob, - inT32 *depth, inT8 *width, inT8 *found_em); +int account_splits(const SEAM *seam, const TWERD *word, int blob_index, + int blob_direction); bool find_split_in_blob(SPLIT *split, TBLOB *blob); -SEAM *join_two_seams(SEAM *seam1, SEAM *seam2); - -SEAM *new_seam(PRIORITY priority, - const TPOINT& location, - SPLIT *split1, - SPLIT *split2, - SPLIT *split3); - -SEAMS new_seam_list(); +SEAM *join_two_seams(const SEAM *seam1, const SEAM *seam2); void print_seam(const char *label, SEAM *seam); -void print_seams(const char *label, SEAMS seams); +void print_seams(const char *label, const GenericVector& seams); -int shared_split_points(SEAM *seam1, SEAM *seam2); +int shared_split_points(const SEAM *seam1, const SEAM *seam2); -void break_pieces(TBLOB *blobs, SEAMS seams, inT16 start, inT16 end); +void break_pieces(const GenericVector& seams, + int first, int last, TWERD *word); -void join_pieces(TBLOB *piece_blobs, SEAMS seams, inT16 start, inT16 end); +void join_pieces(const GenericVector& seams, + int first, int last, TWERD *word); void hide_seam(SEAM *seam); diff --git a/TesseractOCR/include/tesseract/search_column.h b/TesseractOCR/include/tesseract/search_column.h new file mode 100644 index 00000000..da077d68 --- /dev/null +++ b/TesseractOCR/include/tesseract/search_column.h @@ -0,0 +1,84 @@ +/********************************************************************** + * File: search_column.h + * Description: Declaration of the Beam Search Column Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The SearchColumn class abstracts a column in the lattice that is created +// by the BeamSearch during the recognition process +// The class holds the lattice nodes. New nodes are added by calls to AddNode +// made from the BeamSearch +// The class maintains a hash table of the nodes to be able to lookup nodes +// quickly using their lang_mod_edge. This is needed to merge similar paths +// in the lattice + +#ifndef SEARCH_COLUMN_H +#define SEARCH_COLUMN_H + +#include "search_node.h" +#include "lang_mod_edge.h" +#include "cube_reco_context.h" + +namespace tesseract { + +class SearchColumn { + public: + SearchColumn(int col_idx, int max_node_cnt); + ~SearchColumn(); + // Accessor functions + inline int ColIdx() const { return col_idx_; } + inline int NodeCount() const { return node_cnt_; } + inline SearchNode **Nodes() const { return node_array_; } + + // Prune the nodes if necessary. Pruning is done such that a max + // number of nodes is kept, i.e., the beam width + void Prune(); + SearchNode *AddNode(LangModEdge *edge, int score, + SearchNode *parent, CubeRecoContext *cntxt); + // Returns the node with the least cost + SearchNode *BestNode(); + // Sort the lattice nodes. Needed for visualization + void Sort(); + // Free up the Hash Table. Added to be called by the Beam Search after + // a column is pruned to reduce memory foot print + void FreeHashTable() { + if (node_hash_table_ != NULL) { + delete node_hash_table_; + node_hash_table_ = NULL; + } + } + + private: + static const int kNodeAllocChunk = 1024; + static const int kScoreBins = 1024; + bool init_; + int min_cost_; + int max_cost_; + int max_node_cnt_; + int node_cnt_; + int col_idx_; + int score_bins_[kScoreBins]; + SearchNode **node_array_; + SearchNodeHashTable *node_hash_table_; + + // Free node array and hash table + void Cleanup(); + // Create hash table + bool Init(); +}; +} + +#endif // SEARCH_COLUMN_H diff --git a/TesseractOCR/include/tesseract/search_node.h b/TesseractOCR/include/tesseract/search_node.h new file mode 100644 index 00000000..b4b69b8c --- /dev/null +++ b/TesseractOCR/include/tesseract/search_node.h @@ -0,0 +1,168 @@ +/********************************************************************** + * File: search_node.h + * Description: Declaration of the Beam Search Node Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The SearchNode class abstracts the search lattice node in the lattice +// generated by the BeamSearch class +// The SearchNode class holds the lang_mod_edge associated with the lattice +// node. It also holds a pointer to the parent SearchNode in the search path +// In addition it holds the recognition and the language model costs of the +// node and the path leading to this node + +#ifndef SEARCH_NODE_H +#define SEARCH_NODE_H + +#include "lang_mod_edge.h" +#include "cube_reco_context.h" + +namespace tesseract { + +class SearchNode { + public: + SearchNode(CubeRecoContext *cntxt, SearchNode *parent_node, + int char_reco_cost, LangModEdge *edge, int col_idx); + + ~SearchNode(); + + // Updates the parent of the current node if the specified path yields + // a better path cost + bool UpdateParent(SearchNode *new_parent, int new_reco_cost, + LangModEdge *new_edge); + // returns the 32-bit string corresponding to the path leading to this node + char_32 *PathString(); + // True if the two input nodes correspond to the same path + static bool IdenticalPath(SearchNode *node1, SearchNode *node2); + + inline const char_32 *NodeString() { return str_; } + inline void SetString(char_32 *str) { str_ = str; } + + // This node's character recognition cost. + inline int CharRecoCost() { return char_reco_cost_; } + // Total character recognition cost of the nodes in the best path, + // excluding this node. + inline int BestPathRecoCost() { return best_path_reco_cost_; } + // Number of nodes in best path. + inline int BestPathLength() { return best_path_len_; } + // Mean mixed cost, i.e., mean character recognition cost + + // current language model cost, all weighted by the RecoWgt parameter + inline int BestCost() { return best_cost_; } + // Mean character recognition cost of the nodes on the best path, + // including this node. + inline int BestRecoCost() { return mean_char_reco_cost_ ; } + + inline int ColIdx() { return col_idx_; } + inline SearchNode *ParentNode() { return parent_node_; } + inline LangModEdge *LangModelEdge() { return lang_mod_edge_;} + inline int LangModCost() { return LangModCost(lang_mod_edge_, parent_node_); } + + // A comparer function that allows the SearchColumn class to sort the + // nodes based on the path cost + inline static int SearchNodeComparer(const void *node1, const void *node2) { + return (*(reinterpret_cast(node1)))->best_cost_ - + (*(reinterpret_cast(node2)))->best_cost_; + } + + private: + CubeRecoContext *cntxt_; + // Character code + const char_32 *str_; + // Recognition cost of most recent character + int char_reco_cost_; + // Mean mixed cost, i.e., mean character recognition cost + + // current language model cost, all weighted by the RecoWgt parameter + int best_cost_; + // Mean character recognition cost of the nodes on the best path, + // including this node. + int mean_char_reco_cost_ ; + // Total character recognition cost of the nodes in the best path, + // excluding this node. + int best_path_reco_cost_; + // Number of nodes in best path. + int best_path_len_; + // Column index + int col_idx_; + // Parent Node + SearchNode *parent_node_; + // Language model edge + LangModEdge *lang_mod_edge_; + static int LangModCost(LangModEdge *lang_mod_edge, SearchNode *parent_node); +}; + +// Implments a SearchNode hash table used to detect if a Search Node exists +// or not. This is needed to make sure that identical paths in the BeamSearch +// converge +class SearchNodeHashTable { + public: + SearchNodeHashTable() { + memset(bin_size_array_, 0, sizeof(bin_size_array_)); + } + + ~SearchNodeHashTable() { + } + + // inserts an entry in the hash table + inline bool Insert(LangModEdge *lang_mod_edge, SearchNode *srch_node) { + // compute hash based on the edge and its parent node edge + unsigned int edge_hash = lang_mod_edge->Hash(); + unsigned int parent_hash = (srch_node->ParentNode() == NULL ? + 0 : srch_node->ParentNode()->LangModelEdge()->Hash()); + unsigned int hash_bin = (edge_hash + parent_hash) % kSearchNodeHashBins; + + // already maxed out, just fail + if (bin_size_array_[hash_bin] >= kMaxSearchNodePerBin) { + return false; + } + + bin_array_[hash_bin][bin_size_array_[hash_bin]++] = srch_node; + + return true; + } + + // Looks up an entry in the hash table + inline SearchNode *Lookup(LangModEdge *lang_mod_edge, + SearchNode *parent_node) { + // compute hash based on the edge and its parent node edge + unsigned int edge_hash = lang_mod_edge->Hash(); + unsigned int parent_hash = (parent_node == NULL ? + 0 : parent_node->LangModelEdge()->Hash()); + unsigned int hash_bin = (edge_hash + parent_hash) % kSearchNodeHashBins; + + // lookup the entries in the hash bin + for (int node_idx = 0; node_idx < bin_size_array_[hash_bin]; node_idx++) { + if (lang_mod_edge->IsIdentical( + bin_array_[hash_bin][node_idx]->LangModelEdge()) == true && + SearchNode::IdenticalPath( + bin_array_[hash_bin][node_idx]->ParentNode(), parent_node) == true) { + return bin_array_[hash_bin][node_idx]; + } + } + + return NULL; + } + + private: + // Hash bin size parameters. These were determined emperically. These affect + // the speed of the beam search but have no impact on accuracy + static const int kSearchNodeHashBins = 4096; + static const int kMaxSearchNodePerBin = 512; + int bin_size_array_[kSearchNodeHashBins]; + SearchNode *bin_array_[kSearchNodeHashBins][kMaxSearchNodePerBin]; +}; +} + +#endif // SEARCH_NODE_H diff --git a/TesseractOCR/include/tesseract/search_object.h b/TesseractOCR/include/tesseract/search_object.h new file mode 100644 index 00000000..84b866e6 --- /dev/null +++ b/TesseractOCR/include/tesseract/search_object.h @@ -0,0 +1,55 @@ +/********************************************************************** + * File: search_object.h + * Description: Declaration of the Beam Search Object Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The SearchObject class represents a char_samp (a word bitmap) that is +// being searched for characters (or recognizeable entities). +// This is an abstract class that all SearchObjects should inherit from +// A SearchObject class provides methods to: +// 1- Returns the count of segments +// 2- Recognize a segment range +// 3- Creates a CharSamp for a segment range + +#ifndef SEARCH_OBJECT_H +#define SEARCH_OBJECT_H + +#include "char_altlist.h" +#include "char_samp.h" +#include "cube_reco_context.h" + +namespace tesseract { +class SearchObject { + public: + explicit SearchObject(CubeRecoContext *cntxt) { cntxt_ = cntxt; } + virtual ~SearchObject() {} + + virtual int SegPtCnt() = 0; + virtual CharAltList *RecognizeSegment(int start_pt, int end_pt) = 0; + virtual CharSamp *CharSample(int start_pt, int end_pt) = 0; + virtual Box* CharBox(int start_pt, int end_pt) = 0; + + virtual int SpaceCost(int seg_pt) = 0; + virtual int NoSpaceCost(int seg_pt) = 0; + virtual int NoSpaceCost(int start_pt, int end_pt) = 0; + + protected: + CubeRecoContext *cntxt_; +}; +} + +#endif // SEARCH_OBJECT_H diff --git a/TesseractOCR/include/tesseract/secname.h b/TesseractOCR/include/tesseract/secname.h old mode 100755 new mode 100644 index 5ca4e198..7a2b36b3 --- a/TesseractOCR/include/tesseract/secname.h +++ b/TesseractOCR/include/tesseract/secname.h @@ -1,9 +1 @@ -/* Include this file in any module which needs to have conditional compilation - of sensitive code for UNLV. In INTERNAL mode SECURE_NAMES is NOT defined. - For UNLV mode it IS defined, allowing multiple modules to do conditional - compilation on the same name. -*/ - -#ifndef SECURE_NAMES -/* #define SECURE_NAMES */ -#endif +/* Redundant. Delete me. */ diff --git a/TesseractOCR/include/tesseract/serialis.h b/TesseractOCR/include/tesseract/serialis.h old mode 100755 new mode 100644 index 9d80acdc..7be8e5c1 --- a/TesseractOCR/include/tesseract/serialis.h +++ b/TesseractOCR/include/tesseract/serialis.h @@ -23,14 +23,8 @@ #include #include #include -#include "memry.h" -#include "errcode.h" -#include "fileerr.h" -// Switch endinan. -extern DLLSYM uinT64 reverse64(uinT64); -extern DLLSYM uinT32 reverse32(uinT32); -extern DLLSYM uinT16 reverse16(uinT16); +#include "genericvector.h" /*********************************************************************** QUOTE_IT MACRO DEFINITION @@ -40,4 +34,42 @@ Replace with "". may be an arbitrary number of tokens #define QUOTE_IT( parm ) #parm +namespace tesseract { + +// Simple file class. Only does input for now. +// Allows for portable file input from memory. +class TFile { + public: + TFile(); + + // All the Open methods load the whole file into memory. + // Opens a file with a supplied reader, or NULL to use the default. + bool Open(const STRING& filename, FileReader reader); + // From an existing memory buffer. + bool Open(const char* data, int size); + // From an open file and an end offset. + bool Open(FILE* fp, inT64 end_offset); + + // Reads a line like fgets. Returns NULL on EOF, otherwise buffer. + // Reads at most buffer_size bytes, including '\0' terminator, even if + // the line is longer. Does nothing if buffer_size <= 0. + char* FGets(char* buffer, int buffer_size); + // Replicates fread, returning the number of items read. + int FRead(void* buffer, int size, int count); + // To use fscanf use FGets and sscanf. + + // Resets the TFile as if it has been Opened, but nothing read. + void Rewind() { + offset_ = 0; + } + + private: + // The number of bytes used so far. + int offset_; + // The buffered data from the file. + GenericVector data_; +}; + +} // namespace tesseract. + #endif diff --git a/TesseractOCR/include/tesseract/shapeclassifier.h b/TesseractOCR/include/tesseract/shapeclassifier.h new file mode 100644 index 00000000..5069f375 --- /dev/null +++ b/TesseractOCR/include/tesseract/shapeclassifier.h @@ -0,0 +1,124 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +/////////////////////////////////////////////////////////////////////// +// File: shapeclassifier.h +// Description: Base interface class for classifiers that return a +// shape index. +// Author: Ray Smith +// Created: Tue Sep 13 11:26:32 PDT 2011 +// +// (C) Copyright 2011, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_CLASSIFY_SHAPECLASSIFIER_H_ +#define TESSERACT_CLASSIFY_SHAPECLASSIFIER_H_ + +#include "unichar.h" + +template class GenericVector; +struct Pix; +class ScrollView; +class UNICHARSET; + +namespace tesseract { + +template class PointerVector; +struct ShapeRating; +class ShapeTable; +class TrainingSample; +class TrainingSampleSet; +struct UnicharRating; + +// Interface base class for classifiers that produce ShapeRating results. +class ShapeClassifier { + public: + virtual ~ShapeClassifier() {} + + // Classifies the given [training] sample, writing to results. + // If page_pix is not NULL, the overriding function may call + // sample.GetSamplePix(padding, page_pix) to get an image of the sample + // padded (with real image data) by the given padding to extract features + // from the image of the character. Other members of TrainingSample: + // features(), micro_features(), cn_feature(), geo_feature() may be used + // to get the appropriate tesseract features. + // If debug is non-zero, then various degrees of classifier dependent debug + // information is provided. + // If keep_this (a UNICHAR_ID) is >= 0, then the results should always + // contain keep_this, and (if possible) anything of intermediate confidence. + // (Used for answering "Why didn't it get that right?" questions.) It must + // be a UNICHAR_ID as the callers have no clue how to choose the best shape + // that may contain a desired answer. + // The return value is the number of classes saved in results. + // NOTE that overriding functions MUST clear and sort the results by + // descending rating unless the classifier is working with a team of such + // classifiers. + // NOTE: Neither overload of ClassifySample is pure, but at least one must + // be overridden by a classifier in order for it to do anything. + virtual int UnicharClassifySample(const TrainingSample& sample, Pix* page_pix, + int debug, UNICHAR_ID keep_this, + GenericVector* results); + + protected: + virtual int ClassifySample(const TrainingSample& sample, Pix* page_pix, + int debug, UNICHAR_ID keep_this, + GenericVector* results); + + public: + // Returns the shape that contains unichar_id that has the best result. + // If result is not NULL, it is set with the shape_id and rating. + // Returns -1 if ClassifySample fails to provide any result containing + // unichar_id. BestShapeForUnichar does not need to be overridden if + // ClassifySample respects the keep_this rule. + virtual int BestShapeForUnichar(const TrainingSample& sample, Pix* page_pix, + UNICHAR_ID unichar_id, ShapeRating* result); + + // Provides access to the ShapeTable that this classifier works with. + virtual const ShapeTable* GetShapeTable() const = 0; + // Provides access to the UNICHARSET that this classifier works with. + // Must be overridden IFF GetShapeTable() returns NULL. + virtual const UNICHARSET& GetUnicharset() const; + + // Visual debugger classifies the given sample, displays the results and + // solicits user input to display other classifications. Returns when + // the user has finished with debugging the sample. + // Probably doesn't need to be overridden if the subclass provides + // DisplayClassifyAs. + virtual void DebugDisplay(const TrainingSample& sample, Pix* page_pix, + UNICHAR_ID unichar_id); + + + // Displays classification as the given unichar_id. Creates as many windows + // as it feels fit, using index as a guide for placement. Adds any created + // windows to the windows output and returns a new index that may be used + // by any subsequent classifiers. Caller waits for the user to view and + // then destroys the windows by clearing the vector. + virtual int DisplayClassifyAs(const TrainingSample& sample, Pix* page_pix, + UNICHAR_ID unichar_id, int index, + PointerVector* windows); + + // Prints debug information on the results. context is some introductory/title + // message. + virtual void UnicharPrintResults( + const char* context, const GenericVector& results) const; + virtual void PrintResults(const char* context, + const GenericVector& results) const; + + protected: + // Removes any result that has all its unichars covered by a better choice, + // regardless of font. + void FilterDuplicateUnichars(GenericVector* results) const; +}; + +} // namespace tesseract. + +#endif // TESSERACT_CLASSIFY_SHAPECLASSIFIER_H_ diff --git a/TesseractOCR/include/tesseract/shapetable.h b/TesseractOCR/include/tesseract/shapetable.h new file mode 100644 index 00000000..87f4245f --- /dev/null +++ b/TesseractOCR/include/tesseract/shapetable.h @@ -0,0 +1,392 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +/////////////////////////////////////////////////////////////////////// +// File: shapetable.h +// Description: Class to map a classifier shape index to unicharset +// indices and font indices. +// Author: Ray Smith +// Created: Thu Oct 28 17:46:32 PDT 2010 +// +// (C) Copyright 2010, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_CLASSIFY_SHAPETABLE_H_ +#define TESSERACT_CLASSIFY_SHAPETABLE_H_ + +#include "bitvector.h" +#include "genericheap.h" +#include "genericvector.h" +#include "intmatcher.h" + +class STRING; +class UNICHARSET; + +namespace tesseract { + +struct FontInfo; +class FontInfoTable; +class ShapeTable; + +// Simple struct to hold a single classifier unichar selection, a corresponding +// rating, and a list of appropriate fonts. +struct UnicharRating { + UnicharRating() : unichar_id(0), rating(0.0f) {} + UnicharRating(int u, float r) + : unichar_id(u), rating(r) {} + + // Sort function to sort ratings appropriately by descending rating. + static int SortDescendingRating(const void* t1, const void* t2) { + const UnicharRating* a = reinterpret_cast(t1); + const UnicharRating* b = reinterpret_cast(t2); + if (a->rating > b->rating) { + return -1; + } else if (a->rating < b->rating) { + return 1; + } else { + return a->unichar_id - b->unichar_id; + } + } + // Helper function to get the index of the first result with the required + // unichar_id. If the results are sorted by rating, this will also be the + // best result with the required unichar_id. + // Returns -1 if the unichar_id is not found + static int FirstResultWithUnichar(const GenericVector& results, + UNICHAR_ID unichar_id); + + // Index into some UNICHARSET table indicates the class of the answer. + UNICHAR_ID unichar_id; + // Rating from classifier with 1.0 perfect and 0.0 impossible. + // Call it a probability if you must. + float rating; + // Set of fonts for this shape in order of decreasing preference. + // (There is no mechanism for storing scores for fonts as yet.) + GenericVector fonts; +}; + +// Classifier result from a low-level classification is an index into some +// ShapeTable and a rating. +struct ShapeRating { + ShapeRating() + : shape_id(0), rating(0.0f), raw(0.0f), font(0.0f), + joined(false), broken(false) {} + ShapeRating(int s, float r) + : shape_id(s), rating(r), raw(1.0f), font(0.0f), + joined(false), broken(false) {} + + // Sort function to sort ratings appropriately by descending rating. + static int SortDescendingRating(const void* t1, const void* t2) { + const ShapeRating* a = reinterpret_cast(t1); + const ShapeRating* b = reinterpret_cast(t2); + if (a->rating > b->rating) { + return -1; + } else if (a->rating < b->rating) { + return 1; + } else { + return a->shape_id - b->shape_id; + } + } + // Helper function to get the index of the first result with the required + // unichar_id. If the results are sorted by rating, this will also be the + // best result with the required unichar_id. + // Returns -1 if the unichar_id is not found + static int FirstResultWithUnichar(const GenericVector& results, + const ShapeTable& shape_table, + UNICHAR_ID unichar_id); + + // Index into some shape table indicates the class of the answer. + int shape_id; + // Rating from classifier with 1.0 perfect and 0.0 impossible. + // Call it a probability if you must. + float rating; + // Subsidiary rating that a classifier may use internally. + float raw; + // Subsidiary rating that a classifier may use internally. + float font; + // Flag indicating that the input may be joined. + bool joined; + // Flag indicating that the input may be broken (a fragment). + bool broken; +}; + +// Simple struct to hold an entry for a heap-based priority queue of +// ShapeRating. +struct ShapeQueueEntry { + ShapeQueueEntry() : result(ShapeRating(0, 0.0f)), level(0) {} + ShapeQueueEntry(const ShapeRating& rating, int level0) + : result(rating), level(level0) {} + + // Sort by decreasing rating and decreasing level for equal rating. + bool operator<(const ShapeQueueEntry& other) const { + if (result.rating > other.result.rating) return true; + if (result.rating == other.result.rating) + return level > other.level; + return false; + } + + // Output from classifier. + ShapeRating result; + // Which level in the tree did this come from? + int level; +}; +typedef GenericHeap ShapeQueue; + +// Simple struct to hold a set of fonts associated with a single unichar-id. +// A vector of UnicharAndFonts makes a shape. +struct UnicharAndFonts { + UnicharAndFonts() : unichar_id(0) { + } + UnicharAndFonts(int uni_id, int font_id) : unichar_id(uni_id) { + font_ids.push_back(font_id); + } + + // Writes to the given file. Returns false in case of error. + bool Serialize(FILE* fp) const; + // Reads from the given file. Returns false in case of error. + // If swap is true, assumes a big/little-endian swap is needed. + bool DeSerialize(bool swap, FILE* fp); + + // Sort function to sort a pair of UnicharAndFonts by unichar_id. + static int SortByUnicharId(const void* v1, const void* v2); + + GenericVector font_ids; + inT32 unichar_id; +}; + +// A Shape is a collection of unichar-ids and a list of fonts associated with +// each, organized as a vector of UnicharAndFonts. Conceptually a Shape is +// a classifiable unit, and represents a group of characters or parts of +// characters that have a similar or identical shape. Shapes/ShapeTables may +// be organized hierarchically from identical shapes at the leaves to vaguely +// similar shapes near the root. +class Shape { + public: + Shape() : destination_index_(-1) {} + + // Writes to the given file. Returns false in case of error. + bool Serialize(FILE* fp) const; + // Reads from the given file. Returns false in case of error. + // If swap is true, assumes a big/little-endian swap is needed. + bool DeSerialize(bool swap, FILE* fp); + + int destination_index() const { + return destination_index_; + } + void set_destination_index(int index) { + destination_index_ = index; + } + int size() const { + return unichars_.size(); + } + // Returns a UnicharAndFonts entry for the given index, which must be + // in the range [0, size()). + const UnicharAndFonts& operator[](int index) const { + return unichars_[index]; + } + // Sets the unichar_id of the given index to the new unichar_id. + void SetUnicharId(int index, int unichar_id) { + unichars_[index].unichar_id = unichar_id; + } + // Adds a font_id for the given unichar_id. If the unichar_id is not + // in the shape, it is added. + void AddToShape(int unichar_id, int font_id); + // Adds everything in other to this. + void AddShape(const Shape& other); + // Returns true if the shape contains the given unichar_id, font_id pair. + bool ContainsUnicharAndFont(int unichar_id, int font_id) const; + // Returns true if the shape contains the given unichar_id, ignoring font. + bool ContainsUnichar(int unichar_id) const; + // Returns true if the shape contains the given font, ignoring unichar_id. + bool ContainsFont(int font_id) const; + // Returns true if the shape contains the given font properties, ignoring + // unichar_id. + bool ContainsFontProperties(const FontInfoTable& font_table, + uinT32 properties) const; + // Returns true if the shape contains multiple different font properties, + // ignoring unichar_id. + bool ContainsMultipleFontProperties(const FontInfoTable& font_table) const; + // Returns true if this shape is equal to other (ignoring order of unichars + // and fonts). + bool operator==(const Shape& other) const; + // Returns true if this is a subset (including equal) of other. + bool IsSubsetOf(const Shape& other) const; + // Returns true if the lists of unichar ids are the same in this and other, + // ignoring fonts. + // NOT const, as it will sort the unichars on demand. + bool IsEqualUnichars(Shape* other); + + private: + // Sorts the unichars_ vector by unichar. + void SortUnichars(); + + // Flag indicates that the unichars are sorted, allowing faster set + // operations with another shape. + bool unichars_sorted_; + // If this Shape is part of a ShapeTable the destiation_index_ is the index + // of some other shape in the ShapeTable with which this shape is merged. + int destination_index_; + // Array of unichars, each with a set of fonts. Each unichar has at most + // one entry in the vector. + GenericVector unichars_; +}; + +// ShapeTable is a class to encapsulate the triple indirection that is +// used here. +// ShapeTable is a vector of shapes. +// Each shape is a vector of UnicharAndFonts representing the set of unichars +// that the shape represents. +// Each UnicharAndFonts also lists the fonts of the unichar_id that were +// mapped to the shape during training. +class ShapeTable { + public: + ShapeTable(); + // The UNICHARSET reference supplied here, or in set_unicharset below must + // exist for the entire life of the ShapeTable. It is used only by DebugStr. + explicit ShapeTable(const UNICHARSET& unicharset); + + // Writes to the given file. Returns false in case of error. + bool Serialize(FILE* fp) const; + // Reads from the given file. Returns false in case of error. + // If swap is true, assumes a big/little-endian swap is needed. + bool DeSerialize(bool swap, FILE* fp); + + // Accessors. + int NumShapes() const { + return shape_table_.size(); + } + const UNICHARSET& unicharset() const { + return *unicharset_; + } + // Returns the number of fonts used in this ShapeTable, computing it if + // necessary. + int NumFonts() const; + // Shapetable takes a pointer to the UNICHARSET, so it must persist for the + // entire life of the ShapeTable. + void set_unicharset(const UNICHARSET& unicharset) { + unicharset_ = &unicharset; + } + // Re-indexes the class_ids in the shapetable according to the given map. + // Useful in conjunction with set_unicharset. + void ReMapClassIds(const GenericVector& unicharset_map); + // Returns a string listing the classes/fonts in a shape. + STRING DebugStr(int shape_id) const; + // Returns a debug string summarizing the table. + STRING SummaryStr() const; + + // Adds a new shape starting with the given unichar_id and font_id. + // Returns the assigned index. + int AddShape(int unichar_id, int font_id); + // Adds a copy of the given shape unless it is already present. + // Returns the assigned index or index of existing shape if already present. + int AddShape(const Shape& other); + // Removes the shape given by the shape index. All indices above are changed! + void DeleteShape(int shape_id); + // Adds a font_id to the given existing shape index for the given + // unichar_id. If the unichar_id is not in the shape, it is added. + void AddToShape(int shape_id, int unichar_id, int font_id); + // Adds the given shape to the existing shape with the given index. + void AddShapeToShape(int shape_id, const Shape& other); + // Returns the id of the shape that contains the given unichar and font. + // If not found, returns -1. + // If font_id < 0, the font_id is ignored and the first shape that matches + // the unichar_id is returned. + int FindShape(int unichar_id, int font_id) const; + // Returns the first unichar_id and font_id in the given shape. + void GetFirstUnicharAndFont(int shape_id, + int* unichar_id, int* font_id) const; + + // Accessors for the Shape with the given shape_id. + const Shape& GetShape(int shape_id) const { + return *shape_table_[shape_id]; + } + Shape* MutableShape(int shape_id) { + return shape_table_[shape_id]; + } + + // Expands all the classes/fonts in the shape individually to build + // a ShapeTable. + int BuildFromShape(const Shape& shape, const ShapeTable& master_shapes); + + // Returns true if the shapes are already merged. + bool AlreadyMerged(int shape_id1, int shape_id2) const; + // Returns true if any shape contains multiple unichars. + bool AnyMultipleUnichars() const; + // Returns the maximum number of unichars over all shapes. + int MaxNumUnichars() const; + // Merges shapes with a common unichar over the [start, end) interval. + // Assumes single unichar per shape. + void ForceFontMerges(int start, int end); + // Returns the number of unichars in the master shape. + int MasterUnicharCount(int shape_id) const; + // Returns the sum of the font counts in the master shape. + int MasterFontCount(int shape_id) const; + // Returns the number of unichars that would result from merging the shapes. + int MergedUnicharCount(int shape_id1, int shape_id2) const; + // Merges two shape_ids, leaving shape_id2 marked as merged. + void MergeShapes(int shape_id1, int shape_id2); + // Swaps two shape_ids. + void SwapShapes(int shape_id1, int shape_id2); + // Appends the master shapes from other to this. + // Used to create a clean ShapeTable from a merged one, or to create a + // copy of a ShapeTable. + // If not NULL, shape_map is set to map other shape_ids to this's shape_ids. + void AppendMasterShapes(const ShapeTable& other, + GenericVector* shape_map); + // Returns the number of master shapes remaining after merging. + int NumMasterShapes() const; + // Returns the destination of this shape, (if merged), taking into account + // the fact that the destination may itself have been merged. + // For a non-merged shape, returns the input shape_id. + int MasterDestinationIndex(int shape_id) const; + + // Returns false if the unichars in neither shape is a subset of the other.. + bool SubsetUnichar(int shape_id1, int shape_id2) const; + // Returns false if the unichars in neither shape is a subset of the other.. + bool MergeSubsetUnichar(int merge_id1, int merge_id2, int shape_id) const; + // Returns true if the unichar sets are equal between the shapes. + bool EqualUnichars(int shape_id1, int shape_id2) const; + bool MergeEqualUnichars(int merge_id1, int merge_id2, int shape_id) const; + // Returns true if there is a common unichar between the shapes. + bool CommonUnichars(int shape_id1, int shape_id2) const; + // Returns true if there is a common font id between the shapes. + bool CommonFont(int shape_id1, int shape_id2) const; + + // Adds the unichars of the given shape_id to the vector of results. Any + // unichar_id that is already present just has the fonts added to the + // font set for that result without adding a new entry in the vector. + // NOTE: it is assumed that the results are given to this function in order + // of decreasing rating. + // The unichar_map vector indicates the index of the results entry containing + // each unichar, or -1 if the unichar is not yet included in results. + void AddShapeToResults(const ShapeRating& shape_rating, + GenericVector* unichar_map, + GenericVector* results) const; + + private: + // Adds the given unichar_id to the results if needed, updating unichar_map + // and returning the index of unichar in results. + int AddUnicharToResults(int unichar_id, float rating, + GenericVector* unichar_map, + GenericVector* results) const; + + // Pointer to a provided unicharset used only by the Debugstr member. + const UNICHARSET* unicharset_; + // Vector of pointers to the Shapes in this ShapeTable. + PointerVector shape_table_; + + // Cached data calculated on demand. + mutable int num_fonts_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_CLASSIFY_SHAPETABLE_H_ diff --git a/TesseractOCR/include/tesseract/sortflts.h b/TesseractOCR/include/tesseract/sortflts.h new file mode 100644 index 00000000..cf02ac98 --- /dev/null +++ b/TesseractOCR/include/tesseract/sortflts.h @@ -0,0 +1,73 @@ +/********************************************************************** + * File: sortflts.h (Formerly sfloats.h) + * Description: Code to maintain a sorted list of floats. + * Author: Ray Smith + * Created: Mon Oct 4 16:15:40 BST 1993 + * + * (C) Copyright 1993, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef SORTFLTS_H +#define SORTFLTS_H + +#include "elst.h" + +class SORTED_FLOAT:public ELIST_LINK +{ + friend class SORTED_FLOATS; + + public: + SORTED_FLOAT() { + } //empty constructor + SORTED_FLOAT( //create one + float value, //value of entry + inT32 key) { //reference + entry = value; + address = key; + } + private: + float entry; //value of float + inT32 address; //key +}; + +ELISTIZEH (SORTED_FLOAT) +class SORTED_FLOATS +{ + public: + /** empty constructor */ + SORTED_FLOATS() { + it.set_to_list (&list); + } + /** + * add sample + * @param value sample float + * @param key retrieval key + */ + void add(float value, + inT32 key); + /** + * delete sample + * @param key key to delete + */ + void remove(inT32 key); + /** + * index to list + * @param index item to get + */ + float operator[] (inT32 index); + + private: + SORTED_FLOAT_LIST list; //list of floats + SORTED_FLOAT_IT it; //iterator built-in +}; +#endif diff --git a/TesseractOCR/include/tesseract/sorthelper.h b/TesseractOCR/include/tesseract/sorthelper.h old mode 100755 new mode 100644 index 4e6542de..4da13b92 --- a/TesseractOCR/include/tesseract/sorthelper.h +++ b/TesseractOCR/include/tesseract/sorthelper.h @@ -56,7 +56,9 @@ class SortHelper { } // Constructor takes a hint of the array size, but it need not be accurate. - explicit SortHelper(int sizehint) : counts_(sizehint) {} + explicit SortHelper(int sizehint) { + counts_.reserve(sizehint); + } // Add a value that may be a duplicate of an existing value. // Uses a linear search. diff --git a/TesseractOCR/include/tesseract/split.h b/TesseractOCR/include/tesseract/split.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/statistc.h b/TesseractOCR/include/tesseract/statistc.h old mode 100755 new mode 100644 index 69fd7132..96bd9e39 --- a/TesseractOCR/include/tesseract/statistc.h +++ b/TesseractOCR/include/tesseract/statistc.h @@ -22,8 +22,12 @@ #include #include "host.h" +#include "kdpair.h" #include "scrollview.h" +template class GenericVector; + + // Simple histogram-based statistics for integer values in a known // range, such that the range is small compared to the number of samples. class STATS { @@ -102,6 +106,16 @@ class STATS { inT32 max_clusters, // max no to make STATS *clusters); // array of clusters +// Finds (at most) the top max_modes modes, well actually the whole peak around +// each mode, returning them in the given modes vector as a pair in order of decreasing total count. +// Since the mean is the key and the count the data in the pair, a single call +// to sort on the output will re-sort by increasing mean of peak if that is +// more useful than decreasing total count. +// Returns the actual number of modes found. + int top_n_modes( + int max_modes, + GenericVector >* modes) const; // Prints a summary and table of the histogram. void print() const; diff --git a/TesseractOCR/include/tesseract/stderr.h b/TesseractOCR/include/tesseract/stderr.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/stepblob.h b/TesseractOCR/include/tesseract/stepblob.h old mode 100755 new mode 100644 index e229487e..ae6e25d5 --- a/TesseractOCR/include/tesseract/stepblob.h +++ b/TesseractOCR/include/tesseract/stepblob.h @@ -23,7 +23,9 @@ #include "coutln.h" #include "rect.h" +class C_BLOB; struct Pix; +ELISTIZEH(C_BLOB) class C_BLOB:public ELIST_LINK { @@ -35,6 +37,26 @@ class C_BLOB:public ELIST_LINK // already been fully initialized. explicit C_BLOB(C_OUTLINE* outline); + // Builds a set of one or more blobs from a list of outlines. + // Input: one outline on outline_list contains all the others, but the + // nesting and order are undefined. + // If good_blob is true, the blob is added to good_blobs_it, unless + // an illegal (generation-skipping) parent-child relationship is found. + // If so, the parent blob goes to bad_blobs_it, and the immediate children + // are promoted to the top level, recursively being sent to good_blobs_it. + // If good_blob is false, all created blobs will go to the bad_blobs_it. + // Output: outline_list is empty. One or more blobs are added to + // good_blobs_it and/or bad_blobs_it. + static void ConstructBlobsFromOutlines(bool good_blob, + C_OUTLINE_LIST* outline_list, + C_BLOB_IT* good_blobs_it, + C_BLOB_IT* bad_blobs_it); + + // Sets the COUT_INVERSE flag appropriately on the outlines and their + // children recursively, reversing the outlines if needed so that + // everything has an anticlockwise top-level. + void CheckInverseFlagAndDirection(); + // Build and return a fake blob containing a single fake outline with no // steps. static C_BLOB* FakeBlob(const TBOX& box); @@ -53,6 +75,14 @@ class C_BLOB:public ELIST_LINK void move(const ICOORD vec); // repostion blob by vector void rotate(const FCOORD& rotation); // Rotate by given vector. + // Adds sub-pixel resolution EdgeOffsets for the outlines using greyscale + // if the supplied pix is 8-bit or the binary edges if NULL. + void ComputeEdgeOffsets(int threshold, Pix* pix); + + // Estimates and returns the baseline position based on the shape of the + // outlines. + inT16 EstimateBaselinePosition(); + // Returns a Pix rendering of the blob. pixDestroy after use. Pix* render(); // Returns a Pix rendering of the outline of the blob. (no fill). @@ -64,6 +94,13 @@ class C_BLOB:public ELIST_LINK ScrollView* window, //window to draw in ScrollView::Color blob_colour, //for outer bits ScrollView::Color child_colour); //for holes + // Draws the blob in the given colour, and child_colour, normalized + // using the given denorm, making use of sub-pixel accurate information + // if available. + void plot_normed(const DENORM& denorm, + ScrollView::Color blob_colour, + ScrollView::Color child_colour, + ScrollView* window); #endif // GRAPHICS_DISABLED C_BLOB& operator= (const C_BLOB & source) { @@ -83,5 +120,4 @@ class C_BLOB:public ELIST_LINK C_OUTLINE_LIST outlines; //master elements }; -ELISTIZEH (C_BLOB) #endif diff --git a/TesseractOCR/include/tesseract/stopper.h b/TesseractOCR/include/tesseract/stopper.h new file mode 100644 index 00000000..a2d7b362 --- /dev/null +++ b/TesseractOCR/include/tesseract/stopper.h @@ -0,0 +1,50 @@ +/****************************************************************************** + ** Filename: stopper.h + ** Purpose: Stopping criteria for word classifier. + ** Author: Dan Johnson + ** History: Wed May 1 09:42:57 1991, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef STOPPER_H +#define STOPPER_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ + +#include "genericvector.h" +#include "params.h" +#include "ratngs.h" +#include "unichar.h" + +class WERD_CHOICE; + +typedef uinT8 BLOB_WIDTH; + +struct DANGERR_INFO { + DANGERR_INFO() : + begin(-1), end(-1), dangerous(false), correct_is_ngram(false), + leftmost(INVALID_UNICHAR_ID) {} + DANGERR_INFO(int b, int e, bool d, bool n, UNICHAR_ID l) : + begin(b), end(e), dangerous(d), correct_is_ngram(n), leftmost(l) {} + int begin; + int end; + bool dangerous; + bool correct_is_ngram; + UNICHAR_ID leftmost; // in the replacement, what's the leftmost character? +}; + +typedef GenericVector DANGERR; + + +#endif diff --git a/TesseractOCR/include/tesseract/strcasestr.h b/TesseractOCR/include/tesseract/strcasestr.h new file mode 100644 index 00000000..0472241f --- /dev/null +++ b/TesseractOCR/include/tesseract/strcasestr.h @@ -0,0 +1,59 @@ +/* +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies of the Software and its Copyright notices. In addition publicly +documented acknowledgment must be given that this software has been used if no +source code of this software is made available publicly. Making the source +available publicly means including the source for this software with the +distribution, or a method to get this software via some reasonable mechanism +(electronic transfer via a network or media) as well as making an offer to +supply the source on request. This Copyright notice serves as an offer to +supply the source on on request as well. Instead of this, supplying +acknowledgments of use of this software in either Copyright notices, Manuals, +Publicity and Marketing documents or any documentation provided with any +product containing this software. This License does not apply to any software +that links to the libraries provided by this software (statically or +dynamically), but only to the software provided. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Source: +Evil 1.7.4 +The Evil library tried to port some convenient Unix functions +to the Windows (XP or CE) platform. They are planned to be used + +http://git.enlightenment.org/legacy/evil.git/tree/src/lib/evil_string.h?id=eeaddf80d0d547d4c216974038c0599b34359695 +*/ + +#ifndef VS2010_PORT_STRCASESTR_H_ +#define VS2010_PORT_STRCASESTR_H_ +/** + * @brief Locatea substring into a string, ignoring case. + * + * @param haystack The string to search in. + * @param needle The substring to find. + * @return + * + * This function locates the string @p needle into the string @p haystack, + * ignoring the case of the characters. It returns apointer to the + * beginning of the substring, or NULL if the substring is not found. + * If @p haystack or @p needle are @c NULL, this function returns @c NULL. + * + * Conformity: Non applicable. + * + * Supported OS: Windows XP, Windows CE + */ +char *strcasestr(const char *haystack, const char *needle); + +#endif /* VS2010_PORT_STRCASESTR_H_ */ diff --git a/TesseractOCR/include/tesseract/tfacep.h b/TesseractOCR/include/tesseract/string_32.h old mode 100755 new mode 100644 similarity index 53% rename from TesseractOCR/include/tesseract/tfacep.h rename to TesseractOCR/include/tesseract/string_32.h index dd3e7850..0ae0ceec --- a/TesseractOCR/include/tesseract/tfacep.h +++ b/TesseractOCR/include/tesseract/string_32.h @@ -1,10 +1,10 @@ /********************************************************************** - * File: tfacep.h (Formerly tfacep.h) - * Description: Declarations of C functions and C owned data. - * Author: Ray Smith - * Created: Mon Apr 27 12:51:28 BST 1992 + * File: string_32.h + * Description: Declaration of a 32 Bit string class + * Author: Ahmad Abdulkader + * Created: 2007 * - * (C) Copyright 1992, Hewlett-Packard Ltd. + * (C) Copyright 2008, Google Inc. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at @@ -17,22 +17,28 @@ * **********************************************************************/ -#ifndef TFACEP_H -#define TFACEP_H +// the string_32 class provides the functionality needed +// for a 32-bit string class -#include "hosthplb.h" -#include "blobs.h" -#include "tessarray.h" -#include "notdll.h" -#include "oldlist.h" -#include "permute.h" -#include "blobclass.h" -#include "stopper.h" -#include "associate.h" -#include "chop.h" -#include "structures.h" +#ifndef STRING_32_H +#define STRING_32_H -typedef void (*TESS_TESTER) (TBLOB *, BOOL8, char *, inT32, LIST); -typedef LIST (*TESS_MATCHER) (TBLOB *, TBLOB *, TBLOB *); +#include +#include +#include +#include +#ifdef USE_STD_NAMESPACE +using std::basic_string; +using std::string; +using std::vector; #endif + +namespace tesseract { + +// basic definitions +typedef signed int char_32; +typedef basic_string string_32; +} + +#endif // STRING_32_H diff --git a/TesseractOCR/include/tesseract/stringrenderer.h b/TesseractOCR/include/tesseract/stringrenderer.h new file mode 100644 index 00000000..e2b7b350 --- /dev/null +++ b/TesseractOCR/include/tesseract/stringrenderer.h @@ -0,0 +1,203 @@ +/********************************************************************** + * File: stringrenderer.h + * Description: Class for rendering UTF-8 text to an image, and retrieving + * bounding boxes around each grapheme cluster. + * + * Instances are created using a font description string + * (eg. "Arial Italic 12"; see pango_font_info.h for the format) + * and the page dimensions. Other renderer properties such as + * spacing, ligaturization, as well a preprocessing behavior such + * as removal of unrenderable words and a special n-gram mode may + * be set using respective set_* methods. + * + * Author: Ranjith Unnikrishnan + * Created: Mon Nov 18 2013 + * + * (C) Copyright 2013, Google Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + **********************************************************************/ + +#ifndef TESSERACT_TRAINING_STRINGRENDERER_H_ +#define TESSERACT_TRAINING_STRINGRENDERER_H_ + +#include +#include + +#include "hashfn.h" +#include "host.h" +#include "pango_font_info.h" +#include "pango/pango-layout.h" +#include "pango/pangocairo.h" + +struct Boxa; +struct Pix; + +namespace tesseract { + +class BoxChar; + +class StringRenderer { + public: + StringRenderer(const string& font_desc, int page_width, int page_height); + ~StringRenderer(); + + // Renders the text with the chosen font and returns the byte offset upto + // which the text could be rendered so as to fit the specified page + // dimensions. + int RenderToImage(const char* text, int text_length, Pix** pix); + int RenderToBinaryImage(const char* text, int text_length, int threshold, + Pix** pix); + // Renders a line of text with all available fonts that were able to render + // the text. + int RenderAllFontsToImage(const char* text, int text_length, + string* font_used, Pix** pix); + + bool set_font(const string& desc); + void set_char_spacing(double char_spacing) { + char_spacing_ = char_spacing; + } + void set_leading(int leading) { + leading_ = leading; + } + void set_resolution(const int resolution); + void set_vertical_text(bool vertical_text) { + vertical_text_ = vertical_text; + } + void set_gravity_hint_strong(bool gravity_hint_strong) { + gravity_hint_strong_ = gravity_hint_strong; + } + void set_render_fullwidth_latin(bool render_fullwidth_latin) { + render_fullwidth_latin_ = render_fullwidth_latin; + } + void set_page(int page) { + page_ = page; + } + void set_box_padding(int val) { + box_padding_ = val; + } + void set_drop_uncovered_chars(bool val) { + drop_uncovered_chars_ = val; + } + void set_strip_unrenderable_words(bool val) { + strip_unrenderable_words_ = val; + } + void set_output_word_boxes(bool val) { + output_word_boxes_ = val; + } + // Before rendering the string, replace latin characters with their optional + // ligatured forms (such as "fi", "ffi" etc.) if the font_ covers those + // unicodes. + void set_add_ligatures(bool add_ligatures) { + add_ligatures_ = add_ligatures; + } + // Set the rgb value of the text ink. Values range in [0, 1.0] + void set_pen_color(double r, double g, double b) { + pen_color_[0] = r; + pen_color_[1] = g; + pen_color_[2] = b; + } + void set_h_margin(const int h_margin) { + h_margin_ = h_margin; + } + void set_v_margin(const int v_margin) { + v_margin_ = v_margin; + } + const PangoFontInfo& font() const { + return font_; + } + const int h_margin() const { + return h_margin_; + } + const int v_margin() const { + return v_margin_; + } + + // Get the boxchars of all clusters rendered thus far (or since the last call + // to ClearBoxes()). + const vector& GetBoxes() const; + // Get the rendered page bounding boxes of all pages created thus far (or + // since last call to ClearBoxes()). + Boxa* GetPageBoxes() const; + + // Rotate the boxes on the most recent page by the given rotation. + void RotatePageBoxes(float rotation); + // Delete all boxes. + void ClearBoxes(); + void WriteAllBoxes(const string& filename) const; + // Removes space-delimited words from the string that are not renderable by + // the current font and returns the count of such words. + int StripUnrenderableWords(string* utf8_text) const; + + // Insert a Word Joiner symbol (U+2060) between adjacent characters, excluding + // spaces and combining types, in each word before rendering to ensure words + // are not broken across lines. The output boxchars will not contain the + // joiner. + static string InsertWordJoiners(const string& text); + + // Helper functions to convert fullwidth Latin and halfwidth Basic Latin. + static string ConvertBasicLatinToFullwidthLatin(const string& text); + static string ConvertFullwidthLatinToBasicLatin(const string& text); + + protected: + // Init and free local renderer objects. + void InitPangoCairo(); + void SetLayoutProperties(); + void FreePangoCairo(); + // Compute bounding boxes around grapheme clusters. + void ComputeClusterBoxes(); + void CorrectBoxPositionsToLayout(vector* boxchars); + bool GetClusterStrings(vector* cluster_text); + int FindFirstPageBreakOffset(const char* text, int text_length); + + PangoFontInfo font_; + // Page properties + int page_width_, page_height_, h_margin_, v_margin_; + // Text rendering properties + int pen_color_[3]; + double char_spacing_; + int leading_, resolution_; + bool vertical_text_; + bool gravity_hint_strong_; + bool render_fullwidth_latin_; + // Text filtering options + bool drop_uncovered_chars_; + bool strip_unrenderable_words_; + bool add_ligatures_; + bool output_word_boxes_; + // Pango and cairo specific objects + cairo_surface_t* surface_; + cairo_t* cr_; + PangoLayout* layout_; + // Internal state of current page number, updated on successive calls to + // RenderToImage() + int start_box_; + int page_; + // Boxes and associated text for all pages rendered with RenderToImage() since + // the last call to ClearBoxes(). + vector boxchars_; + int box_padding_; + // Bounding boxes for pages since the last call to ClearBoxes(). + Boxa* page_boxes_; + + // Objects cached for subsequent calls to RenderAllFontsToImage() + hash_map char_map_; // Time-saving char histogram. + int total_chars_; // Number in the string to be rendered. + int font_index_; // Index of next font to use in font list. + int last_offset_; // Offset returned from last successful rendering + + private: + StringRenderer(const StringRenderer&); + void operator=(const StringRenderer&); +}; +} // namespace tesseract + +#endif // THIRD_PARTY_TESSERACT_TRAINING_STRINGRENDERER_H_ diff --git a/TesseractOCR/include/tesseract/strngs.h b/TesseractOCR/include/tesseract/strngs.h old mode 100755 new mode 100644 index 04d7314d..2943b531 --- a/TesseractOCR/include/tesseract/strngs.h +++ b/TesseractOCR/include/tesseract/strngs.h @@ -55,6 +55,7 @@ class TESS_API STRING inT32 length() const; inT32 size() const { return length(); } const char *string() const; + const char *c_str() const; inline char* strdup() const { inT32 len = length() + 1; @@ -94,8 +95,10 @@ class TESS_API STRING // be ambiguous, and ints usually need a string before or between them // anyway. void add_str_int(const char* str, int number); + // Appends the given string and double (as a %.8g) to this. + void add_str_double(const char* str, double number); - // ensure capcaity but keep pointer encapsulated + // ensure capacity but keep pointer encapsulated inline void ensure(inT32 min_capacity) { ensure_cstr(min_capacity); } private: diff --git a/TesseractOCR/include/tesseract/strokewidth.h b/TesseractOCR/include/tesseract/strokewidth.h new file mode 100644 index 00000000..552e23a5 --- /dev/null +++ b/TesseractOCR/include/tesseract/strokewidth.h @@ -0,0 +1,305 @@ +/////////////////////////////////////////////////////////////////////// +// File: strokewidth.h +// Description: Subclass of BBGrid to find uniformity of strokewidth. +// Author: Ray Smith +// Created: Mon Mar 31 16:17:01 PST 2008 +// +// (C) Copyright 2008, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_STROKEWIDTH_H__ +#define TESSERACT_TEXTORD_STROKEWIDTH_H__ + +#include "blobbox.h" // BlobNeighourDir. +#include "blobgrid.h" // Base class. +#include "colpartitiongrid.h" +#include "textlineprojection.h" + +class DENORM; +class ScrollView; +class TO_BLOCK; + +namespace tesseract { + +class ColPartition_LIST; +class TabFind; +class TextlineProjection; + +// Misc enums to clarify bool arguments for direction-controlling args. +enum LeftOrRight { + LR_LEFT, + LR_RIGHT +}; + +/** + * The StrokeWidth class holds all the normal and large blobs. + * It is used to find good large blobs and move them to the normal blobs + * by virtue of having a reasonable strokewidth compatible neighbour. + */ +class StrokeWidth : public BlobGrid { + public: + StrokeWidth(int gridsize, const ICOORD& bleft, const ICOORD& tright); + virtual ~StrokeWidth(); + + // Sets the neighbours member of the medium-sized blobs in the block. + // Searches on 4 sides of each blob for similar-sized, similar-strokewidth + // blobs and sets pointers to the good neighbours. + void SetNeighboursOnMediumBlobs(TO_BLOCK* block); + + // Sets the neighbour/textline writing direction members of the medium + // and large blobs with optional repair of broken CJK characters first. + // Repair of broken CJK is needed here because broken CJK characters + // can fool the textline direction detection algorithm. + void FindTextlineDirectionAndFixBrokenCJK(bool cjk_merge, + TO_BLOCK* input_block); + + // To save computation, the process of generating partitions is broken + // into the following 4 steps: + // TestVerticalTextDirection + // CorrectForRotation (used only if a rotation is to be applied) + // FindLeaderPartitions + // GradeBlobsIntoPartitions. + // These functions are all required, in sequence, except for + // CorrectForRotation, which is not needed if no rotation is applied. + + // Types all the blobs as vertical or horizontal text or unknown and + // returns true if the majority are vertical. + // If the blobs are rotated, it is necessary to call CorrectForRotation + // after rotating everything, otherwise the work done here will be enough. + // If osd_blobs is not null, a list of blobs from the dominant textline + // direction are returned for use in orientation and script detection. + bool TestVerticalTextDirection(TO_BLOCK* block, + BLOBNBOX_CLIST* osd_blobs); + + // Corrects the data structures for the given rotation. + void CorrectForRotation(const FCOORD& rerotation, + ColPartitionGrid* part_grid); + + // Finds leader partitions and inserts them into the give grid. + void FindLeaderPartitions(TO_BLOCK* block, + ColPartitionGrid* part_grid); + + // Finds and marks noise those blobs that look like bits of vertical lines + // that would otherwise screw up layout analysis. + void RemoveLineResidue(ColPartition_LIST* big_part_list); + + // Types all the blobs as vertical text or horizontal text or unknown and + // puts them into initial ColPartitions in the supplied part_grid. + // rerotation determines how to get back to the image coordinates from the + // blob coordinates (since they may have been rotated for vertical text). + // block is the single block for the whole page or rectangle to be OCRed. + // nontext_pix (full-size), is a binary mask used to prevent merges across + // photo/text boundaries. It is not kept beyond this function. + // denorm provides a mapping back to the image from the current blob + // coordinate space. + // projection provides a measure of textline density over the image and + // provides functions to assist with diacritic detection. It should be a + // pointer to a new TextlineProjection, and will be setup here. + // part_grid is the output grid of textline partitions. + // Large blobs that cause overlap are put in separate partitions and added + // to the big_parts list. + void GradeBlobsIntoPartitions(const FCOORD& rerotation, + TO_BLOCK* block, + Pix* nontext_pix, + const DENORM* denorm, + bool cjk_script, + TextlineProjection* projection, + ColPartitionGrid* part_grid, + ColPartition_LIST* big_parts); + + // Handles a click event in a display window. + virtual void HandleClick(int x, int y); + + private: + // Computes the noise_density_ by summing the number of elements in a + // neighbourhood of each grid cell. + void ComputeNoiseDensity(TO_BLOCK* block, TabFind* line_grid); + + // Detects and marks leader dots/dashes. + // Leaders are horizontal chains of small or noise blobs that look + // monospace according to ColPartition::MarkAsLeaderIfMonospaced(). + // Detected leaders become the only occupants of the block->small_blobs list. + // Non-leader small blobs get moved to the blobs list. + // Non-leader noise blobs remain singletons in the noise list. + // All small and noise blobs in high density regions are marked BTFT_NONTEXT. + // block is the single block for the whole page or rectangle to be OCRed. + // leader_parts is the output. + void FindLeadersAndMarkNoise(TO_BLOCK* block, + ColPartition_LIST* leader_parts); + + /** Inserts the block blobs (normal and large) into this grid. + * Blobs remain owned by the block. */ + void InsertBlobs(TO_BLOCK* block); + + // Fix broken CJK characters, using the fake joined blobs mechanism. + // Blobs are really merged, ie the master takes all the outlines and the + // others are deleted. + // Returns true if sufficient blobs are merged that it may be worth running + // again, due to a better estimate of character size. + bool FixBrokenCJK(TO_BLOCK* block); + + // Collect blobs that overlap or are within max_dist of the input bbox. + // Return them in the list of blobs and expand the bbox to be the union + // of all the boxes. not_this is excluded from the search, as are blobs + // that cause the merged box to exceed max_size in either dimension. + void AccumulateOverlaps(const BLOBNBOX* not_this, bool debug, + int max_size, int max_dist, + TBOX* bbox, BLOBNBOX_CLIST* blobs); + + // For each blob in this grid, Finds the textline direction to be horizontal + // or vertical according to distance to neighbours and 1st and 2nd order + // neighbours. Non-text tends to end up without a definite direction. + // Result is setting of the neighbours and vert_possible/horz_possible + // flags in the BLOBNBOXes currently in this grid. + // This function is called more than once if page orientation is uncertain, + // so display_if_debugging is true on the final call to display the results. + void FindTextlineFlowDirection(bool display_if_debugging); + + // Sets the neighbours and good_stroke_neighbours members of the blob by + // searching close on all 4 sides. + // When finding leader dots/dashes, there is a slightly different rule for + // what makes a good neighbour. + // If activate_line_trap, then line-like objects are found and isolated. + void SetNeighbours(bool leaders, bool activate_line_trap, BLOBNBOX* blob); + + // Sets the good_stroke_neighbours member of the blob if it has a + // GoodNeighbour on the given side. + // Also sets the neighbour in the blob, whether or not a good one is found. + // Return value is the number of neighbours in the line trap size range. + // Leaders get extra special lenient treatment. + int FindGoodNeighbour(BlobNeighbourDir dir, bool leaders, BLOBNBOX* blob); + + // Makes the blob to be only horizontal or vertical where evidence + // is clear based on gaps of 2nd order neighbours. + void SetNeighbourFlows(BLOBNBOX* blob); + + // Nullify the neighbours in the wrong directions where the direction + // is clear-cut based on a distance margin. Good for isolating vertical + // text from neighbouring horizontal text. + void SimplifyObviousNeighbours(BLOBNBOX* blob); + + // Smoothes the vertical/horizontal type of the blob based on the + // 2nd-order neighbours. If reset_all is true, then all blobs are + // changed. Otherwise, only ambiguous blobs are processed. + void SmoothNeighbourTypes(BLOBNBOX* blob, bool desperate); + + // Checks the left or right side of the given leader partition and sets the + // (opposite) leader_on_right or leader_on_left flags for blobs + // that are next to the given side of the given leader partition. + void MarkLeaderNeighbours(const ColPartition* part, LeftOrRight side); + + // Partition creation. Accumulates vertical and horizontal text chains, + // puts the remaining blobs in as unknowns, and then merges/splits to + // minimize overlap and smoothes the types with neighbours and the color + // image if provided. rerotation is used to rotate the coordinate space + // back to the nontext_map_ image. + void FindInitialPartitions(const FCOORD& rerotation, + TO_BLOCK* block, + ColPartitionGrid* part_grid, + ColPartition_LIST* big_parts); + // Finds vertical chains of text-like blobs and puts them in ColPartitions. + void FindVerticalTextChains(ColPartitionGrid* part_grid); + // Finds horizontal chains of text-like blobs and puts them in ColPartitions. + void FindHorizontalTextChains(ColPartitionGrid* part_grid); + // Finds diacritics and saves their base character in the blob. + void TestDiacritics(ColPartitionGrid* part_grid, TO_BLOCK* block); + // Searches this grid for an appropriately close and sized neighbour of the + // given [small] blob. If such a blob is found, the diacritic base is saved + // in the blob and true is returned. + // The small_grid is a secondary grid that contains the small/noise objects + // that are not in this grid, but may be useful for determining a connection + // between blob and its potential base character. (See DiacriticXGapFilled.) + bool DiacriticBlob(BlobGrid* small_grid, BLOBNBOX* blob); + // Returns true if there is no gap between the base char and the diacritic + // bigger than a fraction of the height of the base char: + // Eg: line end.....' + // The quote is a long way from the end of the line, yet it needs to be a + // diacritic. To determine that the quote is not part of an image, or + // a different text block, we check for other marks in the gap between + // the base char and the diacritic. + // '<--Diacritic + // |---------| + // | |<-toobig-gap-> + // | Base | + // |---------| x<-----Dot occupying gap + // The grid is const really. + bool DiacriticXGapFilled(BlobGrid* grid, const TBOX& diacritic_box, + const TBOX& base_box); + // Merges diacritics with the ColPartition of the base character blob. + void MergeDiacritics(TO_BLOCK* block, ColPartitionGrid* part_grid); + // Any blobs on the large_blobs list of block that are still unowned by a + // ColPartition, are probably drop-cap or vertically touching so the blobs + // are removed to the big_parts list and treated separately. + void RemoveLargeUnusedBlobs(TO_BLOCK* block, + ColPartitionGrid* part_grid, + ColPartition_LIST* big_parts); + + // All remaining unused blobs are put in individual ColPartitions. + void PartitionRemainingBlobs(ColPartitionGrid* part_grid); + + // If combine, put all blobs in the cell_list into a single partition, + // otherwise put each one into its own partition. + void MakePartitionsFromCellList(bool combine, + ColPartitionGrid* part_grid, + BLOBNBOX_CLIST* cell_list); + + // Helper function to finish setting up a ColPartition and insert into + // part_grid. + void CompletePartition(ColPartition* part, ColPartitionGrid* part_grid); + + // Merge partitions where the merge appears harmless. + void EasyMerges(ColPartitionGrid* part_grid); + + // Compute a search box based on the orientation of the partition. + // Returns true if a suitable box can be calculated. + // Callback for EasyMerges. + bool OrientationSearchBox(ColPartition* part, TBOX* box); + + // Merge confirmation callback for EasyMerges. + bool ConfirmEasyMerge(const ColPartition* p1, const ColPartition* p2); + + // Returns true if there is no significant noise in between the boxes. + bool NoNoiseInBetween(const TBOX& box1, const TBOX& box2) const; + + // Displays the blobs colored according to the number of good neighbours + // and the vertical/horizontal flow. + ScrollView* DisplayGoodBlobs(const char* window_name, int x, int y); + + // Displays blobs colored according to whether or not they are diacritics. + ScrollView* DisplayDiacritics(const char* window_name, + int x, int y, TO_BLOCK* block); + + private: + // Image map of photo/noise areas on the page. Borrowed pointer (not owned.) + Pix* nontext_map_; + // Textline projection map. Borrowed pointer. + TextlineProjection* projection_; + // DENORM used by projection_ to get back to image coords. Borrowed pointer. + const DENORM* denorm_; + // Bounding box of the grid. + TBOX grid_box_; + // Rerotation to get back to the original image. + FCOORD rerotation_; + // Windows for debug display. + ScrollView* leaders_win_; + ScrollView* initial_widths_win_; + ScrollView* widths_win_; + ScrollView* chains_win_; + ScrollView* diacritics_win_; + ScrollView* textlines_win_; + ScrollView* smoothed_win_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_STROKEWIDTH_H__ diff --git a/TesseractOCR/include/tesseract/strtok_r.h b/TesseractOCR/include/tesseract/strtok_r.h new file mode 100644 index 00000000..bbdae34f --- /dev/null +++ b/TesseractOCR/include/tesseract/strtok_r.h @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////// +// File: strtok_r.h +// Description: Header file for strtok_r.cpp +// source: https://github.com/heimdal/heimdal/blob/master/lib/roken/ +// strtok_r.c +// Author: zdenop +// Created: Fri Aug 12 23:55:06 CET 2011 +// +// (C) Copyright 2011, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef VS2010_PORT_STRTOK_R_H_ +#define VS2010_PORT_STRTOK_R_H_ + +char *strtok_r(char *s1, const char *s2, char **lasts); + +#endif // VS2010_PORT_STRCASESTR_H_ diff --git a/TesseractOCR/include/tesseract/structures.h b/TesseractOCR/include/tesseract/structures.h new file mode 100644 index 00000000..c7e0cde9 --- /dev/null +++ b/TesseractOCR/include/tesseract/structures.h @@ -0,0 +1,64 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: structures.h (Formerly structures.h) + * Description: Allocate all the different types of structures. + * Author: Mark Seaman, OCR Technology + * Created: Wed May 30 10:12:12 1990 + * Modified: Tue May 21 11:07:47 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Experimental (Do Not Distribute) + * + * (c) Copyright 1990, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ +#ifndef STRUCTURES_H +#define STRUCTURES_H + +/*---------------------------------------------------------------------- + I n c l u d e s +----------------------------------------------------------------------*/ +#include "oldlist.h" +#include "freelist.h" +#include "danerror.h" + +/*---------------------------------------------------------------------- + M a c r o s +----------------------------------------------------------------------*/ +/********************************************************************** + * makestructure + * + * Allocate a chunk of memory for a particular data type. This macro + * defines an allocation, deallocation, and status printing function + * for each new data type. + **********************************************************************/ + +#define makestructure(newfunc, old, type) \ +type *newfunc() \ +{ \ + return new type; \ +} \ + \ + \ + \ +void old(type* deadelement) \ +{ \ + delete deadelement; \ +} \ + +/*---------------------------------------------------------------------- + F u n c t i o n s +----------------------------------------------------------------------*/ +extern LIST new_cell(); +extern void free_cell(LIST); +#endif diff --git a/TesseractOCR/include/tesseract/svmnode.h b/TesseractOCR/include/tesseract/svmnode.h new file mode 100644 index 00000000..5e5a8710 --- /dev/null +++ b/TesseractOCR/include/tesseract/svmnode.h @@ -0,0 +1,94 @@ +/////////////////////////////////////////////////////////////////////// +// File: svmnode.h +// description_: ScrollView Menu Node +// Author: Joern Wanke +// Created: Thu Nov 29 2007 +// +// (C) Copyright 2007, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// +// +// A SVMenuNode is an entity which contains the mapping from a menu entry on +// the server side to the corresponding associated commands on the client. +// It is designed to be a tree structure with a root node, which can then be +// used to generate the appropriate messages to the server to display the +// menu structure there. +// A SVMenuNode can both be used in the context_ of popup menus as well as +// menu bars. + +#ifndef TESSERACT_VIEWER_SVMNODE_H__ +#define TESSERACT_VIEWER_SVMNODE_H__ + +class ScrollView; + +class SVMenuNode { + public: + // Creating the (empty) root menu node. + SVMenuNode(); + + // Destructor for every node. + ~SVMenuNode(); + + // Create a new sub menu node with just a caption. This is used to create + // nodes which act as parent nodes to other nodes (e.g. submenus). + SVMenuNode* AddChild(const char* txt); + + // Create a "normal" menu node which is associated with a command event. + void AddChild(const char* txt, int command_event); + + // Create a flag menu node. + void AddChild(const char* txt, int command_event, int tv); + + // Create a menu node with an associated value (which might be changed + // through the gui). + void AddChild(const char* txt, int command_event, const char* val); + + // Create a menu node with an associated value and description_. + void AddChild(const char* txt, int command_event, + const char* val, const char* desc); + + // Build a menu structure for the server and send the necessary messages. + // Should be called on the root node. If menu_bar is true, a menu_bar menu + // is built (e.g. on top of the window), if it is false a popup menu is + // built which gets shown by right clicking on the window. + void BuildMenu(ScrollView *sv, bool menu_bar = true); + + private: + // Constructor holding the actual node data. + SVMenuNode(int command_event, const char* txt, int tv, + bool check_box_entry, const char* val, const char* desc); + + // Adds a new menu node to the current node. + void AddChild(SVMenuNode* svmn); + + // The parent node of this node. + SVMenuNode* parent_; + // The first child of this node. + SVMenuNode* child_; + // The next "sibling" of this node (e.g. same parent). + SVMenuNode* next_; + // Whether this menu node actually is a flag. + bool is_check_box_entry_; + + // The command event associated with a specific menu node. Should be unique. + int cmd_event_; + // The caption associated with a specific menu node. + char* text_; + // The value of the flag (if this menu node is a flag). + bool toggle_value_; + // The value of the menu node. (optional) + const char* value_; + // A description_ of the value. (optional) + const char* description_; +}; + +#endif // TESSERACT_VIEWER_SVMNODE_H__ diff --git a/TesseractOCR/include/tesseract/svutil.h b/TesseractOCR/include/tesseract/svutil.h new file mode 100644 index 00000000..0d600ede --- /dev/null +++ b/TesseractOCR/include/tesseract/svutil.h @@ -0,0 +1,144 @@ +/////////////////////////////////////////////////////////////////////// +// File: svutil.h +// Description: ScrollView Utilities +// Author: Joern Wanke +// Created: Thu Nov 29 2007 +// +// (C) Copyright 2007, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// +// +// SVUtil contains the SVSync, SVSemaphore, SVMutex and SVNetwork +// classes, which are used for thread/process creation & synchronization +// and network connection. + +#ifndef TESSERACT_VIEWER_SVUTIL_H__ +#define TESSERACT_VIEWER_SVUTIL_H__ + +#ifdef _WIN32 +#ifndef __GNUC__ +#include +#define snprintf _snprintf +#if (_MSC_VER <= 1400) +#define vsnprintf _vsnprintf +#endif +#pragma warning(disable:4786) +#else +#include "platform.h" +#include +#endif +#else +#include +#include +#endif + +#include + +#ifndef MAX +#define MAX(a, b) ((a > b) ? a : b) +#endif + +#ifndef MIN +#define MIN(a, b) ((a < b) ? a : b) +#endif + +/// The SVSync class provides functionality for Thread & Process Creation +class SVSync { + public: + /// Create new thread. + static void StartThread(void *(*func)(void*), void* arg); + /// Signals a thread to exit. + static void ExitThread(); + /// Starts a new process. + static void StartProcess(const char* executable, const char* args); +}; + +/// A semaphore class which encapsulates the main signalling +/// and wait abilities of semaphores for windows and unix. +class SVSemaphore { + public: + /// Sets up a semaphore. + SVSemaphore(); + /// Signal a semaphore. + void Signal(); + /// Wait on a semaphore. + void Wait(); + private: +#ifdef _WIN32 + HANDLE semaphore_; +#elif defined(__APPLE__) + sem_t *semaphore_; +#else + sem_t semaphore_; +#endif +}; + +/// A mutex which encapsulates the main locking and unlocking +/// abilites of mutexes for windows and unix. +class SVMutex { + public: + /// Sets up a new mutex. + SVMutex(); + /// Locks on a mutex. + void Lock(); + /// Unlocks on a mutex. + void Unlock(); + private: +#ifdef _WIN32 + HANDLE mutex_; +#else + pthread_mutex_t mutex_; +#endif +}; + +/// The SVNetwork class takes care of the remote connection for ScrollView +/// This means setting up and maintaining a remote connection, sending and +/// receiving messages and closing the connection. +/// It is designed to work on both Linux and Windows. +class SVNetwork { + public: + /// Set up a connection to hostname on port. + SVNetwork(const char* hostname, int port); + + /// Destructor. + ~SVNetwork(); + + /// Put a message in the messagebuffer to the server and try to send it. + void Send(const char* msg); + + /// Receive a message from the server. + /// This will always return one line of char* (denoted by \n). + char* Receive(); + + /// Close the connection to the server. + void Close(); + + /// Flush the buffer. + void Flush(); + + private: + /// The mutex for access to Send() and Flush(). + SVMutex* mutex_send_; + /// The actual stream_ to the server. + int stream_; + /// Stores the last received message-chunk from the server. + char* msg_buffer_in_; + + /// Stores the messages which are supposed to go out. + std::string msg_buffer_out_; + + bool has_content; // Win32 (strtok) + /// Where we are at in our msg_buffer_in_ + char* buffer_ptr_; // Unix (strtok_r) +}; + +#endif // TESSERACT_VIEWER_SVUTIL_H__ diff --git a/TesseractOCR/include/tesseract/tabfind.h b/TesseractOCR/include/tesseract/tabfind.h new file mode 100644 index 00000000..1bd372c2 --- /dev/null +++ b/TesseractOCR/include/tesseract/tabfind.h @@ -0,0 +1,376 @@ +/////////////////////////////////////////////////////////////////////// +// File: tabfind.h +// Description: Subclass of BBGrid to find tabstops. +// Author: Ray Smith +// Created: Fri Mar 21 15:03:01 PST 2008 +// +// (C) Copyright 2008, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_TABFIND_H__ +#define TESSERACT_TEXTORD_TABFIND_H__ + +#include "alignedblob.h" +#include "tesscallback.h" +#include "tabvector.h" +#include "linefind.h" + +extern BOOL_VAR_H(textord_tabfind_force_vertical_text, false, + "Force using vertical text page mode"); +extern BOOL_VAR_H(textord_tabfind_vertical_horizontal_mix, true, + "find horizontal lines such as headers in vertical page mode"); +extern double_VAR_H(textord_tabfind_vertical_text_ratio, 0.5, + "Fraction of textlines deemed vertical to use vertical page mode"); +extern double_VAR_H(textord_tabfind_aligned_gap_fraction, 0.75, + "Fraction of height used as a minimum gap for aligned blobs."); + +class BLOBNBOX; +class BLOBNBOX_LIST; +class TO_BLOCK; +class ScrollView; +struct Pix; + +namespace tesseract { + +typedef TessResultCallback1 WidthCallback; + +struct AlignedBlobParams; +class ColPartitionGrid; + +/** Pixel resolution of column width estimates. */ +const int kColumnWidthFactor = 20; + +/** + * The TabFind class contains code to find tab-stops and maintain the + * vectors_ list of tab vectors. + * Also provides an interface to find neighbouring blobs + * in the grid of BLOBNBOXes that is used by multiple subclasses. + * Searching is a complex operation because of the need to enforce + * rule/separator lines, and tabstop boundaries, (when available), so + * as the holder of the list of TabVectors this class provides the functions. + */ +class TabFind : public AlignedBlob { + public: + TabFind(int gridsize, const ICOORD& bleft, const ICOORD& tright, + TabVector_LIST* vlines, int vertical_x, int vertical_y, + int resolution); + virtual ~TabFind(); + + /** + * Insert a list of blobs into the given grid (not necessarily this). + * See InsertBlob for the other arguments. + * It would seem to make more sense to swap this and grid, but this way + * around allows grid to not be derived from TabFind, eg a ColPartitionGrid, + * while the grid that provides the tab stops(this) has to be derived from + * TabFind. + */ + void InsertBlobsToGrid(bool h_spread, bool v_spread, + BLOBNBOX_LIST* blobs, + BBGrid* grid); + + /** + * Insert a single blob into the given grid (not necessarily this). + * If h_spread, then all cells covered horizontally by the box are + * used, otherwise, just the bottom-left. Similarly for v_spread. + * A side effect is that the left and right rule edges of the blob are + * set according to the tab vectors in this (not grid). + */ + bool InsertBlob(bool h_spread, bool v_spread, BLOBNBOX* blob, + BBGrid* grid); + // Calls SetBlobRuleEdges for all the blobs in the given block. + void SetBlockRuleEdges(TO_BLOCK* block); + // Sets the left and right rule and crossing_rules for the blobs in the given + // list by finding the next outermost tabvectors for each blob. + void SetBlobRuleEdges(BLOBNBOX_LIST* blobs); + + // Returns the gutter width of the given TabVector between the given y limits. + // Also returns x-shift to be added to the vector to clear any intersecting + // blobs. The shift is deducted from the returned gutter. + // If ignore_unmergeables is true, then blobs of UnMergeableType are + // ignored as if they don't exist. (Used for text on image.) + // max_gutter_width is used as the maximum width worth searching for in case + // there is nothing near the TabVector. + int GutterWidth(int bottom_y, int top_y, const TabVector& v, + bool ignore_unmergeables, int max_gutter_width, + int* required_shift); + /** + * Find the gutter width and distance to inner neighbour for the given blob. + */ + void GutterWidthAndNeighbourGap(int tab_x, int mean_height, + int max_gutter, bool left, + BLOBNBOX* bbox, int* gutter_width, + int* neighbour_gap); + + /** + * Return the x-coord that corresponds to the right edge for the given + * box. If there is a rule line to the right that vertically overlaps it, + * then return the x-coord of the rule line, otherwise return the right + * edge of the page. For details see RightTabForBox below. + */ + int RightEdgeForBox(const TBOX& box, bool crossing, bool extended); + /** + * As RightEdgeForBox, but finds the left Edge instead. + */ + int LeftEdgeForBox(const TBOX& box, bool crossing, bool extended); + + /** + * Return the TabVector that corresponds to the right edge for the given + * box. If there is a TabVector to the right that vertically overlaps it, + * then return it, otherwise return NULL. Note that Right and Left refer + * to the position of the TabVector, not its type, ie RightTabForBox + * returns the nearest TabVector to the right of the box, regardless of + * its type. + * If a TabVector crosses right through the box (as opposed to grazing one + * edge or missing entirely), then crossing false will ignore such a line. + * Crossing true will return the line for BOTH left and right edges. + * If extended is true, then TabVectors are considered to extend to their + * extended_start/end_y, otherwise, just the startpt_ and endpt_. + * These functions make use of an internal iterator to the vectors_ list + * for speed when used repeatedly on neighbouring boxes. The caveat is + * that the iterator must be updated whenever the list is modified. + */ + TabVector* RightTabForBox(const TBOX& box, bool crossing, bool extended); + /** + * As RightTabForBox, but finds the left TabVector instead. + */ + TabVector* LeftTabForBox(const TBOX& box, bool crossing, bool extended); + + /** + * Return true if the given width is close to one of the common + * widths in column_widths_. + */ + bool CommonWidth(int width); + /** + * Return true if the sizes are more than a + * factor of 2 different. + */ + static bool DifferentSizes(int size1, int size2); + /** + * Return true if the sizes are more than a + * factor of 5 different. + */ + static bool VeryDifferentSizes(int size1, int size2); + + /** + * Return a callback for testing CommonWidth. + */ + WidthCallback* WidthCB() { + return width_cb_; + } + + /** + * Return the coords at which to draw the image backdrop. + */ + const ICOORD& image_origin() const { + return image_origin_; + } + + protected: + /** + // Accessors + */ + TabVector_LIST* vectors() { + return &vectors_; + } + TabVector_LIST* dead_vectors() { + return &dead_vectors_; + } + + /** + * Top-level function to find TabVectors in an input page block. + * Returns false if the detected skew angle is impossible. + * Applies the detected skew angle to deskew the tabs, blobs and part_grid. + */ + bool FindTabVectors(TabVector_LIST* hlines, + BLOBNBOX_LIST* image_blobs, TO_BLOCK* block, + int min_gutter_width, + ColPartitionGrid* part_grid, + FCOORD* deskew, FCOORD* reskew); + + // Top-level function to not find TabVectors in an input page block, + // but setup for single column mode. + void DontFindTabVectors(BLOBNBOX_LIST* image_blobs, + TO_BLOCK* block, FCOORD* deskew, FCOORD* reskew); + + // Cleans up the lists of blobs in the block ready for use by TabFind. + // Large blobs that look like text are moved to the main blobs list. + // Main blobs that are superseded by the image blobs are deleted. + void TidyBlobs(TO_BLOCK* block); + + // Helper function to setup search limits for *TabForBox. + void SetupTabSearch(int x, int y, int* min_key, int* max_key); + + /** + * Display the tab vectors found in this grid. + */ + ScrollView* DisplayTabVectors(ScrollView* tab_win); + + // First part of FindTabVectors, which may be used twice if the text + // is mostly of vertical alignment. If find_vertical_text flag is + // true, this finds vertical textlines in possibly rotated blob space. + // In other words, when the page has mostly vertical lines and is rotated, + // setting this to true will find horizontal lines on the page. + ScrollView* FindInitialTabVectors(BLOBNBOX_LIST* image_blobs, + int min_gutter_width, TO_BLOCK* block); + + // Apply the given rotation to the given list of blobs. + static void RotateBlobList(const FCOORD& rotation, BLOBNBOX_LIST* blobs); + + // Flip the vertical and horizontal lines and rotate the grid ready + // for working on the rotated image. + // The min_gutter_width will be adjusted to the median gutter width between + // vertical tabs to set a better threshold for tabboxes in the 2nd pass. + void ResetForVerticalText(const FCOORD& rotate, const FCOORD& rerotate, + TabVector_LIST* horizontal_lines, + int* min_gutter_width); + + // Clear the grid and get rid of the tab vectors, but not separators, + // ready to start again. + void Reset(); + + // Reflect the separator tab vectors and the grids in the y-axis. + // Can only be called after Reset! + void ReflectInYAxis(); + + private: + // For each box in the grid, decide whether it is a candidate tab-stop, + // and if so add it to the left and right tab boxes. + ScrollView* FindTabBoxes(int min_gutter_width); + + // Return true if this box looks like a candidate tab stop, and set + // the appropriate tab type(s) to TT_UNCONFIRMED. + bool TestBoxForTabs(BLOBNBOX* bbox, int min_gutter_width); + + // Returns true if there is nothing in the rectangle of width min_gutter to + // the left of bbox. + bool ConfirmRaggedLeft(BLOBNBOX* bbox, int min_gutter); + // Returns true if there is nothing in the rectangle of width min_gutter to + // the right of bbox. + bool ConfirmRaggedRight(BLOBNBOX* bbox, int min_gutter); + // Returns true if there is nothing in the given search_box that vertically + // overlaps target_box other than target_box itself. + bool NothingYOverlapsInBox(const TBOX& search_box, const TBOX& target_box); + + // Fills the list of TabVector with the tabstops found in the grid, + // and estimates the logical vertical direction. + void FindAllTabVectors(int min_gutter_width); + // Helper for FindAllTabVectors finds the vectors of a particular type. + int FindTabVectors(int search_size_multiple, + TabAlignment alignment, + int min_gutter_width, + TabVector_LIST* vectors, + int* vertical_x, int* vertical_y); + // Finds a vector corresponding to a tabstop running through the + // given box of the given alignment type. + // search_size_multiple is a multiple of height used to control + // the size of the search. + // vertical_x and y are updated with an estimate of the real + // vertical direction. (skew finding.) + // Returns NULL if no decent tabstop can be found. + TabVector* FindTabVector(int search_size_multiple, int min_gutter_width, + TabAlignment alignment, + BLOBNBOX* bbox, + int* vertical_x, int* vertical_y); + + // Set the vertical_skew_ member from the given vector and refit + // all vectors parallel to the skew vector. + void SetVerticalSkewAndParellelize(int vertical_x, int vertical_y); + + // Sort all the current vectors using the vertical_skew_ vector. + void SortVectors(); + + // Evaluate all the current tab vectors. + void EvaluateTabs(); + + // Trace textlines from one side to the other of each tab vector, saving + // the most frequent column widths found in a list so that a given width + // can be tested for being a common width with a simple callback function. + void ComputeColumnWidths(ScrollView* tab_win, + ColPartitionGrid* part_grid); + + // Find column width and pair-up tab vectors with existing ColPartitions. + void ApplyPartitionsToColumnWidths(ColPartitionGrid* part_grid, + STATS* col_widths); + + // Helper makes the list of common column widths in column_widths_ from the + // input col_widths. Destroys the content of col_widths by repeatedly + // finding the mode and erasing the peak. + void MakeColumnWidths(int col_widths_size, STATS* col_widths); + + // Mark blobs as being in a vertical text line where that is the case. + void MarkVerticalText(); + + // Returns the median gutter width between pairs of matching tab vectors + // assuming they are sorted left-to-right. If there are too few data + // points (< kMinLinesInColumn), then 0 is returned. + int FindMedianGutterWidth(TabVector_LIST* tab_vectors); + + // Find the next adjacent (to left or right) blob on this text line, + // with the constraint that it must vertically significantly overlap + // the [top_y, bottom_y] range. + // If ignore_images is true, then blobs with aligned_text() < 0 are treated + // as if they do not exist. + BLOBNBOX* AdjacentBlob(const BLOBNBOX* bbox, + bool look_left, bool ignore_images, + double min_overlap_fraction, + int gap_limit, int top_y, int bottom_y); + + // Add a bi-directional partner relationship between the left + // and the right. If one (or both) of the vectors is a separator, + // extend a nearby extendable vector or create a new one of the + // correct type, using the given left or right blob as a guide. + void AddPartnerVector(BLOBNBOX* left_blob, BLOBNBOX* right_blob, + TabVector* left, TabVector* right); + + /** + * Remove separators and unused tabs from the main vectors_ list + * to the dead_vectors_ list. + */ + void CleanupTabs(); + + /** + * Deskew the tab vectors and blobs, computing the rotation and resetting + * the storked vertical_skew_. The deskew inverse is returned in reskew. + * Returns false if the detected skew angle is impossible. + */ + bool Deskew(TabVector_LIST* hlines, BLOBNBOX_LIST* image_blobs, + TO_BLOCK* block, FCOORD* deskew, FCOORD* reskew); + + // Compute the rotation required to deskew, and its inverse rotation. + void ComputeDeskewVectors(FCOORD* deskew, FCOORD* reskew); + + /** + * Compute and apply constraints to the end positions of TabVectors so + * that where possible partners end at the same y coordinate. + */ + void ApplyTabConstraints(); + + protected: + ICOORD vertical_skew_; //< Estimate of true vertical in this image. + int resolution_; //< Of source image in pixels per inch. + private: + ICOORD image_origin_; //< Top-left of image in deskewed coords + TabVector_LIST vectors_; //< List of rule line and tabstops. + TabVector_IT v_it_; //< Iterator for searching vectors_. + TabVector_LIST dead_vectors_; //< Separators and unpartnered tab vectors. + ICOORDELT_LIST column_widths_; //< List of commonly occurring widths. + /** Callback to test an int for being a common width. */ + WidthCallback* width_cb_; + // Sets of bounding boxes that are candidate tab stops. + GenericVector left_tab_boxes_; + GenericVector right_tab_boxes_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_TABFIND_H__ diff --git a/TesseractOCR/include/tesseract/tablefind.h b/TesseractOCR/include/tesseract/tablefind.h new file mode 100644 index 00000000..3612e48d --- /dev/null +++ b/TesseractOCR/include/tesseract/tablefind.h @@ -0,0 +1,435 @@ +/////////////////////////////////////////////////////////////////////// +// File: tablefind.h +// Description: Helper classes to find tables from ColPartitions. +// Author: Faisal Shafait (faisal.shafait@dfki.de) +// Created: Tue Jan 06 11:13:01 PST 2009 +// +// (C) Copyright 2009, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_TABLEFIND_H__ +#define TESSERACT_TEXTORD_TABLEFIND_H__ + +#include "colpartitiongrid.h" +#include "elst.h" +#include "rect.h" + +namespace tesseract { + +// Possible types for a column segment. +enum ColSegType { + COL_UNKNOWN, + COL_TEXT, + COL_TABLE, + COL_MIXED, + COL_COUNT +}; + +class ColPartitionSet; + +// ColSegment holds rectangular blocks that represent segmentation of a page +// into regions containing single column text/table. +class ColSegment; +ELISTIZEH(ColSegment) +CLISTIZEH(ColSegment) + +class ColSegment : public ELIST_LINK { + public: + ColSegment(); + ~ColSegment(); + + // Simple accessors and mutators + const TBOX& bounding_box() const { + return bounding_box_; + } + + void set_top(int y) { + bounding_box_.set_top(y); + } + + void set_bottom(int y) { + bounding_box_.set_bottom(y); + } + + void set_left(int x) { + bounding_box_.set_left(x); + } + + void set_right(int x) { + bounding_box_.set_right(x); + } + + void set_bounding_box(const TBOX& other) { + bounding_box_ = other; + } + + int get_num_table_cells() const { + return num_table_cells_; + } + + // set the number of table colpartitions covered by the bounding_box_ + void set_num_table_cells(int n) { + num_table_cells_ = n; + } + + int get_num_text_cells() const { + return num_text_cells_; + } + + // set the number of text colpartitions covered by the bounding_box_ + void set_num_text_cells(int n) { + num_text_cells_ = n; + } + + ColSegType type() const { + return type_; + } + + // set the type of the block based on the ratio of table to text + // colpartitions covered by it. + void set_type(); + + // Provides a color for BBGrid to draw the rectangle. + ScrollView::Color BoxColor() const; + + // Insert a rectangle into bounding_box_ + void InsertBox(const TBOX& other); + + private: + TBOX bounding_box_; // bounding box + int num_table_cells_; + int num_text_cells_; + ColSegType type_; +}; + +// Typedef BBGrid of ColSegments +typedef BBGrid ColSegmentGrid; +typedef GridSearch ColSegmentGridSearch; + +// TableFinder is a utility class to find a set of tables given a set of +// ColPartitions and Columns. The TableFinder will mark candidate ColPartitions +// based on research in "Table Detection in Heterogeneous Documents". +// Usage flow is as follows: +// TableFinder finder; +// finder.InsertCleanPartitions(/* grid info */) +// finder.LocateTables(/* ColPartitions and Columns */); +// finder.Update TODO(nbeato) +class TableFinder { + public: + // Constructor is simple initializations + TableFinder(); + ~TableFinder(); + + // Set the resolution of the connected components in ppi. + void set_resolution(int resolution) { + resolution_ = resolution; + } + // Change the reading order. Initially it is left to right. + void set_left_to_right_language(bool order); + + // Initialize + void Init(int grid_size, const ICOORD& bottom_left, const ICOORD& top_right); + + // Copy cleaned partitions from ColumnFinder's part_grid_ to this + // clean_part_grid_ and insert dot-like noise into period_grid_. + // It resizes the grids in this object to the dimensions of grid. + void InsertCleanPartitions(ColPartitionGrid* grid, TO_BLOCK* block); + + // High level function to perform table detection + // Finds tables and updates the grid object with new partitions for the + // tables. The columns and width callbacks are used to merge tables. + // The reskew argument is only used to write the tables to the out.png + // if that feature is enabled. + void LocateTables(ColPartitionGrid* grid, + ColPartitionSet** columns, + WidthCallback* width_cb, + const FCOORD& reskew); + + protected: + // Access for the grid dimensions. + // The results will not be correct until InsertCleanPartitions + // has been called. The values are taken from the grid passed as an argument + // to that function. + int gridsize() const; + int gridwidth() const; + int gridheight() const; + const ICOORD& bleft() const; + const ICOORD& tright() const; + + // Makes a window for debugging, see BBGrid + ScrollView* MakeWindow(int x, int y, const char* window_name); + + //////// Functions to insert objects from the grid into the table finder. + //////// In all cases, ownership is transferred to the table finder. + // Inserts text into the table finder. + void InsertTextPartition(ColPartition* part); + void InsertFragmentedTextPartition(ColPartition* part); + void InsertLeaderPartition(ColPartition* part); + void InsertRulingPartition(ColPartition* part); + void InsertImagePartition(ColPartition* part); + void SplitAndInsertFragmentedTextPartition(ColPartition* part); + bool AllowTextPartition(const ColPartition& part) const; + bool AllowBlob(const BLOBNBOX& blob) const; + + //////// Functions that manipulate ColPartitions in the part_grid_ ///// + //////// to find tables. + //////// + + // Utility function to move segments to col_seg_grid + // Note: Move includes ownership, + // so segments will be be owned by col_seg_grid + void MoveColSegmentsToGrid(ColSegment_LIST* segments, + ColSegmentGrid* col_seg_grid); + + //////// Set up code to run during table detection to correctly + //////// initialize variables on column partitions that are used later. + //////// + + // Initialize the grid and partitions + void InitializePartitions(ColPartitionSet** all_columns); + + // Set left, right and top, bottom spacings of each colpartition. + // Left/right spacings are w.r.t the column boundaries + // Top/bottom spacings are w.r.t. previous and next colpartitions + static void SetPartitionSpacings(ColPartitionGrid* grid, + ColPartitionSet** all_columns); + + // Set spacing and closest neighbors above and below a given colpartition. + void SetVerticalSpacing(ColPartition* part); + + // Set global spacing estimates. This function is dependent on the + // partition spacings. So make sure SetPartitionSpacings is called + // on the same grid before this. + void SetGlobalSpacings(ColPartitionGrid* grid); + // Access to the global median xheight. The xheight is the height + // of a lowercase 'x' character on the page. This can be viewed as the + // average height of a lowercase letter in a textline. As a result + // it is used to make assumptions about spacing between words and + // table cells. + void set_global_median_xheight(int xheight); + // Access to the global median blob width. The width is useful + // when deciding if a partition is noise. + void set_global_median_blob_width(int width); + // Access to the global median ledding. The ledding is the distance between + // two adjacent text lines. This value can be used to get a rough estimate + // for the amount of space between two lines of text. As a result, it + // is used to calculate appropriate spacing between adjacent rows of text. + void set_global_median_ledding(int ledding); + + // Updates the nearest neighbors for each ColPartition in clean_part_grid_. + // The neighbors are most likely SingletonPartner calls after the neighbors + // are assigned. This is hear until it is decided to remove the + // nearest_neighbor code in ColPartition + void FindNeighbors(); + + //////// Functions to mark candidate column partitions as tables. + //////// Tables are marked as described in + //////// Table Detection in Heterogeneous Documents (2010, Shafait & Smith) + //////// + + // High level function to mark partitions as table rows/cells. + // When this function is done, the column partitions in clean_part_grid_ + // should mostly be marked as tables. + void MarkTablePartitions(); + // Marks partitions given a local view of a single partition + void MarkPartitionsUsingLocalInformation(); + /////// Heuristics for local marking + // Check if the partition has at least one large gap between words or no + // significant gap at all + // TODO(nbeato): Make const, prevented because blobnbox array access + bool HasWideOrNoInterWordGap(ColPartition* part) const; + // Checks if a partition is adjacent to leaders on the page + bool HasLeaderAdjacent(const ColPartition& part); + // Filter individual text partitions marked as table partitions + // consisting of paragraph endings, small section headings, and + // headers and footers. + void FilterFalseAlarms(); + void FilterParagraphEndings(); + void FilterHeaderAndFooter(); + // Mark all ColPartitions as table cells that have a table cell above + // and below them + void SmoothTablePartitionRuns(); + + //////// Functions to create bounding boxes (ColSegment) objects for + //////// the columns on the page. The columns are not necessarily + //////// vertical lines, meaning if tab stops strongly suggests that + //////// a column changes horizontal position, as in the case below, + //////// The ColSegment objects will respect that after processing. + //////// + //////// _____________ + //////// Ex. | | | + //////// |_____|______| 5 boxes: 2 on this line + //////// | | | | 3 on this line + //////// |___|____|___| + //////// + + // Get Column segments from best_columns_ + void GetColumnBlocks(ColPartitionSet** columns, + ColSegment_LIST *col_segments); + + // Group Column segments into consecutive single column regions. + void GroupColumnBlocks(ColSegment_LIST *current_segments, + ColSegment_LIST *col_segments); + + // Check if two boxes are consecutive within the same column + bool ConsecutiveBoxes(const TBOX &b1, const TBOX &b2); + + // Set the ratio of candidate table partitions in each column + void SetColumnsType(ColSegment_LIST* col_segments); + + // Merge Column Blocks that were split due to the presence of a table + void GridMergeColumnBlocks(); + + //////// Functions to turn marked ColPartitions into candidate tables + //////// using a modified T-Recs++ algorithm described in + //////// Applying The T-Recs Table Recognition System + //////// To The Business Letter Domain (2001, Kieninger & Dengel) + //////// + + // Merge partititons cells into table columns + // Differs from paper by just looking at marked table partitions + // instead of similarity metric. + // Modified section 4.1 of paper. + void GetTableColumns(ColSegment_LIST *table_columns); + + // Finds regions within a column that potentially contain a table. + // Ie, the table columns from GetTableColumns are turned into boxes + // that span the entire page column (using ColumnBlocks found in + // earlier functions) in the x direction and the min/max extent of + // overlapping table columns in the y direction. + // Section 4.2 of paper. + void GetTableRegions(ColSegment_LIST *table_columns, + ColSegment_LIST *table_regions); + + + //////// Functions to "patch up" found tables + //////// + + // Merge table regions corresponding to tables spanning multiple columns + void GridMergeTableRegions(); + bool BelongToOneTable(const TBOX &box1, const TBOX &box2); + + // Adjust table boundaries by building a tight bounding box around all + // ColPartitions contained in it. + void AdjustTableBoundaries(); + + // Grows a table to include partitions that are partially covered + // by the table. This includes lines and text. It does not include + // noise or images. + // On entry, result_box is the minimum size of the result. The results of the + // function will union the actual result with result_box. + void GrowTableBox(const TBOX& table_box, TBOX* result_box); + // Grow a table by increasing the size of the box to include + // partitions with significant overlap with the table. + void GrowTableToIncludePartials(const TBOX& table_box, + const TBOX& search_range, + TBOX* result_box); + // Grow a table by expanding to the extents of significantly + // overlapping lines. + void GrowTableToIncludeLines(const TBOX& table_box, const TBOX& search_range, + TBOX* result_box); + // Checks whether the horizontal line belong to the table by looking at the + // side spacing of extra ColParitions that will be included in the table + // due to expansion + bool HLineBelongsToTable(const ColPartition& part, const TBOX& table_box); + + // Look for isolated column headers above the given table box and + // include them in the table + void IncludeLeftOutColumnHeaders(TBOX* table_box); + + // Remove false alarms consiting of a single column + void DeleteSingleColumnTables(); + + // Return true if at least one gap larger than the global x-height + // exists in the horizontal projection + bool GapInXProjection(int* xprojection, int length); + + //////// Recognize the tables. + //////// + // This function will run the table recognizer and try to find better + // bounding boxes. The structures of the tables never leave this function + // right now. It just tries to prune and merge tables based on info it + // has available. + void RecognizeTables(); + + //////// Debugging functions. Render different structures to GUI + //////// for visual debugging / intuition. + //////// + + // Displays Colpartitions marked as table row. Overlays them on top of + // part_grid_. + void DisplayColSegments(ScrollView* win, ColSegment_LIST *cols, + ScrollView::Color color); + + // Displays the colpartitions using a new coloring on an existing window. + // Note: This method is only for debug purpose during development and + // would not be part of checked in code + void DisplayColPartitions(ScrollView* win, ColPartitionGrid* grid, + ScrollView::Color text_color, + ScrollView::Color table_color); + void DisplayColPartitions(ScrollView* win, ColPartitionGrid* grid, + ScrollView::Color default_color); + void DisplayColPartitionConnections(ScrollView* win, + ColPartitionGrid* grid, + ScrollView::Color default_color); + void DisplayColSegmentGrid(ScrollView* win, ColSegmentGrid* grid, + ScrollView::Color color); + + // Write ColParitions and Tables to a PIX image + // Note: This method is only for debug purpose during development and + // would not be part of checked in code + void WriteToPix(const FCOORD& reskew); + + // Merge all colpartitions in table regions to make them a single + // colpartition and revert types of isolated table cells not + // assigned to any table to their original types. + void MakeTableBlocks(ColPartitionGrid* grid, + ColPartitionSet** columns, + WidthCallback* width_cb); + + ///////////////////////////////////////////////// + // Useful objects used during table find process. + ///////////////////////////////////////////////// + // Resolution of the connected components in ppi. + int resolution_; + // Estimate of median x-height over the page + int global_median_xheight_; + // Estimate of the median blob width on the page + int global_median_blob_width_; + // Estimate of median leading on the page + int global_median_ledding_; + // Grid to hold cleaned colpartitions after removing all + // colpartitions that consist of only noise blobs, and removing + // noise blobs from remaining colpartitions. + ColPartitionGrid clean_part_grid_; + // Grid contains the leaders and ruling lines. + ColPartitionGrid leader_and_ruling_grid_; + // Grid contains the broken down column partitions. It can be thought + // of as a "word" grid. However, it usually doesn't break apart text lines. + // It does break apart table data (most of the time). + ColPartitionGrid fragmented_text_grid_; + // Grid of page column blocks + ColSegmentGrid col_seg_grid_; + // Grid of detected tables + ColSegmentGrid table_grid_; + // The reading order of text. Defaults to true, for languages such as English. + bool left_to_right_language_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_TABLEFIND_H__ diff --git a/TesseractOCR/include/tesseract/tablerecog.h b/TesseractOCR/include/tesseract/tablerecog.h new file mode 100644 index 00000000..d83e96af --- /dev/null +++ b/TesseractOCR/include/tesseract/tablerecog.h @@ -0,0 +1,378 @@ +/////////////////////////////////////////////////////////////////////// +// File: tablerecog.h +// Description: Functions to detect structure of tables. +// Author: Nicholas Beato +// Created: Aug 17, 2010 +// +// (C) Copyright 2010, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TABLERECOG_H_ +#define TABLERECOG_H_ + +#include "colpartitiongrid.h" +#include "genericvector.h" + +namespace tesseract { + +// There are 2 classes in this file. They have 2 different purposes. +// - StructuredTable contains the methods to find the structure given +// a specific bounding box and grow that structure. +// - TableRecognizer contains the methods to adjust the possible positions +// of a table without worrying about structure. +// +// To use these classes, the assumption is that the TableFinder will +// have a guess of the location of a table (or possibly over/undersegmented +// tables). The TableRecognizer is responsible for finding the table boundaries +// at a high level. The StructuredTable class is responsible for determining +// the structure of the table and trying to maximize its bounds while retaining +// the structure. +// (The latter part is not implemented yet, but that was the goal). +// +// While on the boundary discussion, keep in mind that this is a first pass. +// There should eventually be some things like internal structure checks, +// and, more importantly, surrounding text flow checks. +// + +// Usage: +// The StructuredTable class contains methods to query a potential table. +// It has functions to find structure, count rows, find ColPartitions that +// intersect gridlines, etc. It is not meant to blindly find a table. It +// is meant to start with a known table location and enhance it. +// Usage: +// ColPartitionGrid text_grid, line_grid; // init +// TBOX table_box; // known location of table location +// +// StructuredTable table; +// table.Init(); // construction code +// table.set_text_grid(/* text */); // These 2 grids can be the same! +// table.set_line_grid(/* lines */); +// table.set_min_text_height(10); // Filter vertical and tall text. +// // IMPORTANT! The table needs to be told where it is! +// table.set_bounding_box(table_box); // Set initial table location. +// if (table.FindWhitespacedStructure()) { +// // process table +// table.column_count(); // number of columns +// table.row_count(); // number of rows +// table.cells_count(); // number of cells +// table.bounding_box(); // updated bounding box +// // etc. +// } +// +class StructuredTable { + public: + StructuredTable(); + ~StructuredTable(); + + // Initialization code. Must be called after the constructor. + void Init(); + + // Sets the grids used by the table. These can be changed between + // calls to Recognize. They are treated as read-only data. + void set_text_grid(ColPartitionGrid* text); + void set_line_grid(ColPartitionGrid* lines); + // Filters text partitions that are ridiculously tall to prevent + // merging rows. + void set_max_text_height(int height); + + // Basic accessors. Some are treated as attributes despite having indirect + // representation. + bool is_lined() const; + int row_count() const; + int column_count() const; + int cell_count() const; + void set_bounding_box(const TBOX& box); + const TBOX& bounding_box() const; + int median_cell_height(); + int median_cell_width(); + int row_height(int row) const; + int column_width(int column) const; + int space_above() const; + int space_below() const; + + // Given enough horizontal and vertical lines in a region, create this table + // based on the structure given by the lines. Return true if it worked out. + // Code assumes the lines exist. It is the caller's responsibility to check + // for lines and find an appropriate bounding box. + bool FindLinedStructure(); + + // The main subroutine for finding generic table structure. The function + // finds the grid structure in the given box. Returns true if a good grid + // exists, implying that "this" table is valid. + bool FindWhitespacedStructure(); + + //////// + //////// Functions to query table info. + //////// + + // Returns true if inserting part into the table does not cause any + // cell merges. + bool DoesPartitionFit(const ColPartition& part) const; + // Checks if a sub-table has multiple data cells filled. + int CountFilledCells(); + int CountFilledCellsInRow(int row); + int CountFilledCellsInColumn(int column); + int CountFilledCells(int row_start, int row_end, + int column_start, int column_end); + + // Makes sure that at least one cell in a row has substantial area filled. + // This can filter out large whitespace caused by growing tables too far + // and page numbers. + // (currently bugged for some reason). + bool VerifyRowFilled(int row); + // Finds the filled area in a cell. + double CalculateCellFilledPercentage(int row, int column); + + // Debug display, draws the table in the given color. If the table is not + // valid, the table and "best" grid lines are still drawn in the given color. + void Display(ScrollView* window, ScrollView::Color color); + + protected: + // Clear the structure information. + void ClearStructure(); + + //////// + //////// Lined tables + //////// + + // Verifies the lines do not intersect partitions. This happens when + // the lines are in column boundaries and extend the full page. As a result, + // the grid lines go through column text. The condition is detectable. + bool VerifyLinedTableCells(); + + //////// + //////// Tables with whitespace + //////// + + // This is the function to change if you want to filter resulting tables + // better. Right now it just checks for a minimum cell count and such. + // You could add things like maximum number of ColPartitions per cell or + // similar. + bool VerifyWhitespacedTable(); + // Find the columns of a table using whitespace. + void FindWhitespacedColumns(); + // Find the rows of a table using whitespace. + void FindWhitespacedRows(); + + //////// + //////// Functions to provide information about the table. + //////// + + // Calculates the whitespace around the table using the table boundary and + // the supplied grids (set_text_grid and set_line_grid). + void CalculateMargins(); + // Update the table margins with the supplied grid. This is + // only called by calculate margins to use multiple grid sources. + void UpdateMargins(ColPartitionGrid* grid); + int FindVerticalMargin(ColPartitionGrid* grid, int start_x, + bool decrease) const; + int FindHorizontalMargin(ColPartitionGrid* grid, int start_y, + bool decrease) const; + // Calculates stats on the table, namely the median cell height and width. + void CalculateStats(); + + //////// + //////// Functions to try to "fix" some table errors. + //////// + + // Given a whitespaced table, this looks for bordering lines that might + // be page layout boxes around the table. It is necessary to get the margins + // correct on the table. If the lines are not joined, the margins will be + // the distance to the line, which is not right. + void AbsorbNearbyLines(); + + // Nice utility function for finding partition gaps. You feed it a sorted + // list of all of the mins/maxes of the partitions in the table, and it gives + // you the gaps (middle). This works for both vertical and horizontal + // gaps. + // + // If you want to allow slight overlap in the division and the partitions, + // just scale down the partitions before inserting them in the list. + // Likewise, you can force at least some space between partitions. + // This trick is how the horizontal partitions are done (since the page + // skew could make it hard to find splits in the text). + // + // As a result, "0 distance" between closest partitions causes a gap. + // This is not a programmatic assumption. It is intentional and simplifies + // things. + // + // "max_merged" indicates both the minimum number of stacked partitions + // to cause a cell (add 1 to it), and the maximum number of partitions that + // a grid line can intersect. For example, if max_merged is 0, then lines + // are inserted wherever space exists between partitions. If it is 2, + // lines may intersect 2 partitions at most, but you also need at least + // 2 partitions to generate a line. + static void FindCellSplitLocations(const GenericVector& min_list, + const GenericVector& max_list, + int max_merged, + GenericVector* locations); + + //////// + //////// Utility function for table queries + //////// + + // Counts the number of ColPartitions that intersect vertical cell + // division at this x value. Used by VerifyLinedTable. + int CountVerticalIntersections(int x); + int CountHorizontalIntersections(int y); + + // Counts how many text partitions are in this box. + int CountPartitions(const TBOX& box); + + //////// + //////// Data members. + //////// + + // Input data, used as read only data to make decisions. + ColPartitionGrid* text_grid_; // Text ColPartitions + ColPartitionGrid* line_grid_; // Line ColPartitions + // Table structure. + // bounding box is a convenient external representation. + // cell_x_ and cell_y_ indicate the grid lines. + TBOX bounding_box_; // Bounding box + GenericVectorEqEq cell_x_; // Locations of vertical divisions (sorted) + GenericVectorEqEq cell_y_; // Locations of horizontal divisions (sorted) + bool is_lined_; // Is the table backed up by a line structure + // Table margins, set via CalculateMargins + int space_above_; + int space_below_; + int space_left_; + int space_right_; + int median_cell_height_; + int median_cell_width_; + // Filters, used to prevent awkward partitions from destroying structure. + int max_text_height_; +}; + +class TableRecognizer { + public: + TableRecognizer(); + ~TableRecognizer(); + + // Initialization code. Must be called after the constructor. + void Init(); + + //////// + //////// Pre-recognize methods to initial table constraints. + //////// + + // Sets the grids used by the table. These can be changed between + // calls to Recognize. They are treated as read-only data. + void set_text_grid(ColPartitionGrid* text); + void set_line_grid(ColPartitionGrid* lines); + // Sets some additional constraints on the table. + void set_min_height(int height); + void set_min_width(int width); + // Filters text partitions that are ridiculously tall to prevent + // merging rows. Note that "filters" refers to allowing horizontal + // cells to slice through them on the premise that they were + // merged text rows during previous layout. + void set_max_text_height(int height); + + // Given a guess location, the RecognizeTable function will try to find a + // structured grid in the area. On success, it will return a new + // StructuredTable (and assumes you will delete it). Otherwise, + // NULL is returned. + // + // Keep in mind, this may "overgrow" or "undergrow" the size of guess. + // Ideally, there is a either a one-to-one correspondence between + // the guess and table or no table at all. This is not the best of + // assumptions right now, but was made to try to keep things simple in + // the first pass. + // + // If a line structure is available on the page in the given region, + // the table will use the linear structure as it is. + // Otherwise, it will try to maximize the whitespace around it while keeping + // a grid structure. This is somewhat working. + // + // Since the combination of adjustments can get high, effort was + // originally made to keep the number of adjustments linear in the number + // of partitions. The underlying structure finding code used to be + // much more complex. I don't know how necessary this constraint is anymore. + // The evaluation of a possible table is kept within O(nlogn) in the size of + // the table (where size is the number of partitions in the table). + // As a result, the algorithm is capable of O(n^2 log n). Depending + // on the grid search size, it may be higher. + // + // Last note: it is possible to just try all partition boundaries at a high + // level O(n^4) and do a verification scheme (at least O(nlogn)). If there + // area 200 partitions on a page, this could be too costly. Effort could go + // into pruning the search, but I opted for something quicker. I'm confident + // that the independent adjustments can get similar results and keep the + // complextiy down. However, the other approach could work without using + // TableFinder at all if it is fast enough. It comes down to properly + // deciding what is a table. The code currently relies on TableFinder's + // guess to the location of a table for that. + StructuredTable* RecognizeTable(const TBOX& guess_box); + + protected: + //////// + //////// Lined tables + //////// + + // Returns true if the given box has a lined table within it. The + // table argument will be updated with the table if the table exists. + bool RecognizeLinedTable(const TBOX& guess_box, StructuredTable* table); + // Returns true if the given box has a large number of horizontal and + // vertical lines present. If so, we assume the extent of these lines + // uniquely defines a table and find that table via SolveLinedTable. + bool HasSignificantLines(const TBOX& guess); + + // Given enough horizontal and vertical lines in a region, find a bounding + // box that encloses all of them (as well as newly introduced lines). + // The bounding box is the smallest box that encloses the lines in guess + // without having any lines sticking out of it. + // bounding_box is an in/out parameter. + // On input, it in the extents of the box to search. + // On output, it is the resulting bounding box. + bool FindLinesBoundingBox(TBOX* bounding_box); + // Iteration in above search. + // bounding_box is an in/out parameter. + // On input, it in the extents of the box to search. + // On output, it is the resulting bounding box. + bool FindLinesBoundingBoxIteration(TBOX* bounding_box); + + //////// + //////// Generic "whitespaced" tables + //////// + + // Returns true if the given box has a whitespaced table within it. The + // table argument will be updated if the table exists. Also note + // that this method will fail if the guess_box center is not + // mostly within the table. + bool RecognizeWhitespacedTable(const TBOX& guess_box, StructuredTable* table); + + // Finds the location of a horizontal split relative to y. + // This function is mostly unused now. If the SolveWhitespacedTable + // changes much, it can be removed. Note, it isn't really as reliable + // as I thought. I went with alternatives for most of the other uses. + int NextHorizontalSplit(int left, int right, int y, bool top_to_bottom); + + // Indicates that a table row is weak. This means that it has + // many missing data cells or very large cell heights compared. + // to the rest of the table. + static bool IsWeakTableRow(StructuredTable* table, int row); + + // Input data, used as read only data to make decisions. + ColPartitionGrid* text_grid_; // Text ColPartitions + ColPartitionGrid* line_grid_; // Line ColPartitions + // Table constraints, a "good" table must satisfy these. + int min_height_; + int min_width_; + // Filters, used to prevent awkward partitions from destroying structure. + int max_text_height_; // Horizontal lines may intersect taller text. +}; + +} // namespace tesseract + +#endif /* TABLERECOG_H_ */ diff --git a/TesseractOCR/include/tesseract/tabvector.h b/TesseractOCR/include/tesseract/tabvector.h new file mode 100644 index 00000000..dbeff106 --- /dev/null +++ b/TesseractOCR/include/tesseract/tabvector.h @@ -0,0 +1,430 @@ +/////////////////////////////////////////////////////////////////////// +// File: tabvector.h +// Description: Class to hold a near-vertical vector representing a tab-stop. +// Author: Ray Smith +// Created: Thu Apr 10 16:25:01 PST 2008 +// +// (C) Copyright 2008, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_TABVECTOR_H__ +#define TESSERACT_TEXTORD_TABVECTOR_H__ + +#include "blobgrid.h" +#include "clst.h" +#include "elst.h" +#include "elst2.h" +#include "rect.h" +#include "bbgrid.h" + +class BLOBNBOX; +class ScrollView; + +namespace tesseract { + + +extern double_VAR_H(textord_tabvector_vertical_gap_fraction, 0.5, + "Max fraction of mean blob width allowed for vertical gaps in vertical text"); +extern double_VAR_H(textord_tabvector_vertical_box_ratio, 0.5, + "Fraction of box matches required to declare a line vertical"); + +// The alignment type that a tab vector represents. +// Keep this enum synced with kAlignmentNames in tabvector.cpp. +enum TabAlignment { + TA_LEFT_ALIGNED, + TA_LEFT_RAGGED, + TA_CENTER_JUSTIFIED, + TA_RIGHT_ALIGNED, + TA_RIGHT_RAGGED, + TA_SEPARATOR, + TA_COUNT +}; + +// Forward declarations. The classes use their own list types, so we +// need to make the list types first. +class TabFind; +class TabVector; +class TabConstraint; + +ELIST2IZEH(TabVector) +CLISTIZEH(TabVector) +ELISTIZEH(TabConstraint) + +// TabConstraint is a totally self-contained class to maintain +// a list of [min,max] constraints, each referring to a TabVector. +// The constraints are manipulated through static methods that act +// on a list of constraints. The list itself is cooperatively owned +// by the TabVectors of the constraints on the list and managed +// by implicit reference counting via the elements of the list. +class TabConstraint : public ELIST_LINK { + public: + TabConstraint() { + // This empty constructor is here only so that the class can be ELISTIZED. + // TODO(rays) change deep_copy in elst.h line 955 to take a callback copier + // and eliminate CLASSNAME##_copier. + } + + // Create a constraint for the top or bottom of this TabVector. + static void CreateConstraint(TabVector* vector, bool is_top); + + // Test to see if the constraints are compatible enough to merge. + static bool CompatibleConstraints(TabConstraint_LIST* list1, + TabConstraint_LIST* list2); + + // Merge the lists of constraints and update the TabVector pointers. + // The second list is deleted. + static void MergeConstraints(TabConstraint_LIST* list1, + TabConstraint_LIST* list2); + + // Set all the tops and bottoms as appropriate to a mean of the + // constrained range. Delete all the constraints and list. + static void ApplyConstraints(TabConstraint_LIST* constraints); + + private: + TabConstraint(TabVector* vector, bool is_top); + + // Get the max of the mins and the min of the maxes. + static void GetConstraints(TabConstraint_LIST* constraints, + int* y_min, int* y_max); + + // The TabVector this constraint applies to. + TabVector* vector_; + // If true then we refer to the top of the vector_. + bool is_top_; + // The allowed range of this vector_. + int y_min_; + int y_max_; +}; + +// Class to hold information about a single vector +// that represents a tab stop or a rule line. +class TabVector : public ELIST2_LINK { + public: + TabVector() { + // TODO(rays) fix this in elst.h line 1076, where it should use the + // copy constructor instead of operator=. + } + ~TabVector(); + + // Public factory to build a TabVector from a list of boxes. + // The TabVector will be of the given alignment type. + // The input vertical vector is used in fitting, and the output + // vertical_x, vertical_y have the resulting line vector added to them + // if the alignment is not ragged. + // The extended_start_y and extended_end_y are the maximum possible + // extension to the line segment that can be used to align with others. + // The input CLIST of BLOBNBOX good_points is consumed and taken over. + static TabVector* FitVector(TabAlignment alignment, ICOORD vertical, + int extended_start_y, int extended_end_y, + BLOBNBOX_CLIST* good_points, + int* vertical_x, int* vertical_y); + + // Build a ragged TabVector by copying another's direction, shifting it + // to match the given blob, and making its initial extent the height + // of the blob, but its extended bounds from the bounds of the original. + TabVector(const TabVector& src, TabAlignment alignment, + const ICOORD& vertical_skew, BLOBNBOX* blob); + + // Copies basic attributes of a tab vector for simple operations. + // Copies things such startpt, endpt, range, width. + // Does not copy things such as partners, boxes, or constraints. + // This is useful if you only need vector information for processing, such + // as in the table detection code. + TabVector* ShallowCopy() const; + + // Simple accessors. + const ICOORD& startpt() const { + return startpt_; + } + const ICOORD& endpt() const { + return endpt_; + } + int extended_ymax() const { + return extended_ymax_; + } + int extended_ymin() const { + return extended_ymin_; + } + int sort_key() const { + return sort_key_; + } + int mean_width() const { + return mean_width_; + } + void set_top_constraints(TabConstraint_LIST* constraints) { + top_constraints_ = constraints; + } + void set_bottom_constraints(TabConstraint_LIST* constraints) { + bottom_constraints_ = constraints; + } + TabVector_CLIST* partners() { + return &partners_; + } + void set_startpt(const ICOORD& start) { + startpt_ = start; + } + void set_endpt(const ICOORD& end) { + endpt_ = end; + } + bool intersects_other_lines() const { + return intersects_other_lines_; + } + void set_intersects_other_lines(bool value) { + intersects_other_lines_ = value; + } + + // Inline quasi-accessors that require some computation. + + // Compute the x coordinate at the given y coordinate. + int XAtY(int y) const { + int height = endpt_.y() - startpt_.y(); + if (height != 0) + return (y - startpt_.y()) * (endpt_.x() - startpt_.x()) / height + + startpt_.x(); + else + return startpt_.x(); + } + + // Compute the vertical overlap with the other TabVector. + int VOverlap(const TabVector& other) const { + return MIN(other.endpt_.y(), endpt_.y()) - + MAX(other.startpt_.y(), startpt_.y()); + } + // Compute the vertical overlap with the given y bounds. + int VOverlap(int top_y, int bottom_y) const { + return MIN(top_y, endpt_.y()) - MAX(bottom_y, startpt_.y()); + } + // Compute the extended vertical overlap with the given y bounds. + int ExtendedOverlap(int top_y, int bottom_y) const { + return MIN(top_y, extended_ymax_) - MAX(bottom_y, extended_ymin_); + } + + // Return true if this is a left tab stop, either aligned, or ragged. + bool IsLeftTab() const { + return alignment_ == TA_LEFT_ALIGNED || alignment_ == TA_LEFT_RAGGED; + } + // Return true if this is a right tab stop, either aligned, or ragged. + bool IsRightTab() const { + return alignment_ == TA_RIGHT_ALIGNED || alignment_ == TA_RIGHT_RAGGED; + } + // Return true if this is a separator. + bool IsSeparator() const { + return alignment_ == TA_SEPARATOR; + } + // Return true if this is a center aligned tab stop. + bool IsCenterTab() const { + return alignment_ == TA_CENTER_JUSTIFIED; + } + // Return true if this is a ragged tab top, either left or right. + bool IsRagged() const { + return alignment_ == TA_LEFT_RAGGED || alignment_ == TA_RIGHT_RAGGED; + } + + // Return true if this vector is to the left of the other in terms + // of sort_key_. + bool IsLeftOf(const TabVector& other) const { + return sort_key_ < other.sort_key_; + } + + // Return true if the vector has no partners. + bool Partnerless() { + return partners_.empty(); + } + + // Return the number of tab boxes in this vector. + int BoxCount() { + return boxes_.length(); + } + + // Lock the vector from refits by clearing the boxes_ list. + void Freeze() { + boxes_.shallow_clear(); + } + + // Flip x and y on the ends so a vector can be created from flipped input. + void XYFlip() { + int x = startpt_.y(); + startpt_.set_y(startpt_.x()); + startpt_.set_x(x); + x = endpt_.y(); + endpt_.set_y(endpt_.x()); + endpt_.set_x(x); + } + + // Reflect the tab vector in the y-axis. + void ReflectInYAxis() { + startpt_.set_x(-startpt_.x()); + endpt_.set_x(-endpt_.x()); + sort_key_ = -sort_key_; + if (alignment_ == TA_LEFT_ALIGNED) + alignment_ = TA_RIGHT_ALIGNED; + else if (alignment_ == TA_RIGHT_ALIGNED) + alignment_ = TA_LEFT_ALIGNED; + if (alignment_ == TA_LEFT_RAGGED) + alignment_ = TA_RIGHT_RAGGED; + else if (alignment_ == TA_RIGHT_RAGGED) + alignment_ = TA_LEFT_RAGGED; + } + + // Separate function to compute the sort key for a given coordinate pair. + static int SortKey(const ICOORD& vertical, int x, int y) { + ICOORD pt(x, y); + return pt * vertical; + } + + // Return the x at the given y for the given sort key. + static int XAtY(const ICOORD& vertical, int sort_key, int y) { + if (vertical.y() != 0) + return (vertical.x() * y + sort_key) / vertical.y(); + else + return sort_key; + } + + // Sort function for E2LIST::sort to sort by sort_key_. + static int SortVectorsByKey(const void* v1, const void* v2) { + const TabVector* tv1 = *reinterpret_cast(v1); + const TabVector* tv2 = *reinterpret_cast(v2); + return tv1->sort_key_ - tv2->sort_key_; + } + + // More complex members. + + // Extend this vector to include the supplied blob if it doesn't + // already have it. + void ExtendToBox(BLOBNBOX* blob); + + // Set the ycoord of the start and move the xcoord to match. + void SetYStart(int start_y); + // Set the ycoord of the end and move the xcoord to match. + void SetYEnd(int end_y); + + // Rotate the ends by the given vector. + void Rotate(const FCOORD& rotation); + + // Setup the initial constraints, being the limits of + // the vector and the extended ends. + void SetupConstraints(); + + // Setup the constraints between the partners of this TabVector. + void SetupPartnerConstraints(); + + // Setup the constraints between this and its partner. + void SetupPartnerConstraints(TabVector* partner); + + // Use the constraints to modify the top and bottom. + void ApplyConstraints(); + + // Merge close tab vectors of the same side that overlap. + static void MergeSimilarTabVectors(const ICOORD& vertical, + TabVector_LIST* vectors, BlobGrid* grid); + + // Return true if this vector is the same side, overlaps, and close + // enough to the other to be merged. + bool SimilarTo(const ICOORD& vertical, + const TabVector& other, BlobGrid* grid) const; + + // Eat the other TabVector into this and delete it. + void MergeWith(const ICOORD& vertical, TabVector* other); + + // Add a new element to the list of partner TabVectors. + // Partners must be added in order of increasing y coordinate of the text line + // that makes them partners. + // Groups of identical partners are merged into one. + void AddPartner(TabVector* partner); + + // Return true if other is a partner of this. + bool IsAPartner(const TabVector* other); + + // Print basic information about this tab vector. + void Print(const char* prefix); + + // Print basic information about this tab vector and every box in it. + void Debug(const char* prefix); + + // Draw this tabvector in place in the given window. + void Display(ScrollView* tab_win); + + // Refit the line and/or re-evaluate the vector if the dirty flags are set. + void FitAndEvaluateIfNeeded(const ICOORD& vertical, TabFind* finder); + + // Evaluate the vector in terms of coverage of its length by good-looking + // box edges. A good looking box is one where its nearest neighbour on the + // inside is nearer than half the distance its nearest neighbour on the + // outside of the putative column. Bad boxes are removed from the line. + // A second pass then further filters boxes by requiring that the gutter + // width be a minimum fraction of the mean gutter along the line. + void Evaluate(const ICOORD& vertical, TabFind* finder); + + // (Re)Fit a line to the stored points. Returns false if the line + // is degenerate. Althougth the TabVector code mostly doesn't care about the + // direction of lines, XAtY would give silly results for a horizontal line. + // The class is mostly aimed at use for vertical lines representing + // horizontal tab stops. + bool Fit(ICOORD vertical, bool force_parallel); + + // Return the partner of this TabVector if the vector qualifies as + // being a vertical text line, otherwise NULL. + TabVector* VerticalTextlinePartner(); + + // Return the matching tabvector if there is exactly one partner, or + // NULL otherwise. This can be used after matching is done, eg. by + // VerticalTextlinePartner(), without checking if the line is vertical. + TabVector* GetSinglePartner(); + + private: + // Constructor is private as the static factory is the external way + // to build a TabVector. + TabVector(int extended_ymin, int extended_ymax, + TabAlignment alignment, BLOBNBOX_CLIST* boxes); + + // Delete this, but first, repoint all the partners to point to + // replacement. If replacement is NULL, then partner relationships + // are removed. + void Delete(TabVector* replacement); + + private: + // The bottom of the tab line. + ICOORD startpt_; + // The top of the tab line. + ICOORD endpt_; + // The lowest y that the vector might extend to. + int extended_ymin_; + // The highest y that the vector might extend to. + int extended_ymax_; + // Perpendicular distance of vector from a given vertical for sorting. + int sort_key_; + // Result of Evaluate 0-100. Coverage of line with good boxes. + int percent_score_; + // The mean width of the blobs. Meaningful only for separator lines. + int mean_width_; + // True if the boxes_ list has been modified, so a refit is needed. + bool needs_refit_; + // True if a fit has been done, so re-evaluation is needed. + bool needs_evaluation_; + // True if a separator line intersects at least 2 other lines. + bool intersects_other_lines_; + // The type of this TabVector. + TabAlignment alignment_; + // The list of boxes whose edges are aligned at this TabVector. + BLOBNBOX_CLIST boxes_; + // List of TabVectors that have a connection with this via a text line. + TabVector_CLIST partners_; + // Constraints used to resolve the exact location of the top and bottom + // of the tab line. + TabConstraint_LIST* top_constraints_; + TabConstraint_LIST* bottom_constraints_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_TABVECTOR_H__ diff --git a/TesseractOCR/include/tesseract/tess_lang_mod_edge.h b/TesseractOCR/include/tesseract/tess_lang_mod_edge.h new file mode 100644 index 00000000..206a160d --- /dev/null +++ b/TesseractOCR/include/tesseract/tess_lang_mod_edge.h @@ -0,0 +1,234 @@ +/********************************************************************** + * File: tess_lang_mod_edge.h + * Description: Declaration of the Tesseract Language Model Edge Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The TessLangModEdge models an edge in the Tesseract language models +// It inherits from the LangModEdge class + +#ifndef TESS_LANG_MOD_EDGE_H +#define TESS_LANG_MOD_EDGE_H + +#include "dawg.h" +#include "char_set.h" + +#include "lang_mod_edge.h" +#include "cube_reco_context.h" +#include "cube_utils.h" + +// Macros needed to identify punctuation in the langmodel state +#ifdef _HMSW32_H +#define LEAD_PUNC_EDGE_REF_MASK (inT64) 0x0000000100000000i64 +#define TRAIL_PUNC_EDGE_REF_MASK (inT64) 0x0000000200000000i64 +#define TRAIL_PUNC_REPEAT_MASK (inT64) 0xffff000000000000i64 +#else +#define LEAD_PUNC_EDGE_REF_MASK (inT64) 0x0000000100000000ll +#define TRAIL_PUNC_EDGE_REF_MASK (inT64) 0x0000000200000000ll +#define TRAIL_PUNC_REPEAT_MASK (inT64) 0xffff000000000000ll +#endif + +// Number state machine macros +#define NUMBER_STATE_SHIFT 0 +#define NUMBER_STATE_MASK 0x0000000fl +#define NUMBER_LITERAL_SHIFT 4 +#define NUMBER_LITERAL_MASK 0x000000f0l +#define NUMBER_REPEAT_SHIFT 8 +#define NUMBER_REPEAT_MASK 0x00000f00l +#define NUM_TRM -99 +#define TRAIL_PUNC_REPEAT_SHIFT 48 + +#define IsLeadingPuncEdge(edge_mask) \ + ((edge_mask & LEAD_PUNC_EDGE_REF_MASK) != 0) +#define IsTrailingPuncEdge(edge_mask) \ + ((edge_mask & TRAIL_PUNC_EDGE_REF_MASK) != 0) +#define TrailingPuncCount(edge_mask) \ + ((edge_mask & TRAIL_PUNC_REPEAT_MASK) >> TRAIL_PUNC_REPEAT_SHIFT) +#define TrailingPuncEdgeMask(Cnt) \ + (TRAIL_PUNC_EDGE_REF_MASK | ((Cnt) << TRAIL_PUNC_REPEAT_SHIFT)) + +// State machine IDs +#define DAWG_OOD 0 +#define DAWG_NUMBER 1 + +namespace tesseract { +class TessLangModEdge : public LangModEdge { + public: + // Different ways of constructing a TessLangModEdge + TessLangModEdge(CubeRecoContext *cntxt, const Dawg *edge_array, + EDGE_REF edge, int class_id); + TessLangModEdge(CubeRecoContext *cntxt, const Dawg *edge_array, + EDGE_REF start_edge_idx, EDGE_REF end_edge_idx, + int class_id); + TessLangModEdge(CubeRecoContext *cntxt, int class_id); + ~TessLangModEdge() {} + + // Accessors + inline bool IsRoot() const { + return root_; + } + inline void SetRoot(bool flag) { root_ = flag; } + + inline bool IsOOD() const { + return (dawg_ == (Dawg *)DAWG_OOD); + } + + inline bool IsNumber() const { + return (dawg_ == (Dawg *)DAWG_NUMBER); + } + + inline bool IsEOW() const { + return (IsTerminal() || (dawg_->end_of_word(end_edge_) != 0)); + } + + inline const Dawg *GetDawg() const { return dawg_; } + inline EDGE_REF StartEdge() const { return start_edge_; } + inline EDGE_REF EndEdge() const { return end_edge_; } + inline EDGE_REF EdgeMask() const { return edge_mask_; } + inline const char_32 * EdgeString() const { return str_; } + inline int ClassID () const { return class_id_; } + inline int PathCost() const { return path_cost_; } + inline void SetEdgeMask(EDGE_REF edge_mask) { edge_mask_ = edge_mask; } + inline void SetDawg(Dawg *dawg) { dawg_ = dawg; } + inline void SetStartEdge(EDGE_REF edge_idx) { start_edge_ = edge_idx; } + inline void SetEndEdge(EDGE_REF edge_idx) { end_edge_ = edge_idx; } + + // is this a terminal node: + // we can terminate at any OOD char, trailing punc or + // when the dawg terminates + inline bool IsTerminal() const { + return (IsOOD() || IsNumber() || IsTrailingPuncEdge(start_edge_) || + dawg_->next_node(end_edge_) == 0); + } + + // How many signals does the LM provide for tuning. These are flags like: + // OOD or not, Number of not that are used by the training to compute + // extra costs for each word. + inline int SignalCnt() const { + return 2; + } + + // returns the weight assigned to a specified signal + inline double SignalWgt(int signal) const { + CubeTuningParams *params = + reinterpret_cast(cntxt_->Params()); + if (params != NULL) { + switch (signal) { + case 0: + return params->OODWgt(); + break; + + case 1: + return params->NumWgt(); + break; + } + } + + return 0.0; + } + + // sets the weight assigned to a specified signal: Used in training + void SetSignalWgt(int signal, double wgt) { + CubeTuningParams *params = + reinterpret_cast(cntxt_->Params()); + if (params != NULL) { + switch (signal) { + case 0: + params->SetOODWgt(wgt); + break; + + case 1: + params->SetNumWgt(wgt); + break; + } + } + } + + // returns the actual value of a specified signal + int Signal(int signal) { + switch (signal) { + case 0: + return IsOOD() ? MIN_PROB_COST : 0; + break; + + case 1: + return IsNumber() ? MIN_PROB_COST : 0; + break; + + default: + return 0; + } + } + + // returns the Hash value of the edge. Used by the SearchNode hash table + // to quickly lookup exisiting edges to converge during search + inline unsigned int Hash() const { + return static_cast(((start_edge_ | end_edge_) ^ + ((reinterpret_cast(dawg_)))) ^ + ((unsigned int)edge_mask_) ^ + class_id_); + } + + // A verbal description of the edge: Used by visualizers + char *Description() const; + + // Is this edge identical to the specified edge + inline bool IsIdentical(LangModEdge *lang_mod_edge) const { + return (class_id_ == + reinterpret_cast(lang_mod_edge)->class_id_ && + str_ == reinterpret_cast(lang_mod_edge)->str_ && + dawg_ == reinterpret_cast(lang_mod_edge)->dawg_ && + start_edge_ == + reinterpret_cast(lang_mod_edge)->start_edge_ && + end_edge_ == + reinterpret_cast(lang_mod_edge)->end_edge_ && + edge_mask_ == + reinterpret_cast(lang_mod_edge)->edge_mask_); + } + + // Creates a set of fan-out edges for the specified edge + static int CreateChildren(CubeRecoContext *cntxt, + const Dawg *edges, + NODE_REF edge_reg, + LangModEdge **lm_edges); + + private: + bool root_; + CubeRecoContext *cntxt_; + const Dawg *dawg_; + EDGE_REF start_edge_; + EDGE_REF end_edge_; + EDGE_REF edge_mask_; + int path_cost_; + int class_id_; + const char_32 * str_; + // returns the cost of the lang_mod_edge + inline int Cost() const { + if (cntxt_ != NULL) { + CubeTuningParams *params = + reinterpret_cast(cntxt_->Params()); + if (dawg_ == (Dawg *)DAWG_OOD) { + return static_cast(params->OODWgt() * MIN_PROB_COST); + } else if (dawg_ == (Dawg *)DAWG_NUMBER) { + return static_cast(params->NumWgt() * MIN_PROB_COST); + } + } + return 0; + } +}; +} // namespace tesseract + +#endif // TESS_LANG_MOD_EDGE_H diff --git a/TesseractOCR/include/tesseract/tess_lang_model.h b/TesseractOCR/include/tesseract/tess_lang_model.h new file mode 100644 index 00000000..3e0c63a1 --- /dev/null +++ b/TesseractOCR/include/tesseract/tess_lang_model.h @@ -0,0 +1,142 @@ +/********************************************************************** + * File: tess_lang_model.h + * Description: Declaration of the Tesseract Language Model Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef TESS_LANG_MODEL_H +#define TESS_LANG_MODEL_H + +#include + +#include "char_altlist.h" +#include "cube_reco_context.h" +#include "cube_tuning_params.h" +#include "dict.h" +#include "lang_model.h" +#include "tessdatamanager.h" +#include "tess_lang_mod_edge.h" + +namespace tesseract { + +const int kStateCnt = 4; +const int kNumLiteralCnt = 5; + +class TessLangModel : public LangModel { + public: + TessLangModel(const string &lm_params, + const string &data_file_path, + bool load_system_dawg, + TessdataManager *tessdata_manager, + CubeRecoContext *cntxt); + ~TessLangModel() { + if (word_dawgs_ != NULL) { + word_dawgs_->delete_data_pointers(); + delete word_dawgs_; + } + } + + // returns a pointer to the root of the language model + inline TessLangModEdge *Root() { + return NULL; + } + + // The general fan-out generation function. Returns the list of edges + // fanning-out of the specified edge and their count. If an AltList is + // specified, only the class-ids with a minimum cost are considered + LangModEdge **GetEdges(CharAltList *alt_list, + LangModEdge *edge, + int *edge_cnt); + // Determines if a sequence of 32-bit chars is valid in this language model + // starting from the root. If the eow_flag is ON, also checks for + // a valid EndOfWord. If final_edge is not NULL, returns a pointer to the last + // edge + bool IsValidSequence(const char_32 *sequence, bool eow_flag, + LangModEdge **final_edge = NULL); + bool IsLeadingPunc(char_32 ch); + bool IsTrailingPunc(char_32 ch); + bool IsDigit(char_32 ch); + + void RemoveInvalidCharacters(string *lm_str); + private: + // static LM state machines + static const Dawg *ood_dawg_; + static const Dawg *number_dawg_; + static const int num_state_machine_[kStateCnt][kNumLiteralCnt]; + static const int num_max_repeat_[kStateCnt]; + // word_dawgs_ should only be loaded if cube has its own version of the + // unicharset (different from the one used by tesseract) and therefore + // can not use the dawgs loaded for tesseract (since the unichar ids + // encoded in the dawgs differ). + DawgVector *word_dawgs_; + + static int max_edge_; + static int max_ood_shape_cost_; + + // remaining language model elements needed by cube. These get loaded from + // the .lm file + string lead_punc_; + string trail_punc_; + string num_lead_punc_; + string num_trail_punc_; + string operators_; + string digits_; + string alphas_; + // String of characters in RHS of each line of .cube.lm + // Each element is hard-coded to correspond to a specific token type + // (see LoadLangModelElements) + string *literal_str_[kNumLiteralCnt]; + // Recognition context needed to access language properties + // (case, cursive,..) + CubeRecoContext *cntxt_; + bool has_case_; + + // computes and returns the edges that fan out of an edge ref + int FanOut(CharAltList *alt_list, + const Dawg *dawg, EDGE_REF edge_ref, EDGE_REF edge_ref_mask, + const char_32 *str, bool root_flag, LangModEdge **edge_array); + // generate edges from an NULL terminated string + // (used for punctuation, operators and digits) + int Edges(const char *strng, const Dawg *dawg, + EDGE_REF edge_ref, EDGE_REF edge_ref_mask, + LangModEdge **edge_array); + // Generate the edges fanning-out from an edge in the number state machine + int NumberEdges(EDGE_REF edge_ref, LangModEdge **edge_array); + // Generate OOD edges + int OODEdges(CharAltList *alt_list, EDGE_REF edge_ref, + EDGE_REF edge_ref_mask, LangModEdge **edge_array); + // Cleanup an edge array + void FreeEdges(int edge_cnt, LangModEdge **edge_array); + // Determines if a sequence of 32-bit chars is valid in this language model + // starting from the specified edge. If the eow_flag is ON, also checks for + // a valid EndOfWord. If final_edge is not NULL, returns a pointer to the last + // edge + bool IsValidSequence(LangModEdge *edge, const char_32 *sequence, + bool eow_flag, LangModEdge **final_edge); + // Parse language model elements from the given string, which should + // have been loaded from .cube.lm file, e.g. in CubeRecoContext + bool LoadLangModelElements(const string &lm_params); + + // Returns the number of word Dawgs in the language model. + int NumDawgs() const; + + // Returns the dawgs with the given index from either the dawgs + // stored by the Tesseract object, or the word_dawgs_. + const Dawg *GetDawg(int index) const; +}; +} // tesseract + +#endif // TESS_LANG_MODEL_H diff --git a/TesseractOCR/include/tesseract/tessbox.h b/TesseractOCR/include/tesseract/tessbox.h old mode 100755 new mode 100644 index b031007d..d655a204 --- a/TesseractOCR/include/tesseract/tessbox.h +++ b/TesseractOCR/include/tesseract/tessbox.h @@ -21,7 +21,6 @@ #define TESSBOX_H #include "ratngs.h" -#include "notdll.h" #include "tesseractclass.h" // TODO(ocr-team): Delete this along with other empty header files. diff --git a/TesseractOCR/include/tesseract/tesscallback.h b/TesseractOCR/include/tesseract/tesscallback.h old mode 100755 new mode 100644 index b34cdb14..1f20c6b4 --- a/TesseractOCR/include/tesseract/tesscallback.h +++ b/TesseractOCR/include/tesseract/tesscallback.h @@ -270,43 +270,8537 @@ NewPermanentTessCallback(R (*function)()) { return new _TessFunctionResultCallback_0_0(function); } + + +// Specified by TR1 [4.7.2] Reference modifications. +template struct remove_reference; +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +// Identity::type is a typedef of T. Useful for preventing the +// compiler from inferring the type of an argument in templates. +template +struct Identity { + typedef T type; +}; + +template +class _ConstTessMemberResultCallback_1_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_0(const T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_); + return result; + } else { + R result = (object_->*member_)(p1_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_1_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_0(const T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_); + } else { + (object_->*member_)(p1_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_0::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1) const, typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_0(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_0::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1) const, typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_0(obj, member, p1); +} +#endif + +template +class _TessMemberResultCallback_1_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_0( T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_); + return result; + } else { + R result = (object_->*member_)(p1_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_1_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_0( T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_); + } else { + (object_->*member_)(p1_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_0::base* +NewTessCallback( T1* obj, R (T2::*member)(P1) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_0(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_0::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_0(obj, member, p1); +} +#endif + +template +class _TessFunctionResultCallback_1_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (*FunctionSignature)(P1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_0(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual R Run() { + if (!del) { + R result = (*function_)(p1_); + return result; + } else { + R result = (*function_)(p1_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_1_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (*FunctionSignature)(P1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_0(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual void Run() { + if (!del) { + (*function_)(p1_); + } else { + (*function_)(p1_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_1_0::base* +NewTessCallback(R (*function)(P1), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_0(function, p1); +} + +template +inline typename _TessFunctionResultCallback_1_0::base* +NewPermanentTessCallback(R (*function)(P1), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_0(function, p1); +} + +template +class _ConstTessMemberResultCallback_2_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1,P2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_0(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_,p2_); + return result; + } else { + R result = (object_->*member_)(p1_,p2_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_2_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1,P2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_0(const T* object, MemberSignature member, P1 p1, P2 p2) + : + object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_,p2_); + } else { + (object_->*member_)(p1_,p2_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_0::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_0(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_0::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_0(obj, member, p1, p2); +} +#endif + +template +class _TessMemberResultCallback_2_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1,P2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_0( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_,p2_); + return result; + } else { + R result = (object_->*member_)(p1_,p2_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_2_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1,P2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_0( T* object, MemberSignature member, P1 p1, P2 p2) + : + object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_,p2_); + } else { + (object_->*member_)(p1_,p2_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_0::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_0(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_0::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_0(obj, member, p1, p2); +} +#endif + +template +class _TessFunctionResultCallback_2_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (*FunctionSignature)(P1,P2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_0(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual R Run() { + if (!del) { + R result = (*function_)(p1_,p2_); + return result; + } else { + R result = (*function_)(p1_,p2_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_2_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (*FunctionSignature)(P1,P2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_0(FunctionSignature function, P1 p1, P2 p2) + : + function_(function), p1_(p1), p2_(p2) { } + + virtual void Run() { + if (!del) { + (*function_)(p1_,p2_); + } else { + (*function_)(p1_,p2_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_2_0::base* +NewTessCallback(R (*function)(P1,P2), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_0(function, p1, p2); +} + +template +inline typename _TessFunctionResultCallback_2_0::base* +NewPermanentTessCallback(R (*function)(P1,P2), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_0(function, p1, p2); +} + +template +class _ConstTessMemberResultCallback_3_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1,P2,P3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _ConstTessMemberResultCallback_3_0(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : + object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_3_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1,P2,P3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _ConstTessMemberResultCallback_3_0(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_,p2_,p3_); + } else { + (object_->*member_)(p1_,p2_,p3_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_3_0::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_0(obj, member, p1, p2, p3); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_3_0::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_0(obj, member, p1, p2, p3); +} +#endif + +template +class _TessMemberResultCallback_3_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1,P2,P3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessMemberResultCallback_3_0( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_3_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1,P2,P3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessMemberResultCallback_3_0( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_,p2_,p3_); + } else { + (object_->*member_)(p1_,p2_,p3_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_3_0::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_0(obj, member, p1, p2, p3); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_3_0::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_0(obj, member, p1, p2, p3); +} +#endif + +template +class _TessFunctionResultCallback_3_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (*FunctionSignature)(P1,P2,P3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessFunctionResultCallback_3_0(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run() { + if (!del) { + R result = (*function_)(p1_,p2_,p3_); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_3_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (*FunctionSignature)(P1,P2,P3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessFunctionResultCallback_3_0(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run() { + if (!del) { + (*function_)(p1_,p2_,p3_); + } else { + (*function_)(p1_,p2_,p3_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_3_0::base* +NewTessCallback(R (*function)(P1,P2,P3), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_0(function, p1, p2, p3); +} + +template +inline typename _TessFunctionResultCallback_3_0::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_0(function, p1, p2, p3); +} + +template +class _ConstTessMemberResultCallback_4_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _ConstTessMemberResultCallback_4_0(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_4_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _ConstTessMemberResultCallback_4_0(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_4_0::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_0(obj, member, p1, p2, p3, p4); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_4_0::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_0(obj, member, p1, p2, p3, p4); +} +#endif + +template +class _TessMemberResultCallback_4_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessMemberResultCallback_4_0( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_4_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessMemberResultCallback_4_0( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_4_0::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_0(obj, member, p1, p2, p3, p4); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_4_0::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_0(obj, member, p1, p2, p3, p4); +} +#endif + +template +class _TessFunctionResultCallback_4_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (*FunctionSignature)(P1,P2,P3,P4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessFunctionResultCallback_4_0(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run() { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_4_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (*FunctionSignature)(P1,P2,P3,P4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessFunctionResultCallback_4_0(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run() { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_); + } else { + (*function_)(p1_,p2_,p3_,p4_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_4_0::base* +NewTessCallback(R (*function)(P1,P2,P3,P4), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_0(function, p1, p2, p3, p4); +} + +template +inline typename _TessFunctionResultCallback_4_0::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_0(function, p1, p2, p3, p4); +} + +template +class _ConstTessMemberResultCallback_5_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _ConstTessMemberResultCallback_5_0(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_5_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _ConstTessMemberResultCallback_5_0(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_5_0::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_0(obj, member, p1, p2, p3, p4, p5); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_5_0::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_0(obj, member, p1, p2, p3, p4, p5); +} +#endif + +template +class _TessMemberResultCallback_5_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessMemberResultCallback_5_0( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_5_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessMemberResultCallback_5_0( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_5_0::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_0(obj, member, p1, p2, p3, p4, p5); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_5_0::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_0(obj, member, p1, p2, p3, p4, p5); +} +#endif + +template +class _TessFunctionResultCallback_5_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessFunctionResultCallback_5_0(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run() { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_5_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessFunctionResultCallback_5_0(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run() { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,p5_); + } else { + (*function_)(p1_,p2_,p3_,p4_,p5_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_5_0::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_0(function, p1, p2, p3, p4, p5); +} + +template +inline typename _TessFunctionResultCallback_5_0::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_0(function, p1, p2, p3, p4, p5); +} + +template +class _ConstTessMemberResultCallback_6_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _ConstTessMemberResultCallback_6_0(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_6_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _ConstTessMemberResultCallback_6_0(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_6_0::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_0(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_6_0::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_0(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +template +class _TessMemberResultCallback_6_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessMemberResultCallback_6_0( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run() { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_6_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessMemberResultCallback_6_0( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run() { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_6_0::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_0(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_6_0::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_0(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +template +class _TessFunctionResultCallback_6_0 : public TessResultCallback { + public: + typedef TessResultCallback base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,P6); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessFunctionResultCallback_6_0(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run() { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_6_0 : public TessClosure { + public: + typedef TessClosure base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,P6); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessFunctionResultCallback_6_0(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run() { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_); + } else { + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_6_0::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,P6), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_0(function, p1, p2, p3, p4, p5, p6); +} + +template +inline typename _TessFunctionResultCallback_6_0::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,P6), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_0(function, p1, p2, p3, p4, p5, p6); +} + template class TessCallback1 { public: - virtual ~TessCallback1() { } - virtual void Run(A1) = 0; + virtual ~TessCallback1() { } + virtual void Run(A1) = 0; +}; + +template +class TessResultCallback1 { + public: + virtual ~TessResultCallback1() { } + virtual R Run(A1) = 0; +}; + + +template +class TessCallback2 { + public: + virtual ~TessCallback2() { } + virtual void Run(A1,A2) = 0; +}; + +template +class TessResultCallback2 { + public: + virtual ~TessResultCallback2() { } + virtual R Run(A1,A2) = 0; +}; + +template +class TessCallback3 { + public: + virtual ~TessCallback3() { } + virtual void Run(A1,A2,A3) = 0; +}; + +template +class TessResultCallback3 { + public: + virtual ~TessResultCallback3() { } + virtual R Run(A1,A2,A3) = 0; +}; + +template +class TessCallback4 { + public: + virtual ~TessCallback4() { } + virtual void Run(A1,A2,A3,A4) = 0; +}; + +template +class TessResultCallback4 { + public: + virtual ~TessResultCallback4() { } + virtual R Run(A1,A2,A3,A4) = 0; +}; + +template +class _ConstTessMemberResultCallback_0_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(A1) const; + + private: + const T* object_; + MemberSignature member_; + + public: + inline _ConstTessMemberResultCallback_0_1( + const T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(a1); + return result; + } else { + R result = (object_->*member_)(a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_0_1 + : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(A1) const; + + private: + const T* object_; + MemberSignature member_; + + public: + inline _ConstTessMemberResultCallback_0_1( + const T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(a1); + } else { + (object_->*member_)(a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_0_1::base* +NewTessCallback( + const T1* obj, R (T2::*member)(A1) const) { + return new _ConstTessMemberResultCallback_0_1( + obj, member); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_0_1::base* +NewPermanentTessCallback( + const T1* obj, R (T2::*member)(A1) const) { + return new _ConstTessMemberResultCallback_0_1( + obj, member); +} +#endif + +template +class _TessMemberResultCallback_0_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(A1) ; + + private: + T* object_; + MemberSignature member_; + + public: + inline _TessMemberResultCallback_0_1( + T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(a1); + return result; + } else { + R result = (object_->*member_)(a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_0_1 + : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(A1) ; + + private: + T* object_; + MemberSignature member_; + + public: + inline _TessMemberResultCallback_0_1( + T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(a1); + } else { + (object_->*member_)(a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_0_1::base* +NewTessCallback( + T1* obj, R (T2::*member)(A1) ) { + return new _TessMemberResultCallback_0_1( + obj, member); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_0_1::base* +NewPermanentTessCallback( + T1* obj, R (T2::*member)(A1) ) { + return new _TessMemberResultCallback_0_1( + obj, member); +} +#endif + +template +class _TessFunctionResultCallback_0_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (*FunctionSignature)(A1); + + private: + FunctionSignature function_; + + public: + inline _TessFunctionResultCallback_0_1( + FunctionSignature function) + : function_(function) { + } + + virtual R Run(A1 a1) { + if (!del) { + R result = (*function_)(a1); + return result; + } else { + R result = (*function_)(a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_0_1 + : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (*FunctionSignature)(A1); + + private: + FunctionSignature function_; + + public: + inline _TessFunctionResultCallback_0_1( + FunctionSignature function) + : function_(function) { + } + + virtual void Run(A1 a1) { + if (!del) { + (*function_)(a1); + } else { + (*function_)(a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_0_1::base* +NewTessCallback(R (*function)(A1)) { + return new _TessFunctionResultCallback_0_1(function); +} + +template +inline typename _TessFunctionResultCallback_0_1::base* +NewPermanentTessCallback(R (*function)(A1)) { + return new _TessFunctionResultCallback_0_1(function); +} + +template +class _ConstTessMemberResultCallback_1_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_1(const T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_1_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_1(const T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,a1); + } else { + (object_->*member_)(p1_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_1::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,A1) const, typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_1(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_1::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,A1) const, typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_1(obj, member, p1); +} +#endif + +template +class _TessMemberResultCallback_1_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_1( T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_1_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_1( T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,a1); + } else { + (object_->*member_)(p1_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_1::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,A1) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_1(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_1::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,A1) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_1(obj, member, p1); +} +#endif + +template +class _TessFunctionResultCallback_1_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (*FunctionSignature)(P1,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_1(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (*function_)(p1_,a1); + return result; + } else { + R result = (*function_)(p1_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_1_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (*FunctionSignature)(P1,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_1(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual void Run(A1 a1) { + if (!del) { + (*function_)(p1_,a1); + } else { + (*function_)(p1_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_1_1::base* +NewTessCallback(R (*function)(P1,A1), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_1(function, p1); +} + +template +inline typename _TessFunctionResultCallback_1_1::base* +NewPermanentTessCallback(R (*function)(P1,A1), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_1(function, p1); +} + +template +class _ConstTessMemberResultCallback_2_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,P2,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_1(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_2_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,P2,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_1(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,p2_,a1); + } else { + (object_->*member_)(p1_,p2_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_1::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,A1) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_1(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_1::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,A1) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_1(obj, member, p1, p2); +} +#endif + +template +class _TessMemberResultCallback_2_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,P2,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_1( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_2_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,P2,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_1( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,p2_,a1); + } else { + (object_->*member_)(p1_,p2_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_1::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,A1) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_1(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_1::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,A1) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_1(obj, member, p1, p2); +} +#endif + +template +class _TessFunctionResultCallback_2_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (*FunctionSignature)(P1,P2,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_1(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (*function_)(p1_,p2_,a1); + return result; + } else { + R result = (*function_)(p1_,p2_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_2_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (*FunctionSignature)(P1,P2,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_1(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1) { + if (!del) { + (*function_)(p1_,p2_,a1); + } else { + (*function_)(p1_,p2_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_2_1::base* +NewTessCallback(R (*function)(P1,P2,A1), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_1(function, p1, p2); +} + +template +inline typename _TessFunctionResultCallback_2_1::base* +NewPermanentTessCallback(R (*function)(P1,P2,A1), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_1(function, p1, p2); +} + +template +class _ConstTessMemberResultCallback_3_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,P2,P3,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _ConstTessMemberResultCallback_3_1(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_3_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,P2,P3,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _ConstTessMemberResultCallback_3_1(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,a1); + } else { + (object_->*member_)(p1_,p2_,p3_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_3_1::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,A1) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_1(obj, member, p1, p2, p3); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_3_1::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,A1) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_1(obj, member, p1, p2, p3); +} +#endif + +template +class _TessMemberResultCallback_3_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,P2,P3,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessMemberResultCallback_3_1( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_3_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,P2,P3,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessMemberResultCallback_3_1( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,a1); + } else { + (object_->*member_)(p1_,p2_,p3_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_3_1::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,A1) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_1(obj, member, p1, p2, p3); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_3_1::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,A1) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_1(obj, member, p1, p2, p3); +} +#endif + +template +class _TessFunctionResultCallback_3_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (*FunctionSignature)(P1,P2,P3,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessFunctionResultCallback_3_1(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,a1); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_3_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (*FunctionSignature)(P1,P2,P3,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessFunctionResultCallback_3_1(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1) { + if (!del) { + (*function_)(p1_,p2_,p3_,a1); + } else { + (*function_)(p1_,p2_,p3_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_3_1::base* +NewTessCallback(R (*function)(P1,P2,P3,A1), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_1(function, p1, p2, p3); +} + +template +inline typename _TessFunctionResultCallback_3_1::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,A1), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_1(function, p1, p2, p3); +} + +template +class _ConstTessMemberResultCallback_4_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _ConstTessMemberResultCallback_4_1(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_4_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _ConstTessMemberResultCallback_4_1(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,a1); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_4_1::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,A1) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_1(obj, member, p1, p2, p3, p4); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_4_1::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,A1) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_1(obj, member, p1, p2, p3, p4); +} +#endif + +template +class _TessMemberResultCallback_4_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessMemberResultCallback_4_1( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_4_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessMemberResultCallback_4_1( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,a1); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_4_1::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,A1) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_1(obj, member, p1, p2, p3, p4); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_4_1::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,A1) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_1(obj, member, p1, p2, p3, p4); +} +#endif + +template +class _TessFunctionResultCallback_4_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessFunctionResultCallback_4_1(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,a1); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_4_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessFunctionResultCallback_4_1(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,a1); + } else { + (*function_)(p1_,p2_,p3_,p4_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_4_1::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,A1), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_1(function, p1, p2, p3, p4); +} + +template +inline typename _TessFunctionResultCallback_4_1::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,A1), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_1(function, p1, p2, p3, p4); +} + +template +class _ConstTessMemberResultCallback_5_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _ConstTessMemberResultCallback_5_1(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_5_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _ConstTessMemberResultCallback_5_1(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_5_1::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_1(obj, member, p1, p2, p3, p4, p5); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_5_1::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_1(obj, member, p1, p2, p3, p4, p5); +} +#endif + +template +class _TessMemberResultCallback_5_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessMemberResultCallback_5_1( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_5_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessMemberResultCallback_5_1( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_5_1::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_1(obj, member, p1, p2, p3, p4, p5); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_5_1::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_1(obj, member, p1, p2, p3, p4, p5); +} +#endif + +template +class _TessFunctionResultCallback_5_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessFunctionResultCallback_5_1(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,a1); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_5_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessFunctionResultCallback_5_1(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,p5_,a1); + } else { + (*function_)(p1_,p2_,p3_,p4_,p5_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_5_1::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,A1), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_1(function, p1, p2, p3, p4, p5); +} + +template +inline typename _TessFunctionResultCallback_5_1::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,A1), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_1(function, p1, p2, p3, p4, p5); +} + +template +class _ConstTessMemberResultCallback_6_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _ConstTessMemberResultCallback_6_1(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_6_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _ConstTessMemberResultCallback_6_1(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_6_1::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_1(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_6_1::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_1(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +template +class _TessMemberResultCallback_6_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessMemberResultCallback_6_1( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_6_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessMemberResultCallback_6_1( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_6_1::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_1(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_6_1::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_1(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +template +class _TessFunctionResultCallback_6_1 : public TessResultCallback1 { + public: + typedef TessResultCallback1 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,P6,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessFunctionResultCallback_6_1(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_6_1 : public TessCallback1 { + public: + typedef TessCallback1 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,P6,A1); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessFunctionResultCallback_6_1(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + } else { + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_6_1::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,P6,A1), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_1(function, p1, p2, p3, p4, p5, p6); +} + +template +inline typename _TessFunctionResultCallback_6_1::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,P6,A1), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_1(function, p1, p2, p3, p4, p5, p6); +} + +template +class _ConstTessMemberResultCallback_0_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + + public: + inline _ConstTessMemberResultCallback_0_2( + const T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(a1,a2); + return result; + } else { + R result = (object_->*member_)(a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_0_2 + : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + + public: + inline _ConstTessMemberResultCallback_0_2( + const T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(a1,a2); + } else { + (object_->*member_)(a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_0_2::base* +NewTessCallback( + const T1* obj, R (T2::*member)(A1,A2) const) { + return new _ConstTessMemberResultCallback_0_2( + obj, member); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_0_2::base* +NewPermanentTessCallback( + const T1* obj, R (T2::*member)(A1,A2) const) { + return new _ConstTessMemberResultCallback_0_2( + obj, member); +} +#endif + +template +class _TessMemberResultCallback_0_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(A1,A2) ; + + private: + T* object_; + MemberSignature member_; + + public: + inline _TessMemberResultCallback_0_2( + T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(a1,a2); + return result; + } else { + R result = (object_->*member_)(a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_0_2 + : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(A1,A2) ; + + private: + T* object_; + MemberSignature member_; + + public: + inline _TessMemberResultCallback_0_2( + T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(a1,a2); + } else { + (object_->*member_)(a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_0_2::base* +NewTessCallback( + T1* obj, R (T2::*member)(A1,A2) ) { + return new _TessMemberResultCallback_0_2( + obj, member); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_0_2::base* +NewPermanentTessCallback( + T1* obj, R (T2::*member)(A1,A2) ) { + return new _TessMemberResultCallback_0_2( + obj, member); +} +#endif + +template +class _TessFunctionResultCallback_0_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (*FunctionSignature)(A1,A2); + + private: + FunctionSignature function_; + + public: + inline _TessFunctionResultCallback_0_2( + FunctionSignature function) + : function_(function) { + } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (*function_)(a1,a2); + return result; + } else { + R result = (*function_)(a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_0_2 + : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (*FunctionSignature)(A1,A2); + + private: + FunctionSignature function_; + + public: + inline _TessFunctionResultCallback_0_2( + FunctionSignature function) + : function_(function) { + } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (*function_)(a1,a2); + } else { + (*function_)(a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_0_2::base* +NewTessCallback(R (*function)(A1,A2)) { + return new _TessFunctionResultCallback_0_2(function); +} + +template +inline typename _TessFunctionResultCallback_0_2::base* +NewPermanentTessCallback(R (*function)(A1,A2)) { + return new _TessFunctionResultCallback_0_2(function); +} + +template +class _ConstTessMemberResultCallback_1_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_2(const T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_1_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_2(const T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,a1,a2); + } else { + (object_->*member_)(p1_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_2::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,A1,A2) const, typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_2(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_2::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,A1,A2) const, typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_2(obj, member, p1); +} +#endif + +template +class _TessMemberResultCallback_1_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_2( T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_1_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_2( T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,a1,a2); + } else { + (object_->*member_)(p1_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_2::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,A1,A2) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_2(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_2::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,A1,A2) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_2(obj, member, p1); +} +#endif + +template +class _TessFunctionResultCallback_1_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (*FunctionSignature)(P1,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_2(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (*function_)(p1_,a1,a2); + return result; + } else { + R result = (*function_)(p1_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_1_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (*FunctionSignature)(P1,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_2(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (*function_)(p1_,a1,a2); + } else { + (*function_)(p1_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_1_2::base* +NewTessCallback(R (*function)(P1,A1,A2), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_2(function, p1); +} + +template +inline typename _TessFunctionResultCallback_1_2::base* +NewPermanentTessCallback(R (*function)(P1,A1,A2), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_2(function, p1); +} + +template +class _ConstTessMemberResultCallback_2_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,P2,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_2(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_2_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,P2,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_2(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,p2_,a1,a2); + } else { + (object_->*member_)(p1_,p2_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_2::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,A1,A2) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_2(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_2::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,A1,A2) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_2(obj, member, p1, p2); +} +#endif + +template +class _TessMemberResultCallback_2_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,P2,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_2( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_2_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,P2,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_2( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,p2_,a1,a2); + } else { + (object_->*member_)(p1_,p2_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_2::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,A1,A2) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_2(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_2::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,A1,A2) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_2(obj, member, p1, p2); +} +#endif + +template +class _TessFunctionResultCallback_2_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (*FunctionSignature)(P1,P2,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_2(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (*function_)(p1_,p2_,a1,a2); + return result; + } else { + R result = (*function_)(p1_,p2_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_2_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (*FunctionSignature)(P1,P2,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_2(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (*function_)(p1_,p2_,a1,a2); + } else { + (*function_)(p1_,p2_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_2_2::base* +NewTessCallback(R (*function)(P1,P2,A1,A2), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_2(function, p1, p2); +} + +template +inline typename _TessFunctionResultCallback_2_2::base* +NewPermanentTessCallback(R (*function)(P1,P2,A1,A2), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_2(function, p1, p2); +} + +template +class _ConstTessMemberResultCallback_3_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,P2,P3,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _ConstTessMemberResultCallback_3_2(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_3_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,P2,P3,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _ConstTessMemberResultCallback_3_2(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,a1,a2); + } else { + (object_->*member_)(p1_,p2_,p3_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_3_2::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,A1,A2) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_2(obj, member, p1, p2, p3); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_3_2::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,A1,A2) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_2(obj, member, p1, p2, p3); +} +#endif + +template +class _TessMemberResultCallback_3_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,P2,P3,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessMemberResultCallback_3_2( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_3_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,P2,P3,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessMemberResultCallback_3_2( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,a1,a2); + } else { + (object_->*member_)(p1_,p2_,p3_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_3_2::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,A1,A2) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_2(obj, member, p1, p2, p3); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_3_2::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,A1,A2) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_2(obj, member, p1, p2, p3); +} +#endif + +template +class _TessFunctionResultCallback_3_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (*FunctionSignature)(P1,P2,P3,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessFunctionResultCallback_3_2(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,a1,a2); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_3_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (*FunctionSignature)(P1,P2,P3,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessFunctionResultCallback_3_2(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (*function_)(p1_,p2_,p3_,a1,a2); + } else { + (*function_)(p1_,p2_,p3_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_3_2::base* +NewTessCallback(R (*function)(P1,P2,P3,A1,A2), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_2(function, p1, p2, p3); +} + +template +inline typename _TessFunctionResultCallback_3_2::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,A1,A2), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_2(function, p1, p2, p3); +} + +template +class _ConstTessMemberResultCallback_4_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _ConstTessMemberResultCallback_4_2(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_4_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _ConstTessMemberResultCallback_4_2(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_4_2::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_2(obj, member, p1, p2, p3, p4); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_4_2::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_2(obj, member, p1, p2, p3, p4); +} +#endif + +template +class _TessMemberResultCallback_4_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessMemberResultCallback_4_2( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_4_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessMemberResultCallback_4_2( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_4_2::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_2(obj, member, p1, p2, p3, p4); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_4_2::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_2(obj, member, p1, p2, p3, p4); +} +#endif + +template +class _TessFunctionResultCallback_4_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessFunctionResultCallback_4_2(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,a1,a2); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_4_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessFunctionResultCallback_4_2(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,a1,a2); + } else { + (*function_)(p1_,p2_,p3_,p4_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_4_2::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,A1,A2), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_2(function, p1, p2, p3, p4); +} + +template +inline typename _TessFunctionResultCallback_4_2::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,A1,A2), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_2(function, p1, p2, p3, p4); +} + +template +class _ConstTessMemberResultCallback_5_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _ConstTessMemberResultCallback_5_2(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_5_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _ConstTessMemberResultCallback_5_2(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_5_2::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_2(obj, member, p1, p2, p3, p4, p5); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_5_2::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_2(obj, member, p1, p2, p3, p4, p5); +} +#endif + +template +class _TessMemberResultCallback_5_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessMemberResultCallback_5_2( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_5_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessMemberResultCallback_5_2( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_5_2::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_2(obj, member, p1, p2, p3, p4, p5); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_5_2::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_2(obj, member, p1, p2, p3, p4, p5); +} +#endif + +template +class _TessFunctionResultCallback_5_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessFunctionResultCallback_5_2(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_5_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessFunctionResultCallback_5_2(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + } else { + (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_5_2::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,A1,A2), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_2(function, p1, p2, p3, p4, p5); +} + +template +inline typename _TessFunctionResultCallback_5_2::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,A1,A2), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_2(function, p1, p2, p3, p4, p5); +} + +template +class _ConstTessMemberResultCallback_6_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _ConstTessMemberResultCallback_6_2(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_6_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _ConstTessMemberResultCallback_6_2(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_6_2::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_2(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_6_2::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_2(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +template +class _TessMemberResultCallback_6_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessMemberResultCallback_6_2( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_6_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessMemberResultCallback_6_2( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_6_2::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_2(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_6_2::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_2(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +template +class _TessFunctionResultCallback_6_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,P6,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessFunctionResultCallback_6_2(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1,A2 a2) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_6_2 : public TessCallback2 { + public: + typedef TessCallback2 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,P6,A1,A2); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessFunctionResultCallback_6_2(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1,A2 a2) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + } else { + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_6_2::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,P6,A1,A2), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_2(function, p1, p2, p3, p4, p5, p6); +} + +template +inline typename _TessFunctionResultCallback_6_2::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,P6,A1,A2), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_2(function, p1, p2, p3, p4, p5, p6); +} + +template +class _ConstTessMemberResultCallback_0_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + + public: + inline _ConstTessMemberResultCallback_0_3( + const T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_0_3 + : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + + public: + inline _ConstTessMemberResultCallback_0_3( + const T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(a1,a2,a3); + } else { + (object_->*member_)(a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_0_3::base* +NewTessCallback( + const T1* obj, R (T2::*member)(A1,A2,A3) const) { + return new _ConstTessMemberResultCallback_0_3( + obj, member); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_0_3::base* +NewPermanentTessCallback( + const T1* obj, R (T2::*member)(A1,A2,A3) const) { + return new _ConstTessMemberResultCallback_0_3( + obj, member); +} +#endif + +template +class _TessMemberResultCallback_0_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + + public: + inline _TessMemberResultCallback_0_3( + T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_0_3 + : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + + public: + inline _TessMemberResultCallback_0_3( + T* object, MemberSignature member) + : object_(object), + member_(member) { + } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(a1,a2,a3); + } else { + (object_->*member_)(a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_0_3::base* +NewTessCallback( + T1* obj, R (T2::*member)(A1,A2,A3) ) { + return new _TessMemberResultCallback_0_3( + obj, member); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_0_3::base* +NewPermanentTessCallback( + T1* obj, R (T2::*member)(A1,A2,A3) ) { + return new _TessMemberResultCallback_0_3( + obj, member); +} +#endif + +template +class _TessFunctionResultCallback_0_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (*FunctionSignature)(A1,A2,A3); + + private: + FunctionSignature function_; + + public: + inline _TessFunctionResultCallback_0_3( + FunctionSignature function) + : function_(function) { + } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (*function_)(a1,a2,a3); + return result; + } else { + R result = (*function_)(a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_0_3 + : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (*FunctionSignature)(A1,A2,A3); + + private: + FunctionSignature function_; + + public: + inline _TessFunctionResultCallback_0_3( + FunctionSignature function) + : function_(function) { + } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (*function_)(a1,a2,a3); + } else { + (*function_)(a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_0_3::base* +NewTessCallback(R (*function)(A1,A2,A3)) { + return new _TessFunctionResultCallback_0_3(function); +} + +template +inline typename _TessFunctionResultCallback_0_3::base* +NewPermanentTessCallback(R (*function)(A1,A2,A3)) { + return new _TessFunctionResultCallback_0_3(function); +} + +template +class _ConstTessMemberResultCallback_1_3 + : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,A1,A2,A3) const; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_3(T* object, + MemberSignature member, P1 p1) + : object_(object), member_(member), p1_(p1) { } + + virtual R Run(A1 a1, A2 a2, A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_1_3 + : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,A1,A2,A3) const; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_3(T* object, + MemberSignature member, P1 p1) + : object_(object), member_(member), p1_(p1) { } + + virtual void Run(A1 a1, A2 a2, A3 a3) { + if (!del) { + (object_->*member_)(p1_,a1,a2,a3); + } else { + (object_->*member_)(p1_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_3::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3) , typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_3(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_3::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3) , typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_3(obj, member, p1); +} +#endif + +template +class _TessMemberResultCallback_1_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_3(T* object, + MemberSignature member, P1 p1) + : object_(object), member_(member), p1_(p1) { } + + virtual R Run(A1 a1, A2 a2, A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_1_3 + : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_3(T* object, + MemberSignature member, P1 p1) + : object_(object), member_(member), p1_(p1) { } + + virtual void Run(A1 a1, A2 a2, A3 a3) { + if (!del) { + (object_->*member_)(p1_,a1,a2,a3); + } else { + (object_->*member_)(p1_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_3::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_3(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_3::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_3(obj, member, p1); +} +#endif + +template +class _TessFunctionResultCallback_1_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef R (*FunctionSignature)(P1,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_3(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual R Run(A1 a1, A2 a2, A3 a3) { + if (!del) { + R result = (*function_)(p1_,a1,a2,a3); + return result; + } else { + R result = (*function_)(p1_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_1_3 + : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (*FunctionSignature)(P1,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_3(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual void Run(A1 a1, A2 a2, A3 a3) { + if (!del) { + (*function_)(p1_,a1,a2,a3); + } else { + (*function_)(p1_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_1_3::base* +NewTessCallback(R (*function)(P1,A1,A2,A3), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_3(function, p1); +} + +template +inline typename _TessFunctionResultCallback_1_3::base* +NewPermanentTessCallback(R (*function)(P1,A1,A2,A3), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_3(function, p1); +} + +template +class _ConstTessMemberResultCallback_2_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,P2,A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_3(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_2_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,P2,A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_3(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(p1_,p2_,a1,a2,a3); + } else { + (object_->*member_)(p1_,p2_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_3::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,A1,A2,A3) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_3(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_3::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,A1,A2,A3) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_3(obj, member, p1, p2); +} +#endif + +template +class _TessMemberResultCallback_2_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,P2,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_3( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_2_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,P2,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_3( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(p1_,p2_,a1,a2,a3); + } else { + (object_->*member_)(p1_,p2_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_3::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,A1,A2,A3) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_3(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_3::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,A1,A2,A3) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_3(obj, member, p1, p2); +} +#endif + +template +class _TessFunctionResultCallback_2_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (*FunctionSignature)(P1,P2,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_3(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (*function_)(p1_,p2_,a1,a2,a3); + return result; + } else { + R result = (*function_)(p1_,p2_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_2_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (*FunctionSignature)(P1,P2,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_3(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (*function_)(p1_,p2_,a1,a2,a3); + } else { + (*function_)(p1_,p2_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_2_3::base* +NewTessCallback(R (*function)(P1,P2,A1,A2,A3), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_3(function, p1, p2); +} + +template +inline typename _TessFunctionResultCallback_2_3::base* +NewPermanentTessCallback(R (*function)(P1,P2,A1,A2,A3), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_3(function, p1, p2); +} + +template +class _ConstTessMemberResultCallback_3_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,P2,P3,A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _ConstTessMemberResultCallback_3_3(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_3_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,P2,P3,A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _ConstTessMemberResultCallback_3_3(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3); + } else { + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_3_3::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_3(obj, member, p1, p2, p3); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_3_3::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_3(obj, member, p1, p2, p3); +} +#endif + +template +class _TessMemberResultCallback_3_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,P2,P3,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessMemberResultCallback_3_3( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_3_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,P2,P3,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessMemberResultCallback_3_3( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3); + } else { + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_3_3::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_3(obj, member, p1, p2, p3); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_3_3::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_3(obj, member, p1, p2, p3); +} +#endif + +template +class _TessFunctionResultCallback_3_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (*FunctionSignature)(P1,P2,P3,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessFunctionResultCallback_3_3(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,a1,a2,a3); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_3_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (*FunctionSignature)(P1,P2,P3,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessFunctionResultCallback_3_3(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (*function_)(p1_,p2_,p3_,a1,a2,a3); + } else { + (*function_)(p1_,p2_,p3_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_3_3::base* +NewTessCallback(R (*function)(P1,P2,P3,A1,A2,A3), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_3(function, p1, p2, p3); +} + +template +inline typename _TessFunctionResultCallback_3_3::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,A1,A2,A3), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_3(function, p1, p2, p3); +} + +template +class _ConstTessMemberResultCallback_4_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _ConstTessMemberResultCallback_4_3(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_4_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _ConstTessMemberResultCallback_4_3(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_4_3::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_3(obj, member, p1, p2, p3, p4); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_4_3::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_3(obj, member, p1, p2, p3, p4); +} +#endif + +template +class _TessMemberResultCallback_4_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessMemberResultCallback_4_3( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_4_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessMemberResultCallback_4_3( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_4_3::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_3(obj, member, p1, p2, p3, p4); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_4_3::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_3(obj, member, p1, p2, p3, p4); +} +#endif + +template +class _TessFunctionResultCallback_4_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessFunctionResultCallback_4_3(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_4_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessFunctionResultCallback_4_3(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3); + } else { + (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_4_3::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,A1,A2,A3), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_3(function, p1, p2, p3, p4); +} + +template +inline typename _TessFunctionResultCallback_4_3::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,A1,A2,A3), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_3(function, p1, p2, p3, p4); +} + +template +class _ConstTessMemberResultCallback_5_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _ConstTessMemberResultCallback_5_3(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_5_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _ConstTessMemberResultCallback_5_3(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_5_3::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_3(obj, member, p1, p2, p3, p4, p5); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_5_3::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_3(obj, member, p1, p2, p3, p4, p5); +} +#endif + +template +class _TessMemberResultCallback_5_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessMemberResultCallback_5_3( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_5_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessMemberResultCallback_5_3( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_5_3::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_3(obj, member, p1, p2, p3, p4, p5); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_5_3::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_3(obj, member, p1, p2, p3, p4, p5); +} +#endif + +template +class _TessFunctionResultCallback_5_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessFunctionResultCallback_5_3(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_5_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessFunctionResultCallback_5_3(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + } else { + (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_5_3::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,A1,A2,A3), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_3(function, p1, p2, p3, p4, p5); +} + +template +inline typename _TessFunctionResultCallback_5_3::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,A1,A2,A3), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_3(function, p1, p2, p3, p4, p5); +} + +template +class _ConstTessMemberResultCallback_6_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _ConstTessMemberResultCallback_6_3(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_6_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _ConstTessMemberResultCallback_6_3(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_6_3::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_3(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_6_3::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_3(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +template +class _TessMemberResultCallback_6_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessMemberResultCallback_6_3( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_6_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessMemberResultCallback_6_3( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_6_3::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_3(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_6_3::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_3(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +template +class _TessFunctionResultCallback_6_3 : public TessResultCallback3 { + public: + typedef TessResultCallback3 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessFunctionResultCallback_6_3(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_6_3 : public TessCallback3 { + public: + typedef TessCallback3 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessFunctionResultCallback_6_3(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1,A2 a2,A3 a3) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + } else { + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_6_3::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,P6,A1,A2,A3), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_3(function, p1, p2, p3, p4, p5, p6); +} + +template +inline typename _TessFunctionResultCallback_6_3::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,P6,A1,A2,A3), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_3(function, p1, p2, p3, p4, p5, p6); +} + +template +class _ConstTessMemberResultCallback_0_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + + public: + inline _ConstTessMemberResultCallback_0_4(const T* object, MemberSignature member) + : object_(object), + member_(member) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_0_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + + public: + inline _ConstTessMemberResultCallback_0_4(const T* object, MemberSignature member) + : object_(object), + member_(member) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(a1,a2,a3,a4); + } else { + (object_->*member_)(a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_0_4::base* +NewTessCallback(const T1* obj, R (T2::*member)(A1,A2,A3,A4) const) { + return new _ConstTessMemberResultCallback_0_4(obj, member); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_0_4::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(A1,A2,A3,A4) const) { + return new _ConstTessMemberResultCallback_0_4(obj, member); +} +#endif + +template +class _TessMemberResultCallback_0_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + + public: + inline _TessMemberResultCallback_0_4( T* object, MemberSignature member) + : object_(object), + member_(member) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_0_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + + public: + inline _TessMemberResultCallback_0_4( T* object, MemberSignature member) + : object_(object), + member_(member) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(a1,a2,a3,a4); + } else { + (object_->*member_)(a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_0_4::base* +NewTessCallback( T1* obj, R (T2::*member)(A1,A2,A3,A4) ) { + return new _TessMemberResultCallback_0_4(obj, member); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_0_4::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(A1,A2,A3,A4) ) { + return new _TessMemberResultCallback_0_4(obj, member); +} +#endif + +template +class _TessFunctionResultCallback_0_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (*FunctionSignature)(A1,A2,A3,A4); + + private: + FunctionSignature function_; + + public: + inline _TessFunctionResultCallback_0_4(FunctionSignature function) + : function_(function) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (*function_)(a1,a2,a3,a4); + return result; + } else { + R result = (*function_)(a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_0_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (*FunctionSignature)(A1,A2,A3,A4); + + private: + FunctionSignature function_; + + public: + inline _TessFunctionResultCallback_0_4(FunctionSignature function) + : function_(function) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (*function_)(a1,a2,a3,a4); + } else { + (*function_)(a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_0_4::base* +NewTessCallback(R (*function)(A1,A2,A3,A4)) { + return new _TessFunctionResultCallback_0_4(function); +} + +template +inline typename _TessFunctionResultCallback_0_4::base* +NewPermanentTessCallback(R (*function)(A1,A2,A3,A4)) { + return new _TessFunctionResultCallback_0_4(function); +} + +template +class _ConstTessMemberResultCallback_1_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_4(const T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_1_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_4(const T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_4::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,A1,A2,A3,A4) const, typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_4(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_4::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,A1,A2,A3,A4) const, typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_4(obj, member, p1); +} +#endif + +template +class _TessMemberResultCallback_1_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_4( T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_1_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_4( T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_4::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3,A4) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_4(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_4::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3,A4) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_4(obj, member, p1); +} +#endif + +template +class _TessFunctionResultCallback_1_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (*FunctionSignature)(P1,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_4(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (*function_)(p1_,a1,a2,a3,a4); + return result; + } else { + R result = (*function_)(p1_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_1_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (*FunctionSignature)(P1,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_4(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (*function_)(p1_,a1,a2,a3,a4); + } else { + (*function_)(p1_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_1_4::base* +NewTessCallback(R (*function)(P1,A1,A2,A3,A4), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_4(function, p1); +} + +template +inline typename _TessFunctionResultCallback_1_4::base* +NewPermanentTessCallback(R (*function)(P1,A1,A2,A3,A4), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_4(function, p1); +} + +template +class _ConstTessMemberResultCallback_2_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,P2,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_4(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_2_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,P2,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_4(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,p2_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,p2_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_4::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,A1,A2,A3,A4) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_4(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_4::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,A1,A2,A3,A4) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_4(obj, member, p1, p2); +} +#endif + +template +class _TessMemberResultCallback_2_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,P2,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_4( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_2_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,P2,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_4( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,p2_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,p2_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_4::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,A1,A2,A3,A4) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_4(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_4::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,A1,A2,A3,A4) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_4(obj, member, p1, p2); +} +#endif + +template +class _TessFunctionResultCallback_2_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (*FunctionSignature)(P1,P2,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_4(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (*function_)(p1_,p2_,a1,a2,a3,a4); + return result; + } else { + R result = (*function_)(p1_,p2_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_2_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (*FunctionSignature)(P1,P2,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_4(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (*function_)(p1_,p2_,a1,a2,a3,a4); + } else { + (*function_)(p1_,p2_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_2_4::base* +NewTessCallback(R (*function)(P1,P2,A1,A2,A3,A4), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_4(function, p1, p2); +} + +template +inline typename _TessFunctionResultCallback_2_4::base* +NewPermanentTessCallback(R (*function)(P1,P2,A1,A2,A3,A4), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_4(function, p1, p2); +} + +template +class _ConstTessMemberResultCallback_3_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,P2,P3,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _ConstTessMemberResultCallback_3_4(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_3_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,P2,P3,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _ConstTessMemberResultCallback_3_4(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_3_4::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3,A4) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_4(obj, member, p1, p2, p3); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_3_4::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3,A4) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_4(obj, member, p1, p2, p3); +} +#endif + +template +class _TessMemberResultCallback_3_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,P2,P3,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessMemberResultCallback_3_4( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_3_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,P2,P3,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessMemberResultCallback_3_4( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_3_4::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3,A4) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_4(obj, member, p1, p2, p3); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_3_4::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3,A4) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_4(obj, member, p1, p2, p3); +} +#endif + +template +class _TessFunctionResultCallback_3_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (*FunctionSignature)(P1,P2,P3,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessFunctionResultCallback_3_4(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,a1,a2,a3,a4); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_3_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (*FunctionSignature)(P1,P2,P3,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + + public: + inline _TessFunctionResultCallback_3_4(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (*function_)(p1_,p2_,p3_,a1,a2,a3,a4); + } else { + (*function_)(p1_,p2_,p3_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_3_4::base* +NewTessCallback(R (*function)(P1,P2,P3,A1,A2,A3,A4), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_4(function, p1, p2, p3); +} + +template +inline typename _TessFunctionResultCallback_3_4::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,A1,A2,A3,A4), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_4(function, p1, p2, p3); +} + +template +class _ConstTessMemberResultCallback_4_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _ConstTessMemberResultCallback_4_4(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_4_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _ConstTessMemberResultCallback_4_4(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_4_4::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3,A4) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_4(obj, member, p1, p2, p3, p4); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_4_4::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3,A4) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_4(obj, member, p1, p2, p3, p4); +} +#endif + +template +class _TessMemberResultCallback_4_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessMemberResultCallback_4_4( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_4_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessMemberResultCallback_4_4( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_4_4::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3,A4) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_4(obj, member, p1, p2, p3, p4); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_4_4::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3,A4) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_4(obj, member, p1, p2, p3, p4); +} +#endif + +template +class _TessFunctionResultCallback_4_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessFunctionResultCallback_4_4(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_4_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + + public: + inline _TessFunctionResultCallback_4_4(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + } else { + (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_4_4::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,A1,A2,A3,A4), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_4(function, p1, p2, p3, p4); +} + +template +inline typename _TessFunctionResultCallback_4_4::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,A1,A2,A3,A4), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_4(function, p1, p2, p3, p4); +} + +template +class _ConstTessMemberResultCallback_5_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _ConstTessMemberResultCallback_5_4(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_5_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _ConstTessMemberResultCallback_5_4(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_5_4::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3,A4) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_4(obj, member, p1, p2, p3, p4, p5); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_5_4::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3,A4) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_4(obj, member, p1, p2, p3, p4, p5); +} +#endif + +template +class _TessMemberResultCallback_5_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessMemberResultCallback_5_4( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_5_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessMemberResultCallback_5_4( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_5_4::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3,A4) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_4(obj, member, p1, p2, p3, p4, p5); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_5_4::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3,A4) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_4(obj, member, p1, p2, p3, p4, p5); +} +#endif + +template +class _TessFunctionResultCallback_5_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessFunctionResultCallback_5_4(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_5_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + + public: + inline _TessFunctionResultCallback_5_4(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + } else { + (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_5_4::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,A1,A2,A3,A4), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_4(function, p1, p2, p3, p4, p5); +} + +template +inline typename _TessFunctionResultCallback_5_4::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,A1,A2,A3,A4), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_4(function, p1, p2, p3, p4, p5); +} + +template +class _ConstTessMemberResultCallback_6_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _ConstTessMemberResultCallback_6_4(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_6_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _ConstTessMemberResultCallback_6_4(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_6_4::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_4(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_6_4::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_4(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +template +class _TessMemberResultCallback_6_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessMemberResultCallback_6_4( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_6_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessMemberResultCallback_6_4( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + } else { + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_6_4::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_4(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_6_4::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_4(obj, member, p1, p2, p3, p4, p5, p6); +} +#endif + +template +class _TessFunctionResultCallback_6_4 : public TessResultCallback4 { + public: + typedef TessResultCallback4 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessFunctionResultCallback_6_4(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + return result; + } else { + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_6_4 : public TessCallback4 { + public: + typedef TessCallback4 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; + + public: + inline _TessFunctionResultCallback_6_4(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4) { + if (!del) { + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + } else { + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_6_4::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_4(function, p1, p2, p3, p4, p5, p6); +} + +template +inline typename _TessFunctionResultCallback_6_4::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_4(function, p1, p2, p3, p4, p5, p6); +} + +template +class TessCallback5 { + public: + virtual ~TessCallback5() { } + virtual void Run(A1,A2,A3,A4,A5) = 0; +}; + +template +class TessResultCallback5 { + public: + virtual ~TessResultCallback5() { } + virtual R Run(A1,A2,A3,A4,A5) = 0; +}; + +template +class _ConstTessMemberResultCallback_0_5 : public TessResultCallback5 { + public: + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(A1,A2,A3,A4,A5) const; + + private: + const T* object_; + MemberSignature member_; + + public: + inline _ConstTessMemberResultCallback_0_5(const T* object, MemberSignature member) + : object_(object), + member_(member) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + R result = (object_->*member_)(a1,a2,a3,a4,a5); + return result; + } else { + R result = (object_->*member_)(a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_0_5 : public TessCallback5 { + public: + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(A1,A2,A3,A4,A5) const; + + private: + const T* object_; + MemberSignature member_; + + public: + inline _ConstTessMemberResultCallback_0_5(const T* object, MemberSignature member) + : object_(object), + member_(member) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + (object_->*member_)(a1,a2,a3,a4,a5); + } else { + (object_->*member_)(a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_0_5::base* +NewTessCallback(const T1* obj, R (T2::*member)(A1,A2,A3,A4,A5) const) { + return new _ConstTessMemberResultCallback_0_5(obj, member); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_0_5::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(A1,A2,A3,A4,A5) const) { + return new _ConstTessMemberResultCallback_0_5(obj, member); +} +#endif + +template +class _TessMemberResultCallback_0_5 : public TessResultCallback5 { + public: + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(A1,A2,A3,A4,A5) ; + + private: + T* object_; + MemberSignature member_; + + public: + inline _TessMemberResultCallback_0_5( T* object, MemberSignature member) + : object_(object), + member_(member) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + R result = (object_->*member_)(a1,a2,a3,a4,a5); + return result; + } else { + R result = (object_->*member_)(a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_0_5 : public TessCallback5 { + public: + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(A1,A2,A3,A4,A5) ; + + private: + T* object_; + MemberSignature member_; + + public: + inline _TessMemberResultCallback_0_5( T* object, MemberSignature member) + : object_(object), + member_(member) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + (object_->*member_)(a1,a2,a3,a4,a5); + } else { + (object_->*member_)(a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_0_5::base* +NewTessCallback( T1* obj, R (T2::*member)(A1,A2,A3,A4,A5) ) { + return new _TessMemberResultCallback_0_5(obj, member); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_0_5::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(A1,A2,A3,A4,A5) ) { + return new _TessMemberResultCallback_0_5(obj, member); +} +#endif + +template +class _TessFunctionResultCallback_0_5 : public TessResultCallback5 { + public: + typedef TessResultCallback5 base; + typedef R (*FunctionSignature)(A1,A2,A3,A4,A5); + + private: + FunctionSignature function_; + + public: + inline _TessFunctionResultCallback_0_5(FunctionSignature function) + : function_(function) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + R result = (*function_)(a1,a2,a3,a4,a5); + return result; + } else { + R result = (*function_)(a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_0_5 : public TessCallback5 { + public: + typedef TessCallback5 base; + typedef void (*FunctionSignature)(A1,A2,A3,A4,A5); + + private: + FunctionSignature function_; + + public: + inline _TessFunctionResultCallback_0_5(FunctionSignature function) + : function_(function) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + (*function_)(a1,a2,a3,a4,a5); + } else { + (*function_)(a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_0_5::base* +NewTessCallback(R (*function)(A1,A2,A3,A4,A5)) { + return new _TessFunctionResultCallback_0_5(function); +} + +template +inline typename _TessFunctionResultCallback_0_5::base* +NewPermanentTessCallback(R (*function)(A1,A2,A3,A4,A5)) { + return new _TessFunctionResultCallback_0_5(function); +} + +template +class _ConstTessMemberResultCallback_1_5 : public TessResultCallback5 { + public: + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,A1,A2,A3,A4,A5) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_5(const T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + R result = (object_->*member_)(p1_,a1,a2,a3,a4,a5); + return result; + } else { + R result = (object_->*member_)(p1_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_1_5 : public TessCallback5 { + public: + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,A1,A2,A3,A4,A5) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _ConstTessMemberResultCallback_1_5(const T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + (object_->*member_)(p1_,a1,a2,a3,a4,a5); + } else { + (object_->*member_)(p1_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_5::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,A1,A2,A3,A4,A5) const, typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_5(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_1_5::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,A1,A2,A3,A4,A5) const, typename Identity::type p1) { + return new _ConstTessMemberResultCallback_1_5(obj, member, p1); +} +#endif + +template +class _TessMemberResultCallback_1_5 : public TessResultCallback5 { + public: + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,A1,A2,A3,A4,A5) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_5( T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + R result = (object_->*member_)(p1_,a1,a2,a3,a4,a5); + return result; + } else { + R result = (object_->*member_)(p1_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_1_5 : public TessCallback5 { + public: + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,A1,A2,A3,A4,A5) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + + public: + inline _TessMemberResultCallback_1_5( T* object, MemberSignature member, P1 p1) + : object_(object), + member_(member), p1_(p1) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + (object_->*member_)(p1_,a1,a2,a3,a4,a5); + } else { + (object_->*member_)(p1_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_5::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3,A4,A5) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_5(obj, member, p1); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_1_5::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3,A4,A5) , typename Identity::type p1) { + return new _TessMemberResultCallback_1_5(obj, member, p1); +} +#endif + +template +class _TessFunctionResultCallback_1_5 : public TessResultCallback5 { + public: + typedef TessResultCallback5 base; + typedef R (*FunctionSignature)(P1,A1,A2,A3,A4,A5); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_5(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + R result = (*function_)(p1_,a1,a2,a3,a4,a5); + return result; + } else { + R result = (*function_)(p1_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessFunctionResultCallback_1_5 : public TessCallback5 { + public: + typedef TessCallback5 base; + typedef void (*FunctionSignature)(P1,A1,A2,A3,A4,A5); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + + public: + inline _TessFunctionResultCallback_1_5(FunctionSignature function, P1 p1) + : function_(function), p1_(p1) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + (*function_)(p1_,a1,a2,a3,a4,a5); + } else { + (*function_)(p1_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } +}; + +template +inline typename _TessFunctionResultCallback_1_5::base* +NewTessCallback(R (*function)(P1,A1,A2,A3,A4,A5), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_5(function, p1); +} + +template +inline typename _TessFunctionResultCallback_1_5::base* +NewPermanentTessCallback(R (*function)(P1,A1,A2,A3,A4,A5), typename Identity::type p1) { + return new _TessFunctionResultCallback_1_5(function, p1); +} + +template +class _ConstTessMemberResultCallback_2_5 : public TessResultCallback5 { + public: + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,P2,A1,A2,A3,A4,A5) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_5(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3,a4,a5); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _ConstTessMemberResultCallback_2_5 : public TessCallback5 { + public: + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,P2,A1,A2,A3,A4,A5) const; + + private: + const T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _ConstTessMemberResultCallback_2_5(const T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + (object_->*member_)(p1_,p2_,a1,a2,a3,a4,a5); + } else { + (object_->*member_)(p1_,p2_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_5::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,A1,A2,A3,A4,A5) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_5(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _ConstTessMemberResultCallback_2_5::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,A1,A2,A3,A4,A5) const, typename Identity::type p1, typename Identity::type p2) { + return new _ConstTessMemberResultCallback_2_5(obj, member, p1, p2); +} +#endif + +template +class _TessMemberResultCallback_2_5 : public TessResultCallback5 { + public: + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,P2,A1,A2,A3,A4,A5) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_5( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3,a4,a5); + return result; + } else { + R result = (object_->*member_)(p1_,p2_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + return result; + } + } +}; + +template +class _TessMemberResultCallback_2_5 : public TessCallback5 { + public: + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,P2,A1,A2,A3,A4,A5) ; + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_5( T* object, MemberSignature member, P1 p1, P2 p2) + : object_(object), + member_(member), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + (object_->*member_)(p1_,p2_,a1,a2,a3,a4,a5); + } else { + (object_->*member_)(p1_,p2_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + member_ = NULL; + delete this; + } + } +}; + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_5::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,A1,A2,A3,A4,A5) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_5(obj, member, p1, p2); +} +#endif + +#ifndef SWIG +template +inline typename _TessMemberResultCallback_2_5::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,A1,A2,A3,A4,A5) , typename Identity::type p1, typename Identity::type p2) { + return new _TessMemberResultCallback_2_5(obj, member, p1, p2); +} +#endif + +template +class _TessFunctionResultCallback_2_5 : public TessResultCallback5 { + public: + typedef TessResultCallback5 base; + typedef R (*FunctionSignature)(P1,P2,A1,A2,A3,A4,A5); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_5(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + R result = (*function_)(p1_,p2_,a1,a2,a3,a4,a5); + return result; + } else { + R result = (*function_)(p1_,p2_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + return result; + } + } }; -template -class TessResultCallback1 { +template +class _TessFunctionResultCallback_2_5 : public TessCallback5 { public: - virtual ~TessResultCallback1() { } - virtual R Run(A1) = 0; + typedef TessCallback5 base; + typedef void (*FunctionSignature)(P1,P2,A1,A2,A3,A4,A5); + + private: + FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessFunctionResultCallback_2_5(FunctionSignature function, P1 p1, P2 p2) + : function_(function), p1_(p1), p2_(p2) { } + + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { + if (!del) { + (*function_)(p1_,p2_,a1,a2,a3,a4,a5); + } else { + (*function_)(p1_,p2_,a1,a2,a3,a4,a5); + // zero out the pointer to ensure segfault if used again + function_ = NULL; + delete this; + } + } }; -template -class _ConstTessMemberResultCallback_0_1 : public TessResultCallback1 { +template +inline typename _TessFunctionResultCallback_2_5::base* +NewTessCallback(R (*function)(P1,P2,A1,A2,A3,A4,A5), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_5(function, p1, p2); +} + +template +inline typename _TessFunctionResultCallback_2_5::base* +NewPermanentTessCallback(R (*function)(P1,P2,A1,A2,A3,A4,A5), typename Identity::type p1, typename Identity::type p2) { + return new _TessFunctionResultCallback_2_5(function, p1, p2); +} + +template +class _ConstTessMemberResultCallback_3_5 : public TessResultCallback5 { public: - typedef TessResultCallback1 base; - typedef R (T::*MemberSignature)(A1) const; + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,P2,P3,A1,A2,A3,A4,A5) const; private: const T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; public: - inline _ConstTessMemberResultCallback_0_1( - const T* object, MemberSignature member) + inline _ConstTessMemberResultCallback_3_5(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3) { } - virtual R Run(A1 a1) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (object_->*member_)(a1); + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); return result; } else { - R result = (object_->*member_)(a1); + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -315,29 +8809,29 @@ class _ConstTessMemberResultCallback_0_1 : public TessResultCallback1 { } }; -template -class _ConstTessMemberResultCallback_0_1 - : public TessCallback1 { +template +class _ConstTessMemberResultCallback_3_5 : public TessCallback5 { public: - typedef TessCallback1 base; - typedef void (T::*MemberSignature)(A1) const; + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,P2,P3,A1,A2,A3,A4,A5) const; private: const T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; public: - inline _ConstTessMemberResultCallback_0_1( - const T* object, MemberSignature member) + inline _ConstTessMemberResultCallback_3_5(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3) { } - virtual void Run(A1 a1) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (object_->*member_)(a1); + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); } else { - (object_->*member_)(a1); + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -346,48 +8840,45 @@ class _ConstTessMemberResultCallback_0_1 }; #ifndef SWIG -template -inline typename _ConstTessMemberResultCallback_0_1::base* -NewTessCallback( - const T1* obj, R (T2::*member)(A1) const) { - return new _ConstTessMemberResultCallback_0_1( - obj, member); +template +inline typename _ConstTessMemberResultCallback_3_5::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3,A4,A5) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_5(obj, member, p1, p2, p3); } #endif #ifndef SWIG -template -inline typename _ConstTessMemberResultCallback_0_1::base* -NewPermanentTessCallback( - const T1* obj, R (T2::*member)(A1) const) { - return new _ConstTessMemberResultCallback_0_1( - obj, member); +template +inline typename _ConstTessMemberResultCallback_3_5::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3,A4,A5) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _ConstTessMemberResultCallback_3_5(obj, member, p1, p2, p3); } #endif -template -class _TessMemberResultCallback_0_1 : public TessResultCallback1 { +template +class _TessMemberResultCallback_3_5 : public TessResultCallback5 { public: - typedef TessResultCallback1 base; - typedef R (T::*MemberSignature)(A1) ; + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,P2,P3,A1,A2,A3,A4,A5) ; private: T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; public: - inline _TessMemberResultCallback_0_1( - T* object, MemberSignature member) + inline _TessMemberResultCallback_3_5( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3) { } - virtual R Run(A1 a1) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (object_->*member_)(a1); + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); return result; } else { - R result = (object_->*member_)(a1); + R result = (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -396,29 +8887,29 @@ class _TessMemberResultCallback_0_1 : public TessResultCallback1 { } }; -template -class _TessMemberResultCallback_0_1 - : public TessCallback1 { +template +class _TessMemberResultCallback_3_5 : public TessCallback5 { public: - typedef TessCallback1 base; - typedef void (T::*MemberSignature)(A1) ; + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,P2,P3,A1,A2,A3,A4,A5) ; private: T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; public: - inline _TessMemberResultCallback_0_1( - T* object, MemberSignature member) + inline _TessMemberResultCallback_3_5( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3) { } - virtual void Run(A1 a1) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (object_->*member_)(a1); + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); } else { - (object_->*member_)(a1); + (object_->*member_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -427,46 +8918,43 @@ class _TessMemberResultCallback_0_1 }; #ifndef SWIG -template -inline typename _TessMemberResultCallback_0_1::base* -NewTessCallback( - T1* obj, R (T2::*member)(A1) ) { - return new _TessMemberResultCallback_0_1( - obj, member); +template +inline typename _TessMemberResultCallback_3_5::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3,A4,A5) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_5(obj, member, p1, p2, p3); } #endif #ifndef SWIG -template -inline typename _TessMemberResultCallback_0_1::base* -NewPermanentTessCallback( - T1* obj, R (T2::*member)(A1) ) { - return new _TessMemberResultCallback_0_1( - obj, member); +template +inline typename _TessMemberResultCallback_3_5::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,A1,A2,A3,A4,A5) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessMemberResultCallback_3_5(obj, member, p1, p2, p3); } #endif -template -class _TessFunctionResultCallback_0_1 : public TessResultCallback1 { +template +class _TessFunctionResultCallback_3_5 : public TessResultCallback5 { public: - typedef TessResultCallback1 base; - typedef R (*FunctionSignature)(A1); + typedef TessResultCallback5 base; + typedef R (*FunctionSignature)(P1,P2,P3,A1,A2,A3,A4,A5); private: FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; public: - inline _TessFunctionResultCallback_0_1( - FunctionSignature function) - : function_(function) { - } + inline _TessFunctionResultCallback_3_5(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } - virtual R Run(A1 a1) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (*function_)(a1); + R result = (*function_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); return result; } else { - R result = (*function_)(a1); + R result = (*function_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again function_ = NULL; delete this; @@ -475,27 +8963,27 @@ class _TessFunctionResultCallback_0_1 : public TessResultCallback1 { } }; -template -class _TessFunctionResultCallback_0_1 - : public TessCallback1 { +template +class _TessFunctionResultCallback_3_5 : public TessCallback5 { public: - typedef TessCallback1 base; - typedef void (*FunctionSignature)(A1); + typedef TessCallback5 base; + typedef void (*FunctionSignature)(P1,P2,P3,A1,A2,A3,A4,A5); private: FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; public: - inline _TessFunctionResultCallback_0_1( - FunctionSignature function) - : function_(function) { - } + inline _TessFunctionResultCallback_3_5(FunctionSignature function, P1 p1, P2 p2, P3 p3) + : function_(function), p1_(p1), p2_(p2), p3_(p3) { } - virtual void Run(A1 a1) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (*function_)(a1); + (*function_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); } else { - (*function_)(a1); + (*function_)(p1_,p2_,p3_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again function_ = NULL; delete this; @@ -503,55 +8991,43 @@ class _TessFunctionResultCallback_0_1 } }; -template -inline typename _TessFunctionResultCallback_0_1::base* -NewTessCallback(R (*function)(A1)) { - return new _TessFunctionResultCallback_0_1(function); +template +inline typename _TessFunctionResultCallback_3_5::base* +NewTessCallback(R (*function)(P1,P2,P3,A1,A2,A3,A4,A5), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_5(function, p1, p2, p3); } -template -inline typename _TessFunctionResultCallback_0_1::base* -NewPermanentTessCallback(R (*function)(A1)) { - return new _TessFunctionResultCallback_0_1(function); +template +inline typename _TessFunctionResultCallback_3_5::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,A1,A2,A3,A4,A5), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3) { + return new _TessFunctionResultCallback_3_5(function, p1, p2, p3); } -template -class TessCallback2 { - public: - virtual ~TessCallback2() { } - virtual void Run(A1,A2) = 0; -}; - -template -class TessResultCallback2 { - public: - virtual ~TessResultCallback2() { } - virtual R Run(A1,A2) = 0; -}; - -template -class _ConstTessMemberResultCallback_0_2 : public TessResultCallback2 { +template +class _ConstTessMemberResultCallback_4_5 : public TessResultCallback5 { public: - typedef TessResultCallback2 base; - typedef R (T::*MemberSignature)(A1,A2) const; + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3,A4,A5) const; private: const T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; public: - inline _ConstTessMemberResultCallback_0_2( - const T* object, MemberSignature member) + inline _ConstTessMemberResultCallback_4_5(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } - virtual R Run(A1 a1,A2 a2) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (object_->*member_)(a1,a2); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); return result; } else { - R result = (object_->*member_)(a1,a2); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -560,29 +9036,30 @@ class _ConstTessMemberResultCallback_0_2 : public TessResultCallback2 { } }; -template -class _ConstTessMemberResultCallback_0_2 - : public TessCallback2 { +template +class _ConstTessMemberResultCallback_4_5 : public TessCallback5 { public: - typedef TessCallback2 base; - typedef void (T::*MemberSignature)(A1,A2) const; + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3,A4,A5) const; private: const T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; public: - inline _ConstTessMemberResultCallback_0_2( - const T* object, MemberSignature member) + inline _ConstTessMemberResultCallback_4_5(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } - virtual void Run(A1 a1,A2 a2) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (object_->*member_)(a1,a2); + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); } else { - (object_->*member_)(a1,a2); + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -591,48 +9068,46 @@ class _ConstTessMemberResultCallback_0_2 }; #ifndef SWIG -template -inline typename _ConstTessMemberResultCallback_0_2::base* -NewTessCallback( - const T1* obj, R (T2::*member)(A1,A2) const) { - return new _ConstTessMemberResultCallback_0_2( - obj, member); +template +inline typename _ConstTessMemberResultCallback_4_5::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3,A4,A5) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_5(obj, member, p1, p2, p3, p4); } #endif #ifndef SWIG -template -inline typename _ConstTessMemberResultCallback_0_2::base* -NewPermanentTessCallback( - const T1* obj, R (T2::*member)(A1,A2) const) { - return new _ConstTessMemberResultCallback_0_2( - obj, member); +template +inline typename _ConstTessMemberResultCallback_4_5::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3,A4,A5) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _ConstTessMemberResultCallback_4_5(obj, member, p1, p2, p3, p4); } #endif -template -class _TessMemberResultCallback_0_2 : public TessResultCallback2 { +template +class _TessMemberResultCallback_4_5 : public TessResultCallback5 { public: - typedef TessResultCallback2 base; - typedef R (T::*MemberSignature)(A1,A2) ; + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3,A4,A5) ; private: T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; public: - inline _TessMemberResultCallback_0_2( - T* object, MemberSignature member) + inline _TessMemberResultCallback_4_5( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } - virtual R Run(A1 a1,A2 a2) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (object_->*member_)(a1,a2); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); return result; } else { - R result = (object_->*member_)(a1,a2); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -641,29 +9116,30 @@ class _TessMemberResultCallback_0_2 : public TessResultCallback2 { } }; -template -class _TessMemberResultCallback_0_2 - : public TessCallback2 { +template +class _TessMemberResultCallback_4_5 : public TessCallback5 { public: - typedef TessCallback2 base; - typedef void (T::*MemberSignature)(A1,A2) ; + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,A1,A2,A3,A4,A5) ; private: T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; public: - inline _TessMemberResultCallback_0_2( - T* object, MemberSignature member) + inline _TessMemberResultCallback_4_5( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } - virtual void Run(A1 a1,A2 a2) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (object_->*member_)(a1,a2); + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); } else { - (object_->*member_)(a1,a2); + (object_->*member_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -672,46 +9148,44 @@ class _TessMemberResultCallback_0_2 }; #ifndef SWIG -template -inline typename _TessMemberResultCallback_0_2::base* -NewTessCallback( - T1* obj, R (T2::*member)(A1,A2) ) { - return new _TessMemberResultCallback_0_2( - obj, member); +template +inline typename _TessMemberResultCallback_4_5::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3,A4,A5) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_5(obj, member, p1, p2, p3, p4); } #endif #ifndef SWIG -template -inline typename _TessMemberResultCallback_0_2::base* -NewPermanentTessCallback( - T1* obj, R (T2::*member)(A1,A2) ) { - return new _TessMemberResultCallback_0_2( - obj, member); +template +inline typename _TessMemberResultCallback_4_5::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,A1,A2,A3,A4,A5) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessMemberResultCallback_4_5(obj, member, p1, p2, p3, p4); } #endif -template -class _TessFunctionResultCallback_0_2 : public TessResultCallback2 { +template +class _TessFunctionResultCallback_4_5 : public TessResultCallback5 { public: - typedef TessResultCallback2 base; - typedef R (*FunctionSignature)(A1,A2); + typedef TessResultCallback5 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,A1,A2,A3,A4,A5); private: FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; public: - inline _TessFunctionResultCallback_0_2( - FunctionSignature function) - : function_(function) { - } + inline _TessFunctionResultCallback_4_5(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } - virtual R Run(A1 a1,A2 a2) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (*function_)(a1,a2); + R result = (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); return result; } else { - R result = (*function_)(a1,a2); + R result = (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again function_ = NULL; delete this; @@ -720,27 +9194,28 @@ class _TessFunctionResultCallback_0_2 : public TessResultCallback2 { } }; -template -class _TessFunctionResultCallback_0_2 - : public TessCallback2 { +template +class _TessFunctionResultCallback_4_5 : public TessCallback5 { public: - typedef TessCallback2 base; - typedef void (*FunctionSignature)(A1,A2); + typedef TessCallback5 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,A1,A2,A3,A4,A5); private: FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; public: - inline _TessFunctionResultCallback_0_2( - FunctionSignature function) - : function_(function) { - } + inline _TessFunctionResultCallback_4_5(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4) { } - virtual void Run(A1 a1,A2 a2) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (*function_)(a1,a2); + (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); } else { - (*function_)(a1,a2); + (*function_)(p1_,p2_,p3_,p4_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again function_ = NULL; delete this; @@ -748,55 +9223,45 @@ class _TessFunctionResultCallback_0_2 } }; -template -inline typename _TessFunctionResultCallback_0_2::base* -NewTessCallback(R (*function)(A1,A2)) { - return new _TessFunctionResultCallback_0_2(function); +template +inline typename _TessFunctionResultCallback_4_5::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,A1,A2,A3,A4,A5), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_5(function, p1, p2, p3, p4); } -template -inline typename _TessFunctionResultCallback_0_2::base* -NewPermanentTessCallback(R (*function)(A1,A2)) { - return new _TessFunctionResultCallback_0_2(function); +template +inline typename _TessFunctionResultCallback_4_5::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,A1,A2,A3,A4,A5), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4) { + return new _TessFunctionResultCallback_4_5(function, p1, p2, p3, p4); } -template -class TessCallback3 { - public: - virtual ~TessCallback3() { } - virtual void Run(A1,A2,A3) = 0; -}; - -template -class TessResultCallback3 { - public: - virtual ~TessResultCallback3() { } - virtual R Run(A1,A2,A3) = 0; -}; - -template -class _ConstTessMemberResultCallback_0_3 : public TessResultCallback3 { +template +class _ConstTessMemberResultCallback_5_5 : public TessResultCallback5 { public: - typedef TessResultCallback3 base; - typedef R (T::*MemberSignature)(A1,A2,A3) const; + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5) const; private: const T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; public: - inline _ConstTessMemberResultCallback_0_3( - const T* object, MemberSignature member) + inline _ConstTessMemberResultCallback_5_5(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } - virtual R Run(A1 a1,A2 a2,A3 a3) { + + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (object_->*member_)(a1,a2,a3); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); return result; } else { - R result = (object_->*member_)(a1,a2,a3); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -805,29 +9270,31 @@ class _ConstTessMemberResultCallback_0_3 : public TessResultCallback3 -class _ConstTessMemberResultCallback_0_3 - : public TessCallback3 { +template +class _ConstTessMemberResultCallback_5_5 : public TessCallback5 { public: - typedef TessCallback3 base; - typedef void (T::*MemberSignature)(A1,A2,A3) const; + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5) const; private: const T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; public: - inline _ConstTessMemberResultCallback_0_3( - const T* object, MemberSignature member) + inline _ConstTessMemberResultCallback_5_5(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } - virtual void Run(A1 a1,A2 a2,A3 a3) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (object_->*member_)(a1,a2,a3); + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); } else { - (object_->*member_)(a1,a2,a3); + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -836,48 +9303,47 @@ class _ConstTessMemberResultCallback_0_3 }; #ifndef SWIG -template -inline typename _ConstTessMemberResultCallback_0_3::base* -NewTessCallback( - const T1* obj, R (T2::*member)(A1,A2,A3) const) { - return new _ConstTessMemberResultCallback_0_3( - obj, member); +template +inline typename _ConstTessMemberResultCallback_5_5::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_5(obj, member, p1, p2, p3, p4, p5); } #endif #ifndef SWIG -template -inline typename _ConstTessMemberResultCallback_0_3::base* -NewPermanentTessCallback( - const T1* obj, R (T2::*member)(A1,A2,A3) const) { - return new _ConstTessMemberResultCallback_0_3( - obj, member); +template +inline typename _ConstTessMemberResultCallback_5_5::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _ConstTessMemberResultCallback_5_5(obj, member, p1, p2, p3, p4, p5); } #endif -template -class _TessMemberResultCallback_0_3 : public TessResultCallback3 { +template +class _TessMemberResultCallback_5_5 : public TessResultCallback5 { public: - typedef TessResultCallback3 base; - typedef R (T::*MemberSignature)(A1,A2,A3) ; + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5) ; private: T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; public: - inline _TessMemberResultCallback_0_3( - T* object, MemberSignature member) + inline _TessMemberResultCallback_5_5( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } - virtual R Run(A1 a1,A2 a2,A3 a3) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (object_->*member_)(a1,a2,a3); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); return result; } else { - R result = (object_->*member_)(a1,a2,a3); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -886,29 +9352,31 @@ class _TessMemberResultCallback_0_3 : public TessResultCallback3 { } }; -template -class _TessMemberResultCallback_0_3 - : public TessCallback3 { +template +class _TessMemberResultCallback_5_5 : public TessCallback5 { public: - typedef TessCallback3 base; - typedef void (T::*MemberSignature)(A1,A2,A3) ; + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5) ; private: T* object_; MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; public: - inline _TessMemberResultCallback_0_3( - T* object, MemberSignature member) + inline _TessMemberResultCallback_5_5( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) : object_(object), - member_(member) { - } + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } - virtual void Run(A1 a1,A2 a2,A3 a3) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (object_->*member_)(a1,a2,a3); + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); } else { - (object_->*member_)(a1,a2,a3); + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -917,46 +9385,45 @@ class _TessMemberResultCallback_0_3 }; #ifndef SWIG -template -inline typename _TessMemberResultCallback_0_3::base* -NewTessCallback( - T1* obj, R (T2::*member)(A1,A2,A3) ) { - return new _TessMemberResultCallback_0_3( - obj, member); +template +inline typename _TessMemberResultCallback_5_5::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_5(obj, member, p1, p2, p3, p4, p5); } #endif #ifndef SWIG -template -inline typename _TessMemberResultCallback_0_3::base* -NewPermanentTessCallback( - T1* obj, R (T2::*member)(A1,A2,A3) ) { - return new _TessMemberResultCallback_0_3( - obj, member); +template +inline typename _TessMemberResultCallback_5_5::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessMemberResultCallback_5_5(obj, member, p1, p2, p3, p4, p5); } #endif -template -class _TessFunctionResultCallback_0_3 : public TessResultCallback3 { +template +class _TessFunctionResultCallback_5_5 : public TessResultCallback5 { public: - typedef TessResultCallback3 base; - typedef R (*FunctionSignature)(A1,A2,A3); + typedef TessResultCallback5 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5); private: FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; public: - inline _TessFunctionResultCallback_0_3( - FunctionSignature function) - : function_(function) { - } + inline _TessFunctionResultCallback_5_5(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } - virtual R Run(A1 a1,A2 a2,A3 a3) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (*function_)(a1,a2,a3); + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); return result; } else { - R result = (*function_)(a1,a2,a3); + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again function_ = NULL; delete this; @@ -965,27 +9432,29 @@ class _TessFunctionResultCallback_0_3 : public TessResultCallback3 { } }; -template -class _TessFunctionResultCallback_0_3 - : public TessCallback3 { +template +class _TessFunctionResultCallback_5_5 : public TessCallback5 { public: - typedef TessCallback3 base; - typedef void (*FunctionSignature)(A1,A2,A3); + typedef TessCallback5 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5); private: FunctionSignature function_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; public: - inline _TessFunctionResultCallback_0_3( - FunctionSignature function) - : function_(function) { - } + inline _TessFunctionResultCallback_5_5(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5) { } - virtual void Run(A1 a1,A2 a2,A3 a3) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (*function_)(a1,a2,a3); + (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); } else { - (*function_)(a1,a2,a3); + (*function_)(p1_,p2_,p3_,p4_,p5_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again function_ = NULL; delete this; @@ -993,53 +9462,45 @@ class _TessFunctionResultCallback_0_3 } }; -template -inline typename _TessFunctionResultCallback_0_3::base* -NewTessCallback(R (*function)(A1,A2,A3)) { - return new _TessFunctionResultCallback_0_3(function); +template +inline typename _TessFunctionResultCallback_5_5::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_5(function, p1, p2, p3, p4, p5); } -template -inline typename _TessFunctionResultCallback_0_3::base* -NewPermanentTessCallback(R (*function)(A1,A2,A3)) { - return new _TessFunctionResultCallback_0_3(function); +template +inline typename _TessFunctionResultCallback_5_5::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,A1,A2,A3,A4,A5), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5) { + return new _TessFunctionResultCallback_5_5(function, p1, p2, p3, p4, p5); } -// Specified by TR1 [4.7.2] Reference modifications. -template struct remove_reference; -template struct remove_reference { typedef T type; }; -template struct remove_reference { typedef T type; }; - -// Identity::type is a typedef of T. Useful for preventing the -// compiler from inferring the type of an argument in templates. -template -struct Identity { - typedef T type; -}; - -template -class _ConstTessMemberResultCallback_1_3 - : public TessResultCallback3 { +template +class _ConstTessMemberResultCallback_6_5 : public TessResultCallback5 { public: - typedef TessResultCallback3 base; - typedef R (T::*MemberSignature)(P1,A1,A2,A3) const; + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5) const; private: - T* object_; + const T* object_; MemberSignature member_; typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; public: - inline _ConstTessMemberResultCallback_1_3(T* object, - MemberSignature member, P1 p1) - : object_(object), member_(member), p1_(p1) { } + inline _ConstTessMemberResultCallback_6_5(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } - virtual R Run(A1 a1, A2 a2, A3 a3) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (object_->*member_)(p1_,a1,a2,a3); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); return result; } else { - R result = (object_->*member_)(p1_,a1,a2,a3); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -1048,28 +9509,32 @@ class _ConstTessMemberResultCallback_1_3 } }; -template -class _ConstTessMemberResultCallback_1_3 - : public TessCallback3 { +template +class _ConstTessMemberResultCallback_6_5 : public TessCallback5 { public: - typedef TessCallback3 base; - typedef void (T::*MemberSignature)(P1,A1,A2,A3) const; + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5) const; private: - T* object_; + const T* object_; MemberSignature member_; typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; public: - inline _ConstTessMemberResultCallback_1_3(T* object, - MemberSignature member, P1 p1) - : object_(object), member_(member), p1_(p1) { } + inline _ConstTessMemberResultCallback_6_5(const T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } - virtual void Run(A1 a1, A2 a2, A3 a3) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (object_->*member_)(p1_,a1,a2,a3); + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); } else { - (object_->*member_)(p1_,a1,a2,a3); + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -1078,43 +9543,48 @@ class _ConstTessMemberResultCallback_1_3 }; #ifndef SWIG -template -inline typename _ConstTessMemberResultCallback_1_3::base* -NewTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3) , typename Identity::type p1) { - return new _ConstTessMemberResultCallback_1_3(obj, member, p1); +template +inline typename _ConstTessMemberResultCallback_6_5::base* +NewTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_5(obj, member, p1, p2, p3, p4, p5, p6); } #endif #ifndef SWIG -template -inline typename _ConstTessMemberResultCallback_1_3::base* -NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3) , typename Identity::type p1) { - return new _ConstTessMemberResultCallback_1_3(obj, member, p1); +template +inline typename _ConstTessMemberResultCallback_6_5::base* +NewPermanentTessCallback(const T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5) const, typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _ConstTessMemberResultCallback_6_5(obj, member, p1, p2, p3, p4, p5, p6); } #endif -template -class _TessMemberResultCallback_1_3 : public TessResultCallback3 { +template +class _TessMemberResultCallback_6_5 : public TessResultCallback5 { public: - typedef TessResultCallback3 base; - typedef R (T::*MemberSignature)(P1,A1,A2,A3) ; + typedef TessResultCallback5 base; + typedef R (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5) ; private: T* object_; MemberSignature member_; typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; public: - inline _TessMemberResultCallback_1_3(T* object, - MemberSignature member, P1 p1) - : object_(object), member_(member), p1_(p1) { } + inline _TessMemberResultCallback_6_5( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } - virtual R Run(A1 a1, A2 a2, A3 a3) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (object_->*member_)(p1_,a1,a2,a3); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); return result; } else { - R result = (object_->*member_)(p1_,a1,a2,a3); + R result = (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -1123,28 +9593,32 @@ class _TessMemberResultCallback_1_3 : public TessResultCallback3 { } }; -template -class _TessMemberResultCallback_1_3 - : public TessCallback3 { +template +class _TessMemberResultCallback_6_5 : public TessCallback5 { public: - typedef TessCallback3 base; - typedef void (T::*MemberSignature)(P1,A1,A2,A3) ; + typedef TessCallback5 base; + typedef void (T::*MemberSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5) ; private: T* object_; MemberSignature member_; typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; public: - inline _TessMemberResultCallback_1_3(T* object, - MemberSignature member, P1 p1) - : object_(object), member_(member), p1_(p1) { } + inline _TessMemberResultCallback_6_5( T* object, MemberSignature member, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + member_(member), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } - virtual void Run(A1 a1, A2 a2, A3 a3) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (object_->*member_)(p1_,a1,a2,a3); + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); } else { - (object_->*member_)(p1_,a1,a2,a3); + (object_->*member_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again member_ = NULL; delete this; @@ -1153,41 +9627,46 @@ class _TessMemberResultCallback_1_3 }; #ifndef SWIG -template -inline typename _TessMemberResultCallback_1_3::base* -NewTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3) , typename Identity::type p1) { - return new _TessMemberResultCallback_1_3(obj, member, p1); +template +inline typename _TessMemberResultCallback_6_5::base* +NewTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_5(obj, member, p1, p2, p3, p4, p5, p6); } #endif #ifndef SWIG -template -inline typename _TessMemberResultCallback_1_3::base* -NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,A1,A2,A3) , typename Identity::type p1) { - return new _TessMemberResultCallback_1_3(obj, member, p1); +template +inline typename _TessMemberResultCallback_6_5::base* +NewPermanentTessCallback( T1* obj, R (T2::*member)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5) , typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessMemberResultCallback_6_5(obj, member, p1, p2, p3, p4, p5, p6); } #endif -template -class _TessFunctionResultCallback_1_3 : public TessCallback3 { +template +class _TessFunctionResultCallback_6_5 : public TessResultCallback5 { public: - typedef TessCallback3 base; - typedef R (*FunctionSignature)(P1,A1,A2,A3); + typedef TessResultCallback5 base; + typedef R (*FunctionSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5); private: FunctionSignature function_; typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; public: - inline _TessFunctionResultCallback_1_3(FunctionSignature function, P1 p1) - : function_(function), p1_(p1) { } + inline _TessFunctionResultCallback_6_5(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } - virtual R Run(A1 a1, A2 a2, A3 a3) { + virtual R Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - R result = (*function_)(p1_,a1,a2,a3); + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); return result; } else { - R result = (*function_)(p1_,a1,a2,a3); + R result = (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again function_ = NULL; delete this; @@ -1196,26 +9675,30 @@ class _TessFunctionResultCallback_1_3 : public TessCallback3 { } }; -template -class _TessFunctionResultCallback_1_3 - : public TessCallback3 { +template +class _TessFunctionResultCallback_6_5 : public TessCallback5 { public: - typedef TessCallback3 base; - typedef void (*FunctionSignature)(P1,A1,A2,A3); + typedef TessCallback5 base; + typedef void (*FunctionSignature)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5); private: FunctionSignature function_; typename remove_reference::type p1_; + typename remove_reference::type p2_; + typename remove_reference::type p3_; + typename remove_reference::type p4_; + typename remove_reference::type p5_; + typename remove_reference::type p6_; public: - inline _TessFunctionResultCallback_1_3(FunctionSignature function, P1 p1) - : function_(function), p1_(p1) { } + inline _TessFunctionResultCallback_6_5(FunctionSignature function, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : function_(function), p1_(p1), p2_(p2), p3_(p3), p4_(p4), p5_(p5), p6_(p6) { } - virtual void Run(A1 a1, A2 a2, A3 a3) { + virtual void Run(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) { if (!del) { - (*function_)(p1_,a1,a2,a3); + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); } else { - (*function_)(p1_,a1,a2,a3); + (*function_)(p1_,p2_,p3_,p4_,p5_,p6_,a1,a2,a3,a4,a5); // zero out the pointer to ensure segfault if used again function_ = NULL; delete this; @@ -1223,16 +9706,16 @@ class _TessFunctionResultCallback_1_3 } }; -template -inline typename _TessFunctionResultCallback_1_3::base* -NewTessCallback(R (*function)(P1,A1,A2,A3), typename Identity::type p1) { - return new _TessFunctionResultCallback_1_3(function, p1); +template +inline typename _TessFunctionResultCallback_6_5::base* +NewTessCallback(R (*function)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_5(function, p1, p2, p3, p4, p5, p6); } -template -inline typename _TessFunctionResultCallback_1_3::base* -NewPermanentTessCallback(R (*function)(P1,A1,A2,A3), typename Identity::type p1) { - return new _TessFunctionResultCallback_1_3(function, p1); +template +inline typename _TessFunctionResultCallback_6_5::base* +NewPermanentTessCallback(R (*function)(P1,P2,P3,P4,P5,P6,A1,A2,A3,A4,A5), typename Identity::type p1, typename Identity::type p2, typename Identity::type p3, typename Identity::type p4, typename Identity::type p5, typename Identity::type p6) { + return new _TessFunctionResultCallback_6_5(function, p1, p2, p3, p4, p5, p6); } #endif /* _TESS_CALLBACK_SPECIALIZATIONS_H */ diff --git a/TesseractOCR/include/tesseract/tessclassifier.h b/TesseractOCR/include/tesseract/tessclassifier.h new file mode 100644 index 00000000..57a04861 --- /dev/null +++ b/TesseractOCR/include/tesseract/tessclassifier.h @@ -0,0 +1,77 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +/////////////////////////////////////////////////////////////////////// +// File: tessclassifier.h +// Description: Tesseract implementation of a ShapeClassifier. +// Author: Ray Smith +// Created: Tue Nov 22 14:10:45 PST 2011 +// +// (C) Copyright 2011, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef THIRD_PARTY_TESSERACT_CLASSIFY_TESSCLASSIFIER_H_ +#define THIRD_PARTY_TESSERACT_CLASSIFY_TESSCLASSIFIER_H_ + +#include "shapeclassifier.h" + +namespace tesseract { + +class Classify; +class TrainingSample; + +// Tesseract implementation of a ShapeClassifier. +// Due to limitations in the content of TrainingSample, this currently +// only works for the static classifier and only works if the ShapeTable +// in classify is not NULL. +class TessClassifier : public ShapeClassifier { + public: + TessClassifier(bool pruner_only, tesseract::Classify* classify) + : pruner_only_(pruner_only), classify_(classify) {} + virtual ~TessClassifier() {} + + // Classifies the given [training] sample, writing to results. + // See ShapeClassifier for a full description. + virtual int UnicharClassifySample(const TrainingSample& sample, Pix* page_pix, + int debug, UNICHAR_ID keep_this, + GenericVector* results); + // Provides access to the ShapeTable that this classifier works with. + virtual const ShapeTable* GetShapeTable() const; + // Provides access to the UNICHARSET that this classifier works with. + // Only needs to be overridden if GetShapeTable() can return NULL. + virtual const UNICHARSET& GetUnicharset() const; + + // Displays classification as the given shape_id. Creates as many windows + // as it feels fit, using index as a guide for placement. Adds any created + // windows to the windows output and returns a new index that may be used + // by any subsequent classifiers. Caller waits for the user to view and + // then destroys the windows by clearing the vector. + virtual int DisplayClassifyAs(const TrainingSample& sample, Pix* page_pix, + int unichar_id, int index, + PointerVector* windows); + + private: + // Indicates that this classifier is to use just the ClassPruner, or the + // full classifier if false. + bool pruner_only_; + // Borrowed pointer to the actual Tesseract classifier. + tesseract::Classify* classify_; +}; + + +} // namespace tesseract + + + + + +#endif /* THIRD_PARTY_TESSERACT_CLASSIFY_TESSCLASSIFIER_H_ */ diff --git a/TesseractOCR/include/tesseract/tessdatamanager.h b/TesseractOCR/include/tesseract/tessdatamanager.h old mode 100755 new mode 100644 index 2da4a2f4..7d7bed01 --- a/TesseractOCR/include/tesseract/tessdatamanager.h +++ b/TesseractOCR/include/tesseract/tessdatamanager.h @@ -21,7 +21,9 @@ #define TESSERACT_CCUTIL_TESSDATAMANAGER_H_ #include + #include "host.h" +#include "strngs.h" #include "tprintf.h" static const char kTrainedDataSuffix[] = "traineddata"; @@ -44,7 +46,7 @@ static const char kCubeSystemDawgFileSuffix[] = "cube-word-dawg"; static const char kShapeTableFileSuffix[] = "shapetable"; static const char kBigramDawgFileSuffix[] = "bigram-dawg"; static const char kUnambigDawgFileSuffix[] = "unambig-dawg"; -static const char kParamsTrainingModelFileSuffix[] = "params-training-model"; +static const char kParamsModelFileSuffix[] = "params-model"; namespace tesseract { @@ -59,13 +61,13 @@ enum TessdataType { TESSDATA_SYSTEM_DAWG, // 7 TESSDATA_NUMBER_DAWG, // 8 TESSDATA_FREQ_DAWG, // 9 - TESSDATA_FIXED_LENGTH_DAWGS, // 10 + TESSDATA_FIXED_LENGTH_DAWGS, // 10 // deprecated TESSDATA_CUBE_UNICHARSET, // 11 TESSDATA_CUBE_SYSTEM_DAWG, // 12 TESSDATA_SHAPE_TABLE, // 13 TESSDATA_BIGRAM_DAWG, // 14 TESSDATA_UNAMBIG_DAWG, // 15 - TESSDATA_PARAMS_TRAINING_MODEL, // 16 + TESSDATA_PARAMS_MODEL, // 16 TESSDATA_NUM_ENTRIES }; @@ -85,13 +87,13 @@ static const char * const kTessdataFileSuffixes[] = { kSystemDawgFileSuffix, // 7 kNumberDawgFileSuffix, // 8 kFreqDawgFileSuffix, // 9 - kFixedLengthDawgsFileSuffix, // 10 + kFixedLengthDawgsFileSuffix, // 10 // deprecated kCubeUnicharsetFileSuffix, // 11 kCubeSystemDawgFileSuffix, // 12 kShapeTableFileSuffix, // 13 kBigramDawgFileSuffix, // 14 kUnambigDawgFileSuffix, // 15 - kParamsTrainingModelFileSuffix, // 16 + kParamsModelFileSuffix, // 16 }; /** @@ -109,13 +111,13 @@ static const bool kTessdataFileIsText[] = { false, // 7 false, // 8 false, // 9 - false, // 10 + false, // 10 // deprecated true, // 11 false, // 12 false, // 13 false, // 14 false, // 15 - false, // 16 + true, // 16 }; /** @@ -146,6 +148,9 @@ class TessdataManager { */ bool Init(const char *data_file_name, int debug_level); + // Return the name of the underlying data file. + const STRING &GetDataFileName() const { return data_file_name_; } + /** Returns data file pointer. */ inline FILE *GetDataFilePtr() const { return data_file_; } @@ -195,7 +200,9 @@ class TessdataManager { } /** Writes the number of entries and the given offset table to output_file. */ - static void WriteMetadata(inT64 *offset_table, FILE *output_file); + static void WriteMetadata(inT64 *offset_table, + const char *language_data_path_prefix, + FILE *output_file); /** * Reads all the standard tesseract config and data files for a language @@ -277,6 +284,7 @@ class TessdataManager { * when new tessdata types are introduced. */ inT32 actual_tessdata_num_entries_; + STRING data_file_name_; // name of the data file. FILE *data_file_; ///< pointer to the data file. int debug_level_; // True if the bytes need swapping. diff --git a/TesseractOCR/include/tesseract/tessedit.h b/TesseractOCR/include/tesseract/tessedit.h old mode 100755 new mode 100644 index e19e5dde..5510e195 --- a/TesseractOCR/include/tesseract/tessedit.h +++ b/TesseractOCR/include/tesseract/tessedit.h @@ -22,7 +22,6 @@ #include "blobs.h" #include "pgedit.h" -#include "notdll.h" //progress monitor extern ETEXT_DESC *global_monitor; diff --git a/TesseractOCR/include/tesseract/tesseract_cube_combiner.h b/TesseractOCR/include/tesseract/tesseract_cube_combiner.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/tesseractclass.h b/TesseractOCR/include/tesseract/tesseractclass.h old mode 100755 new mode 100644 index 929a5aee..bb502e04 --- a/TesseractOCR/include/tesseract/tesseractclass.h +++ b/TesseractOCR/include/tesseract/tesseractclass.h @@ -36,7 +36,6 @@ class PAGE_RES_IT; class BLOCK_LIST; class CharSamp; class TO_BLOCK_LIST; -class IMAGE; class WERD_RES; class ROW; class TBOX; @@ -100,10 +99,6 @@ class EquationDetect; class Tesseract; class TesseractCubeCombiner; -typedef void (Tesseract::*WordRecognizer)(BLOCK* block, - ROW *row, - WERD_RES *word); - // A collection of various variables for statistics and debugging. struct TesseractStats { TesseractStats() @@ -136,6 +131,24 @@ struct TesseractStats { bool write_results_empty_block; }; +// Struct to hold all the pointers to relevant data for processing a word. +struct WordData { + WordData() : word(NULL), row(NULL), block(NULL), prev_word(NULL) {} + explicit WordData(const PAGE_RES_IT& page_res_it) + : word(page_res_it.word()), row(page_res_it.row()->row), + block(page_res_it.block()->block), prev_word(NULL) {} + WordData(BLOCK* block_in, ROW* row_in, WERD_RES* word_res) + : word(word_res), row(row_in), block(block_in), prev_word(NULL) {} + + WERD_RES* word; + ROW* row; + BLOCK* block; + WordData* prev_word; + GenericVector lang_words; +}; + +typedef void (Tesseract::*WordRecognizer)(WordData* word_data, WERD_RES* word); + class Tesseract : public Wordrec { public: Tesseract(); @@ -181,6 +194,10 @@ class Tesseract : public Wordrec { Pix* BestPix() const { return pix_grey_ != NULL ? pix_grey_ : pix_binary_; } + void set_pix_thresholds(Pix* thresholds) { + pixDestroy(&pix_thresholds_); + pix_thresholds_ = thresholds; + } int source_resolution() const { return source_resolution_; } @@ -239,17 +256,30 @@ class Tesseract : public Wordrec { int SegmentPage(const STRING* input_file, BLOCK_LIST* blocks, Tesseract* osd_tess, OSResults* osr); void SetupWordScripts(BLOCK_LIST* blocks); - int AutoPageSeg(bool single_column, bool osd, bool only_osd, + int AutoPageSeg(PageSegMode pageseg_mode, BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks, Tesseract* osd_tess, OSResults* osr); ColumnFinder* SetupPageSegAndDetectOrientation( bool single_column, bool osd, bool only_osd, BLOCK_LIST* blocks, Tesseract* osd_tess, OSResults* osr, TO_BLOCK_LIST* to_blocks, Pix** photo_mask_pix, Pix** music_mask_pix); + // par_control.cpp + void PrerecAllWordsPar(const GenericVector& words); //// control.h ///////////////////////////////////////////////////////// bool ProcessTargetWord(const TBOX& word_box, const TBOX& target_word_box, const char* word_config, int pass); + // Sets up the words ready for whichever engine is to be run + void SetupAllWordsPassN(int pass_n, + const TBOX* target_word_box, + const char* word_config, + PAGE_RES* page_res, + GenericVector* words); + // Sets up the single word ready for whichever engine is to be run. + void SetupWordPassN(int pass_n, WordData* word); + // Runs word recognition on all the words. + bool RecogAllWordsPassN(int pass_n, ETEXT_DESC* monitor, + GenericVector* words); bool recog_all_words(PAGE_RES* page_res, ETEXT_DESC* monitor, const TBOX* target_word_box, @@ -261,13 +291,15 @@ class Tesseract : public Wordrec { const char* word_config); void bigram_correction_pass(PAGE_RES *page_res); void blamer_pass(PAGE_RES* page_res); + // Sets script positions and detects smallcaps on all output words. + void script_pos_pass(PAGE_RES* page_res); // Helper to recognize the word using the given (language-specific) tesseract. // Returns true if the result was better than previously. - bool RetryWithLanguage(WERD_RES *word, BLOCK* block, ROW *row, - WordRecognizer recognizer); + bool RetryWithLanguage(const WERD_RES& best_word, WordData* word_data, + WERD_RES* word, WordRecognizer recognizer); void classify_word_and_language(WordRecognizer recognizer, - BLOCK* block, ROW *row, WERD_RES *word); - void classify_word_pass1(BLOCK* block, ROW *row, WERD_RES *word); + WordData* word_data); + void classify_word_pass1(WordData* word_data, WERD_RES* word); void recog_pseudo_word(PAGE_RES* page_res, // blocks to check TBOX &selection_box); @@ -277,23 +309,46 @@ class Tesseract : public Wordrec { ACCEPTABLE_WERD_TYPE acceptable_word_string(const UNICHARSET& char_set, const char *s, const char *lengths); - void match_word_pass2( //recog one word - WERD_RES *word, //word to do - ROW *row, - BLOCK* block); - void classify_word_pass2(BLOCK* block, ROW *row, WERD_RES *word); + void match_word_pass_n(int pass_n, WERD_RES *word, ROW *row, BLOCK* block); + void classify_word_pass2(WordData* word_data, WERD_RES* word); void ReportXhtFixResult(bool accept_new_word, float new_x_ht, WERD_RES* word, WERD_RES* new_word); bool RunOldFixXht(WERD_RES *word, BLOCK* block, ROW *row); bool TrainedXheightFix(WERD_RES *word, BLOCK* block, ROW *row); BOOL8 recog_interactive(BLOCK* block, ROW* row, WERD_RES* word_res); - void set_word_fonts( - WERD_RES *word, // set fonts of this word - BLOB_CHOICE_LIST_CLIST *blob_choices); // detailed results + // Set fonts of this word. + void set_word_fonts(WERD_RES *word); void font_recognition_pass(PAGE_RES* page_res); BOOL8 check_debug_pt(WERD_RES *word, int location); + //// superscript.cpp //////////////////////////////////////////////////// + bool SubAndSuperscriptFix(WERD_RES *word_res); + void GetSubAndSuperscriptCandidates(const WERD_RES *word, + int *num_rebuilt_leading, + ScriptPos *leading_pos, + float *leading_certainty, + int *num_rebuilt_trailing, + ScriptPos *trailing_pos, + float *trailing_certainty, + float *avg_certainty, + float *unlikely_threshold); + WERD_RES *TrySuperscriptSplits(int num_chopped_leading, + float leading_certainty, + ScriptPos leading_pos, + int num_chopped_trailing, + float trailing_certainty, + ScriptPos trailing_pos, + WERD_RES *word, + bool *is_good, + int *retry_leading, + int *retry_trailing); + bool BelievableSuperscript(bool debug, + const WERD_RES &word, + float certainty_threshold, + int *left_ok, + int *right_ok) const; + //// cube_control.cpp /////////////////////////////////////////////////// bool init_cube_objects(bool load_combiner, TessdataManager *tessdata_manager); @@ -314,7 +369,6 @@ class Tesseract : public Wordrec { // Sets up a fake result and returns false if something goes wrong. bool cube_recognize(CubeObject *cube_obj, BLOCK* block, WERD_RES *word); void fill_werd_res(const BoxWord& cube_box_word, - WERD_CHOICE* cube_werd_choice, const char* cube_best_str, WERD_RES* tess_werd_res); bool extract_cube_state(CubeObject* cube_obj, int* num_chars, @@ -429,13 +483,10 @@ class Tesseract : public Wordrec { // #ifndef GRAPHICS_DISABLED BOOL8 word_dumper(BLOCK* block, ROW* row, WERD_RES* word_res); // #endif // GRAPHICS_DISABLED + void blob_feature_display(PAGE_RES* page_res, const TBOX& selection_box); //// reject.h ////////////////////////////////////////////////////////// - void make_reject_map( //make rej map for wd //detailed results - WERD_RES *word, - BLOB_CHOICE_LIST_CLIST *blob_choices, - ROW *row, - inT16 pass //1st or 2nd? - ); + // make rej map for word + void make_reject_map(WERD_RES *word, ROW *row, inT16 pass); BOOL8 one_ell_conflict(WERD_RES *word_res, BOOL8 update_map); inT16 first_alphanum_index(const char *word, const char *word_lengths); @@ -456,8 +507,6 @@ class Tesseract : public Wordrec { WERD_RES *word, ROW *row); void nn_recover_rejects(WERD_RES *word, ROW *row); - BOOL8 test_ambig_word( //test for ambiguity - WERD_RES *word); void set_done( //set done flag WERD_RES *word, inT16 pass); @@ -472,12 +521,16 @@ class Tesseract : public Wordrec { uinT16 mode); //// tfacepp.cpp /////////////////////////////////////////////////////// - void recog_word_recursive(WERD_RES* word, - BLOB_CHOICE_LIST_CLIST *blob_choices); - void recog_word(WERD_RES *word, - BLOB_CHOICE_LIST_CLIST *blob_choices); - void split_and_recog_word(WERD_RES* word, - BLOB_CHOICE_LIST_CLIST *blob_choices); + void recog_word_recursive(WERD_RES* word); + void recog_word(WERD_RES *word); + void split_and_recog_word(WERD_RES* word); + void split_word(WERD_RES *word, + int split_pt, + WERD_RES **right_piece, + BlamerBundle **orig_blamer_bundle) const; + void join_words(WERD_RES *word, + WERD_RES *word2, + BlamerBundle *orig_bb) const; //// fixspace.cpp /////////////////////////////////////////////////////// BOOL8 digit_or_numeric_punct(WERD_RES *word, int char_position); inT16 eval_word_spacing(WERD_RES_LIST &word_res_list); @@ -495,7 +548,6 @@ class Tesseract : public Wordrec { PAGE_RES *page_res); void dump_words(WERD_RES_LIST &perm, inT16 score, inT16 mode, BOOL8 improved); - BOOL8 uniformly_spaced(WERD_RES *word); BOOL8 fixspace_thinks_word_done(WERD_RES *word); inT16 worst_noise_blob(WERD_RES *word_res, float *worst_noise_score); float blob_noise_score(TBLOB *blob); @@ -538,14 +590,9 @@ class Tesseract : public Wordrec { void tess_add_doc_word( //test acceptability WERD_CHOICE *word_choice //after context ); - void tess_segment_pass1(WERD_RES *word, - BLOB_CHOICE_LIST_CLIST *blob_choices); - void tess_segment_pass2(WERD_RES *word, - BLOB_CHOICE_LIST_CLIST *blob_choices); - BOOL8 tess_acceptable_word( //test acceptability - WERD_CHOICE *word_choice, //after context - WERD_CHOICE *raw_choice //before context - ); + void tess_segment_pass_n(int pass_n, WERD_RES *word); + bool tess_acceptable_word(WERD_RES *word); + //// applybox.cpp ////////////////////////////////////////////////////// // Applies the box file based on the image name fname, and resegments // the words in the block_list (page), with: @@ -649,7 +696,7 @@ class Tesseract : public Wordrec { // estimate. float ComputeCompatibleXheight(WERD_RES *word_res); //// Data members /////////////////////////////////////////////////////// - // TODO(ocr-team): Remove obsolete parameters. + // TODO(ocr-team): Find and remove obsolete parameters. BOOL_VAR_H(tessedit_resegment_from_boxes, false, "Take segmentation and labeling from box file"); BOOL_VAR_H(tessedit_resegment_from_line_boxes, false, @@ -684,9 +731,6 @@ class Tesseract : public Wordrec { "documents while performing ocr."); STRING_VAR_H(tessedit_write_params_to_file, "", "Write all parameters to the given file."); - BOOL_VAR_H(tessedit_adapt_to_char_fragments, true, - "Adapt to words that contain " - " a character composed form fragments"); BOOL_VAR_H(tessedit_adaption_debug, false, "Generate and print debug information for adaption"); INT_VAR_H(bidi_debug, 0, "Debug level for BiDi"); @@ -706,6 +750,7 @@ class Tesseract : public Wordrec { BOOL_VAR_H(tessedit_display_outwords, false, "Draw output words"); BOOL_VAR_H(tessedit_training_tess, false, "Call Tess to learn blobs"); BOOL_VAR_H(tessedit_dump_choices, false, "Dump char choices"); + BOOL_VAR_H(tessedit_timing_debug, false, "Print timing stats"); BOOL_VAR_H(tessedit_fix_fuzzy_spaces, true, "Try to improve fuzzy spaces"); BOOL_VAR_H(tessedit_unrej_any_wd, false, @@ -716,7 +761,7 @@ class Tesseract : public Wordrec { "Add words to the document dictionary"); BOOL_VAR_H(tessedit_debug_fonts, false, "Output font info per char"); BOOL_VAR_H(tessedit_debug_block_rejection, false, "Block and Row stats"); - BOOL_VAR_H(tessedit_enable_bigram_correction, false, + BOOL_VAR_H(tessedit_enable_bigram_correction, true, "Enable correction based on the word bigram dictionary."); INT_VAR_H(tessedit_bigram_debug, 0, "Amount of debug output for bigram " "correction."); @@ -731,8 +776,6 @@ class Tesseract : public Wordrec { "good_quality_doc lte outline error limit"); double_VAR_H(quality_char_pc, 0.95, "good_quality_doc gte good char limit"); INT_VAR_H(quality_min_initial_alphas_reqd, 2, "alphas in a good word"); - BOOL_VAR_H(tessedit_tess_adapt_to_rejmap, false, - "Use reject map to control Tesseract adaption"); INT_VAR_H(tessedit_tess_adaption_mode, 0x27, "Adaptation decision algorithm for tess"); BOOL_VAR_H(tessedit_minimal_rej_pass1, false, @@ -741,13 +784,13 @@ class Tesseract : public Wordrec { BOOL_VAR_H(tessedit_matcher_log, false, "Log matcher activity"); INT_VAR_H(tessedit_test_adaption_mode, 3, "Adaptation decision algorithm for tess"); - BOOL_VAR_H(save_blob_choices, false, - "Save the results of the recognition step" - " (blob_choices) within the corresponding WERD_CHOICE"); BOOL_VAR_H(test_pt, false, "Test for point"); double_VAR_H(test_pt_x, 99999.99, "xcoord"); double_VAR_H(test_pt_y, 99999.99, "ycoord"); INT_VAR_H(paragraph_debug_level, 0, "Print paragraph debug info."); + BOOL_VAR_H(paragraph_text_based, true, + "Run paragraph detection on the post-text-recognition " + "(more accurate)"); INT_VAR_H(cube_debug_level, 1, "Print cube debug info."); STRING_VAR_H(outlines_odd, "%| ", "Non standard number of outlines"); STRING_VAR_H(outlines_2, "ij!?%\":;", "Non standard number of outlines"); @@ -832,12 +875,33 @@ class Tesseract : public Wordrec { INT_VAR_H(x_ht_acceptance_tolerance, 8, "Max allowed deviation of blob top outside of font data"); INT_VAR_H(x_ht_min_change, 8, "Min change in xht before actually trying it"); + INT_VAR_H(superscript_debug, 0, "Debug level for sub & superscript fixer"); + double_VAR_H(superscript_worse_certainty, 2.0, "How many times worse " + "certainty does a superscript position glyph need to be for us " + "to try classifying it as a char with a different baseline?"); + double_VAR_H(superscript_bettered_certainty, 0.97, "What reduction in " + "badness do we think sufficient to choose a superscript over " + "what we'd thought. For example, a value of 0.6 means we want " + "to reduce badness of certainty by 40%"); + double_VAR_H(superscript_scaledown_ratio, 0.4, + "A superscript scaled down more than this is unbelievably " + "small. For example, 0.3 means we expect the font size to " + "be no smaller than 30% of the text line font size."); + double_VAR_H(subscript_max_y_top, 0.5, + "Maximum top of a character measured as a multiple of x-height " + "above the baseline for us to reconsider whether it's a " + "subscript."); + double_VAR_H(superscript_min_y_bottom, 0.3, + "Minimum bottom of a character measured as a multiple of " + "x-height above the baseline for us to reconsider whether it's " + "a superscript."); BOOL_VAR_H(tessedit_write_block_separators, false, "Write block separators in output"); BOOL_VAR_H(tessedit_write_rep_codes, false, "Write repetition char code"); BOOL_VAR_H(tessedit_write_unlv, false, "Write .unlv output file"); BOOL_VAR_H(tessedit_create_hocr, false, "Write .html hOCR output file"); + BOOL_VAR_H(tessedit_create_pdf, false, "Write .pdf output file"); STRING_VAR_H(unrecognised_char, "|", "Output char for unidentified blobs"); INT_VAR_H(suspect_level, 99, "Suspect marker level"); @@ -856,7 +920,6 @@ class Tesseract : public Wordrec { "Dont reject ANYTHING AT ALL"); BOOL_VAR_H(tessedit_consistent_reps, true, "Force all rep chars the same"); INT_VAR_H(tessedit_reject_mode, 0, "Rejection algorithm"); - INT_VAR_H(tessedit_ok_mode, 5, "Acceptance decision algorithm"); BOOL_VAR_H(tessedit_rejection_debug, false, "Adaption debug"); BOOL_VAR_H(tessedit_flip_0O, true, "Contextual 0O O0 flips"); double_VAR_H(tessedit_lower_flip_hyphen, 1.5, @@ -888,16 +951,81 @@ class Tesseract : public Wordrec { "Debug level for TessdataManager functions."); STRING_VAR_H(tessedit_load_sublangs, "", "List of languages to load with this one"); + BOOL_VAR_H(tessedit_use_primary_params_model, false, + "In multilingual mode use params model of the primary language"); // Min acceptable orientation margin (difference in scores between top and 2nd // choice in OSResults::orientations) to believe the page orientation. double_VAR_H(min_orientation_margin, 7.0, "Min acceptable orientation margin"); BOOL_VAR_H(textord_tabfind_show_vlines, false, "Debug line finding"); BOOL_VAR_H(textord_use_cjk_fp_model, FALSE, "Use CJK fixed pitch model"); + BOOL_VAR_H(poly_allow_detailed_fx, false, + "Allow feature extractors to see the original outline"); BOOL_VAR_H(tessedit_init_config_only, false, "Only initialize with the config file. Useful if the instance is " "not going to be used for OCR but say only for layout analysis."); BOOL_VAR_H(textord_equation_detect, false, "Turn on equation detector"); + INT_VAR_H(tessedit_parallelize, 0, "Run in parallel where possible"); + + // The following parameters were deprecated and removed from their original + // locations. The parameters are temporarily kept here to give Tesseract + // users a chance to updated their [lang].traineddata and config files + // without introducing failures during Tesseract initialization. + // TODO(ocr-team): remove these parameters from the code once we are + // reasonably sure that Tesseract users have updated their data files. + // + // BEGIN DEPRECATED PARAMETERS + INT_VAR_H(tessedit_ok_mode, 5, "Acceptance decision algorithm"); + BOOL_VAR_H(load_fixed_length_dawgs, true, "Load fixed length" + " dawgs (e.g. for non-space delimited languages)"); + INT_VAR_H(segment_debug, 0, "Debug the whole segmentation process"); + BOOL_VAR_H(permute_debug, 0, "char permutation debug"); + double_VAR_H(bestrate_pruning_factor, 2.0, "Multiplying factor of" + " current best rate to prune other hypotheses"); + BOOL_VAR_H(permute_script_word, 0, + "Turn on word script consistency permuter"); + BOOL_VAR_H(segment_segcost_rating, 0, + "incorporate segmentation cost in word rating?"); + double_VAR_H(segment_reward_script, 0.95, + "Score multipler for script consistency within a word. " + "Being a 'reward' factor, it should be <= 1. " + "Smaller value implies bigger reward."); + BOOL_VAR_H(permute_fixed_length_dawg, 0, + "Turn on fixed-length phrasebook search permuter"); + BOOL_VAR_H(permute_chartype_word, 0, + "Turn on character type (property) consistency permuter"); + double_VAR_H(segment_reward_chartype, 0.97, + "Score multipler for char type consistency within a word. "); + double_VAR_H(segment_reward_ngram_best_choice, 0.99, + "Score multipler for ngram permuter's best choice" + " (only used in the Han script path)."); + BOOL_VAR_H(ngram_permuter_activated, false, + "Activate character-level n-gram-based permuter"); + BOOL_VAR_H(permute_only_top, false, "Run only the top choice permuter"); + INT_VAR_H(language_model_fixed_length_choices_depth, 3, + "Depth of blob choice lists to explore" + " when fixed length dawgs are on"); + BOOL_VAR_H(use_new_state_cost, FALSE, + "use new state cost heuristics for segmentation state evaluation"); + double_VAR_H(heuristic_segcost_rating_base, 1.25, + "base factor for adding segmentation cost into word rating." + "It's a multiplying factor, the larger the value above 1, " + "the bigger the effect of segmentation cost."); + double_VAR_H(heuristic_weight_rating, 1, + "weight associated with char rating in combined cost of state"); + double_VAR_H(heuristic_weight_width, 1000.0, + "weight associated with width evidence in combined cost of" + " state"); + double_VAR_H(heuristic_weight_seamcut, 0, + "weight associated with seam cut in combined cost of state"); + double_VAR_H(heuristic_max_char_wh_ratio, 2.0, + "max char width-to-height ratio allowed in segmentation"); + BOOL_VAR_H(enable_new_segsearch, false, + "Enable new segmentation search path."); + double_VAR_H(segsearch_max_fixed_pitch_char_wh_ratio, 2.0, + "Maximum character width-to-height ratio for" + "fixed pitch fonts"); + // END DEPRECATED PARAMETERS //// ambigsrecog.cpp ///////////////////////////////////////////////////////// FILE *init_recog_training(const STRING &fname); @@ -927,6 +1055,8 @@ class Tesseract : public Wordrec { Pix* cube_binary_; // Grey-level input image if the input was not binary, otherwise NULL. Pix* pix_grey_; + // Thresholds that were used to generate the thresholded image from grey. + Pix* pix_thresholds_; // Input image resolution after any scaling. The resolution is not well // transmitted by operations on Pix, so we keep an independent record here. int source_resolution_; diff --git a/TesseractOCR/include/tesseract/tesseractmain.h b/TesseractOCR/include/tesseract/tesseractmain.h deleted file mode 100755 index f5abc27a..00000000 --- a/TesseractOCR/include/tesseract/tesseractmain.h +++ /dev/null @@ -1,50 +0,0 @@ -/********************************************************************** - * File: tessedit.h (Formerly tessedit.h) - * Description: Main program for merge of tess and editor. - * Author: Ray Smith - * Created: Tue Jan 07 15:21:46 GMT 1992 - * - * (C) Copyright 1992, Hewlett-Packard Ltd. - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** http://www.apache.org/licenses/LICENSE-2.0 - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - * - **********************************************************************/ - -#ifndef TESSERACTMAIN_H -#define TESSERACTMAIN_H - -#ifdef _WIN32 -/** - * main for windows command line - */ -int WINAPI WinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpszCmdLine, - int nCmdShow); -/** - * message handler - * @param hwnd window with message - * @param msg message type - */ -LONG WINAPI WndProc(HWND hwnd, - UINT msg, - WPARAM wParam, - LPARAM lParam); -/** - * refine argument list - * @param argc number of input arguments - * @param argv input arguments - * @param arglist output arguments - */ -int parse_args (int argc, - char *argv[], - char *arglist[]); -#endif -#endif diff --git a/TesseractOCR/include/tesseract/notdll.h b/TesseractOCR/include/tesseract/tessopt.h old mode 100755 new mode 100644 similarity index 59% rename from TesseractOCR/include/tesseract/notdll.h rename to TesseractOCR/include/tesseract/tessopt.h index 46a79a2d..5ff5e9f5 --- a/TesseractOCR/include/tesseract/notdll.h +++ b/TesseractOCR/include/tesseract/tessopt.h @@ -1,10 +1,10 @@ /********************************************************************** - * File: notdll.h - * Description: Defines for dll symbols for any program using a dll. + * File: getopt.h + * Description: Re-implementation of the unix code. * Author: Ray Smith - * Created: Tue Apr 30 16:15:01 MDT 1996 + * Created: Tue Nov 28 05:52:50 MST 1995 * - * (C) Copyright 1996, Hewlett-Packard Co. + * (C) Copyright 1995, Hewlett-Packard Co. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at @@ -17,12 +17,13 @@ * **********************************************************************/ -//This file does NOT use the usual single inclusion code as it -//is necessary to allow it to be executed every time it is included. -//#ifndef NOTDLL_H -//#define NOTDLL_H +#include "host.h" -#undef DLLSYM -#define DLLSYM +extern int tessoptind; +extern char *tessoptarg; -//#endif +int tessopt ( //parse args +inT32 argc, //arg count +char *argv[], //args +const char *arglist //string of arg chars +); diff --git a/TesseractOCR/include/tesseract/tessvars.h b/TesseractOCR/include/tesseract/tessvars.h old mode 100755 new mode 100644 index eeaa3585..326efef5 --- a/TesseractOCR/include/tesseract/tessvars.h +++ b/TesseractOCR/include/tesseract/tessvars.h @@ -22,8 +22,6 @@ #include -#include "img.h" -#include "notdll.h" extern FILE *debug_fp; // write debug stuff here #endif diff --git a/TesseractOCR/include/tesseract/textlineprojection.h b/TesseractOCR/include/tesseract/textlineprojection.h new file mode 100644 index 00000000..ce125999 --- /dev/null +++ b/TesseractOCR/include/tesseract/textlineprojection.h @@ -0,0 +1,206 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef TESSERACT_TEXTORD_TEXTLINEPROJECTION_H_ +#define TESSERACT_TEXTORD_TEXTLINEPROJECTION_H_ + +#include "blobgrid.h" // For BlobGrid + +class DENORM; +struct Pix; +struct TPOINT; + +namespace tesseract { + +class ColPartition; + +// Simple class to encapsulate the computation of an image representing +// local textline density, and function(s) to make use of it. +// The underlying principle is that if you smear connected components +// horizontally (vertically for components on a vertically written textline) +// and count the number of smeared components in an image, then the resulting +// image shows the density of the textlines at each image position. +class TextlineProjection { + public: + // The down-scaling factor is computed to obtain a projection resolution + // of about 100 dpi, whatever the input. + explicit TextlineProjection(int resolution); + ~TextlineProjection(); + + // Build the projection profile given the input_block containing lists of + // blobs, a rotation to convert to image coords, + // and a full-resolution nontext_map, marking out areas to avoid. + // During construction, we have the following assumptions: + // The rotation is a multiple of 90 degrees, ie no deskew yet. + // The blobs have had their left and right rules set to also limit + // the range of projection. + void ConstructProjection(TO_BLOCK* input_block, + const FCOORD& rotation, Pix* nontext_map); + + // Display the blobs in the window colored according to textline quality. + void PlotGradedBlobs(BLOBNBOX_LIST* blobs, ScrollView* win); + + // Moves blobs that look like they don't sit well on a textline from the + // input blobs list to the output small_blobs list. + // This gets them away from initial textline finding to stop diacritics + // from forming incorrect textlines. (Introduced mainly to fix Thai.) + void MoveNonTextlineBlobs(BLOBNBOX_LIST* blobs, + BLOBNBOX_LIST* small_blobs) const; + + // Create a window and display the projection in it. + void DisplayProjection() const; + + // Compute the distance of the box from the partition using curved projection + // space. As DistanceOfBoxFromBox, except that the direction is taken from + // the ColPartition and the median bounds of the ColPartition are used as + // the to_box. + int DistanceOfBoxFromPartition(const TBOX& box, const ColPartition& part, + const DENORM* denorm, bool debug) const; + + // Compute the distance from the from_box to the to_box using curved + // projection space. Separation that involves a decrease in projection + // density (moving from the from_box to the to_box) is weighted more heavily + // than constant density, and an increase is weighted less. + // If horizontal_textline is true, then curved space is used vertically, + // as for a diacritic on the edge of a textline. + // The projection uses original image coords, so denorm is used to get + // back to the image coords from box/part space. + int DistanceOfBoxFromBox(const TBOX& from_box, const TBOX& to_box, + bool horizontal_textline, + const DENORM* denorm, bool debug) const; + + // Compute the distance between (x, y1) and (x, y2) using the rule that + // a decrease in textline density is weighted more heavily than an increase. + // The coordinates are in source image space, ie processed by any denorm + // already, but not yet scaled by scale_factor_. + // Going from the outside of a textline to the inside should measure much + // less distance than going from the inside of a textline to the outside. + int VerticalDistance(bool debug, int x, int y1, int y2) const; + + // Compute the distance between (x1, y) and (x2, y) using the rule that + // a decrease in textline density is weighted more heavily than an increase. + int HorizontalDistance(bool debug, int x1, int x2, int y) const; + + // Returns true if the blob appears to be outside of a horizontal textline. + // Such blobs are potentially diacritics (even if large in Thai) and should + // be kept away from initial textline finding. + bool BoxOutOfHTextline(const TBOX& box, const DENORM* denorm, + bool debug) const; + + // Evaluates the textlineiness of a ColPartition. Uses EvaluateBox below, + // but uses the median top/bottom for horizontal and median left/right for + // vertical instead of the bounding box edges. + // Evaluates for both horizontal and vertical and returns the best result, + // with a positive value for horizontal and a negative value for vertical. + int EvaluateColPartition(const ColPartition& part, const DENORM* denorm, + bool debug) const; + + // Computes the mean projection gradients over the horizontal and vertical + // edges of the box: + // -h-h-h-h-h-h + // |------------| mean=htop -v|+v--------+v|-v + // |+h+h+h+h+h+h| -v|+v +v|-v + // | | -v|+v +v|-v + // | box | -v|+v box +v|-v + // | | -v|+v +v|-v + // |+h+h+h+h+h+h| -v|+v +v|-v + // |------------| mean=hbot -v|+v--------+v|-v + // -h-h-h-h-h-h + // mean=vleft mean=vright + // + // Returns MAX(htop,hbot) - MAX(vleft,vright), which is a positive number + // for a horizontal textline, a negative number for a vertical textline, + // and near zero for undecided. Undecided is most likely non-text. + int EvaluateBox(const TBOX& box, const DENORM* denorm, bool debug) const; + + private: + // Internal version of EvaluateBox returns the unclipped gradients as well + // as the result of EvaluateBox. + // hgrad1 and hgrad2 are the gradients for the horizontal textline. + int EvaluateBoxInternal(const TBOX& box, const DENORM* denorm, bool debug, + int* hgrad1, int* hgrad2, + int* vgrad1, int* vgrad2) const; + + // Helper returns the mean gradient value for the horizontal row at the given + // y, (in the external coordinates) by subtracting the mean of the transformed + // row 2 pixels above from the mean of the transformed row 2 pixels below. + // This gives a positive value for a good top edge and negative for bottom. + // Returns the best result out of +2/-2, +3/-1, +1/-3 pixels from the edge. + int BestMeanGradientInRow(const DENORM* denorm, inT16 min_x, inT16 max_x, + inT16 y, bool best_is_max) const; + + // Helper returns the mean gradient value for the vertical column at the + // given x, (in the external coordinates) by subtracting the mean of the + // transformed column 2 pixels left from the mean of the transformed column + // 2 pixels to the right. + // This gives a positive value for a good left edge and negative for right. + // Returns the best result out of +2/-2, +3/-1, +1/-3 pixels from the edge. + int BestMeanGradientInColumn(const DENORM* denorm, inT16 x, inT16 min_y, + inT16 max_y, bool best_is_max) const; + + // Helper returns the mean pixel value over the line between the start_pt and + // end_pt (inclusive), but shifted perpendicular to the line in the projection + // image by offset pixels. For simplicity, it is assumed that the vector is + // either nearly horizontal or nearly vertical. It works on skewed textlines! + // The end points are in external coordinates, and will be denormalized with + // the denorm if not NULL before further conversion to pix coordinates. + // After all the conversions, the offset is added to the direction + // perpendicular to the line direction. The offset is thus in projection image + // coordinates, which allows the caller to get a guaranteed displacement + // between pixels used to calculate gradients. + int MeanPixelsInLineSegment(const DENORM* denorm, int offset, + TPOINT start_pt, TPOINT end_pt) const; + + // Helper function to add 1 to a rectangle in source image coords to the + // internal projection pix_. + void IncrementRectangle8Bit(const TBOX& box); + // Inserts a list of blobs into the projection. + // Rotation is a multiple of 90 degrees to get from blob coords to + // nontext_map coords, image_box is the bounds of the nontext_map. + // Blobs are spread horizontally or vertically according to their internal + // flags, but the spreading is truncated by set pixels in the nontext_map + // and also by the horizontal rule line limits on the blobs. + void ProjectBlobs(BLOBNBOX_LIST* blobs, const FCOORD& rotation, + const TBOX& image_box, Pix* nontext_map); + // Pads the bounding box of the given blob according to whether it is on + // a horizontal or vertical text line, taking into account tab-stops near + // the blob. Returns true if padding was in the horizontal direction. + bool PadBlobBox(BLOBNBOX* blob, TBOX* bbox); + + // Helper denormalizes the TPOINT with the denorm if not NULL, then + // converts to pix_ coordinates. + void TransformToPixCoords(const DENORM* denorm, TPOINT* pt) const; + + // Helper truncates the TPOINT to be within the pix_. + void TruncateToImageBounds(TPOINT* pt) const; + + // Transform tesseract coordinates to coordinates used in the pix. + int ImageXToProjectionX(int x) const; + int ImageYToProjectionY(int y) const; + + // The down-sampling scale factor used in building the image. + int scale_factor_; + // The blob coordinates of the top-left (origin of the pix_) in tesseract + // coordinates. Used to transform the bottom-up tesseract coordinates to + // the top-down coordinates of the pix. + int x_origin_; + int y_origin_; + // The image of horizontally smeared blob boxes summed to provide a + // textline density map. As with a horizontal projection, the map has + // dips in the gaps between textlines. + Pix* pix_; +}; + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_TEXTLINEPROJECTION_H_ diff --git a/TesseractOCR/include/tesseract/textord.h b/TesseractOCR/include/tesseract/textord.h new file mode 100644 index 00000000..2b2b881d --- /dev/null +++ b/TesseractOCR/include/tesseract/textord.h @@ -0,0 +1,360 @@ +/////////////////////////////////////////////////////////////////////// +// File: textord.h +// Description: The Textord class definition gathers text line and word +// finding functionality. +// Author: Ray Smith +// Created: Fri Mar 13 14:29:01 PDT 2009 +// +// (C) Copyright 2009, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_TEXTORD_H__ +#define TESSERACT_TEXTORD_TEXTORD_H__ + +#include "ccstruct.h" +#include "blobbox.h" +#include "gap_map.h" +#include "publictypes.h" // For PageSegMode. + +class FCOORD; +class BLOCK_LIST; +class PAGE_RES; +class TO_BLOCK; +class TO_BLOCK_LIST; +class ScrollView; + +namespace tesseract { + +class Textord { + public: + explicit Textord(CCStruct* ccstruct); + ~Textord(); + + // Make the textlines and words inside each block. + // binary_pix is mandatory and is the binarized input after line removal. + // grey_pix is optional, but if present must match the binary_pix in size, + // and must be a *real* grey image instead of binary_pix * 255. + // thresholds_pix is expected to be present iff grey_pix is present and + // can be an integer factor reduction of the grey_pix. It represents the + // thresholds that were used to create the binary_pix from the grey_pix. + void TextordPage(PageSegMode pageseg_mode, const FCOORD& reskew, + int width, int height, Pix* binary_pix, + Pix* thresholds_pix, Pix* grey_pix, + bool use_box_bottoms, + BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks); + + // If we were supposed to return only a single textline, and there is more + // than one, clean up and leave only the best. + void CleanupSingleRowResult(PageSegMode pageseg_mode, PAGE_RES* page_res); + + bool use_cjk_fp_model() const { + return use_cjk_fp_model_; + } + void set_use_cjk_fp_model(bool flag) { + use_cjk_fp_model_ = flag; + } + + // tospace.cpp /////////////////////////////////////////// + void to_spacing( + ICOORD page_tr, //topright of page + TO_BLOCK_LIST *blocks //blocks on page + ); + ROW *make_prop_words(TO_ROW *row, // row to make + FCOORD rotation // for drawing + ); + ROW *make_blob_words(TO_ROW *row, // row to make + FCOORD rotation // for drawing + ); + // tordmain.cpp /////////////////////////////////////////// + void find_components(Pix* pix, BLOCK_LIST *blocks, TO_BLOCK_LIST *to_blocks); + void filter_blobs(ICOORD page_tr, TO_BLOCK_LIST *blocks, BOOL8 testing_on); + + private: + // For underlying memory management and other utilities. + CCStruct* ccstruct_; + + // The size of the input image. + ICOORD page_tr_; + + bool use_cjk_fp_model_; + + // makerow.cpp /////////////////////////////////////////// + // Make the textlines inside each block. + void MakeRows(PageSegMode pageseg_mode, const FCOORD& skew, + int width, int height, TO_BLOCK_LIST* to_blocks); + // Make the textlines inside a single block. + void MakeBlockRows(int min_spacing, int max_spacing, + const FCOORD& skew, TO_BLOCK* block, + ScrollView* win); + + public: + void compute_block_xheight(TO_BLOCK *block, float gradient); + void compute_row_xheight(TO_ROW *row, // row to do + const FCOORD& rotation, + float gradient, // global skew + int block_line_size); + void make_spline_rows(TO_BLOCK *block, // block to do + float gradient, // gradient to fit + BOOL8 testing_on); + private: + //// oldbasel.cpp //////////////////////////////////////// + void make_old_baselines(TO_BLOCK *block, // block to do + BOOL8 testing_on, // correct orientation + float gradient); + void correlate_lines(TO_BLOCK *block, float gradient); + void correlate_neighbours(TO_BLOCK *block, // block rows are in. + TO_ROW **rows, // rows of block. + int rowcount); // no of rows to do. + int correlate_with_stats(TO_ROW **rows, // rows of block. + int rowcount, // no of rows to do. + TO_BLOCK* block); + void find_textlines(TO_BLOCK *block, // block row is in + TO_ROW *row, // row to do + int degree, // required approximation + QSPLINE *spline); // starting spline + // tospace.cpp /////////////////////////////////////////// + //DEBUG USE ONLY + void block_spacing_stats(TO_BLOCK *block, + GAPMAP *gapmap, + BOOL8 &old_text_ord_proportional, + //resulting estimate + inT16 &block_space_gap_width, + //resulting estimate + inT16 &block_non_space_gap_width + ); + void row_spacing_stats(TO_ROW *row, + GAPMAP *gapmap, + inT16 block_idx, + inT16 row_idx, + //estimate for block + inT16 block_space_gap_width, + //estimate for block + inT16 block_non_space_gap_width + ); + void old_to_method(TO_ROW *row, + STATS *all_gap_stats, + STATS *space_gap_stats, + STATS *small_gap_stats, + inT16 block_space_gap_width, + //estimate for block + inT16 block_non_space_gap_width + ); + BOOL8 isolated_row_stats(TO_ROW *row, + GAPMAP *gapmap, + STATS *all_gap_stats, + BOOL8 suspected_table, + inT16 block_idx, + inT16 row_idx); + inT16 stats_count_under(STATS *stats, inT16 threshold); + void improve_row_threshold(TO_ROW *row, STATS *all_gap_stats); + BOOL8 make_a_word_break(TO_ROW *row, // row being made + TBOX blob_box, // for next_blob // how many blanks? + inT16 prev_gap, + TBOX prev_blob_box, + inT16 real_current_gap, + inT16 within_xht_current_gap, + TBOX next_blob_box, + inT16 next_gap, + uinT8 &blanks, + BOOL8 &fuzzy_sp, + BOOL8 &fuzzy_non, + BOOL8& prev_gap_was_a_space, + BOOL8& break_at_next_gap); + BOOL8 narrow_blob(TO_ROW *row, TBOX blob_box); + BOOL8 wide_blob(TO_ROW *row, TBOX blob_box); + BOOL8 suspected_punct_blob(TO_ROW *row, TBOX box); + void peek_at_next_gap(TO_ROW *row, + BLOBNBOX_IT box_it, + TBOX &next_blob_box, + inT16 &next_gap, + inT16 &next_within_xht_gap); + void mark_gap(TBOX blob, //blob following gap + inT16 rule, // heuristic id + inT16 prev_gap, + inT16 prev_blob_width, + inT16 current_gap, + inT16 next_blob_width, + inT16 next_gap); + float find_mean_blob_spacing(WERD *word); + BOOL8 ignore_big_gap(TO_ROW *row, + inT32 row_length, + GAPMAP *gapmap, + inT16 left, + inT16 right); + //get bounding box + TBOX reduced_box_next(TO_ROW *row, //current row + BLOBNBOX_IT *it //iterator to blobds + ); + TBOX reduced_box_for_blob(BLOBNBOX *blob, TO_ROW *row, inT16 *left_above_xht); + // tordmain.cpp /////////////////////////////////////////// + float filter_noise_blobs(BLOBNBOX_LIST *src_list, + BLOBNBOX_LIST *noise_list, + BLOBNBOX_LIST *small_list, + BLOBNBOX_LIST *large_list); + // Fixes the block so it obeys all the rules: + // Must have at least one ROW. + // Must have at least one WERD. + // WERDs contain a fake blob. + void cleanup_nontext_block(BLOCK* block); + void cleanup_blocks(BLOCK_LIST *blocks); + BOOL8 clean_noise_from_row(ROW *row); + void clean_noise_from_words(ROW *row); + // Remove outlines that are a tiny fraction in either width or height + // of the word height. + void clean_small_noise_from_words(ROW *row); + public: + // makerow.cpp /////////////////////////////////////////// + BOOL_VAR_H(textord_single_height_mode, false, + "Script has no xheight, so use a single mode for horizontal text"); + // tospace.cpp /////////////////////////////////////////// + BOOL_VAR_H(tosp_old_to_method, false, "Space stats use prechopping?"); + BOOL_VAR_H(tosp_old_to_constrain_sp_kn, false, + "Constrain relative values of inter and intra-word gaps for " + "old_to_method."); + BOOL_VAR_H(tosp_only_use_prop_rows, true, + "Block stats to use fixed pitch rows?"); + BOOL_VAR_H(tosp_force_wordbreak_on_punct, false, + "Force word breaks on punct to break long lines in non-space " + "delimited langs"); + BOOL_VAR_H(tosp_use_pre_chopping, false, + "Space stats use prechopping?"); + BOOL_VAR_H(tosp_old_to_bug_fix, false, + "Fix suspected bug in old code"); + BOOL_VAR_H(tosp_block_use_cert_spaces, true, + "Only stat OBVIOUS spaces"); + BOOL_VAR_H(tosp_row_use_cert_spaces, true, + "Only stat OBVIOUS spaces"); + BOOL_VAR_H(tosp_narrow_blobs_not_cert, true, + "Only stat OBVIOUS spaces"); + BOOL_VAR_H(tosp_row_use_cert_spaces1, true, + "Only stat OBVIOUS spaces"); + BOOL_VAR_H(tosp_recovery_isolated_row_stats, true, + "Use row alone when inadequate cert spaces"); + BOOL_VAR_H(tosp_only_small_gaps_for_kern, false, "Better guess"); + BOOL_VAR_H(tosp_all_flips_fuzzy, false, "Pass ANY flip to context?"); + BOOL_VAR_H(tosp_fuzzy_limit_all, true, + "Dont restrict kn->sp fuzzy limit to tables"); + BOOL_VAR_H(tosp_stats_use_xht_gaps, true, + "Use within xht gap for wd breaks"); + BOOL_VAR_H(tosp_use_xht_gaps, true, + "Use within xht gap for wd breaks"); + BOOL_VAR_H(tosp_only_use_xht_gaps, false, + "Only use within xht gap for wd breaks"); + BOOL_VAR_H(tosp_rule_9_test_punct, false, + "Dont chng kn to space next to punct"); + BOOL_VAR_H(tosp_flip_fuzz_kn_to_sp, true, "Default flip"); + BOOL_VAR_H(tosp_flip_fuzz_sp_to_kn, true, "Default flip"); + BOOL_VAR_H(tosp_improve_thresh, false, + "Enable improvement heuristic"); + INT_VAR_H(tosp_debug_level, 0, "Debug data"); + INT_VAR_H(tosp_enough_space_samples_for_median, 3, + "or should we use mean"); + INT_VAR_H(tosp_redo_kern_limit, 10, + "No.samples reqd to reestimate for row"); + INT_VAR_H(tosp_few_samples, 40, + "No.gaps reqd with 1 large gap to treat as a table"); + INT_VAR_H(tosp_short_row, 20, + "No.gaps reqd with few cert spaces to use certs"); + INT_VAR_H(tosp_sanity_method, 1, "How to avoid being silly"); + double_VAR_H(tosp_old_sp_kn_th_factor, 2.0, + "Factor for defining space threshold in terms of space and " + "kern sizes"); + double_VAR_H(tosp_threshold_bias1, 0, + "how far between kern and space?"); + double_VAR_H(tosp_threshold_bias2, 0, + "how far between kern and space?"); + double_VAR_H(tosp_narrow_fraction, 0.3, + "Fract of xheight for narrow"); + double_VAR_H(tosp_narrow_aspect_ratio, 0.48, + "narrow if w/h less than this"); + double_VAR_H(tosp_wide_fraction, 0.52, "Fract of xheight for wide"); + double_VAR_H(tosp_wide_aspect_ratio, 0.0, + "wide if w/h less than this"); + double_VAR_H(tosp_fuzzy_space_factor, 0.6, + "Fract of xheight for fuzz sp"); + double_VAR_H(tosp_fuzzy_space_factor1, 0.5, + "Fract of xheight for fuzz sp"); + double_VAR_H(tosp_fuzzy_space_factor2, 0.72, + "Fract of xheight for fuzz sp"); + double_VAR_H(tosp_gap_factor, 0.83, "gap ratio to flip sp->kern"); + double_VAR_H(tosp_kern_gap_factor1, 2.0, + "gap ratio to flip kern->sp"); + double_VAR_H(tosp_kern_gap_factor2, 1.3, + "gap ratio to flip kern->sp"); + double_VAR_H(tosp_kern_gap_factor3, 2.5, + "gap ratio to flip kern->sp"); + double_VAR_H(tosp_ignore_big_gaps, -1, "xht multiplier"); + double_VAR_H(tosp_ignore_very_big_gaps, 3.5, "xht multiplier"); + double_VAR_H(tosp_rep_space, 1.6, "rep gap multiplier for space"); + double_VAR_H(tosp_enough_small_gaps, 0.65, + "Fract of kerns reqd for isolated row stats"); + double_VAR_H(tosp_table_kn_sp_ratio, 2.25, + "Min difference of kn & sp in table"); + double_VAR_H(tosp_table_xht_sp_ratio, 0.33, + "Expect spaces bigger than this"); + double_VAR_H(tosp_table_fuzzy_kn_sp_ratio, 3.0, + "Fuzzy if less than this"); + double_VAR_H(tosp_fuzzy_kn_fraction, 0.5, "New fuzzy kn alg"); + double_VAR_H(tosp_fuzzy_sp_fraction, 0.5, "New fuzzy sp alg"); + double_VAR_H(tosp_min_sane_kn_sp, 1.5, + "Dont trust spaces less than this time kn"); + double_VAR_H(tosp_init_guess_kn_mult, 2.2, + "Thresh guess - mult kn by this"); + double_VAR_H(tosp_init_guess_xht_mult, 0.28, + "Thresh guess - mult xht by this"); + double_VAR_H(tosp_max_sane_kn_thresh, 5.0, + "Multiplier on kn to limit thresh"); + double_VAR_H(tosp_flip_caution, 0.0, + "Dont autoflip kn to sp when large separation"); + double_VAR_H(tosp_large_kerning, 0.19, + "Limit use of xht gap with large kns"); + double_VAR_H(tosp_dont_fool_with_small_kerns, -1, + "Limit use of xht gap with odd small kns"); + double_VAR_H(tosp_near_lh_edge, 0, + "Dont reduce box if the top left is non blank"); + double_VAR_H(tosp_silly_kn_sp_gap, 0.2, + "Dont let sp minus kn get too small"); + double_VAR_H(tosp_pass_wide_fuzz_sp_to_context, 0.75, + "How wide fuzzies need context"); + // tordmain.cpp /////////////////////////////////////////// + BOOL_VAR_H(textord_no_rejects, false, "Don't remove noise blobs"); + BOOL_VAR_H(textord_show_blobs, false, "Display unsorted blobs"); + BOOL_VAR_H(textord_show_boxes, false, "Display boxes"); + INT_VAR_H(textord_max_noise_size, 7, "Pixel size of noise"); + INT_VAR_H(textord_baseline_debug, 0, "Baseline debug level"); + double_VAR_H(textord_blob_size_bigile, 95, "Percentile for large blobs"); + double_VAR_H(textord_noise_area_ratio, 0.7, + "Fraction of bounding box for noise"); + double_VAR_H(textord_blob_size_smallile, 20, "Percentile for small blobs"); + double_VAR_H(textord_initialx_ile, 0.75, "Ile of sizes for xheight guess"); + double_VAR_H(textord_initialasc_ile, 0.90, "Ile of sizes for xheight guess"); + INT_VAR_H(textord_noise_sizefraction, 10, "Fraction of size for maxima"); + double_VAR_H(textord_noise_sizelimit, 0.5, "Fraction of x for big t count"); + INT_VAR_H(textord_noise_translimit, 16, "Transitions for normal blob"); + double_VAR_H(textord_noise_normratio, 2.0, "Dot to norm ratio for deletion"); + BOOL_VAR_H(textord_noise_rejwords, true, "Reject noise-like words"); + BOOL_VAR_H(textord_noise_rejrows, true, "Reject noise-like rows"); + double_VAR_H(textord_noise_syfract, 0.2, "xh fract error for norm blobs"); + double_VAR_H(textord_noise_sxfract, 0.4, + "xh fract width error for norm blobs"); + double_VAR_H(textord_noise_hfract, 1.0/64, + "Height fraction to discard outlines as speckle noise"); + INT_VAR_H(textord_noise_sncount, 1, "super norm blobs to save row"); + double_VAR_H(textord_noise_rowratio, 6.0, "Dot to norm ratio for deletion"); + BOOL_VAR_H(textord_noise_debug, FALSE, "Debug row garbage detector"); + double_VAR_H(textord_blshift_maxshift, 0.00, "Max baseline shift"); + double_VAR_H(textord_blshift_xfraction, 9.99, "Min size of baseline shift"); +}; +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_TEXTORD_H__ diff --git a/TesseractOCR/include/tesseract/tfacepp.h b/TesseractOCR/include/tesseract/tfacepp.h deleted file mode 100755 index 7484eec5..00000000 --- a/TesseractOCR/include/tesseract/tfacepp.h +++ /dev/null @@ -1,42 +0,0 @@ -/********************************************************************** - * File: tfacepp.h (Formerly tface++.h) - * Description: C++ side of the C/C++ Tess/Editor interface. - * Author: Ray Smith - * Created: Thu Apr 23 15:39:23 BST 1992 - * - * (C) Copyright 1992, Hewlett-Packard Ltd. - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** http://www.apache.org/licenses/LICENSE-2.0 - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - * - **********************************************************************/ - -#ifndef TFACEPP_H -#define TFACEPP_H - -#include "ratngs.h" -#include "blobs.h" -#include "notdll.h" -#include "tesseractclass.h" - -void call_tester( //call a tester - TBLOB *tessblob, //blob to test - BOOL8 correct_blob, //true if good - char *text, //source text - inT32 count, //chars in text - LIST result //output of matcher - ); -void call_train_tester( //call a tester - TBLOB *tessblob, //blob to test - BOOL8 correct_blob, //true if good - char *text, //source text - inT32 count, //chars in text - LIST result //output of matcher - ); -#endif diff --git a/TesseractOCR/include/tesseract/thresholder.h b/TesseractOCR/include/tesseract/thresholder.h old mode 100755 new mode 100644 index a22cf0c5..f35fa131 --- a/TesseractOCR/include/tesseract/thresholder.h +++ b/TesseractOCR/include/tesseract/thresholder.h @@ -20,7 +20,8 @@ #ifndef TESSERACT_CCMAIN_THRESHOLDER_H__ #define TESSERACT_CCMAIN_THRESHOLDER_H__ -class IMAGE; +#include "platform.h" + struct Pix; namespace tesseract { @@ -31,7 +32,7 @@ namespace tesseract { /// Each instance deals with a single image, but the design is intended to /// be useful for multiple calls to SetRectangle and ThresholdTo* if /// desired. -class ImageThresholder { +class TESS_API ImageThresholder { public: ImageThresholder(); virtual ~ImageThresholder(); @@ -42,10 +43,8 @@ class ImageThresholder { /// Return true if no image has been set. bool IsEmpty() const; - /// SetImage makes a copy of only the metadata, not the underlying - /// image buffer. It promises to treat the source as read-only in either case, - /// but in return assumes that the Pix or image buffer remain valid - /// throughout the life of the ImageThresholder. + /// SetImage makes a copy of all the image data, so it may be deleted + /// immediately after this call. /// Greyscale of 8 and color of 24 or 32 bits per pixel may be given. /// Palette color images will not work properly and must be converted to /// 24 bit. @@ -68,12 +67,12 @@ class ImageThresholder { /// Return true if the source image is color. bool IsColor() const { - return image_bytespp_ >= 3; + return pix_channels_ >= 3; } /// Returns true if the source image is binary. bool IsBinary() const { - return image_bytespp_ == 0; + return pix_channels_ == 0; } int GetScaleFactor() const { @@ -107,14 +106,11 @@ class ImageThresholder { return scale_ * estimated_res_; } - /// Pix vs raw, which to use? - /// Implementations should provide the ability to source and target Pix - /// where possible. A future version of Tesseract may choose to use Pix - /// as its internal representation and discard IMAGE altogether. - /// Because of that, an implementation that sources and targets Pix may end up - /// with less copies than an implementation that does not. - /// NOTE: Opposite to SetImage for raw images, SetImage for Pix clones its - /// input, so the source pix may be pixDestroyed immediately after. + /// Pix vs raw, which to use? Pix is the preferred input for efficiency, + /// since raw buffers are copied. + /// SetImage for Pix clones its input, so the source pix may be pixDestroyed + /// immediately after, but may not go away until after the Thresholder has + /// finished with it. void SetImage(const Pix* pix); /// Threshold the source image as efficiently as possible to the output Pix. @@ -122,6 +118,15 @@ class ImageThresholder { /// Caller must use pixDestroy to free the created Pix. virtual void ThresholdToPix(Pix** pix); + // Gets a pix that contains an 8 bit threshold value at each pixel. The + // returned pix may be an integer reduction of the binary image such that + // the scale factor may be inferred from the ratio of the sizes, even down + // to the extreme of a 1x1 pixel thresholds image. + // Ideally the 8 bit threshold should be the exact threshold used to generate + // the binary image in ThresholdToPix, but this is not a hard constraint. + // Returns NULL if the input is binary. PixDestroy after use. + virtual Pix* GetPixRectThresholds(); + /// Get a clone/copy of the source image rectangle. /// The returned Pix must be pixDestroyed. /// This function will be used in the future by the page layout analysis, and @@ -129,12 +134,11 @@ class ImageThresholder { /// so there is no raw equivalent. Pix* GetPixRect(); - /// Get a clone/copy of the source image rectangle, reduced to greyscale. - /// The returned Pix must be pixDestroyed. - /// This function will be used in the future by the page layout analysis, and - /// the layout analysis that uses it will only be available with Leptonica, - /// so there is no raw equivalent. - Pix* GetPixRectGrey(); + // Get a clone/copy of the source image rectangle, reduced to greyscale, + // and at the same resolution as the output binary. + // The returned Pix must be pixDestroyed. + // Provided to the classifier to extract features from the greyscale image. + virtual Pix* GetPixRectGrey(); protected: // ---------------------------------------------------------------------- @@ -149,33 +153,26 @@ class ImageThresholder { rect_width_ == image_width_ && rect_height_ == image_height_; } - /// Otsu threshold the rectangle, taking everything except the image buffer - /// pointer from the class, to the output Pix. - void OtsuThresholdRectToPix(const unsigned char* imagedata, - int bytes_per_pixel, int bytes_per_line, - Pix** pix) const; + // Otsu thresholds the rectangle, taking the rectangle from *this. + void OtsuThresholdRectToPix(Pix* src_pix, Pix** out_pix) const; - /// Threshold the rectangle, taking everything except the image buffer pointer - /// from the class, using thresholds/hi_values to the output IMAGE. - void ThresholdRectToPix(const unsigned char* imagedata, - int bytes_per_pixel, int bytes_per_line, + /// Threshold the rectangle, taking everything except the src_pix + /// from the class, using thresholds/hi_values to the output pix. + /// NOTE that num_channels is the size of the thresholds and hi_values + // arrays and also the bytes per pixel in src_pix. + void ThresholdRectToPix(Pix* src_pix, int num_channels, const int* thresholds, const int* hi_values, Pix** pix) const; - /// Copy the raw image rectangle, taking all data from the class, to the Pix. - void RawRectToPix(Pix** pix) const; - protected: /// Clone or other copy of the source Pix. /// The pix will always be PixDestroy()ed on destruction of the class. Pix* pix_; - /// Exactly one of pix_ and image_data_ is not NULL. - const unsigned char* image_data_; //< Raw source image. - int image_width_; //< Width of source image/pix. - int image_height_; //< Height of source image/pix. - int image_bytespp_; //< Bytes per pixel of source image/pix. - int image_bytespl_; //< Bytes per line of source image/pix. + int image_width_; //< Width of source pix_. + int image_height_; //< Height of source pix_. + int pix_channels_; //< Number of 8-bit channels in pix_. + int pix_wpl_; //< Words per line of pix_. // Limits of image rectangle to be processed. int scale_; //< Scale factor from original image. int yres_; //< y pixels/inch in source image. diff --git a/TesseractOCR/include/tesseract/tlog.h b/TesseractOCR/include/tesseract/tlog.h new file mode 100644 index 00000000..1269b905 --- /dev/null +++ b/TesseractOCR/include/tesseract/tlog.h @@ -0,0 +1,49 @@ +/********************************************************************** + * File: tlog.h + * Description: Variant of printf with logging level controllable by a + * commandline flag. + * Author: Ranjith Unnikrishnan + * Created: Wed Nov 20 2013 + * + * (C) Copyright 2013, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ +#ifndef TESSERACT_TRAINING_TLOG_H_ +#define TESSERACT_TRAINING_TLOG_H_ + +#include "commandlineflags.h" +#include "errcode.h" +#include "tprintf.h" + +DECLARE_INT_PARAM_FLAG(tlog_level); + +// Variant guarded by the numeric logging level parameter FLAGS_tlog_level +// (default 0). Code using ParseCommandLineFlags() can control its value using +// the --tlog_level commandline argument. Otherwise it must be specified in a +// config file like other params. +#define tlog(level, ...) { \ + if (FLAGS_tlog_level >= level) { \ + tprintf_internal(__VA_ARGS__); \ + } \ +} + +#define TLOG_IS_ON(level) (FLAGS_tlog_level >= level) + +#define TLOG_FATAL(msg...) \ + { \ + tprintf(msg); \ + ASSERT_FAILED.error("", ABORT, "in file %s, line %d", \ + __FILE__, __LINE__); \ + } + + +#endif // TESSERACT_TRAINING_TLOG_H_ diff --git a/TesseractOCR/include/tesseract/topitch.h b/TesseractOCR/include/tesseract/topitch.h new file mode 100644 index 00000000..28036779 --- /dev/null +++ b/TesseractOCR/include/tesseract/topitch.h @@ -0,0 +1,188 @@ +/********************************************************************** + * File: topitch.h (Formerly to_pitch.h) + * Description: Code to determine fixed pitchness and the pitch if fixed. + * Author: Ray Smith + * Created: Tue Aug 24 16:57:29 BST 1993 + * + * (C) Copyright 1993, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef TOPITCH_H +#define TOPITCH_H + +#include "blobbox.h" + +namespace tesseract { +class Tesseract; +} +extern BOOL_VAR_H (textord_debug_pitch_test, FALSE, +"Debug on fixed pitch test"); +extern BOOL_VAR_H (textord_debug_pitch_metric, FALSE, +"Write full metric stuff"); +extern BOOL_VAR_H (textord_show_row_cuts, FALSE, "Draw row-level cuts"); +extern BOOL_VAR_H (textord_show_page_cuts, FALSE, "Draw page-level cuts"); +extern BOOL_VAR_H (textord_pitch_cheat, FALSE, +"Use correct answer for fixed/prop"); +extern BOOL_VAR_H (textord_blockndoc_fixed, TRUE, +"Attempt whole doc/block fixed pitch"); +extern BOOL_VAR_H (textord_fast_pitch_test, FALSE, +"Do even faster pitch algorithm"); +extern double_VAR_H (textord_projection_scale, 0.125, +"Ding rate for mid-cuts"); +extern double_VAR_H (textord_balance_factor, 2.0, +"Ding rate for unbalanced char cells"); + +void compute_fixed_pitch(ICOORD page_tr, // top right + TO_BLOCK_LIST *port_blocks, // input list + float gradient, // page skew + FCOORD rotation, // for drawing + BOOL8 testing_on); // correct orientation +void fix_row_pitch( //get some value + TO_ROW *bad_row, //row to fix + TO_BLOCK *bad_block, //block of bad_row + TO_BLOCK_LIST *blocks, //blocks to scan + inT32 row_target, //number of row + inT32 block_target //number of block + ); +void compute_block_pitch( TO_BLOCK *block, // input list + FCOORD rotation, // for drawing + inT32 block_index, // block number + BOOL8 testing_on); // correct orientation +BOOL8 compute_rows_pitch( //find line stats + TO_BLOCK *block, //block to do + inT32 block_index, //block number + BOOL8 testing_on //correct orientation + ); +BOOL8 try_doc_fixed( //determine pitch + ICOORD page_tr, //top right + TO_BLOCK_LIST *port_blocks, //input list + float gradient //page skew + ); +BOOL8 try_block_fixed( //find line stats + TO_BLOCK *block, //block to do + inT32 block_index //block number + ); +BOOL8 try_rows_fixed( //find line stats + TO_BLOCK *block, //block to do + inT32 block_index, //block number + BOOL8 testing_on //correct orientation + ); +void print_block_counts( //find line stats + TO_BLOCK *block, //block to do + inT32 block_index //block number + ); +void count_block_votes( //find line stats + TO_BLOCK *block, //block to do + inT32 &def_fixed, //add to counts + inT32 &def_prop, + inT32 &maybe_fixed, + inT32 &maybe_prop, + inT32 &corr_fixed, + inT32 &corr_prop, + inT32 &dunno); +BOOL8 row_pitch_stats( //find line stats + TO_ROW *row, //current row + inT32 maxwidth, //of spaces + BOOL8 testing_on //correct orientation + ); +BOOL8 find_row_pitch( //find lines + TO_ROW *row, //row to do + inT32 maxwidth, //max permitted space + inT32 dm_gap, //ignorable gaps + TO_BLOCK *block, //block of row + inT32 block_index, //block_number + inT32 row_index, //number of row + BOOL8 testing_on //correct orientation + ); +BOOL8 fixed_pitch_row( //find lines + TO_ROW *row, //row to do + BLOCK* block, + inT32 block_index //block_number + ); +BOOL8 count_pitch_stats( //find lines + TO_ROW *row, //row to do + STATS *gap_stats, //blob gaps + STATS *pitch_stats, //centre-centre stats + float initial_pitch, //guess at pitch + float min_space, //estimate space size + BOOL8 ignore_outsize, //discard big objects + BOOL8 split_outsize, //split big objects + inT32 dm_gap //ignorable gaps + ); +float tune_row_pitch( //find fp cells + TO_ROW *row, //row to do + STATS *projection, //vertical projection + inT16 projection_left, //edge of projection + inT16 projection_right, //edge of projection + float space_size, //size of blank + float &initial_pitch, //guess at pitch + float &best_sp_sd, //space sd + inT16 &best_mid_cuts, //no of cheap cuts + ICOORDELT_LIST *best_cells, //row cells + BOOL8 testing_on //inidividual words + ); +float tune_row_pitch2( //find fp cells + TO_ROW *row, //row to do + STATS *projection, //vertical projection + inT16 projection_left, //edge of projection + inT16 projection_right, //edge of projection + float space_size, //size of blank + float &initial_pitch, //guess at pitch + float &best_sp_sd, //space sd + inT16 &best_mid_cuts, //no of cheap cuts + ICOORDELT_LIST *best_cells, //row cells + BOOL8 testing_on //inidividual words + ); +float compute_pitch_sd ( //find fp cells +TO_ROW * row, //row to do +STATS * projection, //vertical projection +inT16 projection_left, //edge +inT16 projection_right, //edge +float space_size, //size of blank +float initial_pitch, //guess at pitch +float &sp_sd, //space sd +inT16 & mid_cuts, //no of free cuts +ICOORDELT_LIST * row_cells, //list of chop pts +BOOL8 testing_on, //inidividual words +inT16 start = 0, //start of good range +inT16 end = 0 //end of good range +); +float compute_pitch_sd2 ( //find fp cells +TO_ROW * row, //row to do +STATS * projection, //vertical projection +inT16 projection_left, //edge +inT16 projection_right, //edge +float initial_pitch, //guess at pitch +inT16 & occupation, //no of occupied cells +inT16 & mid_cuts, //no of free cuts +ICOORDELT_LIST * row_cells, //list of chop pts +BOOL8 testing_on, //inidividual words +inT16 start = 0, //start of good range +inT16 end = 0 //end of good range +); +void print_pitch_sd( //find fp cells + TO_ROW *row, //row to do + STATS *projection, //vertical projection + inT16 projection_left, //edges //size of blank + inT16 projection_right, + float space_size, + float initial_pitch //guess at pitch + ); +void find_repeated_chars(TO_BLOCK *block, // Block to search. + BOOL8 testing_on); // Debug mode. +void plot_fp_word( //draw block of words + TO_BLOCK *block, //block to draw + float pitch, //pitch to draw with + float nonspace //for space threshold + ); +#endif diff --git a/TesseractOCR/include/tesseract/tordmain.h b/TesseractOCR/include/tesseract/tordmain.h new file mode 100644 index 00000000..340ff1aa --- /dev/null +++ b/TesseractOCR/include/tesseract/tordmain.h @@ -0,0 +1,57 @@ +/********************************************************************** + * File: tordmain.h (Formerly textordp.h) + * Description: C++ top level textord code. + * Author: Ray Smith + * Created: Tue Jul 28 17:12:33 BST 1992 + * + * (C) Copyright 1992, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef TORDMAIN_H +#define TORDMAIN_H + +#include +#include "params.h" +#include "ocrblock.h" +#include "blobs.h" +#include "blobbox.h" + +struct Pix; +namespace tesseract { +class Tesseract; +} + +void make_blocks_from_blobs( //convert & textord + TBLOB *tessblobs, //tess style input + const char *filename, //blob file + ICOORD page_tr, //top right + BOOL8 do_shift, //shift tess coords + BLOCK_LIST *blocks //block list + ); +void SetBlobStrokeWidth(Pix* pix, BLOBNBOX* blob); +void assign_blobs_to_blocks2(Pix* pix, BLOCK_LIST *blocks, + TO_BLOCK_LIST *port_blocks); +void textord_page( //make rows & words + ICOORD page_tr, //top right + BLOCK_LIST *blocks, //block list + TO_BLOCK_LIST *land_blocks, //rotated for landscape + TO_BLOCK_LIST *port_blocks, //output list + tesseract::Tesseract* + ); +void tweak_row_baseline(ROW *row, + double blshift_maxshift, + double blshift_xfraction); +inT32 blob_y_order( //sort function + void *item1, //items to compare + void *item2); +#endif diff --git a/TesseractOCR/include/tesseract/tovars.h b/TesseractOCR/include/tesseract/tovars.h new file mode 100644 index 00000000..17e1de6d --- /dev/null +++ b/TesseractOCR/include/tesseract/tovars.h @@ -0,0 +1,89 @@ +/********************************************************************** + * File: tovars.h (Formerly to_vars.h) + * Description: Variables used by textord. + * Author: Ray Smith + * Created: Tue Aug 24 16:55:02 BST 1993 + * + * (C) Copyright 1993, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef TOVARS_H +#define TOVARS_H + +#include "params.h" + +extern BOOL_VAR_H (textord_show_initial_words, FALSE, +"Display separate words"); +extern BOOL_VAR_H (textord_show_new_words, FALSE, "Display separate words"); +extern BOOL_VAR_H (textord_show_fixed_words, FALSE, +"Display forced fixed pitch words"); +extern BOOL_VAR_H (textord_blocksall_fixed, FALSE, "Moan about prop blocks"); +extern BOOL_VAR_H (textord_blocksall_prop, FALSE, +"Moan about fixed pitch blocks"); +extern BOOL_VAR_H (textord_blocksall_testing, FALSE, +"Dump stats when moaning"); +extern BOOL_VAR_H (textord_test_mode, FALSE, "Do current test"); +extern INT_VAR_H (textord_dotmatrix_gap, 3, +"Max pixel gap for broken pixed pitch"); +extern INT_VAR_H (textord_debug_block, 0, "Block to do debug on"); +extern INT_VAR_H (textord_pitch_range, 2, "Max range test on pitch"); +extern double_VAR_H (textord_wordstats_smooth_factor, 0.05, +"Smoothing gap stats"); +extern double_VAR_H (textord_width_smooth_factor, 0.10, +"Smoothing width stats"); +extern double_VAR_H (textord_words_width_ile, 0.4, +"Ile of blob widths for space est"); +extern double_VAR_H (textord_words_maxspace, 4.0, "Multiple of xheight"); +extern double_VAR_H (textord_words_default_maxspace, 3.5, +"Max believable third space"); +extern double_VAR_H (textord_words_default_minspace, 0.6, +"Fraction of xheight"); +extern double_VAR_H (textord_words_min_minspace, 0.3, "Fraction of xheight"); +extern double_VAR_H (textord_words_default_nonspace, 0.2, +"Fraction of xheight"); +extern double_VAR_H (textord_words_initial_lower, 0.25, +"Max inital cluster size"); +extern double_VAR_H (textord_words_initial_upper, 0.15, +"Min initial cluster spacing"); +extern double_VAR_H (textord_words_minlarge, 0.75, +"Fraction of valid gaps needed"); +extern double_VAR_H (textord_words_pitchsd_threshold, 0.025, +"Pitch sync threshold"); +extern double_VAR_H (textord_words_def_fixed, 0.01, +"Threshold for definite fixed"); +extern double_VAR_H (textord_words_def_prop, 0.06, +"Threshold for definite prop"); +extern INT_VAR_H (textord_words_veto_power, 5, +"Rows required to outvote a veto"); +extern double_VAR_H (textord_pitch_rowsimilarity, 0.08, +"Fraction of xheight for sameness"); +extern BOOL_VAR_H (textord_pitch_scalebigwords, FALSE, +"Scale scores on big words"); +extern double_VAR_H (words_initial_lower, 0.5, "Max inital cluster size"); +extern double_VAR_H (words_initial_upper, 0.15, +"Min initial cluster spacing"); +extern double_VAR_H (words_default_prop_nonspace, 0.25, +"Fraction of xheight"); +extern double_VAR_H (words_default_fixed_space, 0.75, "Fraction of xheight"); +extern double_VAR_H (words_default_fixed_limit, 0.6, "Allowed size variance"); +extern double_VAR_H (textord_words_definite_spread, 0.30, +"Non-fuzzy spacing region"); +extern double_VAR_H (textord_spacesize_ratiofp, 2.8, +"Min ratio space/nonspace"); +extern double_VAR_H (textord_spacesize_ratioprop, 2.0, +"Min ratio space/nonspace"); +extern double_VAR_H (textord_fpiqr_ratio, 1.5, "Pitch IQR/Gap IQR threshold"); +extern double_VAR_H (textord_max_pitch_iqr, 0.20, +"Xh fraction noise in pitch"); +extern double_VAR_H (textord_fp_min_width, 0.5, "Min width of decent blobs"); +#endif diff --git a/TesseractOCR/include/tesseract/tprintf.h b/TesseractOCR/include/tesseract/tprintf.h old mode 100755 new mode 100644 index ed742816..27a33823 --- a/TesseractOCR/include/tesseract/tprintf.h +++ b/TesseractOCR/include/tesseract/tprintf.h @@ -1,5 +1,5 @@ /********************************************************************** - * File: tprintf.c + * File: tprintf.h * Description: Trace version of printf - portable between UX and NT * Author: Phil Cheatle * Created: Wed Jun 28 15:01:15 BST 1995 @@ -17,19 +17,20 @@ * **********************************************************************/ -#ifndef TPRINTF_H -#define TPRINTF_H +#ifndef TESSERACT_CCUTIL_TPRINTF_H +#define TESSERACT_CCUTIL_TPRINTF_H -#include "params.h" +#include "params.h" -extern DLLSYM STRING_VAR_H (debug_file, "", "File to send tprintf output to"); -extern DLLSYM BOOL_VAR_H (debug_window_on, TRUE, -"Send tprintf to window unless file set"); +extern DLLSYM STRING_VAR_H(debug_file, "", + "File to send tprintf output to"); +extern DLLSYM BOOL_VAR_H(debug_window_on, TRUE, + "Send tprintf to window unless file set"); -extern TESS_API void tprintf( // Trace printf -const char *format, ... // special message -); - // special message -DLLSYM BOOL8 pause_continue (const char *format, ... -); -#endif +// Main logging function. +#define tprintf(...) tprintf_internal(__VA_ARGS__) + +extern TESS_API void tprintf_internal( // Trace printf + const char *format, ...); // Message + +#endif // define TESSERACT_CCUTIL_TPRINTF_H diff --git a/TesseractOCR/include/tesseract/trainingsample.h b/TesseractOCR/include/tesseract/trainingsample.h new file mode 100644 index 00000000..6df1ce82 --- /dev/null +++ b/TesseractOCR/include/tesseract/trainingsample.h @@ -0,0 +1,250 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TRAINING_TRAININGSAMPLE_H__ +#define TESSERACT_TRAINING_TRAININGSAMPLE_H__ + +#include "elst.h" +#include "featdefs.h" +#include "intfx.h" +#include "intmatcher.h" +#include "matrix.h" +#include "mf.h" +#include "picofeat.h" +#include "shapetable.h" +#include "unicharset.h" + +struct Pix; + +namespace tesseract { + +class IntFeatureMap; +class IntFeatureSpace; +class ShapeTable; + +// Number of elements of cn_feature_. +static const int kNumCNParams = 4; +// Number of ways to shift the features when randomizing. +static const int kSampleYShiftSize = 5; +// Number of ways to scale the features when randomizing. +static const int kSampleScaleSize = 3; +// Total number of different ways to manipulate the features when randomizing. +// The first and last combinations are removed to avoid an excessive +// top movement (first) and an identity transformation (last). +// WARNING: To avoid patterned duplication of samples, be sure to keep +// kSampleRandomSize prime! +// Eg with current values (kSampleYShiftSize = 5 and TkSampleScaleSize = 3) +// kSampleRandomSize is 13, which is prime. +static const int kSampleRandomSize = kSampleYShiftSize * kSampleScaleSize - 2; +// ASSERT_IS_PRIME(kSampleRandomSize) !! + +class TrainingSample : public ELIST_LINK { + public: + TrainingSample() + : class_id_(INVALID_UNICHAR_ID), font_id_(0), page_num_(0), + num_features_(0), num_micro_features_(0), outline_length_(0), + features_(NULL), micro_features_(NULL), weight_(1.0), + max_dist_(0.0), sample_index_(0), + features_are_indexed_(false), features_are_mapped_(false), + is_error_(false) { + } + ~TrainingSample(); + + // Saves the given features into a TrainingSample. The features are copied, + // so may be deleted afterwards. Delete the return value after use. + static TrainingSample* CopyFromFeatures(const INT_FX_RESULT_STRUCT& fx_info, + const TBOX& bounding_box, + const INT_FEATURE_STRUCT* features, + int num_features); + // Returns the cn_feature as a FEATURE_STRUCT* needed by cntraining. + FEATURE_STRUCT* GetCNFeature() const; + // Constructs and returns a copy "randomized" by the method given by + // the randomizer index. If index is out of [0, kSampleRandomSize) then + // an exact copy is returned. + TrainingSample* RandomizedCopy(int index) const; + // Constructs and returns an exact copy. + TrainingSample* Copy() const; + + // WARNING! Serialize/DeSerialize do not save/restore the "cache" data + // members, which is mostly the mapped features, and the weight. + // It is assumed these can all be reconstructed from what is saved. + // Writes to the given file. Returns false in case of error. + bool Serialize(FILE* fp) const; + // Creates from the given file. Returns NULL in case of error. + // If swap is true, assumes a big/little-endian swap is needed. + static TrainingSample* DeSerializeCreate(bool swap, FILE* fp); + // Reads from the given file. Returns false in case of error. + // If swap is true, assumes a big/little-endian swap is needed. + bool DeSerialize(bool swap, FILE* fp); + + // Extracts the needed information from the CHAR_DESC_STRUCT. + void ExtractCharDesc(int feature_type, int micro_type, + int cn_type, int geo_type, + CHAR_DESC_STRUCT* char_desc); + + // Sets the mapped_features_ from the features_ using the provided + // feature_space to the indexed versions of the features. + void IndexFeatures(const IntFeatureSpace& feature_space); + // Sets the mapped_features_ from the features_ using the provided + // feature_map. + void MapFeatures(const IntFeatureMap& feature_map); + + // Returns a pix representing the sample. (Int features only.) + Pix* RenderToPix(const UNICHARSET* unicharset) const; + // Displays the features in the given window with the given color. + void DisplayFeatures(ScrollView::Color color, ScrollView* window) const; + + // Returns a pix of the original sample image. The pix is padded all round + // by padding wherever possible. + // The returned Pix must be pixDestroyed after use. + // If the input page_pix is NULL, NULL is returned. + Pix* GetSamplePix(int padding, Pix* page_pix) const; + + // Accessors. + UNICHAR_ID class_id() const { + return class_id_; + } + void set_class_id(int id) { + class_id_ = id; + } + int font_id() const { + return font_id_; + } + void set_font_id(int id) { + font_id_ = id; + } + int page_num() const { + return page_num_; + } + void set_page_num(int page) { + page_num_ = page; + } + const TBOX& bounding_box() const { + return bounding_box_; + } + void set_bounding_box(const TBOX& box) { + bounding_box_ = box; + } + int num_features() const { + return num_features_; + } + const INT_FEATURE_STRUCT* features() const { + return features_; + } + int num_micro_features() const { + return num_micro_features_; + } + const MicroFeature* micro_features() const { + return micro_features_; + } + int outline_length() const { + return outline_length_; + } + float cn_feature(int index) const { + return cn_feature_[index]; + } + int geo_feature(int index) const { + return geo_feature_[index]; + } + double weight() const { + return weight_; + } + void set_weight(double value) { + weight_ = value; + } + double max_dist() const { + return max_dist_; + } + void set_max_dist(double value) { + max_dist_ = value; + } + int sample_index() const { + return sample_index_; + } + void set_sample_index(int value) { + sample_index_ = value; + } + bool features_are_mapped() const { + return features_are_mapped_; + } + const GenericVector& mapped_features() const { + ASSERT_HOST(features_are_mapped_); + return mapped_features_; + } + const GenericVector& indexed_features() const { + ASSERT_HOST(features_are_indexed_); + return mapped_features_; + } + bool is_error() const { + return is_error_; + } + void set_is_error(bool value) { + is_error_ = value; + } + + private: + // Unichar id that this sample represents. There obviously must be a + // reference UNICHARSET somewhere. Usually in TrainingSampleSet. + UNICHAR_ID class_id_; + // Font id in which this sample was printed. Refers to a fontinfo_table_ in + // MasterTrainer. + int font_id_; + // Number of page that the sample came from. + int page_num_; + // Bounding box of sample in original image. + TBOX bounding_box_; + // Number of INT_FEATURE_STRUCT in features_ array. + int num_features_; + // Number of MicroFeature in micro_features_ array. + int num_micro_features_; + // Total length of outline in the baseline normalized coordinate space. + // See comment in WERD_RES class definition for a discussion of coordinate + // spaces. + int outline_length_; + // Array of features. + INT_FEATURE_STRUCT* features_; + // Array of features. + MicroFeature* micro_features_; + // The one and only CN feature. Indexed by NORM_PARAM_NAME enum. + float cn_feature_[kNumCNParams]; + // The one and only geometric feature. (Aims at replacing cn_feature_). + // Indexed by GeoParams enum in picofeat.h + int geo_feature_[GeoCount]; + + // Non-serialized cache data. + // Weight used for boosting training. + double weight_; + // Maximum distance to other samples of same class/font used in computing + // the canonical sample. + double max_dist_; + // Global index of this sample. + int sample_index_; + // Indexed/mapped features, as indicated by the bools below. + GenericVector mapped_features_; + bool features_are_indexed_; + bool features_are_mapped_; + // True if the last classification was an error by the current definition. + bool is_error_; + + // Randomizing factors. + static const int kYShiftValues[kSampleYShiftSize]; + static const double kScaleValues[kSampleScaleSize]; +}; + +ELISTIZEH(TrainingSample) + +} // namespace tesseract + +#endif // TESSERACT_TRAINING_TRAININGSAMPLE_H__ diff --git a/TesseractOCR/include/tesseract/trainingsampleset.h b/TesseractOCR/include/tesseract/trainingsampleset.h new file mode 100644 index 00000000..ad92c6c4 --- /dev/null +++ b/TesseractOCR/include/tesseract/trainingsampleset.h @@ -0,0 +1,293 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// Author: rays@google.com (Ray Smith) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TRAINING_TRAININGSAMPLESET_H__ +#define TESSERACT_TRAINING_TRAININGSAMPLESET_H__ + +#include "bitvector.h" +#include "genericvector.h" +#include "indexmapbidi.h" +#include "matrix.h" +#include "shapetable.h" +#include "trainingsample.h" + +class UNICHARSET; + +namespace tesseract { + +struct FontInfo; +class FontInfoTable; +class IntFeatureMap; +class IntFeatureSpace; +class TrainingSample; +struct UnicharAndFonts; + +// Collection of TrainingSample used for training or testing a classifier. +// Provides several useful methods to operate on the collection as a whole, +// including outlier detection and deletion, providing access by font and +// class, finding the canonical sample, finding the "cloud" features (OR of +// all features in all samples), replication of samples, caching of distance +// metrics. +class TrainingSampleSet { + public: + explicit TrainingSampleSet(const FontInfoTable& fontinfo_table); + ~TrainingSampleSet(); + + // Writes to the given file. Returns false in case of error. + bool Serialize(FILE* fp) const; + // Reads from the given file. Returns false in case of error. + // If swap is true, assumes a big/little-endian swap is needed. + bool DeSerialize(bool swap, FILE* fp); + + // Accessors + int num_samples() const { + return samples_.size(); + } + int num_raw_samples() const { + return num_raw_samples_; + } + int NumFonts() const { + return font_id_map_.SparseSize(); + } + const UNICHARSET& unicharset() const { + return unicharset_; + } + int charsetsize() const { + return unicharset_size_; + } + const FontInfoTable& fontinfo_table() const { + return fontinfo_table_; + } + + // Loads an initial unicharset, or sets one up if the file cannot be read. + void LoadUnicharset(const char* filename); + + // Adds a character sample to this sample set. + // If the unichar is not already in the local unicharset, it is added. + // Returns the unichar_id of the added sample, from the local unicharset. + int AddSample(const char* unichar, TrainingSample* sample); + // Adds a character sample to this sample set with the given unichar_id, + // which must correspond to the local unicharset (in this). + void AddSample(int unichar_id, TrainingSample* sample); + + // Returns the number of samples for the given font,class pair. + // If randomize is true, returns the number of samples accessible + // with randomizing on. (Increases the number of samples if small.) + // OrganizeByFontAndClass must have been already called. + int NumClassSamples(int font_id, int class_id, bool randomize) const; + + // Gets a sample by its index. + const TrainingSample* GetSample(int index) const; + + // Gets a sample by its font, class, index. + // OrganizeByFontAndClass must have been already called. + const TrainingSample* GetSample(int font_id, int class_id, int index) const; + + // Get a sample by its font, class, index. Does not randomize. + // OrganizeByFontAndClass must have been already called. + TrainingSample* MutableSample(int font_id, int class_id, int index); + + // Returns a string debug representation of the given sample: + // font, unichar_str, bounding box, page. + STRING SampleToString(const TrainingSample& sample) const; + + // Gets the combined set of features used by all the samples of the given + // font/class combination. + const BitVector& GetCloudFeatures(int font_id, int class_id) const; + // Gets the indexed features of the canonical sample of the given + // font/class combination. + const GenericVector& GetCanonicalFeatures(int font_id, + int class_id) const; + + // Returns the distance between the given UniCharAndFonts pair. + // If matched_fonts, only matching fonts, are considered, unless that yields + // the empty set. + // OrganizeByFontAndClass must have been already called. + float UnicharDistance(const UnicharAndFonts& uf1, const UnicharAndFonts& uf2, + bool matched_fonts, const IntFeatureMap& feature_map); + + // Returns the distance between the given pair of font/class pairs. + // Finds in cache or computes and caches. + // OrganizeByFontAndClass must have been already called. + float ClusterDistance(int font_id1, int class_id1, + int font_id2, int class_id2, + const IntFeatureMap& feature_map); + + // Computes the distance between the given pair of font/class pairs. + float ComputeClusterDistance(int font_id1, int class_id1, + int font_id2, int class_id2, + const IntFeatureMap& feature_map) const; + + // Returns the number of canonical features of font/class 2 for which + // neither the feature nor any of its near neighbors occurs in the cloud + // of font/class 1. Each such feature is a reliable separation between + // the classes, ASSUMING that the canonical sample is sufficiently + // representative that every sample has a feature near that particular + // feature. To check that this is so on the fly would be prohibitively + // expensive, but it might be possible to pre-qualify the canonical features + // to include only those for which this assumption is true. + // ComputeCanonicalFeatures and ComputeCloudFeatures must have been called + // first, or the results will be nonsense. + int ReliablySeparable(int font_id1, int class_id1, + int font_id2, int class_id2, + const IntFeatureMap& feature_map, + bool thorough) const; + + + // Returns the total index of the requested sample. + // OrganizeByFontAndClass must have been already called. + int GlobalSampleIndex(int font_id, int class_id, int index) const; + + // Gets the canonical sample for the given font, class pair. + // ComputeCanonicalSamples must have been called first. + const TrainingSample* GetCanonicalSample(int font_id, int class_id) const; + // Gets the max distance for the given canonical sample. + // ComputeCanonicalSamples must have been called first. + float GetCanonicalDist(int font_id, int class_id) const; + + // Returns a mutable pointer to the sample with the given index. + TrainingSample* mutable_sample(int index) { + return samples_[index]; + } + // Gets ownership of the sample with the given index, removing it from this. + TrainingSample* extract_sample(int index) { + TrainingSample* sample = samples_[index]; + samples_[index] = NULL; + return sample; + } + + // Generates indexed features for all samples with the supplied feature_space. + void IndexFeatures(const IntFeatureSpace& feature_space); + + // Delete outlier samples with few features that are shared with others. + // IndexFeatures must have been called already. + void DeleteOutliers(const IntFeatureSpace& feature_space, bool debug); + + // Marks the given sample for deletion. + // Deletion is actually completed by DeleteDeadSamples. + void KillSample(TrainingSample* sample); + + // Deletes all samples with a negative sample index marked by KillSample. + // Must be called before OrganizeByFontAndClass, and OrganizeByFontAndClass + // must be called after as the samples have been renumbered. + void DeleteDeadSamples(); + + // Callback function returns true if the given sample is to be deleted, due + // to having a negative classid. + bool DeleteableSample(const TrainingSample* sample); + + // Construct an array to access the samples by font,class pair. + void OrganizeByFontAndClass(); + + // Constructs the font_id_map_ which maps real font_ids (sparse) to a compact + // index for the font_class_array_. + void SetupFontIdMap(); + + // Finds the sample for each font, class pair that has least maximum + // distance to all the other samples of the same font, class. + // OrganizeByFontAndClass must have been already called. + void ComputeCanonicalSamples(const IntFeatureMap& map, bool debug); + + // Replicates the samples to a minimum frequency defined by + // 2 * kSampleRandomSize, or for larger counts duplicates all samples. + // After replication, the replicated samples are perturbed slightly, but + // in a predictable and repeatable way. + // Use after OrganizeByFontAndClass(). + void ReplicateAndRandomizeSamples(); + + // Caches the indexed features of the canonical samples. + // ComputeCanonicalSamples must have been already called. + void ComputeCanonicalFeatures(); + // Computes the combined set of features used by all the samples of each + // font/class combination. Use after ReplicateAndRandomizeSamples. + void ComputeCloudFeatures(int feature_space_size); + + // Adds all fonts of the given class to the shape. + void AddAllFontsForClass(int class_id, Shape* shape) const; + + // Display the samples with the given indexed feature that also match + // the given shape. + void DisplaySamplesWithFeature(int f_index, const Shape& shape, + const IntFeatureSpace& feature_space, + ScrollView::Color color, + ScrollView* window) const; + + private: + // Struct to store a triplet of unichar, font, distance in the distance cache. + struct FontClassDistance { + int unichar_id; + int font_id; // Real font id. + float distance; + }; + // Simple struct to store information related to each font/class combination. + struct FontClassInfo { + FontClassInfo(); + + // Writes to the given file. Returns false in case of error. + bool Serialize(FILE* fp) const; + // Reads from the given file. Returns false in case of error. + // If swap is true, assumes a big/little-endian swap is needed. + bool DeSerialize(bool swap, FILE* fp); + + // Number of raw samples. + inT32 num_raw_samples; + // Index of the canonical sample. + inT32 canonical_sample; + // Max distance of the canonical sample from any other. + float canonical_dist; + // Sample indices for the samples, including replicated. + GenericVector samples; + + // Non-serialized cache data. + // Indexed features of the canonical sample. + GenericVector canonical_features; + // The mapped features of all the samples. + BitVector cloud_features; + + // Caches for ClusterDistance. + // Caches for other fonts but matching this unichar. -1 indicates not set. + // Indexed by compact font index from font_id_map_. + GenericVector font_distance_cache; + // Caches for other unichars but matching this font. -1 indicates not set. + GenericVector unichar_distance_cache; + // Cache for the rest (non matching font and unichar.) + // A cache of distances computed by ReliablySeparable. + GenericVector distance_cache; + }; + + PointerVector samples_; + // Number of samples before replication/randomization. + int num_raw_samples_; + // Character set we are training for. + UNICHARSET unicharset_; + // Character set size to which the 2-d arrays below refer. + int unicharset_size_; + // Map to allow the font_class_array_ below to be compact. + // The sparse space is the real font_id, used in samples_ . + // The compact space is an index to font_class_array_ + IndexMapBiDi font_id_map_; + // A 2-d array of FontClassInfo holding information related to each + // (font_id, class_id) pair. + GENERIC_2D_ARRAY* font_class_array_; + + // Reference to the fontinfo_table_ in MasterTrainer. Provides names + // for font_ids in the samples. Not serialized! + const FontInfoTable& fontinfo_table_; +}; + +} // namespace tesseract. + + +#endif // TRAININGSAMPLESETSET_H_ diff --git a/TesseractOCR/include/tesseract/trie.h b/TesseractOCR/include/tesseract/trie.h new file mode 100644 index 00000000..4a89debf --- /dev/null +++ b/TesseractOCR/include/tesseract/trie.h @@ -0,0 +1,433 @@ +/* -*-C-*- + ******************************************************************************** + * + * File: trie.h (Formerly trie.h) + * Description: Functions to build a trie data structure. + * Author: Mark Seaman, SW Productivity + * Created: Fri Oct 16 14:37:00 1987 + * Modified: Fri Jul 26 11:26:34 1991 (Mark Seaman) marks@hpgrlt + * Language: C + * Package: N/A + * Status: Reusable Software Component + * + * (c) Copyright 1987, Hewlett-Packard Company. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + *********************************************************************************/ +#ifndef TRIE_H +#define TRIE_H + +#include "dawg.h" +#include "cutil.h" +#include "genericvector.h" + +class UNICHARSET; + +// Note: if we consider either NODE_REF or EDGE_INDEX to ever exceed +// max int32, we will need to change GenericVector to use int64 for size +// and address indices. This does not seem to be needed immediately, +// since currently the largest number of edges limit used by tesseract +// (kMaxNumEdges in wordlist2dawg.cpp) is far less than max int32. +// There are also int casts below to satisfy the WIN32 compiler that would +// need to be changed. +// It might be cleanest to change the types of most of the Trie/Dawg related +// typedefs to int and restrict the casts to extracting these values from +// the 64 bit EDGE_RECORD. +typedef inT64 EDGE_INDEX; // index of an edge in a given node +typedef bool *NODE_MARKER; +typedef GenericVector EDGE_VECTOR; + +struct TRIE_NODE_RECORD { + EDGE_VECTOR forward_edges; + EDGE_VECTOR backward_edges; +}; +typedef GenericVector TRIE_NODES; + +namespace tesseract { + +/** + * Concrete class for Trie data structure that allows to store a list of + * words (extends Dawg base class) as well as dynamically add new words. + * This class stores a vector of pointers to TRIE_NODE_RECORDs, each of + * which has a vector of forward and backward edges. + */ +class Trie : public Dawg { + public: + enum RTLReversePolicy { + RRP_DO_NO_REVERSE, + RRP_REVERSE_IF_HAS_RTL, + RRP_FORCE_REVERSE, + }; + + // Minimum number of concrete characters at the beginning of user patterns. + static const int kSaneNumConcreteChars = 0; + // Various unicode whitespace characters are used to denote unichar patterns, + // (character classifier would never produce these whitespace characters as a + // valid classification). + static const char kAlphaPatternUnicode[]; + static const char kDigitPatternUnicode[]; + static const char kAlphanumPatternUnicode[]; + static const char kPuncPatternUnicode[]; + static const char kLowerPatternUnicode[]; + static const char kUpperPatternUnicode[]; + + static const char *get_reverse_policy_name( + RTLReversePolicy reverse_policy); + + // max_num_edges argument allows limiting the amount of memory this + // Trie can consume (if a new word insert would cause the Trie to + // contain more edges than max_num_edges, all the edges are cleared + // so that new inserts can proceed). + Trie(DawgType type, const STRING &lang, PermuterType perm, + int unicharset_size, int debug_level) { + init(type, lang, perm, unicharset_size, debug_level); + num_edges_ = 0; + deref_node_index_mask_ = ~letter_mask_; + new_dawg_node(); // need to allocate node 0 + initialized_patterns_ = false; + } + virtual ~Trie() { nodes_.delete_data_pointers(); } + + // Reset the Trie to empty. + void clear(); + + /** Returns the edge that corresponds to the letter out of this node. */ + EDGE_REF edge_char_of(NODE_REF node_ref, UNICHAR_ID unichar_id, + bool word_end) const { + EDGE_RECORD *edge_ptr; + EDGE_INDEX edge_index; + if (!edge_char_of(node_ref, NO_EDGE, FORWARD_EDGE, word_end, unichar_id, + &edge_ptr, &edge_index)) return NO_EDGE; + return make_edge_ref(node_ref, edge_index); + } + + /** + * Fills the given NodeChildVector with all the unichar ids (and the + * corresponding EDGE_REFs) for which there is an edge out of this node. + */ + void unichar_ids_of(NODE_REF node, NodeChildVector *vec, + bool word_end) const { + const EDGE_VECTOR &forward_edges = + nodes_[static_cast(node)]->forward_edges; + for (int i = 0; i < forward_edges.size(); ++i) { + if (!word_end || end_of_word_from_edge_rec(forward_edges[i])) { + vec->push_back(NodeChild(unichar_id_from_edge_rec(forward_edges[i]), + make_edge_ref(node, i))); + } + } + } + + /** + * Returns the next node visited by following the edge + * indicated by the given EDGE_REF. + */ + NODE_REF next_node(EDGE_REF edge_ref) const { + if (edge_ref == NO_EDGE || num_edges_ == 0) return NO_EDGE; + return next_node_from_edge_rec(*deref_edge_ref(edge_ref)); + } + + /** + * Returns true if the edge indicated by the given EDGE_REF + * marks the end of a word. + */ + bool end_of_word(EDGE_REF edge_ref) const { + if (edge_ref == NO_EDGE || num_edges_ == 0) return false; + return end_of_word_from_edge_rec(*deref_edge_ref(edge_ref)); + } + + /** Returns UNICHAR_ID stored in the edge indicated by the given EDGE_REF. */ + UNICHAR_ID edge_letter(EDGE_REF edge_ref) const { + if (edge_ref == NO_EDGE || num_edges_ == 0) return INVALID_UNICHAR_ID; + return unichar_id_from_edge_rec(*deref_edge_ref(edge_ref)); + } + // Sets the UNICHAR_ID in the given edge_rec to 0, marking the edge dead. + void KillEdge(EDGE_RECORD* edge_rec) const { + *edge_rec &= ~letter_mask_; + } + + // Prints the contents of the node indicated by the given NODE_REF. + // At most max_num_edges will be printed. + void print_node(NODE_REF node, int max_num_edges) const; + + // Writes edges from nodes_ to an EDGE_ARRAY and creates a SquishedDawg. + // Eliminates redundant edges and returns the pointer to the SquishedDawg. + // Note: the caller is responsible for deallocating memory associated + // with the returned SquishedDawg pointer. + SquishedDawg *trie_to_dawg(); + + // Reads a list of words from the given file and adds into the Trie. + // Calls WERD_CHOICE::reverse_unichar_ids_if_rtl() according to the reverse + // policy and information in the unicharset. + // Returns false on error. + bool read_and_add_word_list(const char *filename, + const UNICHARSET &unicharset, + Trie::RTLReversePolicy reverse); + + // Reads a list of words from the given file, applying the reverse_policy, + // according to information in the unicharset. + // Returns false on error. + bool read_word_list(const char *filename, + const UNICHARSET &unicharset, + Trie::RTLReversePolicy reverse_policy, + GenericVector* words); + // Adds a list of words previously read using read_word_list to the trie + // using the given unicharset to convert to unichar-ids. + // Returns false on error. + bool add_word_list(const GenericVector& words, + const UNICHARSET &unicharset); + + // Inserts the list of patterns from the given file into the Trie. + // The pattern list file should contain one pattern per line in UTF-8 format. + // + // Each pattern can contain any non-whitespace characters, however only the + // patterns that contain characters from the unicharset of the corresponding + // language will be useful. + // The only meta character is '\'. To be used in a pattern as an ordinary + // string it should be escaped with '\' (e.g. string "C:\Documents" should + // be written in the patterns file as "C:\\Documents"). + // This function supports a very limited regular expression syntax. One can + // express a character, a certain character class and a number of times the + // entity should be repeated in the pattern. + // + // To denote a character class use one of: + // \c - unichar for which UNICHARSET::get_isalpha() is true (character) + // \d - unichar for which UNICHARSET::get_isdigit() is true + // \n - unichar for which UNICHARSET::get_isdigit() and + // UNICHARSET::isalpha() are true + // \p - unichar for which UNICHARSET::get_ispunct() is true + // \a - unichar for which UNICHARSET::get_islower() is true + // \A - unichar for which UNICHARSET::get_isupper() is true + // + // \* could be specified after each character or pattern to indicate that + // the character/pattern can be repeated any number of times before the next + // character/pattern occurs. + // + // Examples: + // 1-8\d\d-GOOG-411 will be expanded to strings: + // 1-800-GOOG-411, 1-801-GOOG-411, ... 1-899-GOOG-411. + // + // http://www.\n\*.com will be expanded to strings like: + // http://www.a.com http://www.a123.com ... http://www.ABCDefgHIJKLMNop.com + // + // Note: In choosing which patterns to include please be aware of the fact + // providing very generic patterns will make tesseract run slower. + // For example \n\* at the beginning of the pattern will make Tesseract + // consider all the combinations of proposed character choices for each + // of the segmentations, which will be unacceptably slow. + // Because of potential problems with speed that could be difficult to + // identify, each user pattern has to have at least kSaneNumConcreteChars + // concrete characters from the unicharset at the beginning. + bool read_pattern_list(const char *filename, const UNICHARSET &unicharset); + + // Initializes the values of *_pattern_ unichar ids. + // This function should be called before calling read_pattern_list(). + void initialize_patterns(UNICHARSET *unicharset); + + // Fills in the given unichar id vector with the unichar ids that represent + // the patterns of the character classes of the given unichar_id. + void unichar_id_to_patterns(UNICHAR_ID unichar_id, + const UNICHARSET &unicharset, + GenericVector *vec) const; + + // Returns the given EDGE_REF if the EDGE_RECORD that it points to has + // a self loop and the given unichar_id matches the unichar_id stored in the + // EDGE_RECORD, returns NO_EDGE otherwise. + virtual EDGE_REF pattern_loop_edge(EDGE_REF edge_ref, + UNICHAR_ID unichar_id, + bool word_end) const { + if (edge_ref == NO_EDGE) return NO_EDGE; + EDGE_RECORD *edge_rec = deref_edge_ref(edge_ref); + return (marker_flag_from_edge_rec(*edge_rec) && + unichar_id == unichar_id_from_edge_rec(*edge_rec) && + word_end == end_of_word_from_edge_rec(*edge_rec)) ? + edge_ref : NO_EDGE; + } + + // Adds a word to the Trie (creates the necessary nodes and edges). + // + // If repetitions vector is not NULL, each entry in the vector indicates + // whether the unichar id with the corresponding index in the word is allowed + // to repeat an unlimited number of times. For each entry that is true, MARKER + // flag of the corresponding edge created for this unichar id is set to true). + // + // Return true if add succeeded, false otherwise (e.g. when a word contained + // an invalid unichar id or the trie was getting too large and was cleared). + bool add_word_to_dawg(const WERD_CHOICE &word, + const GenericVector *repetitions); + bool add_word_to_dawg(const WERD_CHOICE &word) { + return add_word_to_dawg(word, NULL); + } + + protected: + // The structure of an EDGE_REF for Trie edges is as follows: + // [LETTER_START_BIT, flag_start_bit_): + // edge index in *_edges in a TRIE_NODE_RECORD + // [flag_start_bit, 30th bit]: node index in nodes (TRIE_NODES vector) + // + // With this arrangement there are enough bits to represent edge indices + // (each node can have at most unicharset_size_ forward edges and + // the position of flag_start_bit is set to be log2(unicharset_size_)). + // It is also possible to accommodate a maximum number of nodes that is at + // least as large as that of the SquishedDawg representation (in SquishedDawg + // each EDGE_RECORD has 32-(flag_start_bit+NUM_FLAG_BITS) bits to represent + // the next node index). + // + + // Returns the pointer to EDGE_RECORD after decoding the location + // of the edge from the information in the given EDGE_REF. + // This function assumes that EDGE_REF holds valid node/edge indices. + inline EDGE_RECORD *deref_edge_ref(EDGE_REF edge_ref) const { + int edge_index = static_cast( + (edge_ref & letter_mask_) >> LETTER_START_BIT); + int node_index = static_cast( + (edge_ref & deref_node_index_mask_) >> flag_start_bit_); + TRIE_NODE_RECORD *node_rec = nodes_[node_index]; + return &(node_rec->forward_edges[edge_index]); + } + /** Constructs EDGE_REF from the given node_index and edge_index. */ + inline EDGE_REF make_edge_ref(NODE_REF node_index, + EDGE_INDEX edge_index) const { + return ((node_index << flag_start_bit_) | + (edge_index << LETTER_START_BIT)); + } + /** Sets up this edge record to the requested values. */ + inline void link_edge(EDGE_RECORD *edge, NODE_REF nxt, bool repeats, + int direction, bool word_end, UNICHAR_ID unichar_id) { + EDGE_RECORD flags = 0; + if (repeats) flags |= MARKER_FLAG; + if (word_end) flags |= WERD_END_FLAG; + if (direction == BACKWARD_EDGE) flags |= DIRECTION_FLAG; + *edge = ((nxt << next_node_start_bit_) | + (static_cast(flags) << flag_start_bit_) | + (static_cast(unichar_id) << LETTER_START_BIT)); + } + /** Prints the given EDGE_RECORD. */ + inline void print_edge_rec(const EDGE_RECORD &edge_rec) const { + tprintf("|" REFFORMAT "|%s%s%s|%d|", next_node_from_edge_rec(edge_rec), + marker_flag_from_edge_rec(edge_rec) ? "R," : "", + (direction_from_edge_rec(edge_rec) == FORWARD_EDGE) ? "F" : "B", + end_of_word_from_edge_rec(edge_rec) ? ",E" : "", + unichar_id_from_edge_rec(edge_rec)); + } + // Returns true if the next node in recorded the given EDGE_RECORD + // has exactly one forward edge. + inline bool can_be_eliminated(const EDGE_RECORD &edge_rec) { + NODE_REF node_ref = next_node_from_edge_rec(edge_rec); + return (node_ref != NO_EDGE && + nodes_[static_cast(node_ref)]->forward_edges.size() == 1); + } + + // Prints the contents of the Trie. + // At most max_num_edges will be printed for each node. + void print_all(const char* msg, int max_num_edges) { + tprintf("\n__________________________\n%s\n", msg); + for (int i = 0; i < nodes_.size(); ++i) print_node(i, max_num_edges); + tprintf("__________________________\n"); + } + + // Finds the edge with the given direction, word_end and unichar_id + // in the node indicated by node_ref. Fills in the pointer to the + // EDGE_RECORD and the index of the edge with the the values + // corresponding to the edge found. Returns true if an edge was found. + bool edge_char_of(NODE_REF node_ref, NODE_REF next_node, + int direction, bool word_end, UNICHAR_ID unichar_id, + EDGE_RECORD **edge_ptr, EDGE_INDEX *edge_index) const; + + // Adds an single edge linkage between node1 and node2 in the direction + // indicated by direction argument. + bool add_edge_linkage(NODE_REF node1, NODE_REF node2, bool repeats, + int direction, bool word_end, + UNICHAR_ID unichar_id); + + // Adds forward edge linkage from node1 to node2 and the corresponding + // backward edge linkage in the other direction. + bool add_new_edge(NODE_REF node1, NODE_REF node2, + bool repeats, bool word_end, UNICHAR_ID unichar_id) { + return (add_edge_linkage(node1, node2, repeats, FORWARD_EDGE, + word_end, unichar_id) && + add_edge_linkage(node2, node1, repeats, BACKWARD_EDGE, + word_end, unichar_id)); + } + + // Sets the word ending flags in an already existing edge pair. + // Returns true on success. + void add_word_ending(EDGE_RECORD *edge, + NODE_REF the_next_node, + bool repeats, + UNICHAR_ID unichar_id); + + // Allocates space for a new node in the Trie. + NODE_REF new_dawg_node(); + + // Removes a single edge linkage to between node1 and node2 in the + // direction indicated by direction argument. + void remove_edge_linkage(NODE_REF node1, NODE_REF node2, int direction, + bool word_end, UNICHAR_ID unichar_id); + + // Removes forward edge linkage from node1 to node2 and the corresponding + // backward edge linkage in the other direction. + void remove_edge(NODE_REF node1, NODE_REF node2, + bool word_end, UNICHAR_ID unichar_id) { + remove_edge_linkage(node1, node2, FORWARD_EDGE, word_end, unichar_id); + remove_edge_linkage(node2, node1, BACKWARD_EDGE, word_end, unichar_id); + } + + // Compares edge1 and edge2 in the given node to see if they point to two + // next nodes that could be collapsed. If they do, performs the reduction + // and returns true. + bool eliminate_redundant_edges(NODE_REF node, const EDGE_RECORD &edge1, + const EDGE_RECORD &edge2); + + // Assuming that edge_index indicates the first edge in a group of edges + // in this node with a particular letter value, looks through these edges + // to see if any of them can be collapsed. If so does it. Returns to the + // caller when all edges with this letter have been reduced. + // Returns true if further reduction is possible with this same letter. + bool reduce_lettered_edges(EDGE_INDEX edge_index, + UNICHAR_ID unichar_id, + NODE_REF node, + EDGE_VECTOR* backward_edges, + NODE_MARKER reduced_nodes); + + /** + * Order num_edges of consequtive EDGE_RECORDS in the given EDGE_VECTOR in + * increasing order of unichar ids. This function is normally called + * for all edges in a single node, and since number of edges in each node + * is usually quite small, selection sort is used. + */ + void sort_edges(EDGE_VECTOR *edges); + + /** Eliminates any redundant edges from this node in the Trie. */ + void reduce_node_input(NODE_REF node, NODE_MARKER reduced_nodes); + + // Returns the pattern unichar id for the given character class code. + UNICHAR_ID character_class_to_pattern(char ch); + + // Member variables + TRIE_NODES nodes_; // vector of nodes in the Trie + uinT64 num_edges_; // sum of all edges (forward and backward) + uinT64 deref_direction_mask_; // mask for EDGE_REF to extract direction + uinT64 deref_node_index_mask_; // mask for EDGE_REF to extract node index + // Freelist of edges in the root backwards node that were previously zeroed. + GenericVector root_back_freelist_; + // Variables for translating character class codes denoted in user patterns + // file to the unichar ids used to represent them in a Trie. + bool initialized_patterns_; + UNICHAR_ID alpha_pattern_; + UNICHAR_ID digit_pattern_; + UNICHAR_ID alphanum_pattern_; + UNICHAR_ID punc_pattern_; + UNICHAR_ID lower_pattern_; + UNICHAR_ID upper_pattern_; +}; +} // namespace tesseract + +#endif diff --git a/TesseractOCR/include/tesseract/tuning_params.h b/TesseractOCR/include/tesseract/tuning_params.h new file mode 100644 index 00000000..4d4943a2 --- /dev/null +++ b/TesseractOCR/include/tesseract/tuning_params.h @@ -0,0 +1,129 @@ +/********************************************************************** + * File: tuning_params.h + * Description: Declaration of the Tuning Parameters Base Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The TuningParams class abstracts all the parameters that can be learned or +// tuned during the training process. It is a base class that all TuningParams +// classes should inherit from. + +#ifndef TUNING_PARAMS_H +#define TUNING_PARAMS_H + +#include +#ifdef USE_STD_NAMESPACE +using std::string; +#endif + +namespace tesseract { +class TuningParams { + public: + enum type_classifer { + NN, + HYBRID_NN + }; + enum type_feature { + BMP, + CHEBYSHEV, + HYBRID + }; + + TuningParams() {} + virtual ~TuningParams() {} + // Accessor functions + inline double RecoWgt() const { return reco_wgt_; } + inline double SizeWgt() const { return size_wgt_; } + inline double CharBigramWgt() const { return char_bigrams_wgt_; } + inline double WordUnigramWgt() const { return word_unigrams_wgt_; } + inline int MaxSegPerChar() const { return max_seg_per_char_; } + inline int BeamWidth() const { return beam_width_; } + inline int TypeClassifier() const { return tp_classifier_; } + inline int TypeFeature() const { return tp_feat_; } + inline int ConvGridSize() const { return conv_grid_size_; } + inline int HistWindWid() const { return hist_wind_wid_; } + inline int MinConCompSize() const { return min_con_comp_size_; } + inline double MaxWordAspectRatio() const { return max_word_aspect_ratio_; } + inline double MinSpaceHeightRatio() const { return min_space_height_ratio_; } + inline double MaxSpaceHeightRatio() const { return max_space_height_ratio_; } + inline double CombinerRunThresh() const { return combiner_run_thresh_; } + inline double CombinerClassifierThresh() const { + return combiner_classifier_thresh_; } + + inline void SetRecoWgt(double wgt) { reco_wgt_ = wgt; } + inline void SetSizeWgt(double wgt) { size_wgt_ = wgt; } + inline void SetCharBigramWgt(double wgt) { char_bigrams_wgt_ = wgt; } + inline void SetWordUnigramWgt(double wgt) { word_unigrams_wgt_ = wgt; } + inline void SetMaxSegPerChar(int max_seg_per_char) { + max_seg_per_char_ = max_seg_per_char; + } + inline void SetBeamWidth(int beam_width) { beam_width_ = beam_width; } + inline void SetTypeClassifier(type_classifer tp_classifier) { + tp_classifier_ = tp_classifier; + } + inline void SetTypeFeature(type_feature tp_feat) {tp_feat_ = tp_feat;} + inline void SetHistWindWid(int hist_wind_wid) { + hist_wind_wid_ = hist_wind_wid; + } + + virtual bool Save(string file_name) = 0; + virtual bool Load(string file_name) = 0; + + protected: + // weight of recognition cost. This includes the language model cost + double reco_wgt_; + // weight of size cost + double size_wgt_; + // weight of character bigrams cost + double char_bigrams_wgt_; + // weight of word unigrams cost + double word_unigrams_wgt_; + // Maximum number of segments per character + int max_seg_per_char_; + // Beam width equal to the maximum number of nodes kept in the beam search + // trellis column after pruning + int beam_width_; + // Classifier type: See enum type_classifer for classifier types + type_classifer tp_classifier_; + // Feature types: See enum type_feature for feature types + type_feature tp_feat_; + // Grid size to scale a grapheme bitmap used by the BMP feature type + int conv_grid_size_; + // Histogram window size as a ratio of the word height used in computing + // the vertical pixel density histogram in the segmentation algorithm + int hist_wind_wid_; + // Minimum possible size of a connected component + int min_con_comp_size_; + // Maximum aspect ratio of a word (width / height) + double max_word_aspect_ratio_; + // Minimum ratio relative to the line height of a gap to be considered as + // a word break + double min_space_height_ratio_; + // Maximum ratio relative to the line height of a gap to be considered as + // a definite word break + double max_space_height_ratio_; + // When Cube and Tesseract are run in combined mode, only run + // combiner classifier when tesseract confidence is below this + // threshold. When Cube is run without Tesseract, this is ignored. + double combiner_run_thresh_; + // When Cube and tesseract are run in combined mode, threshold on + // output of combiner binary classifier (chosen from ROC during + // combiner training). When Cube is run without Tesseract, this is ignored. + double combiner_classifier_thresh_; +}; +} + +#endif // TUNING_PARAMS_H diff --git a/TesseractOCR/include/tesseract/underlin.h b/TesseractOCR/include/tesseract/underlin.h new file mode 100644 index 00000000..c3b4b47a --- /dev/null +++ b/TesseractOCR/include/tesseract/underlin.h @@ -0,0 +1,52 @@ +/********************************************************************** + * File: underlin.h (Formerly undrline.h) + * Description: Code to chop blobs apart from underlines. + * Author: Ray Smith + * Created: Mon Aug 8 11:14:00 BST 1994 + * + * (C) Copyright 1994, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef UNDERLIN_H +#define UNDERLIN_H + +#include "fpchop.h" + +extern double_VAR_H (textord_underline_offset, 0.1, +"Fraction of x to ignore"); +extern BOOL_VAR_H (textord_restore_underlines, FALSE, +"Chop underlines & put back"); +void restore_underlined_blobs( //get chop points + TO_BLOCK *block //block to do + ); +TO_ROW *most_overlapping_row( //find best row + TO_ROW_LIST *rows, //list of rows + BLOBNBOX *blob //blob to place + ); +void find_underlined_blobs( //get chop points + BLOBNBOX *u_line, //underlined unit + QSPLINE *baseline, //actual baseline + float xheight, //height of line + float baseline_offset, //amount to shrinke it + ICOORDELT_LIST *chop_cells //places to chop + ); +void vertical_cunderline_projection( //project outlines + C_OUTLINE *outline, //outline to project + QSPLINE *baseline, //actual baseline + float xheight, //height of line + float baseline_offset, //amount to shrinke it + STATS *lower_proj, //below baseline + STATS *middle_proj, //centre region + STATS *upper_proj //top region + ); +#endif diff --git a/TesseractOCR/include/tesseract/unichar.h b/TesseractOCR/include/tesseract/unichar.h old mode 100755 new mode 100644 index d1c8e51e..9b55f806 --- a/TesseractOCR/include/tesseract/unichar.h +++ b/TesseractOCR/include/tesseract/unichar.h @@ -83,6 +83,69 @@ class UNICHAR { // Get the number of bytes in the first character of the given utf8 string. static int utf8_step(const char* utf8_str); + // A class to simplify iterating over and accessing elements of a UTF8 + // string. Note that unlike the UNICHAR class, const_iterator does NOT COPY or + // take ownership of the underlying byte array. It also does not permit + // modification of the array (as the name suggests). + // + // Example: + // for (UNICHAR::const_iterator it = UNICHAR::begin(str, str_len); + // it != UNICHAR::end(str, len); + // ++it) { + // tprintf("UCS-4 symbol code = %d\n", *it); + // char buf[5]; + // int char_len = it.get_utf8(buf); buf[char_len] = '\0'; + // tprintf("Char = %s\n", buf); + // } + class const_iterator { + typedef const_iterator CI; + + public: + // Step to the next UTF8 character. + // If the current position is at an illegal UTF8 character, then print an + // error message and step by one byte. If the current position is at a NULL + // value, don't step past it. + const_iterator& operator++(); + + // Return the UCS-4 value at the current position. + // If the current position is at an illegal UTF8 value, return a single + // space character. + int operator*() const; + + // Store the UTF-8 encoding of the current codepoint into buf, which must be + // at least 4 bytes long. Return the number of bytes written. + // If the current position is at an illegal UTF8 value, writes a single + // space character and returns 1. + // Note that this method does not null-terminate the buffer. + int get_utf8(char* buf) const; + // Returns the number of bytes of the current codepoint. Returns 1 if the + // current position is at an illegal UTF8 value. + int utf8_len() const; + + // Return the pointer into the string at the current position. + const char* utf8_data() const { return it_; } + + // Iterator equality operators. + friend bool operator==(const CI& lhs, const CI& rhs) { + return lhs.it_ == rhs.it_; + } + friend bool operator!=(const CI& lhs, const CI& rhs) { + return !(lhs == rhs); + } + + private: + friend class UNICHAR; + explicit const_iterator(const char* it) : it_(it) {} + + const char* it_; // Pointer into the string. + }; + + // Create a start/end iterator pointing to a string. Note that these methods + // are static and do NOT create a copy or take ownership of the underlying + // array. + static const_iterator begin(const char* utf8_str, const int byte_length); + static const_iterator end(const char* utf8_str, const int byte_length); + private: // A UTF-8 representation of 1 or more Unicode characters. // The last element (chars[UNICHAR_LEN - 1]) is a length if diff --git a/TesseractOCR/include/tesseract/unicharmap.h b/TesseractOCR/include/tesseract/unicharmap.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/unicharset.h b/TesseractOCR/include/tesseract/unicharset.h old mode 100755 new mode 100644 index 24f1b28c..c2a4f585 --- a/TesseractOCR/include/tesseract/unicharset.h +++ b/TesseractOCR/include/tesseract/unicharset.h @@ -21,12 +21,23 @@ #define TESSERACT_CCUTIL_UNICHARSET_H__ #include "errcode.h" +#include "genericvector.h" #include "helpers.h" #include "strngs.h" #include "tesscallback.h" #include "unichar.h" #include "unicharmap.h" +// Enum holding special values of unichar_id. Every unicharset has these. +// Warning! Keep in sync with kSpecialUnicharCodes. +enum SpecialUnicharCodes { + UNICHAR_SPACE, + UNICHAR_JOINED, + UNICHAR_BROKEN, + + SPECIAL_UNICHAR_CODES_COUNT +}; + class CHAR_FRAGMENT { public: // Minimum number of characters used for fragment representation. @@ -131,6 +142,9 @@ class UNICHARSET { // by only few font families (eg. Wyld, Adobe Caslon Pro). static const char* kCustomLigatures[][2]; + // List of strings for the SpecialUnicharCodes. Keep in sync with the enum. + static const char* kSpecialUnicharCodes[SPECIAL_UNICHAR_CODES_COUNT]; + // ICU 2.0 UCharDirection enum (from third_party/icu/include/unicode/uchar.h) enum Direction { U_LEFT_TO_RIGHT = 0, @@ -170,16 +184,39 @@ class UNICHARSET { int length) const; // Return the minimum number of bytes that matches a legal UNICHAR_ID, - // while leaving a legal UNICHAR_ID afterwards. In other words, if there - // is both a short and a long match to the string, return the length that - // ensures there is a legal match after it. + // while leaving the rest of the string encodable. Returns 0 if the + // beginning of the string is not encodable. + // WARNING: this function now encodes the whole string for precision. + // Use encode_string in preference to repeatedly calling step. int step(const char* str) const; + // As step except constraining the search to unichar-ids that are + // self-normalized. Unlike step, does not encode the whole string, therefore + // should be used on short strings (like those obtained from + // get_normed_unichar.) + int normed_step(const char* str) const; // Return whether the given UTF-8 string is encodable with this UNICHARSET. // If not encodable, write the first byte offset which cannot be converted // into the second (return) argument. bool encodable_string(const char *str, int *first_bad_position) const; + // Encodes the given UTF-8 string with this UNICHARSET. + // Any part of the string that cannot be encoded (because the utf8 can't + // be broken up into pieces that are in the unicharset) then: + // if give_up_on_failure, stops and returns a partial encoding, + // else continues and inserts an INVALID_UNICHAR_ID in the returned encoding. + // Returns true if the encoding succeeds completely, false if there is at + // least one failure. + // If lengths is not NULL, then it is filled with the corresponding + // byte length of each encoded UNICHAR_ID. + // If encoded_length is not NULL then on return it contains the length of + // str that was encoded. (if give_up_on_failure the location of the first + // failure, otherwise strlen(str).) + bool encode_string(const char* str, bool give_up_on_failure, + GenericVector* encoding, + GenericVector* lengths, + int* encoded_length) const; + // Return the unichar representation corresponding to the given UNICHAR_ID // within the UNICHARSET. const char* const id_to_unichar(UNICHAR_ID id) const; @@ -386,7 +423,11 @@ class UNICHARSET { // Record normalized version of unichar with the given unichar_id. void set_normed(UNICHAR_ID unichar_id, const char* normed) { unichars[unichar_id].properties.normed = normed; + unichars[unichar_id].properties.normed_ids.truncate(0); } + // Sets the normed_ids vector from the normed string. normed_ids is not + // stored in the file, and needs to be set when the UNICHARSET is loaded. + void set_normed_ids(UNICHAR_ID unichar_id); // Return the isalpha property of the given unichar. bool get_isalpha(UNICHAR_ID unichar_id) const { @@ -443,15 +484,25 @@ class UNICHARSET { // Sets all the properties for this unicharset given a src_unicharset with // everything set. The unicharsets don't have to be the same, and graphemes // are correctly accounted for. - void SetPropertiesFromOther(const UNICHARSET& src); + void SetPropertiesFromOther(const UNICHARSET& src) { + PartialSetPropertiesFromOther(0, src); + } + // Sets properties from Other, starting only at the given index. + void PartialSetPropertiesFromOther(int start_index, const UNICHARSET& src); // Expands the tops and bottoms and widths for this unicharset given a // src_unicharset with ranges in it. The unicharsets don't have to be the // same, and graphemes are correctly accounted for. void ExpandRangesFromOther(const UNICHARSET& src); + // Makes this a copy of src. Clears this completely first, so the automattic + // ids will not be present in this if not in src. + void CopyFrom(const UNICHARSET& src); // For each id in src, if it does not occur in this, add it, as in // SetPropertiesFromOther, otherwise expand the ranges, as in // ExpandRangesFromOther. void AppendOtherUnicharset(const UNICHARSET& src); + // Returns true if the acceptable ranges of the tops of the characters do + // not overlap, making their x-height calculations distinct. + bool SizesDistinct(UNICHAR_ID id1, UNICHAR_ID id2) const; // Returns the min and max bottom and top of the given unichar in // baseline-normalized coordinates, ie, where the baseline is // kBlnBaselineOffset and the meanline is kBlnBaselineOffset + kBlnXHeight @@ -605,6 +656,15 @@ class UNICHARSET { return unichars[unichar_id].properties.other_case; } + // Returns true if this UNICHARSET has the special codes in + // SpecialUnicharCodes available. If false then there are normal unichars + // at these codes and they should not be used. + bool has_special_codes() const { + return get_fragment(UNICHAR_BROKEN) != NULL && + strcmp(id_to_unichar(UNICHAR_BROKEN), + kSpecialUnicharCodes[UNICHAR_BROKEN]) == 0; + } + // Return a pointer to the CHAR_FRAGMENT class if the given // unichar id represents a character fragment. const CHAR_FRAGMENT *get_fragment(UNICHAR_ID unichar_id) const { @@ -704,6 +764,12 @@ class UNICHARSET { const char *get_normed_unichar(UNICHAR_ID unichar_id) const { return unichars[unichar_id].properties.normed.string(); } + // Returns a vector of UNICHAR_IDs that represent the ids of the normalized + // version of the given id. There may be more than one UNICHAR_ID in the + // vector if unichar_id represents a ligature. + const GenericVector& normed_ids(UNICHAR_ID unichar_id) const { + return unichars[unichar_id].properties.normed_ids; + } // Return the script name of the given unichar representation. // Only the first length characters from unichar_repr are used. @@ -823,6 +889,10 @@ class UNICHARSET { // '[open paren]', 'd', 'r', 'o', 'w', '[close paren]' not // '[close paren]', 'd', 'r', 'o', 'w', '[open paren]'. UNICHAR_ID mirror; + // A string of unichar_ids that represent the corresponding normed string. + // For awkward characters like em-dash, this gives hyphen. + // For ligatures, this gives the string of normal unichars. + GenericVector normed_ids; STRING normed; // normalized version of this unichar // Contains meta information about the fragment if a unichar represents // a fragment of a character, otherwise should be set to NULL. @@ -836,6 +906,24 @@ class UNICHARSET { UNICHAR_PROPERTIES properties; }; + // Internal recursive version of encode_string above. + // str is the start of the whole string. + // str_index is the current position in str. + // str_length is the length of str. + // encoding is a working encoding of str. + // lengths is a working set of lengths of each element of encoding. + // best_total_length is the longest length of str that has been successfully + // encoded so far. + // On return: + // best_encoding contains the encoding that used the longest part of str. + // best_lengths (may be null) contains the lengths of best_encoding. + void encode_string(const char* str, int str_index, int str_length, + GenericVector* encoding, + GenericVector* lengths, + int* best_total_length, + GenericVector* best_encoding, + GenericVector* best_lengths) const; + // Gets the properties for a grapheme string, combining properties for // multiple characters in a meaningful way where possible. // Returns false if no valid match was found in the unicharset. diff --git a/TesseractOCR/include/tesseract/unicity_table.h b/TesseractOCR/include/tesseract/unicity_table.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/unicodes.h b/TesseractOCR/include/tesseract/unicodes.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/universalambigs.h b/TesseractOCR/include/tesseract/universalambigs.h new file mode 100644 index 00000000..bcc633e8 --- /dev/null +++ b/TesseractOCR/include/tesseract/universalambigs.h @@ -0,0 +1,26 @@ +/////////////////////////////////////////////////////////////////////// +// File: universalambigs.h +// Description: Data for a universal ambigs file that is useful for +// any language. +// Author: Ray Smith +// Created: Mon Mar 18 11:26:00 PDT 2013 +// +// (C) Copyright 2013, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +namespace tesseract { + +extern const char kUniversalAmbigsFile[]; +extern const int ksizeofUniversalAmbigsFile; + +} // namespace tesseract diff --git a/TesseractOCR/include/tesseract/util.h b/TesseractOCR/include/tesseract/util.h new file mode 100644 index 00000000..e4f58136 --- /dev/null +++ b/TesseractOCR/include/tesseract/util.h @@ -0,0 +1,68 @@ +/********************************************************************** + * File: util.h + * Description: Misc STL string utility functions. + * Author: Samuel Charron + * Created: Mon Nov 18 2013 + * + * (C) Copyright 2013, Google Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + **********************************************************************/ + +#ifndef TESSERACT_TRAINING_UTIL_H_ +#define TESSERACT_TRAINING_UTIL_H_ + +#include +#include +#include +#include + +#ifdef USE_STD_NAMESPACE +using std::string; +using std::vector; +#endif + +// StringHash is the hashing functor needed by the stl hash map. +#ifndef COMPILER_MSVC +struct StringHash { + size_t operator()(const string& s) const { + size_t hash_code = 0; + const char* str = s.c_str(); + for (int ch = 0; str[ch] != 0; ++ch) { + hash_code += str[ch] << (ch % 24); + } + return hash_code; + } +}; +#else // COMPILER_MSVC +struct StringHash : public stdext::hash_compare { + size_t operator()(const string& s) const { + size_t hash_code = 0; + const char* str = s.c_str(); + for (int ch = 0; str[ch] != 0; ++ch) { + hash_code += str[ch] << (ch % 24); + } + return hash_code; + } + bool operator()(const string& s1, const string& s2) const { + return s1 == s2; + } +}; +#endif // !COMPILER_MSVC + +#ifndef USE_STD_NAMESPACE +#include "base/heap-checker.h" +#define DISABLE_HEAP_LEAK_CHECK HeapLeakChecker::Disabler disabler +#else +#define DISABLE_HEAP_LEAK_CHECK {} +#endif + +#endif // TESSERACT_TRAINING_UTIL_H_ diff --git a/TesseractOCR/include/tesseract/vecfuncs.h b/TesseractOCR/include/tesseract/vecfuncs.h old mode 100755 new mode 100644 index 4a21d7c5..91bbb088 --- a/TesseractOCR/include/tesseract/vecfuncs.h +++ b/TesseractOCR/include/tesseract/vecfuncs.h @@ -28,7 +28,7 @@ #include #include "blobs.h" -class EDGEPT; +struct EDGEPT; /*---------------------------------------------------------------------- M a c r o s @@ -42,8 +42,7 @@ class EDGEPT; #define point_diff(p,p1,p2) \ ((p).x = (p1).x - (p2).x, \ - (p).y = (p1).y - (p2).y, \ - (p)) + (p).y = (p1).y - (p2).y) /********************************************************************** * CROSS diff --git a/TesseractOCR/include/tesseract/version.h b/TesseractOCR/include/tesseract/version.h new file mode 100644 index 00000000..b1bdf4ce --- /dev/null +++ b/TesseractOCR/include/tesseract/version.h @@ -0,0 +1,25 @@ +/////////////////////////////////////////////////////////////////////// +// File: version.h +// Description: define version identifier for Windows +// Author: zdenop@gmail.com +// Created: Fri Nov 19 21:05:06 CET 2010 +// +// (C) Copyright 2010, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef VS2008_PORT_VERSION_H_ +#define VS2008_PORT_VERSION_H_ + +#define VERSION "3.03" + +#endif // VS2008_PORT_VERSION_H_ diff --git a/TesseractOCR/include/tesseract/werd.h b/TesseractOCR/include/tesseract/werd.h old mode 100755 new mode 100644 diff --git a/TesseractOCR/include/tesseract/werdit.h b/TesseractOCR/include/tesseract/werdit.h old mode 100755 new mode 100644 index b3f6181d..bb58e67d --- a/TesseractOCR/include/tesseract/werdit.h +++ b/TesseractOCR/include/tesseract/werdit.h @@ -21,10 +21,9 @@ #define WERDIT_H #include "pageres.h" -#include "notdll.h" WERD *make_pseudo_word(PAGE_RES* page_res, // blocks to check - TBOX &selection_box, + const TBOX &selection_box, BLOCK *&pseudo_block, ROW *&pseudo_row); diff --git a/TesseractOCR/include/tesseract/word_altlist.h b/TesseractOCR/include/tesseract/word_altlist.h new file mode 100644 index 00000000..7b1620fe --- /dev/null +++ b/TesseractOCR/include/tesseract/word_altlist.h @@ -0,0 +1,50 @@ +/********************************************************************** + * File: word_altlist.h + * Description: Declaration of the Word Alternate List Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The WordAltList abstracts a alternate list of words and their corresponding +// costs that result from the word recognition process. The class inherits +// from the AltList class +// It provides methods to add a new word alternate, its corresponding score and +// a tag. + +#ifndef WORD_ALT_LIST_H +#define WORD_ALT_LIST_H + +#include "altlist.h" + +namespace tesseract { +class WordAltList : public AltList { + public: + explicit WordAltList(int max_alt); + ~WordAltList(); + // Sort the list of alternates based on cost + void Sort(); + // insert an alternate word with the specified cost and tag + bool Insert(char_32 *char_ptr, int cost, void *tag = NULL); + // returns the alternate string at the specified position + inline char_32 * Alt(int alt_idx) { return word_alt_[alt_idx]; } + // print each entry of the altlist, both UTF8 and unichar ids, and + // their costs, to stderr + void PrintDebug(); + private: + char_32 **word_alt_; +}; +} // namespace tesseract + +#endif // WORD_ALT_LIST_H diff --git a/TesseractOCR/include/tesseract/word_list_lang_model.h b/TesseractOCR/include/tesseract/word_list_lang_model.h new file mode 100644 index 00000000..099d6294 --- /dev/null +++ b/TesseractOCR/include/tesseract/word_list_lang_model.h @@ -0,0 +1,89 @@ +/********************************************************************** + * File: word_list_lang_model.h + * Description: Declaration of the Word List Language Model Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The WordListLangModel class abstracts a language model that is based on +// a list of words. It inherits from the LangModel abstract class +// Besides providing the methods inherited from the LangModel abstract class, +// the class provided methods to add new strings to the Language Model: +// AddString & AddString32 + +#ifndef WORD_LIST_LANG_MODEL_H +#define WORD_LIST_LANG_MODEL_H + +#include + +#include "cube_reco_context.h" +#include "lang_model.h" +#include "tess_lang_mod_edge.h" + +namespace tesseract { + +class Trie; + +class WordListLangModel : public LangModel { + public: + explicit WordListLangModel(CubeRecoContext *cntxt); + ~WordListLangModel(); + // Returns an edge pointer to the Root + LangModEdge *Root(); + // Returns the edges that fan-out of the specified edge and their count + LangModEdge **GetEdges(CharAltList *alt_list, + LangModEdge *edge, + int *edge_cnt); + // Returns is a sequence of 32-bit characters are valid within this language + // model or net. And EndOfWord flag is specified. If true, the sequence has + // to end on a valid word. The function also optionally returns the list + // of language model edges traversed to parse the string + bool IsValidSequence(const char_32 *sequence, + bool eow_flag, + LangModEdge **edges); + bool IsLeadingPunc(char_32 ch) { return false; } // not yet implemented + bool IsTrailingPunc(char_32 ch) { return false; } // not yet implemented + bool IsDigit(char_32 ch) { return false; } // not yet implemented + // Adds a new UTF-8 string to the language model + bool AddString(const char *char_ptr); + // Adds a new UTF-32 string to the language model + bool AddString32(const char_32 *char_32_ptr); + // Compute all the variants of a 32-bit string in terms of the class-ids. + // This is needed for languages that have ligatures. A word can then have + // more than one spelling in terms of the class-ids. + static void WordVariants(const CharSet &char_set, const UNICHARSET *uchset, + string_32 str32, + vector *word_variants); + private: + // constants needed to configure the language model + static const int kMaxEdge = 512; + + CubeRecoContext *cntxt_; + Trie *dawg_; + bool init_; + // Initialize the language model + bool Init(); + // Cleanup + void Cleanup(); + // Recursive helper function for WordVariants(). + static void WordVariants( + const CharSet &char_set, + string_32 prefix_str32, WERD_CHOICE *word_so_far, + string_32 str32, + vector *word_variants); +}; +} // tesseract + +#endif // WORD_LIST_LANG_MODEL_H diff --git a/TesseractOCR/include/tesseract/word_size_model.h b/TesseractOCR/include/tesseract/word_size_model.h new file mode 100644 index 00000000..fade595b --- /dev/null +++ b/TesseractOCR/include/tesseract/word_size_model.h @@ -0,0 +1,100 @@ +/********************************************************************** + * File: word_size_model.h + * Description: Declaration of the Word Size Model Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The WordSizeModel class abstracts the geometrical relationships +// between characters/shapes in the same word (presumeably of the same font) +// A non-parametric bigram model describes the three geometrical properties of a +// character pair: +// 1- Normalized Width +// 2- Normalized Top +// 3- Normalized Height +// These dimensions are computed for each character pair in a word. These are +// then compared to the same information for each of the fonts that the size +// model knows about. The WordSizeCost is the cost of the font that matches +// best. + +#ifndef WORD_SIZE_MODEL_H +#define WORD_SIZE_MODEL_H + +#include +#include "char_samp.h" +#include "char_set.h" + +namespace tesseract { +struct PairSizeInfo { + int delta_top; + int wid_0; + int hgt_0; + int wid_1; + int hgt_1; +}; + +struct FontPairSizeInfo { + string font_name; + PairSizeInfo **pair_size_info; +}; + +class WordSizeModel { + public: + WordSizeModel(CharSet *, bool contextual); + virtual ~WordSizeModel(); + static WordSizeModel *Create(const string &data_file_path, + const string &lang, + CharSet *char_set, + bool contextual); + // Given a word and number of unichars, return the size cost, + // minimized over all fonts in the size model. + int Cost(CharSamp **samp_array, int samp_cnt) const; + // Given dimensions of a pair of character samples and a font size + // model for that character pair, return the pair's size cost for + // the font. + static double PairCost(int width_0, int height_0, int top_0, + int width_1, int height_1, int top_1, + const PairSizeInfo& pair_info); + bool Save(string file_name); + // Number of fonts in size model. + inline int FontCount() const { + return font_pair_size_models_.size(); + } + inline const FontPairSizeInfo *FontInfo() const { + return &font_pair_size_models_[0]; + } + // Helper functions to convert between size codes, class id and position + // codes + static inline int SizeCode(int cls_id, int start, int end) { + return (cls_id << 2) + (end << 1) + start; + } + + private: + // Scaling constant used to convert floating point ratios in size table + // to fixed point + static const int kShapeModelScale = 1000; + static const int kExpectedTokenCount = 10; + + // Language properties + bool contextual_; + CharSet *char_set_; + // Size ratios table + vector font_pair_size_models_; + + // Initialize the word size model object + bool Init(const string &data_file_path, const string &lang); +}; +} +#endif // WORD_SIZE_MODEL_H diff --git a/TesseractOCR/include/tesseract/word_unigrams.h b/TesseractOCR/include/tesseract/word_unigrams.h new file mode 100644 index 00000000..4fcfd452 --- /dev/null +++ b/TesseractOCR/include/tesseract/word_unigrams.h @@ -0,0 +1,69 @@ + /********************************************************************** + * File: word_unigrams.h + * Description: Declaration of the Word Unigrams Class + * Author: Ahmad Abdulkader + * Created: 2008 + * + * (C) Copyright 2008, Google Inc. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +// The WordUnigram class holds the unigrams of the most frequent set of words +// in a language. It is an optional component of the Cube OCR engine. If +// present, the unigram cost of a word is aggregated with the other costs +// (Recognition, Language Model, Size) to compute a cost for a word. +// The word list is assumed to be sorted in lexicographic order. + +#ifndef WORD_UNIGRAMS_H +#define WORD_UNIGRAMS_H + +#include +#include "char_set.h" +#include "lang_model.h" + +namespace tesseract { +class WordUnigrams { + public: + WordUnigrams(); + ~WordUnigrams(); + // Load the word-list and unigrams from file and create an object + // The word list is assumed to be sorted + static WordUnigrams *Create(const string &data_file_path, + const string &lang); + // Compute the unigram cost of a UTF-32 string. Splits into + // space-separated tokens, strips trailing punctuation from each + // token, evaluates case properties, and calls internal Cost() + // function on UTF-8 version. To avoid unnecessarily penalizing + // all-one-case words or capitalized words (first-letter + // upper-case and remaining letters lower-case) when not all + // versions of the word appear in the .cube.word-freq file, a + // case-invariant cost is computed in those cases, assuming the word + // meets a minimum length. + int Cost(const char_32 *str32, LangModel *lang_mod, + CharSet *char_set) const; + protected: + // Compute the word unigram cost of a UTF-8 string with binary + // search of sorted words_ array. + int CostInternal(const char *str) const; + private: + // Only words this length or greater qualify for all-numeric or + // case-invariant word unigram cost. + static const int kMinLengthNumOrCaseInvariant = 4; + + int word_cnt_; + char **words_; + int *costs_; + int not_in_list_cost_; +}; +} + +#endif // WORD_UNIGRAMS_H diff --git a/TesseractOCR/include/tesseract/wordrec.h b/TesseractOCR/include/tesseract/wordrec.h new file mode 100644 index 00000000..fdf77fcd --- /dev/null +++ b/TesseractOCR/include/tesseract/wordrec.h @@ -0,0 +1,498 @@ +/////////////////////////////////////////////////////////////////////// +// File: wordrec.h +// Description: wordrec class. +// Author: Samuel Charron +// +// (C) Copyright 2006, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_WORDREC_WORDREC_H__ +#define TESSERACT_WORDREC_WORDREC_H__ + +#include "associate.h" +#include "classify.h" +#include "dict.h" +#include "language_model.h" +#include "ratngs.h" +#include "matrix.h" +#include "gradechop.h" +#include "seam.h" +#include "findseam.h" +#include "callcpp.h" + +class WERD_RES; + +namespace tesseract { + +// A class for storing which nodes are to be processed by the segmentation +// search. There is a single SegSearchPending for each column in the ratings +// matrix, and it indicates whether the segsearch should combine all +// BLOB_CHOICES in the column, or just the given row with the parents +// corresponding to *this SegSearchPending, and whether only updated parent +// ViterbiStateEntries should be combined, or all, with the BLOB_CHOICEs. +class SegSearchPending { + public: + SegSearchPending() + : classified_row_(-1), + revisit_whole_column_(false), + column_classified_(false) {} + + // Marks the whole column as just classified. Used to start a search on + // a newly initialized ratings matrix. + void SetColumnClassified() { + column_classified_ = true; + } + // Marks the matrix entry at the given row as just classified. + // Used after classifying a new matrix cell. + // Additional to, not overriding a previous RevisitWholeColumn. + void SetBlobClassified(int row) { + classified_row_ = row; + } + // Marks the whole column as needing work, but not just classified. + // Used when the parent vse list is updated. + // Additional to, not overriding a previous SetBlobClassified. + void RevisitWholeColumn() { + revisit_whole_column_ = true; + } + + // Clears *this to indicate no work to do. + void Clear() { + classified_row_ = -1; + revisit_whole_column_ = false; + column_classified_ = false; + } + + // Returns true if there are updates to do in the column that *this + // represents. + bool WorkToDo() const { + return revisit_whole_column_ || column_classified_ || classified_row_ >= 0; + } + // Returns true if the given row was just classified. + bool IsRowJustClassified(int row) const { + return row == classified_row_ || column_classified_; + } + // Returns the single row to process if there is only one, otherwise -1. + int SingleRow() const { + return revisit_whole_column_ || column_classified_ ? -1 : classified_row_; + } + + private: + // If non-negative, indicates the single row in the ratings matrix that has + // just been classified, and so should be combined with all the parents in the + // column that this SegSearchPending represents. + // Operates independently of revisit_whole_column. + int classified_row_; + // If revisit_whole_column is true, then all BLOB_CHOICEs in this column will + // be processed, but classified_row can indicate a row that is newly + // classified. Overridden if column_classified is true. + bool revisit_whole_column_; + // If column_classified is true, parent vses are processed with all rows + // regardless of whether they are just updated, overriding + // revisit_whole_column and classified_row. + bool column_classified_; +}; + + +/* ccmain/tstruct.cpp *********************************************************/ +class FRAGMENT:public ELIST_LINK +{ + public: + FRAGMENT() { //constructor + } + FRAGMENT(EDGEPT *head_pt, //start + EDGEPT *tail_pt); //end + + ICOORD head; //coords of start + ICOORD tail; //coords of end + EDGEPT *headpt; //start point + EDGEPT *tailpt; //end point +}; +ELISTIZEH(FRAGMENT) + + +class Wordrec : public Classify { + public: + // config parameters ******************************************************* + BOOL_VAR_H(merge_fragments_in_matrix, TRUE, + "Merge the fragments in the ratings matrix and delete them " + "after merging"); + BOOL_VAR_H(wordrec_no_block, FALSE, "Don't output block information"); + BOOL_VAR_H(wordrec_enable_assoc, TRUE, "Associator Enable"); + BOOL_VAR_H(force_word_assoc, FALSE, + "force associator to run regardless of what enable_assoc is." + "This is used for CJK where component grouping is necessary."); + double_VAR_H(wordrec_worst_state, 1, "Worst segmentation state"); + BOOL_VAR_H(fragments_guide_chopper, FALSE, + "Use information from fragments to guide chopping process"); + INT_VAR_H(repair_unchopped_blobs, 1, "Fix blobs that aren't chopped"); + double_VAR_H(tessedit_certainty_threshold, -2.25, "Good blob limit"); + INT_VAR_H(chop_debug, 0, "Chop debug"); + BOOL_VAR_H(chop_enable, 1, "Chop enable"); + BOOL_VAR_H(chop_vertical_creep, 0, "Vertical creep"); + INT_VAR_H(chop_split_length, 10000, "Split Length"); + INT_VAR_H(chop_same_distance, 2, "Same distance"); + INT_VAR_H(chop_min_outline_points, 6, "Min Number of Points on Outline"); + INT_VAR_H(chop_seam_pile_size, 150, "Max number of seams in seam_pile"); + BOOL_VAR_H(chop_new_seam_pile, 1, "Use new seam_pile"); + INT_VAR_H(chop_inside_angle, -50, "Min Inside Angle Bend"); + INT_VAR_H(chop_min_outline_area, 2000, "Min Outline Area"); + double_VAR_H(chop_split_dist_knob, 0.5, "Split length adjustment"); + double_VAR_H(chop_overlap_knob, 0.9, "Split overlap adjustment"); + double_VAR_H(chop_center_knob, 0.15, "Split center adjustment"); + INT_VAR_H(chop_centered_maxwidth, 90, "Width of (smaller) chopped blobs " + "above which we don't care that a chop is not near the center."); + double_VAR_H(chop_sharpness_knob, 0.06, "Split sharpness adjustment"); + double_VAR_H(chop_width_change_knob, 5.0, "Width change adjustment"); + double_VAR_H(chop_ok_split, 100.0, "OK split limit"); + double_VAR_H(chop_good_split, 50.0, "Good split limit"); + INT_VAR_H(chop_x_y_weight, 3, "X / Y length weight"); + INT_VAR_H(segment_adjust_debug, 0, "Segmentation adjustment debug"); + BOOL_VAR_H(assume_fixed_pitch_char_segment, FALSE, + "include fixed-pitch heuristics in char segmentation"); + INT_VAR_H(wordrec_debug_level, 0, "Debug level for wordrec"); + INT_VAR_H(wordrec_max_join_chunks, 4, + "Max number of broken pieces to associate"); + BOOL_VAR_H(wordrec_skip_no_truth_words, false, + "Only run OCR for words that had truth recorded in BlamerBundle"); + BOOL_VAR_H(wordrec_debug_blamer, false, "Print blamer debug messages"); + BOOL_VAR_H(wordrec_run_blamer, false, "Try to set the blame for errors"); + INT_VAR_H(segsearch_debug_level, 0, "SegSearch debug level"); + INT_VAR_H(segsearch_max_pain_points, 2000, + "Maximum number of pain points stored in the queue"); + INT_VAR_H(segsearch_max_futile_classifications, 10, + "Maximum number of pain point classifications per word."); + double_VAR_H(segsearch_max_char_wh_ratio, 2.0, + "Maximum character width-to-height ratio"); + BOOL_VAR_H(save_alt_choices, true, + "Save alternative paths found during chopping " + "and segmentation search"); + + // methods from wordrec/*.cpp *********************************************** + Wordrec(); + virtual ~Wordrec(); + + // Fills word->alt_choices with alternative paths found during + // chopping/segmentation search that are kept in best_choices. + void SaveAltChoices(const LIST &best_choices, WERD_RES *word); + + // Fills character choice lattice in the given BlamerBundle + // using the given ratings matrix and best choice list. + void FillLattice(const MATRIX &ratings, const WERD_CHOICE_LIST &best_choices, + const UNICHARSET &unicharset, BlamerBundle *blamer_bundle); + + // Calls fill_lattice_ member function + // (assumes that fill_lattice_ is not NULL). + void CallFillLattice(const MATRIX &ratings, + const WERD_CHOICE_LIST &best_choices, + const UNICHARSET &unicharset, + BlamerBundle *blamer_bundle) { + (this->*fill_lattice_)(ratings, best_choices, unicharset, blamer_bundle); + } + + // tface.cpp + void program_editup(const char *textbase, + bool init_classifier, + bool init_permute); + void cc_recog(WERD_RES *word); + void program_editdown(inT32 elasped_time); + void set_pass1(); + void set_pass2(); + int end_recog(); + BLOB_CHOICE_LIST *call_matcher(TBLOB* blob); + int dict_word(const WERD_CHOICE &word); + // wordclass.cpp + BLOB_CHOICE_LIST *classify_blob(TBLOB *blob, + const char *string, + C_COL color, + BlamerBundle *blamer_bundle); + + // segsearch.cpp + // SegSearch works on the lower diagonal matrix of BLOB_CHOICE_LISTs. + // Each entry in the matrix represents the classification choice + // for a chunk, i.e. an entry in row 2, column 1 represents the list + // of ratings for the chunks 1 and 2 classified as a single blob. + // The entries on the diagonal of the matrix are classifier choice lists + // for a single chunk from the maximal segmentation. + // + // The ratings matrix given to SegSearch represents the segmentation + // graph / trellis for the current word. The nodes in the graph are the + // individual BLOB_CHOICEs in each of the BLOB_CHOICE_LISTs in the ratings + // matrix. The children of each node (nodes connected by outgoing links) + // are the entries in the column that is equal to node's row+1. The parents + // (nodes connected by the incoming links) are the entries in the row that + // is equal to the node's column-1. Here is an example ratings matrix: + // + // 0 1 2 3 4 + // ------------------------- + // 0| c,( | + // 1| d l,1 | + // 2| o | + // 3| c,( | + // 4| g,y l,1 | + // ------------------------- + // + // In the example above node "o" has children (outgoing connection to nodes) + // "c","(","g","y" and parents (incoming connections from nodes) "l","1","d". + // + // The objective of the search is to find the least cost path, where the cost + // is determined by the language model components and the properties of the + // cut between the blobs on the path. SegSearch starts by populating the + // matrix with the all the entries that were classified by the chopper and + // finding the initial best path. Based on the classifier ratings, language + // model scores and the properties of each cut, a list of "pain points" is + // constructed - those are the points on the path where the choices do not + // look consistent with the neighboring choices, the cuts look particularly + // problematic, or the certainties of the blobs are low. The most troublesome + // "pain point" is picked from the list and the new entry in the ratings + // matrix corresponding to this "pain point" is filled in. Then the language + // model state is updated to reflect the new classification and the new + // "pain points" are added to the list and the next most troublesome + // "pain point" is determined. This continues until either the word choice + // composed from the best paths in the segmentation graph is "good enough" + // (e.g. above a certain certainty threshold, is an unambiguous dictionary + // word, etc) or there are no more "pain points" to explore. + // + // If associate_blobs is set to false no new classifications will be done + // to combine blobs. Segmentation search will run only one "iteration" + // on the classifications already recorded in chunks_record.ratings. + // + // Note: this function assumes that word, output_best_state, + // best_char_choices and fixpt arguments are not NULL. + void SegSearch(WERD_RES* word_res, + BestChoiceBundle* best_choice_bundle, + BlamerBundle* blamer_bundle); + + // Runs SegSearch() function (above) without needing a best_choice_bundle + // or blamer_bundle. Used for testing. + void DoSegSearch(WERD_RES* word_res); + + // chop.cpp + PRIORITY point_priority(EDGEPT *point); + void add_point_to_list(PointHeap* point_heap, EDGEPT *point); + int angle_change(EDGEPT *point1, EDGEPT *point2, EDGEPT *point3); + int is_little_chunk(EDGEPT *point1, EDGEPT *point2); + int is_small_area(EDGEPT *point1, EDGEPT *point2); + EDGEPT *pick_close_point(EDGEPT *critical_point, + EDGEPT *vertical_point, + int *best_dist); + void prioritize_points(TESSLINE *outline, PointHeap* points); + void new_min_point(EDGEPT *local_min, PointHeap* points); + void new_max_point(EDGEPT *local_max, PointHeap* points); + void vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point, + EDGEPT** best_point, + EDGEPT_CLIST *new_points); + + // chopper.cpp + SEAM *attempt_blob_chop(TWERD *word, TBLOB *blob, inT32 blob_number, + bool italic_blob, const GenericVector& seams); + SEAM *chop_numbered_blob(TWERD *word, inT32 blob_number, + bool italic_blob, const GenericVector& seams); + SEAM *chop_overlapping_blob(const GenericVector& boxes, + bool italic_blob, + WERD_RES *word_res, int *blob_number); + SEAM *improve_one_blob(const GenericVector &blob_choices, + DANGERR *fixpt, + bool split_next_to_fragment, + bool italic_blob, + WERD_RES *word, + int *blob_number); + SEAM *chop_one_blob(const GenericVector &boxes, + const GenericVector &blob_choices, + WERD_RES *word_res, + int *blob_number); + void chop_word_main(WERD_RES *word); + void improve_by_chopping(float rating_cert_scale, + WERD_RES *word, + BestChoiceBundle *best_choice_bundle, + BlamerBundle *blamer_bundle, + LMPainPoints *pain_points, + GenericVector* pending); + int select_blob_to_split(const GenericVector &blob_choices, + float rating_ceiling, + bool split_next_to_fragment); + int select_blob_to_split_from_fixpt(DANGERR *fixpt); + + // findseam.cpp + void add_seam_to_queue(float new_priority, SEAM *new_seam, SeamQueue* seams); + void choose_best_seam(SeamQueue* seam_queue, + SPLIT *split, + PRIORITY priority, + SEAM **seam_result, + TBLOB *blob, + SeamPile* seam_pile); + void combine_seam(const SeamPile& seam_pile, + const SEAM* seam, SeamQueue* seam_queue); + inT16 constrained_split(SPLIT *split, TBLOB *blob); + SEAM *pick_good_seam(TBLOB *blob); + PRIORITY seam_priority(SEAM *seam, inT16 xmin, inT16 xmax); + void try_point_pairs (EDGEPT * points[MAX_NUM_POINTS], + inT16 num_points, + SeamQueue* seam_queue, + SeamPile* seam_pile, + SEAM ** seam, TBLOB * blob); + void try_vertical_splits(EDGEPT * points[MAX_NUM_POINTS], + inT16 num_points, + EDGEPT_CLIST *new_points, + SeamQueue* seam_queue, + SeamPile* seam_pile, + SEAM ** seam, TBLOB * blob); + + // gradechop.cpp + PRIORITY full_split_priority(SPLIT *split, inT16 xmin, inT16 xmax); + PRIORITY grade_center_of_blob(register BOUNDS_RECT rect); + PRIORITY grade_overlap(register BOUNDS_RECT rect); + PRIORITY grade_split_length(register SPLIT *split); + PRIORITY grade_sharpness(register SPLIT *split); + PRIORITY grade_width_change(register BOUNDS_RECT rect); + void set_outline_bounds(register EDGEPT *point1, + register EDGEPT *point2, + BOUNDS_RECT rect); + + // outlines.cpp + int crosses_outline(EDGEPT *p0, EDGEPT *p1, EDGEPT *outline); + int is_crossed(TPOINT a0, TPOINT a1, TPOINT b0, TPOINT b1); + int is_same_edgept(EDGEPT *p1, EDGEPT *p2); + bool near_point(EDGEPT *point, EDGEPT *line_pt_0, EDGEPT *line_pt_1, + EDGEPT **near_pt); + void reverse_outline(EDGEPT *outline); + + // pieces.cpp + virtual BLOB_CHOICE_LIST *classify_piece(const GenericVector& seams, + inT16 start, + inT16 end, + const char* description, + TWERD *word, + BlamerBundle *blamer_bundle); + // Try to merge fragments in the ratings matrix and put the result in + // the corresponding row and column + void merge_fragments(MATRIX *ratings, + inT16 num_blobs); + // Recursively go through the ratings matrix to find lists of fragments + // to be merged in the function merge_and_put_fragment_lists. + // current_frag is the postion of the piece we are looking for. + // current_row is the row in the rating matrix we are currently at. + // start is the row we started initially, so that we can know where + // to append the results to the matrix. num_frag_parts is the total + // number of pieces we are looking for and num_blobs is the size of the + // ratings matrix. + void get_fragment_lists(inT16 current_frag, + inT16 current_row, + inT16 start, + inT16 num_frag_parts, + inT16 num_blobs, + MATRIX *ratings, + BLOB_CHOICE_LIST *choice_lists); + // Merge the fragment lists in choice_lists and append it to the + // ratings matrix + void merge_and_put_fragment_lists(inT16 row, + inT16 column, + inT16 num_frag_parts, + BLOB_CHOICE_LIST *choice_lists, + MATRIX *ratings); + // Filter the fragment list so that the filtered_choices only contain + // fragments that are in the correct position. choices is the list + // that we are going to filter. fragment_pos is the position in the + // fragment that we are looking for and num_frag_parts is the the + // total number of pieces. The result will be appended to + // filtered_choices. + void fill_filtered_fragment_list(BLOB_CHOICE_LIST *choices, + int fragment_pos, + int num_frag_parts, + BLOB_CHOICE_LIST *filtered_choices); + + // Member variables. + + LanguageModel *language_model_; + PRIORITY pass2_ok_split; + // Stores the best choice for the previous word in the paragraph. + // This variable is modified by PAGE_RES_IT when iterating over + // words to OCR on the page. + WERD_CHOICE *prev_word_best_choice_; + // Sums of blame reasons computed by the blamer. + GenericVector blame_reasons_; + // Function used to fill char choice lattices. + void (Wordrec::*fill_lattice_)(const MATRIX &ratings, + const WERD_CHOICE_LIST &best_choices, + const UNICHARSET &unicharset, + BlamerBundle *blamer_bundle); + + protected: + inline bool SegSearchDone(int num_futile_classifications) { + return (language_model_->AcceptableChoiceFound() || + num_futile_classifications >= + segsearch_max_futile_classifications); + } + + // Updates the language model state recorded for the child entries specified + // in pending[starting_col]. Enqueues the children of the updated entries + // into pending and proceeds to update (and remove from pending) all the + // remaining entries in pending[col] (col >= starting_col). Upon termination + // of this function all the pending[col] lists will be empty. + // + // The arguments: + // + // starting_col: index of the column in chunks_record->ratings from + // which the update should be started + // + // pending: list of entries listing chunks_record->ratings entries + // that should be updated + // + // pain_points: priority heap listing the pain points generated by + // the language model + // + // temp_pain_points: temporary storage for tentative pain points generated + // by the language model after a single call to LanguageModel::UpdateState() + // (the argument is passed in rather than created before each + // LanguageModel::UpdateState() call to avoid dynamic memory re-allocation) + // + // best_choice_bundle: a collection of variables that should be updated + // if a new best choice is found + // + void UpdateSegSearchNodes( + float rating_cert_scale, + int starting_col, + GenericVector* pending, + WERD_RES *word_res, + LMPainPoints *pain_points, + BestChoiceBundle *best_choice_bundle, + BlamerBundle *blamer_bundle); + + // Process the given pain point: classify the corresponding blob, enqueue + // new pain points to join the newly classified blob with its neighbors. + void ProcessSegSearchPainPoint(float pain_point_priority, + const MATRIX_COORD &pain_point, + const char* pain_point_type, + GenericVector* pending, + WERD_RES *word_res, + LMPainPoints *pain_points, + BlamerBundle *blamer_bundle); + // Resets enough of the results so that the Viterbi search is re-run. + // Needed when the n-gram model is enabled, as the multi-length comparison + // implementation will re-value existing paths to worse values. + void ResetNGramSearch(WERD_RES* word_res, + BestChoiceBundle* best_choice_bundle, + GenericVector* pending); + + // Add pain points for classifying blobs on the correct segmentation path + // (so that we can evaluate correct segmentation path and discover the reason + // for incorrect result). + void InitBlamerForSegSearch(WERD_RES *word_res, + LMPainPoints *pain_points, + BlamerBundle *blamer_bundle, + STRING *blamer_debug); +}; + + +} // namespace tesseract + +#endif // TESSERACT_WORDREC_WORDREC_H__ diff --git a/TesseractOCR/include/tesseract/wordseg.h b/TesseractOCR/include/tesseract/wordseg.h new file mode 100644 index 00000000..6391f621 --- /dev/null +++ b/TesseractOCR/include/tesseract/wordseg.h @@ -0,0 +1,77 @@ +/********************************************************************** + * File: wordseg.h (Formerly wspace.h) + * Description: Code to segment the blobs into words. + * Author: Ray Smith + * Created: Fri Oct 16 11:32:28 BST 1992 + * + * (C) Copyright 1992, Hewlett-Packard Ltd. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + * + **********************************************************************/ + +#ifndef WORDSEG_H +#define WORDSEG_H + +#include "params.h" +#include "blobbox.h" +#include "textord.h" + +namespace tesseract { +class Tesseract; +} + +extern BOOL_VAR_H (textord_fp_chopping, TRUE, "Do fixed pitch chopping"); +extern BOOL_VAR_H(textord_force_make_prop_words, FALSE, + "Force proportional word segmentation on all rows"); +extern BOOL_VAR_H (textord_chopper_test, FALSE, + "Chopper is being tested."); + +void make_single_word(bool one_blob, TO_ROW_LIST *rows, ROW_LIST* real_rows); +void make_words(tesseract::Textord *textord, + ICOORD page_tr, // top right + float gradient, // page skew + BLOCK_LIST *blocks, // block list + TO_BLOCK_LIST *port_blocks); // output list +void set_row_spaces( //find space sizes + TO_BLOCK *block, //block to do + FCOORD rotation, //for drawing + BOOL8 testing_on //correct orientation + ); +inT32 row_words( //compute space size + TO_BLOCK *block, //block it came from + TO_ROW *row, //row to operate on + inT32 maxwidth, //max expected space size + FCOORD rotation, //for drawing + BOOL8 testing_on //for debug + ); +inT32 row_words2( //compute space size + TO_BLOCK *block, //block it came from + TO_ROW *row, //row to operate on + inT32 maxwidth, //max expected space size + FCOORD rotation, //for drawing + BOOL8 testing_on //for debug + ); +void make_real_words( + tesseract::Textord *textord, + TO_BLOCK *block, //block to do + FCOORD rotation //for drawing + ); +ROW *make_rep_words( //make a row + TO_ROW *row, //row to convert + TO_BLOCK *block //block it lives in + ); +WERD *make_real_word( //make a WERD + BLOBNBOX_IT *box_it, //iterator + inT32 blobcount, //no of blobs to use + BOOL8 bol, //start of line + uinT8 blanks //no of blanks + ); +#endif diff --git a/TesseractOCR/include/tesseract/workingpartset.h b/TesseractOCR/include/tesseract/workingpartset.h new file mode 100644 index 00000000..f47c6667 --- /dev/null +++ b/TesseractOCR/include/tesseract/workingpartset.h @@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////////////////////// +// File: workingpartset.h +// Description: Class to hold a working set of partitions of the page +// during construction of text/image regions. +// Author: Ray Smith +// Created: Tue Ocr 28 17:21:01 PDT 2008 +// +// (C) Copyright 2008, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////// + +#ifndef TESSERACT_TEXTORD_WORKINGPARSET_H__ +#define TESSERACT_TEXTORD_WORKINGPARSET_H__ + +#include "blobbox.h" // For TO_BLOCK_LIST and BLOCK_LIST. +#include "colpartition.h" // For ColPartition_LIST. + +namespace tesseract { + +// WorkingPartSet holds a working set of ColPartitions during transformation +// from the grid-based storage to regions in logical reading order, and is +// therefore only used during construction of the regions. +class WorkingPartSet : public ELIST_LINK { + public: + WorkingPartSet() { + } + explicit WorkingPartSet(ColPartition* column) + : column_(column), latest_part_(NULL), part_it_(&part_set_) { + } + + // Simple accessors. + ColPartition* column() const { + return column_; + } + void set_column(ColPartition* col) { + column_ = col; + } + + // Add the partition to this WorkingPartSet. Partitions are generally + // stored in the order in which they are received, but if the partition + // has a SingletonPartner, make sure that it stays with its partner. + void AddPartition(ColPartition* part); + + // Make blocks out of any partitions in this WorkingPartSet, and append + // them to the end of the blocks list. bleft, tright and resolution give + // the bounds and resolution of the source image, so that blocks can be + // made to fit in the bounds. + // All ColPartitions go in the used_parts list, as they need to be kept + // around, but are no longer needed. + void ExtractCompletedBlocks(const ICOORD& bleft, const ICOORD& tright, + int resolution, ColPartition_LIST* used_parts, + BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks); + + // Insert the given blocks at the front of the completed_blocks_ list so + // they can be kept in the correct reading order. + void InsertCompletedBlocks(BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks); + + private: + // Convert the part_set_ into blocks, starting a new block at a break + // in partnerships, or a change in linespacing (for text). + void MakeBlocks(const ICOORD& bleft, const ICOORD& tright, int resolution, + ColPartition_LIST* used_parts); + + // The column that this working set applies to. Used by the caller. + ColPartition* column_; + // The most recently added partition. + ColPartition* latest_part_; + // All the partitions in the block that is currently under construction. + ColPartition_LIST part_set_; + // Iteratorn on part_set_ pointing to the most recent addition. + ColPartition_IT part_it_; + // The blocks that have been made so far and belong before the current block. + BLOCK_LIST completed_blocks_; + TO_BLOCK_LIST to_blocks_; +}; + +ELISTIZEH(WorkingPartSet) + +} // namespace tesseract. + +#endif // TESSERACT_TEXTORD_WORKINGPARSET_H__ + diff --git a/TesseractOCR/include/tesseract/xform2d.h b/TesseractOCR/include/tesseract/xform2d.h new file mode 100644 index 00000000..1cd3bb12 --- /dev/null +++ b/TesseractOCR/include/tesseract/xform2d.h @@ -0,0 +1,60 @@ +/****************************************************************************** + ** Filename: xform2d.h + ** Purpose: Definitions for using 2D point transformation library + ** Author: Dan Johnson + ** History: Fri Sep 22 09:57:08 1989, DSJ, Created. + ** + ** (c) Copyright Hewlett-Packard Company, 1988. + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** http://www.apache.org/licenses/LICENSE-2.0 + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + ******************************************************************************/ +#ifndef XFORM2D_H +#define XFORM2D_H + +/**---------------------------------------------------------------------------- + Include Files and Type Defines +----------------------------------------------------------------------------**/ +#include "fpoint.h" + +typedef struct +{ + FLOAT32 a, b, c, d, tx, ty; +} + + +MATRIX_2D, *MATRIX_2D_PTR; + +/**---------------------------------------------------------------------------- + Public Function Prototypes +----------------------------------------------------------------------------**/ + +void InitMatrix(MATRIX_2D *M); +void CopyMatrix(MATRIX_2D *A, MATRIX_2D *B); + +/* matrix scaling, translation, rotation, mirroring, etc.*/ +void TranslateMatrix(MATRIX_2D *M, FLOAT32 X, FLOAT32 Y); +void ScaleMatrix(MATRIX_2D *M, FLOAT32 X, FLOAT32 Y); + +void MirrorMatrixInX(MATRIX_2D *M); +void MirrorMatrixInY(MATRIX_2D *M); +void MirrorMatrixInXY(MATRIX_2D *M); + +/* using a matrix to map points*/ +FLOAT32 MapX(MATRIX_2D *M, FLOAT32 X, FLOAT32 Y); + +FLOAT32 MapY(MATRIX_2D *M, FLOAT32 X, FLOAT32 Y); + +void MapPoint(MATRIX_2D *M, const FPOINT &A, FPOINT* B); + +FLOAT32 MapDx(MATRIX_2D *M, FLOAT32 DX, FLOAT32 DY); +FLOAT32 MapDy(MATRIX_2D M, FLOAT32 DX, FLOAT32 DY); + + void RotateMatrix(MATRIX_2D_PTR Matrix, FLOAT32 Angle); +#endif diff --git a/TesseractOCR/lib/liblept.a b/TesseractOCR/lib/liblept.a index 7d58dbfc..0b15ba1c 100644 Binary files a/TesseractOCR/lib/liblept.a and b/TesseractOCR/lib/liblept.a differ diff --git a/TesseractOCR/lib/libtesseract_all.a b/TesseractOCR/lib/libtesseract_all.a index aea517c9..f22ca5aa 100644 Binary files a/TesseractOCR/lib/libtesseract_all.a and b/TesseractOCR/lib/libtesseract_all.a differ