tesseract  3.03
/usr/local/google/home/jbreiden/tesseract-ocr-read-only/ccmain/pgedit.cpp
Go to the documentation of this file.
00001 /**********************************************************************
00002  * File:        pgedit.cpp (Formerly pgeditor.c)
00003  * Description: Page structure file editor
00004  * Author:      Phil Cheatle
00005  * Created:     Thu Oct 10 16:25:24 BST 1991
00006  *
00007  *(C) Copyright 1991, Hewlett-Packard Ltd.
00008  ** Licensed under the Apache License, Version 2.0(the "License");
00009  ** you may not use this file except in compliance with the License.
00010  ** You may obtain a copy of the License at
00011  ** http:// www.apache.org/licenses/LICENSE-2.0
00012  ** Unless required by applicable law or agreed to in writing, software
00013  ** distributed under the License is distributed on an "AS IS" BASIS,
00014  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  ** See the License for the specific language governing permissions and
00016  ** limitations under the License.
00017  *
00018  **********************************************************************/
00019 
00020 #ifdef _MSC_VER
00021 #pragma warning(disable:4244)  // Conversion warnings
00022 #endif
00023 
00024 // Include automatically generated configuration file if running autoconf.
00025 #ifdef HAVE_CONFIG_H
00026 #include "config_auto.h"
00027 #endif
00028 
00029 #include          "pgedit.h"
00030 
00031 #include          <ctype.h>
00032 #include          <math.h>
00033 
00034 #include "blread.h"
00035 #include "control.h"
00036 #include "paramsd.h"
00037 #include "pageres.h"
00038 #include "tordmain.h"
00039 #include "scrollview.h"
00040 #include "svmnode.h"
00041 #include "statistc.h"
00042 #include "tesseractclass.h"
00043 #include "werdit.h"
00044 
00045 #ifndef GRAPHICS_DISABLED
00046 #define ASC_HEIGHT     (2 * kBlnBaselineOffset + kBlnXHeight)
00047 #define X_HEIGHT       (kBlnBaselineOffset + kBlnXHeight)
00048 #define BL_HEIGHT     kBlnBaselineOffset
00049 #define DESC_HEIGHT     0
00050 #define MAXSPACING      128      /*max expected spacing in pix */
00051 
00052 const ERRCODE EMPTYBLOCKLIST = "No blocks to edit";
00053 
00054 enum CMD_EVENTS
00055 {
00056   NULL_CMD_EVENT,
00057   CHANGE_DISP_CMD_EVENT,
00058   DUMP_WERD_CMD_EVENT,
00059   SHOW_POINT_CMD_EVENT,
00060   SHOW_BLN_WERD_CMD_EVENT,
00061   DEBUG_WERD_CMD_EVENT,
00062   BLAMER_CMD_EVENT,
00063   BOUNDING_BOX_CMD_EVENT,
00064   CORRECT_TEXT_CMD_EVENT,
00065   POLYGONAL_CMD_EVENT,
00066   BL_NORM_CMD_EVENT,
00067   BITMAP_CMD_EVENT,
00068   IMAGE_CMD_EVENT,
00069   BLOCKS_CMD_EVENT,
00070   BASELINES_CMD_EVENT,
00071   UNIFORM_DISP_CMD_EVENT,
00072   REFRESH_CMD_EVENT,
00073   QUIT_CMD_EVENT,
00074   RECOG_WERDS,
00075   RECOG_PSEUDO,
00076   SHOW_BLOB_FEATURES,
00077   SHOW_SUBSCRIPT_CMD_EVENT,
00078   SHOW_SUPERSCRIPT_CMD_EVENT,
00079   SHOW_ITALIC_CMD_EVENT,
00080   SHOW_BOLD_CMD_EVENT,
00081   SHOW_UNDERLINE_CMD_EVENT,
00082   SHOW_FIXEDPITCH_CMD_EVENT,
00083   SHOW_SERIF_CMD_EVENT,
00084   SHOW_SMALLCAPS_CMD_EVENT,
00085   SHOW_DROPCAPS_CMD_EVENT,
00086 };
00087 
00088 enum ColorationMode {
00089   CM_RAINBOW,
00090   CM_SUBSCRIPT,
00091   CM_SUPERSCRIPT,
00092   CM_ITALIC,
00093   CM_BOLD,
00094   CM_UNDERLINE,
00095   CM_FIXEDPITCH,
00096   CM_SERIF,
00097   CM_SMALLCAPS,
00098   CM_DROPCAPS
00099 };
00100 
00101 /*
00102  *
00103  *  Some global data
00104  *
00105  */
00106 
00107 ScrollView* image_win;
00108 ParamsEditor* pe;
00109 bool stillRunning = false;
00110 
00111 #ifdef __UNIX__
00112 FILE *debug_window = NULL;                // opened on demand
00113 #endif
00114 ScrollView* bln_word_window = NULL;       // baseline norm words
00115 
00116 CMD_EVENTS mode = CHANGE_DISP_CMD_EVENT;  // selected words op
00117 
00118 bool recog_done = false;                  // recog_all_words was called
00119 
00120 // These variables should remain global, since they are only used for the
00121 // debug mode (in which only a single Tesseract thread/instance will be exist).
00122 BITS16 word_display_mode;
00123 static ColorationMode color_mode = CM_RAINBOW;
00124 BOOL8 display_image = FALSE;
00125 BOOL8 display_blocks = FALSE;
00126 BOOL8 display_baselines = FALSE;
00127 
00128 PAGE_RES *current_page_res = NULL;
00129 
00130 STRING_VAR(editor_image_win_name, "EditorImage",
00131            "Editor image window name");
00132 INT_VAR(editor_image_xpos, 590, "Editor image X Pos");
00133 INT_VAR(editor_image_ypos, 10, "Editor image Y Pos");
00134 INT_VAR(editor_image_menuheight, 50, "Add to image height for menu bar");
00135 INT_VAR(editor_image_word_bb_color, ScrollView::BLUE,
00136         "Word bounding box colour");
00137 INT_VAR(editor_image_blob_bb_color, ScrollView::YELLOW,
00138         "Blob bounding box colour");
00139 INT_VAR(editor_image_text_color, ScrollView::WHITE,
00140         "Correct text colour");
00141 
00142 STRING_VAR(editor_dbwin_name, "EditorDBWin",
00143            "Editor debug window name");
00144 INT_VAR(editor_dbwin_xpos, 50, "Editor debug window X Pos");
00145 INT_VAR(editor_dbwin_ypos, 500, "Editor debug window Y Pos");
00146 INT_VAR(editor_dbwin_height, 24, "Editor debug window height");
00147 INT_VAR(editor_dbwin_width, 80, "Editor debug window width");
00148 
00149 STRING_VAR(editor_word_name, "BlnWords", "BL normalized word window");
00150 INT_VAR(editor_word_xpos, 60, "Word window X Pos");
00151 INT_VAR(editor_word_ypos, 510, "Word window Y Pos");
00152 INT_VAR(editor_word_height, 240, "Word window height");
00153 INT_VAR(editor_word_width, 655, "Word window width");
00154 
00155 STRING_VAR(editor_debug_config_file, "", "Config file to apply to single words");
00156 
00157 class BlnEventHandler : public SVEventHandler {
00158  public:
00159   void Notify(const SVEvent* sv_event) {
00160     if (sv_event->type == SVET_DESTROY)
00161       bln_word_window = NULL;
00162     else if (sv_event->type == SVET_CLICK)
00163       show_point(current_page_res, sv_event->x, sv_event->y);
00164   }
00165 };
00166 
00172 ScrollView* bln_word_window_handle() {  // return handle
00173                                  // not opened yet
00174   if (bln_word_window == NULL) {
00175     pgeditor_msg("Creating BLN word window...");
00176     bln_word_window = new ScrollView(editor_word_name.string(),
00177       editor_word_xpos, editor_word_ypos, editor_word_width,
00178       editor_word_height, 4000, 4000, true);
00179     BlnEventHandler* a = new BlnEventHandler();
00180     bln_word_window->AddEventHandler(a);
00181     pgeditor_msg("Creating BLN word window...Done");
00182   }
00183   return bln_word_window;
00184 }
00185 
00193 void build_image_window(int width, int height) {
00194   if (image_win != NULL) { delete image_win; }
00195   image_win = new ScrollView(editor_image_win_name.string(),
00196                              editor_image_xpos, editor_image_ypos,
00197                              width + 1,
00198                              height + editor_image_menuheight + 1,
00199                              width,
00200                              height,
00201                              true);
00202 }
00203 
00210 void display_bln_lines(ScrollView* window,
00211                        ScrollView::Color colour,
00212                        float scale_factor,
00213                        float y_offset,
00214                        float minx,
00215                        float maxx) {
00216   window->Pen(colour);
00217   window->Line(minx, y_offset + scale_factor * DESC_HEIGHT,
00218                maxx, y_offset + scale_factor * DESC_HEIGHT);
00219   window->Line(minx, y_offset + scale_factor * BL_HEIGHT,
00220                maxx, y_offset + scale_factor * BL_HEIGHT);
00221   window->Line(minx, y_offset + scale_factor * X_HEIGHT,
00222                maxx, y_offset + scale_factor * X_HEIGHT);
00223   window->Line(minx, y_offset + scale_factor * ASC_HEIGHT,
00224                maxx, y_offset + scale_factor * ASC_HEIGHT);
00225 }
00226 
00235 void PGEventHandler::Notify(const SVEvent* event) {
00236   char myval = '0';
00237   if (event->type == SVET_POPUP) {
00238     pe->Notify(event);
00239   } // These are handled by ParamsEditor
00240   else if (event->type == SVET_EXIT) { stillRunning = false; }
00241   else if (event->type == SVET_MENU) {
00242      if (strcmp(event->parameter, "true") == 0) { myval = 'T'; }
00243      else if (strcmp(event->parameter, "false") == 0) { myval = 'F'; }
00244      tess_->process_cmd_win_event(event->command_id, &myval);
00245   }
00246   else {
00247     tess_->process_image_event(*event);
00248   }
00249 }
00250 
00256 namespace tesseract {
00257 SVMenuNode *Tesseract::build_menu_new() {
00258   SVMenuNode* parent_menu;
00259   SVMenuNode* root_menu_item = new SVMenuNode();
00260 
00261   SVMenuNode* modes_menu_item = root_menu_item->AddChild("MODES");
00262 
00263   modes_menu_item->AddChild("Change Display", CHANGE_DISP_CMD_EVENT);
00264   modes_menu_item->AddChild("Dump Word", DUMP_WERD_CMD_EVENT);
00265   modes_menu_item->AddChild("Show Point", SHOW_POINT_CMD_EVENT);
00266   modes_menu_item->AddChild("Show BL Norm Word", SHOW_BLN_WERD_CMD_EVENT);
00267   modes_menu_item->AddChild("Config Words", DEBUG_WERD_CMD_EVENT);
00268   modes_menu_item->AddChild("Recog Words", RECOG_WERDS);
00269   modes_menu_item->AddChild("Recog Blobs", RECOG_PSEUDO);
00270   modes_menu_item->AddChild("Show Blob Features", SHOW_BLOB_FEATURES);
00271 
00272   parent_menu = root_menu_item->AddChild("DISPLAY");
00273 
00274   parent_menu->AddChild("Blamer", BLAMER_CMD_EVENT, FALSE);
00275   parent_menu->AddChild("Bounding Boxes", BOUNDING_BOX_CMD_EVENT, FALSE);
00276   parent_menu->AddChild("Correct Text", CORRECT_TEXT_CMD_EVENT, FALSE);
00277   parent_menu->AddChild("Polygonal Approx", POLYGONAL_CMD_EVENT, FALSE);
00278   parent_menu->AddChild("Baseline Normalized", BL_NORM_CMD_EVENT, FALSE);
00279   parent_menu->AddChild("Edge Steps", BITMAP_CMD_EVENT, TRUE);
00280   parent_menu->AddChild("Subscripts", SHOW_SUBSCRIPT_CMD_EVENT);
00281   parent_menu->AddChild("Superscripts", SHOW_SUPERSCRIPT_CMD_EVENT);
00282   parent_menu->AddChild("Italics", SHOW_ITALIC_CMD_EVENT);
00283   parent_menu->AddChild("Bold", SHOW_BOLD_CMD_EVENT);
00284   parent_menu->AddChild("Underline", SHOW_UNDERLINE_CMD_EVENT);
00285   parent_menu->AddChild("FixedPitch", SHOW_FIXEDPITCH_CMD_EVENT);
00286   parent_menu->AddChild("Serifs", SHOW_SERIF_CMD_EVENT);
00287   parent_menu->AddChild("SmallCaps", SHOW_SMALLCAPS_CMD_EVENT);
00288   parent_menu->AddChild("DropCaps", SHOW_DROPCAPS_CMD_EVENT);
00289 
00290 
00291   parent_menu = root_menu_item->AddChild("OTHER");
00292 
00293   parent_menu->AddChild("Quit", QUIT_CMD_EVENT);
00294   parent_menu->AddChild("Show Image", IMAGE_CMD_EVENT, FALSE);
00295   parent_menu->AddChild("ShowBlock Outlines", BLOCKS_CMD_EVENT, FALSE);
00296   parent_menu->AddChild("Show Baselines", BASELINES_CMD_EVENT, FALSE);
00297   parent_menu->AddChild("Uniform Display", UNIFORM_DISP_CMD_EVENT);
00298   parent_menu->AddChild("Refresh Display", REFRESH_CMD_EVENT);
00299 
00300   return root_menu_item;
00301 }
00302 
00308 void Tesseract::do_re_display(
00309     BOOL8 (tesseract::Tesseract::*word_painter)(BLOCK* block,
00310                                                 ROW* row,
00311                                                 WERD_RES* word_res)) {
00312   PAGE_RES_IT pr_it(current_page_res);
00313   int block_count = 1;
00314 
00315   image_win->Clear();
00316   if (display_image != 0) {
00317     image_win->Image(pix_binary_, 0, 0);
00318   }
00319 
00320   for (WERD_RES* word = pr_it.word(); word != NULL; word = pr_it.forward()) {
00321     (this->*word_painter)(pr_it.block()->block, pr_it.row()->row, word);
00322     if (display_baselines && pr_it.row() != pr_it.prev_row())
00323       pr_it.row()->row->plot_baseline(image_win, ScrollView::GREEN);
00324     if (display_blocks && pr_it.block() != pr_it.prev_block())
00325       pr_it.block()->block->plot(image_win, block_count++, ScrollView::RED);
00326   }
00327   image_win->Update();
00328 }
00329 
00338 void Tesseract::pgeditor_main(int width, int height, PAGE_RES *page_res) {
00339   current_page_res = page_res;
00340   if (current_page_res->block_res_list.empty())
00341     return;
00342 
00343   recog_done = false;
00344   stillRunning = true;
00345 
00346   build_image_window(width, height);
00347   word_display_mode.turn_on_bit(DF_EDGE_STEP);
00348   do_re_display(&tesseract::Tesseract::word_set_display);
00349 #ifndef GRAPHICS_DISABLED
00350   pe = new ParamsEditor(this, image_win);
00351 #endif
00352   PGEventHandler pgEventHandler(this);
00353 
00354   image_win->AddEventHandler(&pgEventHandler);
00355   image_win->AddMessageBox();
00356 
00357   SVMenuNode* svMenuRoot = build_menu_new();
00358 
00359   svMenuRoot->BuildMenu(image_win);
00360   image_win->SetVisible(true);
00361 
00362   image_win->AwaitEvent(SVET_DESTROY);
00363   image_win->AddEventHandler(NULL);
00364 }
00365 }  // namespace tesseract
00366 
00367 
00374 void pgeditor_msg( // message display
00375                   const char *msg) {
00376     image_win->AddMessage(msg);
00377 }
00378 
00385 void pgeditor_show_point( // display coords
00386                          SVEvent *event) {
00387   image_win->AddMessage("Pointing at(%d, %d)", event->x, event->y);
00388 }
00389 
00397 namespace tesseract {
00398 BOOL8 Tesseract::process_cmd_win_event(                 // UI command semantics
00399                                        inT32 cmd_event,  // which menu item?
00400                                        char *new_value   // any prompt data
00401                                       ) {
00402   char msg[160];
00403   BOOL8 exit = FALSE;
00404 
00405   color_mode = CM_RAINBOW;
00406 
00407   // Run recognition on the full page if needed.
00408   switch (cmd_event) {
00409     case BLAMER_CMD_EVENT:
00410     case SHOW_SUBSCRIPT_CMD_EVENT:
00411     case SHOW_SUPERSCRIPT_CMD_EVENT:
00412     case SHOW_ITALIC_CMD_EVENT:
00413     case SHOW_BOLD_CMD_EVENT:
00414     case SHOW_UNDERLINE_CMD_EVENT:
00415     case SHOW_FIXEDPITCH_CMD_EVENT:
00416     case SHOW_SERIF_CMD_EVENT:
00417     case SHOW_SMALLCAPS_CMD_EVENT:
00418     case SHOW_DROPCAPS_CMD_EVENT:
00419       if (!recog_done) {
00420         recog_all_words(current_page_res, NULL, NULL, NULL, 0);
00421         recog_done = true;
00422       }
00423       break;
00424     default:
00425       break;
00426   }
00427 
00428   switch (cmd_event) {
00429     case NULL_CMD_EVENT:
00430       break;
00431 
00432     case CHANGE_DISP_CMD_EVENT:
00433     case DUMP_WERD_CMD_EVENT:
00434     case SHOW_POINT_CMD_EVENT:
00435     case SHOW_BLN_WERD_CMD_EVENT:
00436     case RECOG_WERDS:
00437     case RECOG_PSEUDO:
00438     case SHOW_BLOB_FEATURES:
00439       mode =(CMD_EVENTS) cmd_event;
00440       break;
00441     case DEBUG_WERD_CMD_EVENT:
00442       mode = DEBUG_WERD_CMD_EVENT;
00443       word_config_ = image_win->ShowInputDialog("Config File Name");
00444       break;
00445     case BOUNDING_BOX_CMD_EVENT:
00446       if (new_value[0] == 'T')
00447         word_display_mode.turn_on_bit(DF_BOX);
00448       else
00449         word_display_mode.turn_off_bit(DF_BOX);
00450       mode = CHANGE_DISP_CMD_EVENT;
00451       break;
00452     case BLAMER_CMD_EVENT:
00453       if (new_value[0] == 'T')
00454         word_display_mode.turn_on_bit(DF_BLAMER);
00455       else
00456         word_display_mode.turn_off_bit(DF_BLAMER);
00457       do_re_display(&tesseract::Tesseract::word_display);
00458       mode = CHANGE_DISP_CMD_EVENT;
00459       break;
00460     case CORRECT_TEXT_CMD_EVENT:
00461       if (new_value[0] == 'T')
00462         word_display_mode.turn_on_bit(DF_TEXT);
00463       else
00464         word_display_mode.turn_off_bit(DF_TEXT);
00465       mode = CHANGE_DISP_CMD_EVENT;
00466       break;
00467     case POLYGONAL_CMD_EVENT:
00468       if (new_value[0] == 'T')
00469         word_display_mode.turn_on_bit(DF_POLYGONAL);
00470       else
00471         word_display_mode.turn_off_bit(DF_POLYGONAL);
00472       mode = CHANGE_DISP_CMD_EVENT;
00473       break;
00474     case BL_NORM_CMD_EVENT:
00475       if (new_value[0] == 'T')
00476         word_display_mode.turn_on_bit(DF_BN_POLYGONAL);
00477       else
00478         word_display_mode.turn_off_bit(DF_BN_POLYGONAL);
00479       mode = CHANGE_DISP_CMD_EVENT;
00480       break;
00481     case BITMAP_CMD_EVENT:
00482       if (new_value[0] == 'T')
00483         word_display_mode.turn_on_bit(DF_EDGE_STEP);
00484       else
00485         word_display_mode.turn_off_bit(DF_EDGE_STEP);
00486       mode = CHANGE_DISP_CMD_EVENT;
00487       break;
00488     case UNIFORM_DISP_CMD_EVENT:
00489       do_re_display(&tesseract::Tesseract::word_set_display);
00490       break;
00491     case IMAGE_CMD_EVENT:
00492       display_image =(new_value[0] == 'T');
00493       do_re_display(&tesseract::Tesseract::word_display);
00494       break;
00495     case BLOCKS_CMD_EVENT:
00496       display_blocks =(new_value[0] == 'T');
00497       do_re_display(&tesseract::Tesseract::word_display);
00498       break;
00499     case BASELINES_CMD_EVENT:
00500       display_baselines =(new_value[0] == 'T');
00501       do_re_display(&tesseract::Tesseract::word_display);
00502       break;
00503     case SHOW_SUBSCRIPT_CMD_EVENT:
00504       color_mode = CM_SUBSCRIPT;
00505       do_re_display(&tesseract::Tesseract::word_display);
00506       break;
00507     case SHOW_SUPERSCRIPT_CMD_EVENT:
00508       color_mode = CM_SUPERSCRIPT;
00509       do_re_display(&tesseract::Tesseract::word_display);
00510       break;
00511     case SHOW_ITALIC_CMD_EVENT:
00512       color_mode = CM_ITALIC;
00513       do_re_display(&tesseract::Tesseract::word_display);
00514       break;
00515     case SHOW_BOLD_CMD_EVENT:
00516       color_mode = CM_BOLD;
00517       do_re_display(&tesseract::Tesseract::word_display);
00518       break;
00519     case SHOW_UNDERLINE_CMD_EVENT:
00520       color_mode = CM_UNDERLINE;
00521       do_re_display(&tesseract::Tesseract::word_display);
00522       break;
00523     case SHOW_FIXEDPITCH_CMD_EVENT:
00524       color_mode = CM_FIXEDPITCH;
00525       do_re_display(&tesseract::Tesseract::word_display);
00526       break;
00527     case SHOW_SERIF_CMD_EVENT:
00528       color_mode = CM_SERIF;
00529       do_re_display(&tesseract::Tesseract::word_display);
00530       break;
00531     case SHOW_SMALLCAPS_CMD_EVENT:
00532       color_mode = CM_SMALLCAPS;
00533       do_re_display(&tesseract::Tesseract::word_display);
00534       break;
00535     case SHOW_DROPCAPS_CMD_EVENT:
00536       color_mode = CM_DROPCAPS;
00537       do_re_display(&tesseract::Tesseract::word_display);
00538       break;
00539     case REFRESH_CMD_EVENT:
00540       do_re_display(&tesseract::Tesseract::word_display);
00541       break;
00542     case QUIT_CMD_EVENT:
00543       exit = TRUE;
00544       ScrollView::Exit();
00545       break;
00546 
00547     default:
00548       sprintf(msg, "Unrecognised event " INT32FORMAT "(%s)",
00549                cmd_event, new_value);
00550       image_win->AddMessage(msg);
00551     break;
00552   }
00553   return exit;
00554 }
00555 
00556 
00566 void Tesseract::process_image_event( // action in image win
00567                                     const SVEvent &event) {
00568    // The following variable should remain static, since it is used by
00569    // debug editor, which uses a single Tesseract instance.
00570   static ICOORD down;
00571   ICOORD up;
00572   TBOX selection_box;
00573   char msg[80];
00574 
00575   switch(event.type) {
00576 
00577     case SVET_SELECTION:
00578       if (event.type == SVET_SELECTION) {
00579         down.set_x(event.x + event.x_size);
00580         down.set_y(event.y + event.y_size);
00581         if (mode == SHOW_POINT_CMD_EVENT)
00582           show_point(current_page_res, event.x, event.y);
00583       }
00584 
00585       up.set_x(event.x);
00586       up.set_y(event.y);
00587 
00588       selection_box = TBOX(down, up);
00589 
00590       switch(mode) {
00591         case CHANGE_DISP_CMD_EVENT:
00592           process_selected_words(
00593               current_page_res,
00594               selection_box,
00595               &tesseract::Tesseract::word_blank_and_set_display);
00596           break;
00597        case DUMP_WERD_CMD_EVENT:
00598           process_selected_words(current_page_res,
00599                                  selection_box,
00600                                  &tesseract::Tesseract::word_dumper);
00601           break;
00602         case SHOW_BLN_WERD_CMD_EVENT:
00603           process_selected_words(current_page_res,
00604                                  selection_box,
00605                                  &tesseract::Tesseract::word_bln_display);
00606           break;
00607         case DEBUG_WERD_CMD_EVENT:
00608           debug_word(current_page_res, selection_box);
00609           break;
00610         case SHOW_POINT_CMD_EVENT:
00611           break;                 // ignore up event
00612 
00613         case RECOG_WERDS:
00614           image_win->AddMessage("Recogging selected words");
00615           this->process_selected_words(current_page_res,
00616                                        selection_box,
00617                                        &Tesseract::recog_interactive);
00618           break;
00619         case RECOG_PSEUDO:
00620           image_win->AddMessage("Recogging selected blobs");
00621           recog_pseudo_word(current_page_res, selection_box);
00622           break;
00623         case SHOW_BLOB_FEATURES:
00624           blob_feature_display(current_page_res, selection_box);
00625           break;
00626 
00627         default:
00628           sprintf(msg, "Mode %d not yet implemented", mode);
00629           image_win->AddMessage(msg);
00630           break;
00631       }
00632     default:
00633       break;
00634   }
00635 }
00636 
00642 void Tesseract::debug_word(PAGE_RES* page_res, const TBOX &selection_box) {
00643   ResetAdaptiveClassifier();
00644   recog_all_words(page_res, NULL, &selection_box, word_config_.string(), 0);
00645 }
00646 }  // namespace tesseract
00647 
00648 
00656 void show_point(PAGE_RES* page_res, float x, float y) {
00657   FCOORD pt(x, y);
00658   PAGE_RES_IT pr_it(page_res);
00659 
00660   char msg[160];
00661   char *msg_ptr = msg;
00662 
00663   msg_ptr += sprintf(msg_ptr, "Pt:(%0.3f, %0.3f) ", x, y);
00664 
00665   for (WERD_RES* word = pr_it.word(); word != NULL; word = pr_it.forward()) {
00666     if (pr_it.row() != pr_it.prev_row() &&
00667         pr_it.row()->row->bounding_box().contains(pt)) {
00668       msg_ptr += sprintf(msg_ptr, "BL(x)=%0.3f ",
00669                          pr_it.row()->row->base_line(x));
00670     }
00671     if (word->word->bounding_box().contains(pt)) {
00672       TBOX box = word->word->bounding_box();
00673       msg_ptr += sprintf(msg_ptr, "Wd(%d, %d)/(%d, %d) ",
00674                          box.left(), box.bottom(),
00675                          box.right(), box.top());
00676       C_BLOB_IT cblob_it(word->word->cblob_list());
00677       for (cblob_it.mark_cycle_pt();
00678            !cblob_it.cycled_list();
00679            cblob_it.forward()) {
00680         C_BLOB* cblob = cblob_it.data();
00681         box = cblob->bounding_box();
00682         if (box.contains(pt)) {
00683           msg_ptr += sprintf(msg_ptr,
00684                              "CBlb(%d, %d)/(%d, %d) ",
00685                              box.left(), box.bottom(),
00686                              box.right(), box.top());
00687         }
00688       }
00689     }
00690   }
00691   image_win->AddMessage(msg);
00692 }
00693 
00694 
00695 /**********************************************************************
00696  * WERD PROCESSOR FUNCTIONS
00697  * ========================
00698  *
00699  * These routines are invoked by one or more of:
00700  *    process_all_words()
00701  *    process_selected_words()
00702  * or
00703  *    process_all_words_it()
00704  *    process_selected_words_it()
00705  * for each word to be processed
00706  **********************************************************************/
00707 
00714 #endif  // GRAPHICS_DISABLED
00715 namespace tesseract {
00716 #ifndef GRAPHICS_DISABLED
00717 BOOL8 Tesseract:: word_blank_and_set_display(BLOCK* block, ROW* row,
00718                                              WERD_RES* word_res) {
00719   word_res->word->bounding_box().plot(image_win, ScrollView::BLACK,
00720                                       ScrollView::BLACK);
00721   return word_set_display(block, row, word_res);
00722 }
00723 
00724 
00730 BOOL8 Tesseract::word_bln_display(BLOCK* block, ROW* row, WERD_RES* word_res) {
00731   TWERD *bln_word = word_res->chopped_word;
00732   if (bln_word == NULL) {
00733     word_res->SetupForRecognition(unicharset, this, BestPix(),
00734                                   tessedit_ocr_engine_mode, NULL,
00735                                   classify_bln_numeric_mode,
00736                                   textord_use_cjk_fp_model,
00737                                   poly_allow_detailed_fx,
00738                                   row, block);
00739     bln_word = word_res->chopped_word;
00740   }
00741   bln_word_window_handle()->Clear();
00742   display_bln_lines(bln_word_window_handle(), ScrollView::CYAN,
00743                      1.0, 0.0f, -1000.0f, 1000.0f);
00744   C_BLOB_IT it(word_res->word->cblob_list());
00745   ScrollView::Color color = WERD::NextColor(ScrollView::BLACK);
00746   for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
00747     it.data()->plot_normed(word_res->denorm, color, ScrollView::BROWN,
00748                            bln_word_window_handle());
00749     color = WERD::NextColor(color);
00750   }
00751   bln_word_window_handle()->Update();
00752   return TRUE;
00753 }
00754 
00755 
00756 
00762 BOOL8 Tesseract::word_display(BLOCK* block, ROW* row, WERD_RES* word_res) {
00763   WERD* word = word_res->word;
00764   TBOX word_bb;                   // word bounding box
00765   int word_height;               // ht of word BB
00766   BOOL8 displayed_something = FALSE;
00767   float shift;                   // from bot left
00768   C_BLOB_IT c_it;                // cblob iterator
00769 
00770   if (color_mode != CM_RAINBOW && word_res->box_word != NULL) {
00771     BoxWord* box_word = word_res->box_word;
00772     WERD_CHOICE* best_choice = word_res->best_choice;
00773     int length = box_word->length();
00774     if (word_res->fontinfo == NULL) return false;
00775     const FontInfo& font_info = *word_res->fontinfo;
00776     for (int i = 0; i < length; ++i) {
00777       ScrollView::Color color = ScrollView::GREEN;
00778       switch (color_mode) {
00779         case CM_SUBSCRIPT:
00780           if (best_choice->BlobPosition(i) == SP_SUBSCRIPT)
00781             color = ScrollView::RED;
00782           break;
00783         case CM_SUPERSCRIPT:
00784           if (best_choice->BlobPosition(i) == SP_SUPERSCRIPT)
00785             color = ScrollView::RED;
00786           break;
00787         case CM_ITALIC:
00788           if (font_info.is_italic())
00789             color = ScrollView::RED;
00790           break;
00791         case CM_BOLD:
00792           if (font_info.is_bold())
00793             color = ScrollView::RED;
00794           break;
00795         case CM_FIXEDPITCH:
00796           if (font_info.is_fixed_pitch())
00797             color = ScrollView::RED;
00798           break;
00799         case CM_SERIF:
00800           if (font_info.is_serif())
00801             color = ScrollView::RED;
00802           break;
00803         case CM_SMALLCAPS:
00804           if (word_res->small_caps)
00805             color = ScrollView::RED;
00806           break;
00807         case CM_DROPCAPS:
00808           if (best_choice->BlobPosition(i) == SP_DROPCAP)
00809             color = ScrollView::RED;
00810           break;
00811           // TODO(rays) underline is currently completely unsupported.
00812         case CM_UNDERLINE:
00813         default:
00814           break;
00815       }
00816       image_win->Pen(color);
00817       TBOX box = box_word->BlobBox(i);
00818       image_win->Rectangle(box.left(), box.bottom(), box.right(), box.top());
00819     }
00820     return true;
00821   }
00822   /*
00823     Note the double coercions of(COLOUR)((inT32)editor_image_word_bb_color)
00824     etc. are to keep the compiler happy.
00825   */
00826                                  // display bounding box
00827   if (word->display_flag(DF_BOX)) {
00828     word->bounding_box().plot(image_win,
00829      (ScrollView::Color)((inT32)
00830       editor_image_word_bb_color),
00831      (ScrollView::Color)((inT32)
00832       editor_image_word_bb_color));
00833 
00834     ScrollView::Color c = (ScrollView::Color)
00835        ((inT32) editor_image_blob_bb_color);
00836     image_win->Pen(c);
00837     c_it.set_to_list(word->cblob_list());
00838     for (c_it.mark_cycle_pt(); !c_it.cycled_list(); c_it.forward())
00839       c_it.data()->bounding_box().plot(image_win);
00840     displayed_something = TRUE;
00841   }
00842 
00843                                  // display edge steps
00844   if (word->display_flag(DF_EDGE_STEP)) {     // edgesteps available
00845     word->plot(image_win);      // rainbow colors
00846     displayed_something = TRUE;
00847   }
00848 
00849                                  // display poly approx
00850   if (word->display_flag(DF_POLYGONAL)) {
00851                                  // need to convert
00852     TWERD* tword = TWERD::PolygonalCopy(poly_allow_detailed_fx, word);
00853     tword->plot(image_win);
00854     delete tword;
00855     displayed_something = TRUE;
00856   }
00857 
00858   // Display correct text and blamer information.
00859   STRING text;
00860   STRING blame;
00861   if (word->display_flag(DF_TEXT) && word->text() != NULL) {
00862     text = word->text();
00863   }
00864   if (word->display_flag(DF_BLAMER) &&
00865       !(word_res->blamer_bundle != NULL &&
00866         word_res->blamer_bundle->incorrect_result_reason() == IRR_CORRECT)) {
00867     text = "";
00868     const BlamerBundle *blamer_bundle = word_res->blamer_bundle;
00869     if (blamer_bundle == NULL) {
00870       text += "NULL";
00871     } else {
00872       text = blamer_bundle->TruthString();
00873     }
00874     text += " -> ";
00875     STRING best_choice_str;
00876     if (word_res->best_choice == NULL) {
00877       best_choice_str = "NULL";
00878     } else {
00879       word_res->best_choice->string_and_lengths(&best_choice_str, NULL);
00880     }
00881     text += best_choice_str;
00882     IncorrectResultReason reason = (blamer_bundle == NULL) ?
00883         IRR_PAGE_LAYOUT : blamer_bundle->incorrect_result_reason();
00884     ASSERT_HOST(reason < IRR_NUM_REASONS)
00885     blame += " [";
00886     blame += BlamerBundle::IncorrectReasonName(reason);
00887     blame += "]";
00888   }
00889   if (text.length() > 0) {
00890     word_bb = word->bounding_box();
00891     image_win->Pen(ScrollView::RED);
00892     word_height = word_bb.height();
00893     int text_height = 0.50 * word_height;
00894     if (text_height > 20) text_height = 20;
00895     image_win->TextAttributes("Arial", text_height, false, false, false);
00896     shift = (word_height < word_bb.width()) ? 0.25 * word_height : 0.0f;
00897     image_win->Text(word_bb.left() + shift,
00898                     word_bb.bottom() + 0.25 * word_height, text.string());
00899     if (blame.length() > 0) {
00900       image_win->Text(word_bb.left() + shift,
00901                       word_bb.bottom() + 0.25 * word_height - text_height,
00902                       blame.string());
00903     }
00904 
00905     displayed_something = TRUE;
00906   }
00907 
00908   if (!displayed_something)      // display BBox anyway
00909     word->bounding_box().plot(image_win,
00910      (ScrollView::Color)((inT32) editor_image_word_bb_color),
00911      (ScrollView::Color)((inT32)
00912       editor_image_word_bb_color));
00913   return TRUE;
00914 }
00915 #endif  // GRAPHICS_DISABLED
00916 
00922 BOOL8 Tesseract::word_dumper(BLOCK* block, ROW* row, WERD_RES* word_res) {
00923   if (block != NULL) {
00924     tprintf("\nBlock data...\n");
00925     block->print(NULL, FALSE);
00926   }
00927   tprintf("\nRow data...\n");
00928   row->print(NULL);
00929   tprintf("\nWord data...\n");
00930   word_res->word->print();
00931   if (word_res->blamer_bundle != NULL && wordrec_debug_blamer &&
00932       word_res->blamer_bundle->incorrect_result_reason() != IRR_CORRECT) {
00933     tprintf("Current blamer debug: %s\n",
00934             word_res->blamer_bundle->debug().string());
00935   }
00936   return TRUE;
00937 }
00938 
00939 #ifndef GRAPHICS_DISABLED
00940 
00945 BOOL8 Tesseract::word_set_display(BLOCK* block, ROW* row, WERD_RES* word_res) {
00946   WERD* word = word_res->word;
00947   word->set_display_flag(DF_BOX, word_display_mode.bit(DF_BOX));
00948   word->set_display_flag(DF_TEXT, word_display_mode.bit(DF_TEXT));
00949   word->set_display_flag(DF_POLYGONAL, word_display_mode.bit(DF_POLYGONAL));
00950   word->set_display_flag(DF_EDGE_STEP, word_display_mode.bit(DF_EDGE_STEP));
00951   word->set_display_flag(DF_BN_POLYGONAL,
00952     word_display_mode.bit(DF_BN_POLYGONAL));
00953   word->set_display_flag(DF_BLAMER, word_display_mode.bit(DF_BLAMER));
00954   return word_display(block, row, word_res);
00955 }
00956 
00957 // page_res is non-const because the iterator doesn't know if you are going
00958 // to change the items it points to! Really a const here though.
00959 void Tesseract::blob_feature_display(PAGE_RES* page_res,
00960                                      const TBOX& selection_box) {
00961   ROW* row;               // row of word
00962   BLOCK* block;           // block of word
00963   WERD* word = make_pseudo_word(page_res, selection_box, block, row);
00964   if (word != NULL) {
00965     WERD_RES word_res(word);
00966     word_res.x_height = row->x_height();
00967     word_res.SetupForRecognition(unicharset, this, BestPix(),
00968                                  tessedit_ocr_engine_mode, NULL,
00969                                  classify_bln_numeric_mode,
00970                                  textord_use_cjk_fp_model,
00971                                  poly_allow_detailed_fx,
00972                                  row, block);
00973     TWERD* bln_word = word_res.chopped_word;
00974     TBLOB* bln_blob = bln_word->blobs[0];
00975     INT_FX_RESULT_STRUCT fx_info;
00976     GenericVector<INT_FEATURE_STRUCT> bl_features;
00977     GenericVector<INT_FEATURE_STRUCT> cn_features;
00978     Classify::ExtractFeatures(*bln_blob, classify_nonlinear_norm, &bl_features,
00979                               &cn_features, &fx_info, NULL);
00980     // Display baseline features.
00981     ScrollView* bl_win = CreateFeatureSpaceWindow("BL Features", 512, 0);
00982     ClearFeatureSpaceWindow(baseline, bl_win);
00983     for (int f = 0; f < bl_features.size(); ++f)
00984       RenderIntFeature(bl_win, &bl_features[f], ScrollView::GREEN);
00985     bl_win->Update();
00986     // Display cn features.
00987     ScrollView* cn_win = CreateFeatureSpaceWindow("CN Features", 512, 0);
00988     ClearFeatureSpaceWindow(character, cn_win);
00989     for (int f = 0; f < cn_features.size(); ++f)
00990       RenderIntFeature(cn_win, &cn_features[f], ScrollView::GREEN);
00991     cn_win->Update();
00992 
00993     delete word;
00994   }
00995 }
00996 
00997 
00998 #endif  // GRAPHICS_DISABLED
00999 
01000 }  // namespace tesseract
01001 
01002 
01003 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines