2008/11/12 Debayan Banerjee <[EMAIL PROTECTED]>
> I did diff -ur my/ their/ > bengali1.patch ; the only changes are in
> baseapi.cpp , baseapi.h and tesseractmain.cpp.
> It detects skew and corrects it, clips matra, and runs the extra clipping
> code only when flags such as ben, hin, ban etc are used.
> I diffed it against the svn checked out copy today.
Sorry, I made some stupid mistakes in creating that patch. Here is the patch
again diffed against rev 193.
I hope this works.
>
>
> --
> BE INTELLIGENT, USE LINUX
> http://lug.nitdgp.ac.in
> http://mukti09.in
> http://planet-india.randomink.org
>
>
>
--
BE INTELLIGENT, USE LINUX
http://lug.nitdgp.ac.in
http://mukti09.in
http://planet-india.randomink.org
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"tesseract-ocr" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/tesseract-ocr?hl=en
-~----------~----~----~----~------~----~------~--~---
diff -u tesseract-ocr-read-only/ccmain//baseapi.cpp tesseract-ocr-cvs1/ccmain//baseapi.cpp
--- tesseract-ocr-read-only/ccmain//baseapi.cpp 2008-11-12 17:07:07.000000000 +0530
+++ tesseract-ocr-cvs1/ccmain//baseapi.cpp 2008-11-12 17:43:00.000000000 +0530
@@ -18,7 +18,10 @@
**********************************************************************/
#include "baseapi.h"
+#include <iostream>
+#include <math.h>
+using namespace std;
// Include automatically generated configuration file if running autoconf.
#ifdef HAVE_CONFIG_H
@@ -393,6 +396,267 @@
if (omega0_out != NULL) *omega0_out = best_omega_0;
return best_t;
}
+////////////DEBAYAN//Deskew begins//////////////////////
+void deskew(float angle,int srcheight, int srcwidth)
+{
+//angle=4; //45° for example
+IMAGE tempimage;
+
+
+IMAGELINE line;
+//Convert degrees to radians
+float radians=(2*3.1416*angle)/360;
+
+float cosine=(float)cos(radians);
+float sine=(float)sin(radians);
+
+float Point1x=(srcheight*sine);
+float Point1y=(srcheight*cosine);
+float Point2x=(srcwidth*cosine-srcheight*sine);
+float Point2y=(srcheight*cosine+srcwidth*sine);
+float Point3x=(srcwidth*cosine);
+float Point3y=(srcwidth*sine);
+
+float minx=min(0,min(Point1x,min(Point2x,Point3x)));
+float miny=min(0,min(Point1y,min(Point2y,Point3y)));
+float maxx=max(Point1x,max(Point2x,Point3x));
+float maxy=max(Point1y,max(Point2y,Point3y));
+
+int DestWidth=(int)ceil(fabs(maxx)-minx);
+int DestHeight=(int)ceil(fabs(maxy)-miny);
+
+tempimage.create(DestWidth,DestHeight,1);
+line.init(DestWidth);
+
+for(int i=0;i<DestWidth;i++){ //A white line of length=DestWidth
+line.pixels[i]=1;
+}
+
+for(int y=0;y<DestHeight;y++){ //Fill the Destination image with white, else clipmatra wont work
+tempimage.put_line(0,y,DestWidth,&line,0);
+}
+line.init(DestWidth);
+
+
+
+for(int y=0;y<DestHeight;y++) //Start filling the destination image pixels with corresponding source image pixels
+{
+ for(int x=0;x<DestWidth;x++)
+ {
+ int Srcx=(int)((x+minx)*cosine+(y+miny)*sine);
+ int Srcy=(int)((y+miny)*cosine-(x+minx)*sine);
+ if(Srcx>=0&&Srcx<srcwidth&&Srcy>=0&&
+ Srcy<srcheight)
+ {
+ line.pixels[x]=
+ page_image.pixel(Srcx,Srcy);
+ }
+ }
+ tempimage.put_line(0,y,DestWidth,&line,0);
+}
+
+tempimage.write("tempimage.tif");
+page_image=tempimage;//Copy deskewed image to global page image, so it can be worked on further
+tempimage.destroy();
+page_image.write("page_image.tif");
+
+}
+/////////////DEBAYAN//Deskew ends/////////////////////
+
+////////////DEBAYAN//Find skew begins/////////////////
+float findskew(int height, int width)
+{
+int topx=0,topy=0,sign,count=0,offset=1,ifcounter=0;
+float slope=-999,avg=0;
+IMAGELINE line;
+line.init(1);
+line.pixels[0]=0;
+///////Find the top most point of the page: begins///////////
+for(int y=height-1;y>0;y--){
+ for(int x=width-1;x>0;x--){
+ if(page_image.pixel(x,y)==0){
+ topx=x;topy=y;
+ break;
+ }
+
+ }
+
+ if(topx>0){break;};
+}
+///////Find the top most point of the page: ends///////////
+
+
+///////To find pages with no skew: begins//////////////
+int c1,c2=0;
+for(int x=1;x<.25*width;x++){
+ while(page_image.pixel((width/2)+x,c1++)==1){ }
+ while(page_image.pixel((width/2)-x,c2++)==1){ }
+ if(c1==c2){cout<<"0 ANGLE\n";return (0);}
+ c1=c2=0;
+}
+///////To find pages with no skew: ends//////////////
+
+cout<<"width="<<width;
+if(topx>0 && topx<.5*width){
+ sign=1;
+}
+if(topx>0 && topx>.5*width){
+ sign=-1;
+}
+
+
+if(sign==-1){
+ while((topx-offset)>width/2){
+ while(page_image.pixel(topx-offset,topy-count)==1){
+ //page_image.put_line(topx-offset,topy-count,1,&line,0);
+ count++;
+ }
+
+ if((180/3.142)*atan((float)count/offset)<10){
+ slope=(float)count/offset;
+ ifcounter++;
+ avg=(avg+slope);
+ }
+ count=0;
+ offset++;
+ }
+ avg=(float)avg/ifcounter;
+ //cout<<"avg="<<avg<<"\n";
+ page_image.write("findskew.tif");
+ //cout<<"(180/3.142)*atan((float)(count/offset)="<<(180/3.142)*atan(avg)<<"\n";
+ return (sign*(180/3.142)*atan(avg));
+
+}
+if(sign==1){
+ while((topx+offset)<width/2){
+ while(page_image.pixel(topx+offset,topy-count)==1){
+ //page_image.put_line(topx+offset,topy-count,1,&line,0);
+ count++;
+ }
+
+ if((180/3.142)*atan((float)count/offset)<10){
+ slope=(float)count/offset;
+ ifcounter++;
+ avg=(avg+slope);
+ }
+ count=0;
+ offset++;
+ }
+ avg=(float)avg/ifcounter;
+ //cout<<"avg="<<avg<<"\n";
+ page_image.write("findskew.tif");
+ //cout<<"(180/3.142)*atan((float)(count/offset)="<<(180/3.142)*atan(avg)<<"\n";
+ return (sign*(180/3.142)*atan(avg));
+
+}
+
+if(sign==0)
+{return 0;}
+cout<<"SHIT";
+return (0);
+}
+////////////DEBAYAN//Find skew ends///////////////////
+
+//Works on the global image page containing devnagri script.
+//Clips the maatraas and then makes the global image ready for the Tesseract engine.
+//Will be executed for all images during training, but during normal operation, will be
+//used only if the language belongs to devnagri, eg, ben, hin etc.
+void TessBaseAPI::ClipMaatraa(int height, int width)
+{
+IMAGELINE line;
+line.init(width);
+int count,count1=0,blackpixels[height-1][2],arr_row=0,maxbp=0,maxy=0,matras[100][3],char_height;
+//cout<<"Connected Script="<<connected_script<<"\n";
+
+ for(int y=0; y<height-1;y++){
+ count=0;
+ for(int x=0;x<width-1;x++){
+ if(page_image.pixel(x,y)==0)
+ {count++;}
+ }
+
+ if(count>=.05*width){
+
+ blackpixels[arr_row][0]=y;
+ blackpixels[arr_row][1]=count;
+ arr_row++;
+ }
+ }
+ blackpixels[arr_row][0]=blackpixels[arr_row][1]='\0';
+
+ for(int x=0;x<width-1;x++){ //Black Line
+ line.pixels[x]=0;
+ }
+
+ ////////////line_through_matra() begins//////////////////////
+ count=1;
+ //cout<<"\nHeight="<<height<<" arr_row="<<arr_row<<"\n";
+ char_height=blackpixels[0][0]; //max character height per sentence
+ //cout<<"Char Height Init="<<char_height;
+ while(count<=arr_row){
+ //if(count==0){max=blackpixels[count][0];}
+ if((blackpixels[count][0]-blackpixels[count-1][0]==1) && (blackpixels[count][1]>=maxbp)){
+ maxbp=blackpixels[count][1];
+ maxy=blackpixels[count][0];
+ //cout<<"\nMax="<<maxy<<" bpc="<<maxbp;
+ }
+
+ if((blackpixels[count][0]-blackpixels[count-1][0])!=1){
+ /////////////drawline(max)//////////////////////
+
+ // cout<<"\nmax="<<maxy<<" bpc="<<maxbp;
+ // page_image.put_line(0,maxy,width,&line,0);
+
+ char_height=blackpixels[count-1][0]-char_height;
+ matras[count1][0]=maxy; matras[count1][1]=maxbp; matras[count1][2]=char_height; count1++;
+ char_height=blackpixels[count][0];
+
+ //////////// drawline(max)/////////////////////
+ maxbp=blackpixels[count][1];
+ }
+ count++;
+ }
+ matras[count1][0]=matras[count1][1]=matras[count1][2]='\0';
+
+ //delete blackpixels;
+ ////////////line_through_matra() ends//////////////////////
+
+ ////////////clip_matras() begins///////////////////////////
+ for(int i=0;i<100;i++){ //where 100=max number of sentences per page
+ if(matras[i][0]=='\0'){break;}
+ //cout<<"\nY="<<matras[i][0]<<" bpc="<<matras[i][1]<<" chheight="<<matras[i][2];
+ count=i;
+ }
+
+ for(int i=0;i<=count;i++){
+
+ for(int x=0;x<width-1;x++){
+ if(page_image.pixel(x,matras[i][0])==0){
+ count1=0;
+ for(int y=0;y<matras[i][2];y++){
+ if(page_image.pixel(x,matras[i][0]-y)==1){count1++;
+ }
+ }
+ //cout<<"\nWPR @ "<<x<<","<<matras[i][0]<<"="<<count1;
+ if(count1>.8*matras[i][2]){
+ line.init(matras[i][2]+5);
+ for(int j=0;j<matras[i][2]+5;j++){line.pixels[j]=1;}
+ page_image.put_column(x,matras[i][0]-matras[i][2],matras[i][2]+5,&line,0);
+ }
+ }
+ }
+
+ }
+
+page_image.write("bentest.tif");
+
+ ////////////clip_matras() ends/////////////////////////////
+
+/////////DEBAYAN/////////////////
+
+
+}
+
// Threshold the given grey or color image into the tesseract global
// image ready for recognition. Requires thresholds and hi_value
@@ -404,9 +668,11 @@
int width, int height,
const int* thresholds,
const int* hi_values) {
+
IMAGELINE line;
page_image.create(width, height, 1);
line.init(width);
+
// For each line in the image, fill the IMAGELINE class and put it into the
// Tesseract global page_image. Note that Tesseract stores images with the
// bottom at y=0 and 0 is black, so we need 2 kinds of inversion.
@@ -427,8 +693,14 @@
page_image.put_line(0, y, width, &line, 0);
data += bytes_per_line;
}
+page_image.write("benth.tif");
+float angle=findskew(height,width);
+//cout<<"SKEW ANGLE="<<angle<<"\n";
+if(angle!=0){
+deskew(angle,height,width);
+}
+ClipMaatraa(height,width);
}
-
// Cut out the requested rectangle of the binary image to the
// tesseract global image ready for recognition.
void TessBaseAPI::CopyBinaryRect(const unsigned char* imagedata,
Only in tesseract-ocr-cvs1/ccmain/: baseapi.cpp~
diff -u tesseract-ocr-read-only/ccmain//baseapi.h tesseract-ocr-cvs1/ccmain//baseapi.h
--- tesseract-ocr-read-only/ccmain//baseapi.h 2008-11-12 17:07:07.000000000 +0530
+++ tesseract-ocr-cvs1/ccmain//baseapi.h 2008-11-12 17:34:29.000000000 +0530
@@ -170,6 +170,13 @@
int left, int top, int right, int bottom,
int* histogram);
+ //Works on the global image page containing devnagri script.
+ //Clips the maatraas and then makes the global image ready for the Tesseract engine.
+ //Will be executed for all images during training, but during normal operation, will be
+ //used only if the language belongs to devnagri, eg, ben, hin etc.
+ static void ClipMaatraa(int height,
+ int width);
+
// Threshold the given grey or color image into the tesseract global
// image ready for recognition. Requires thresholds and hi_value
// produced by OtsuThreshold above.
Only in tesseract-ocr-cvs1/ccmain/: baseapi.h~
Only in tesseract-ocr-cvs1/ccmain/: .deps
Common subdirectories: tesseract-ocr-read-only/ccmain//.svn and tesseract-ocr-cvs1/ccmain//.svn
Common subdirectories: tesseract-ocr-read-only/ccmain//temp and tesseract-ocr-cvs1/ccmain//temp
diff -u tesseract-ocr-read-only/ccmain//tesseractmain.cpp tesseract-ocr-cvs1/ccmain//tesseractmain.cpp
--- tesseract-ocr-read-only/ccmain//tesseractmain.cpp 2008-11-12 17:07:07.000000000 +0530
+++ tesseract-ocr-cvs1/ccmain//tesseractmain.cpp 2008-11-12 17:43:25.000000000 +0530
@@ -37,6 +37,10 @@
#include "tfacep.h"
#include "callnet.h"
+#include <iostream>
+
+using namespace std;
+
/*
** Include automatically generated configuration file if running autoconf
*/
@@ -74,6 +78,7 @@
const int kMaxIntSize = 22;
const ERRCODE USAGE = "Usage";
char szAppName[] = "Tessedit"; //app name
+bool connected_script=false; //whether language is connected script, eg: hindi, bengali etc
void TesseractImage(const char* input_file, IMAGE* image, STRING* text_out) {
int bytes_per_line = check_legal_image_size(image->get_xsize(),
@@ -156,6 +161,12 @@
lang = argv[4];
arg = 5;
}
+
+ if(strcmp(lang,"ben")==0 || strcmp(lang,"hin")==0 || strcmp(lang,"asm")==0 ||
+ strcmp(lang,"guj")==0 || strcmp(lang,"pan")==0 || strcmp(lang,"ori")==0 || strcmp(lang,"ban")==0){
+ connected_script=true;
+ cout<<"Connected Script Found!!\n";
+ }
// Find the basename of the input file.
STRING infile(argv[1]);
const char* lastdot = strrchr(argv[1], '.');
Only in tesseract-ocr-cvs1/ccmain/: tesseractmain.cpp~