Tesseract
3.02
|
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 "svshowim.h" 00037 #include "paramsd.h" 00038 #include "pageres.h" 00039 #include "tordmain.h" 00040 #include "scrollview.h" 00041 #include "svmnode.h" 00042 #include "statistc.h" 00043 #include "tesseractclass.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_SUBSCRIPT_CMD_EVENT, 00077 SHOW_SUPERSCRIPT_CMD_EVENT, 00078 SHOW_ITALIC_CMD_EVENT, 00079 SHOW_BOLD_CMD_EVENT, 00080 SHOW_UNDERLINE_CMD_EVENT, 00081 SHOW_FIXEDPITCH_CMD_EVENT, 00082 SHOW_SERIF_CMD_EVENT, 00083 SHOW_SMALLCAPS_CMD_EVENT, 00084 SHOW_DROPCAPS_CMD_EVENT, 00085 }; 00086 00087 enum ColorationMode { 00088 CM_RAINBOW, 00089 CM_SUBSCRIPT, 00090 CM_SUPERSCRIPT, 00091 CM_ITALIC, 00092 CM_BOLD, 00093 CM_UNDERLINE, 00094 CM_FIXEDPITCH, 00095 CM_SERIF, 00096 CM_SMALLCAPS, 00097 CM_DROPCAPS 00098 }; 00099 00100 /* 00101 * 00102 * Some global data 00103 * 00104 */ 00105 00106 ScrollView* image_win; 00107 ParamsEditor* pe; 00108 bool stillRunning = false; 00109 00110 #ifdef __UNIX__ 00111 FILE *debug_window = NULL; // opened on demand 00112 #endif 00113 ScrollView* bln_word_window = NULL; // baseline norm words 00114 00115 CMD_EVENTS mode = CHANGE_DISP_CMD_EVENT; // selected words op 00116 00117 bool recog_done = false; // recog_all_words was called 00118 00119 // These variables should remain global, since they are only used for the 00120 // debug mode (in which only a single Tesseract thread/instance will be exist). 00121 BITS16 word_display_mode; 00122 static ColorationMode color_mode = CM_RAINBOW; 00123 BOOL8 display_image = FALSE; 00124 BOOL8 display_blocks = FALSE; 00125 BOOL8 display_baselines = FALSE; 00126 00127 PAGE_RES *current_page_res = NULL; 00128 00129 STRING_VAR(editor_image_win_name, "EditorImage", 00130 "Editor image window name"); 00131 INT_VAR(editor_image_xpos, 590, "Editor image X Pos"); 00132 INT_VAR(editor_image_ypos, 10, "Editor image Y Pos"); 00133 INT_VAR(editor_image_menuheight, 50, "Add to image height for menu bar"); 00134 INT_VAR(editor_image_word_bb_color, ScrollView::BLUE, 00135 "Word bounding box colour"); 00136 INT_VAR(editor_image_blob_bb_color, ScrollView::YELLOW, 00137 "Blob bounding box colour"); 00138 INT_VAR(editor_image_text_color, ScrollView::WHITE, 00139 "Correct text colour"); 00140 00141 STRING_VAR(editor_dbwin_name, "EditorDBWin", 00142 "Editor debug window name"); 00143 INT_VAR(editor_dbwin_xpos, 50, "Editor debug window X Pos"); 00144 INT_VAR(editor_dbwin_ypos, 500, "Editor debug window Y Pos"); 00145 INT_VAR(editor_dbwin_height, 24, "Editor debug window height"); 00146 INT_VAR(editor_dbwin_width, 80, "Editor debug window width"); 00147 00148 STRING_VAR(editor_word_name, "BlnWords", "BL normalized word window"); 00149 INT_VAR(editor_word_xpos, 60, "Word window X Pos"); 00150 INT_VAR(editor_word_ypos, 510, "Word window Y Pos"); 00151 INT_VAR(editor_word_height, 240, "Word window height"); 00152 INT_VAR(editor_word_width, 655, "Word window width"); 00153 00154 STRING_VAR(editor_debug_config_file, "", "Config file to apply to single words"); 00155 00156 class BlnEventHandler : public SVEventHandler { 00157 public: 00158 void Notify(const SVEvent* sv_event) { 00159 if (sv_event->type == SVET_DESTROY) 00160 bln_word_window = NULL; 00161 else if (sv_event->type == SVET_CLICK) 00162 show_point(current_page_res, sv_event->x, sv_event->y); 00163 } 00164 }; 00165 00171 ScrollView* bln_word_window_handle() { // return handle 00172 // not opened yet 00173 if (bln_word_window == NULL) { 00174 pgeditor_msg("Creating BLN word window..."); 00175 bln_word_window = new ScrollView(editor_word_name.string(), 00176 editor_word_xpos, editor_word_ypos, editor_word_width, 00177 editor_word_height, 4000, 4000, true); 00178 BlnEventHandler* a = new BlnEventHandler(); 00179 bln_word_window->AddEventHandler(a); 00180 pgeditor_msg("Creating BLN word window...Done"); 00181 } 00182 return bln_word_window; 00183 } 00184 00192 void build_image_window(int width, int height) { 00193 if (image_win != NULL) { delete image_win; } 00194 image_win = new ScrollView(editor_image_win_name.string(), 00195 editor_image_xpos, editor_image_ypos, 00196 width + 1, 00197 height + editor_image_menuheight + 1, 00198 width, 00199 height, 00200 true); 00201 } 00202 00209 void display_bln_lines(ScrollView* window, 00210 ScrollView::Color colour, 00211 float scale_factor, 00212 float y_offset, 00213 float minx, 00214 float maxx) { 00215 window->Pen(colour); 00216 window->Line(minx, y_offset + scale_factor * DESC_HEIGHT, 00217 maxx, y_offset + scale_factor * DESC_HEIGHT); 00218 window->Line(minx, y_offset + scale_factor * BL_HEIGHT, 00219 maxx, y_offset + scale_factor * BL_HEIGHT); 00220 window->Line(minx, y_offset + scale_factor * X_HEIGHT, 00221 maxx, y_offset + scale_factor * X_HEIGHT); 00222 window->Line(minx, y_offset + scale_factor * ASC_HEIGHT, 00223 maxx, y_offset + scale_factor * ASC_HEIGHT); 00224 } 00225 00234 void PGEventHandler::Notify(const SVEvent* event) { 00235 char myval = '0'; 00236 if (event->type == SVET_POPUP) { 00237 pe->Notify(event); 00238 } // These are handled by ParamsEditor 00239 else if (event->type == SVET_EXIT) { stillRunning = false; } 00240 else if (event->type == SVET_MENU) { 00241 if (strcmp(event->parameter, "true") == 0) { myval = 'T'; } 00242 else if (strcmp(event->parameter, "false") == 0) { myval = 'F'; } 00243 tess_->process_cmd_win_event(event->command_id, &myval); 00244 } 00245 else { 00246 tess_->process_image_event(*event); 00247 } 00248 } 00249 00255 namespace tesseract { 00256 SVMenuNode *Tesseract::build_menu_new() { 00257 SVMenuNode* parent_menu; 00258 SVMenuNode* root_menu_item = new SVMenuNode(); 00259 00260 SVMenuNode* modes_menu_item = root_menu_item->AddChild("MODES"); 00261 00262 modes_menu_item->AddChild("Change Display", CHANGE_DISP_CMD_EVENT); 00263 modes_menu_item->AddChild("Dump Word", DUMP_WERD_CMD_EVENT); 00264 modes_menu_item->AddChild("Show Point", SHOW_POINT_CMD_EVENT); 00265 modes_menu_item->AddChild("Show BL Norm Word", SHOW_BLN_WERD_CMD_EVENT); 00266 modes_menu_item->AddChild("Config Words", DEBUG_WERD_CMD_EVENT); 00267 modes_menu_item->AddChild("Recog Words", RECOG_WERDS); 00268 modes_menu_item->AddChild("Recog Blobs", RECOG_PSEUDO); 00269 00270 parent_menu = root_menu_item->AddChild("DISPLAY"); 00271 00272 parent_menu->AddChild("Blamer", BLAMER_CMD_EVENT, FALSE); 00273 parent_menu->AddChild("Bounding Boxes", BOUNDING_BOX_CMD_EVENT, FALSE); 00274 parent_menu->AddChild("Correct Text", CORRECT_TEXT_CMD_EVENT, FALSE); 00275 parent_menu->AddChild("Polygonal Approx", POLYGONAL_CMD_EVENT, FALSE); 00276 parent_menu->AddChild("Baseline Normalized", BL_NORM_CMD_EVENT, FALSE); 00277 parent_menu->AddChild("Edge Steps", BITMAP_CMD_EVENT, TRUE); 00278 parent_menu->AddChild("Subscripts", SHOW_SUBSCRIPT_CMD_EVENT); 00279 parent_menu->AddChild("Superscripts", SHOW_SUPERSCRIPT_CMD_EVENT); 00280 parent_menu->AddChild("Italics", SHOW_ITALIC_CMD_EVENT); 00281 parent_menu->AddChild("Bold", SHOW_BOLD_CMD_EVENT); 00282 parent_menu->AddChild("Underline", SHOW_UNDERLINE_CMD_EVENT); 00283 parent_menu->AddChild("FixedPitch", SHOW_FIXEDPITCH_CMD_EVENT); 00284 parent_menu->AddChild("Serifs", SHOW_SERIF_CMD_EVENT); 00285 parent_menu->AddChild("SmallCaps", SHOW_SMALLCAPS_CMD_EVENT); 00286 parent_menu->AddChild("DropCaps", SHOW_DROPCAPS_CMD_EVENT); 00287 00288 00289 parent_menu = root_menu_item->AddChild("OTHER"); 00290 00291 parent_menu->AddChild("Quit", QUIT_CMD_EVENT); 00292 parent_menu->AddChild("Show Image", IMAGE_CMD_EVENT, FALSE); 00293 parent_menu->AddChild("ShowBlock Outlines", BLOCKS_CMD_EVENT, FALSE); 00294 parent_menu->AddChild("Show Baselines", BASELINES_CMD_EVENT, FALSE); 00295 parent_menu->AddChild("Uniform Display", UNIFORM_DISP_CMD_EVENT); 00296 parent_menu->AddChild("Refresh Display", REFRESH_CMD_EVENT); 00297 00298 return root_menu_item; 00299 } 00300 00306 void Tesseract::do_re_display( 00307 BOOL8 (tesseract::Tesseract::*word_painter)(BLOCK* block, 00308 ROW* row, 00309 WERD_RES* word_res)) { 00310 PAGE_RES_IT pr_it(current_page_res); 00311 int block_count = 1; 00312 00313 image_win->Clear(); 00314 if (display_image != 0) { 00315 image_win->Image(pix_binary_, 0, 0); 00316 } 00317 00318 for (WERD_RES* word = pr_it.word(); word != NULL; word = pr_it.forward()) { 00319 (this->*word_painter)(pr_it.block()->block, pr_it.row()->row, word); 00320 if (display_baselines && pr_it.row() != pr_it.prev_row()) 00321 pr_it.row()->row->plot_baseline(image_win, ScrollView::GREEN); 00322 if (display_blocks && pr_it.block() != pr_it.prev_block()) 00323 pr_it.block()->block->plot(image_win, block_count++, ScrollView::RED); 00324 } 00325 image_win->Update(); 00326 } 00327 00336 void Tesseract::pgeditor_main(int width, int height, PAGE_RES *page_res) { 00337 current_page_res = page_res; 00338 if (current_page_res->block_res_list.empty()) 00339 return; 00340 00341 recog_done = false; 00342 stillRunning = true; 00343 00344 build_image_window(width, height); 00345 word_display_mode.turn_on_bit(DF_EDGE_STEP); 00346 do_re_display(&tesseract::Tesseract::word_set_display); 00347 #ifndef GRAPHICS_DISABLED 00348 pe = new ParamsEditor(this, image_win); 00349 #endif 00350 PGEventHandler pgEventHandler(this); 00351 00352 image_win->AddEventHandler(&pgEventHandler); 00353 image_win->AddMessageBox(); 00354 00355 SVMenuNode* svMenuRoot = build_menu_new(); 00356 00357 svMenuRoot->BuildMenu(image_win); 00358 image_win->SetVisible(true); 00359 00360 image_win->AwaitEvent(SVET_DESTROY); 00361 image_win->AddEventHandler(NULL); 00362 } 00363 } // namespace tesseract 00364 00365 00372 void pgeditor_msg( // message display 00373 const char *msg) { 00374 image_win->AddMessage(msg); 00375 } 00376 00383 void pgeditor_show_point( // display coords 00384 SVEvent *event) { 00385 image_win->AddMessage("Pointing at(%d, %d)", event->x, event->y); 00386 } 00387 00395 namespace tesseract { 00396 BOOL8 Tesseract::process_cmd_win_event( // UI command semantics 00397 inT32 cmd_event, // which menu item? 00398 char *new_value // any prompt data 00399 ) { 00400 char msg[160]; 00401 BOOL8 exit = FALSE; 00402 00403 color_mode = CM_RAINBOW; 00404 00405 // Run recognition on the full page if needed. 00406 switch (cmd_event) { 00407 case BLAMER_CMD_EVENT: 00408 case SHOW_SUBSCRIPT_CMD_EVENT: 00409 case SHOW_SUPERSCRIPT_CMD_EVENT: 00410 case SHOW_ITALIC_CMD_EVENT: 00411 case SHOW_BOLD_CMD_EVENT: 00412 case SHOW_UNDERLINE_CMD_EVENT: 00413 case SHOW_FIXEDPITCH_CMD_EVENT: 00414 case SHOW_SERIF_CMD_EVENT: 00415 case SHOW_SMALLCAPS_CMD_EVENT: 00416 case SHOW_DROPCAPS_CMD_EVENT: 00417 if (!recog_done) { 00418 recog_all_words(current_page_res, NULL, NULL, NULL, 0); 00419 recog_done = true; 00420 } 00421 break; 00422 default: 00423 break; 00424 } 00425 00426 switch (cmd_event) { 00427 case NULL_CMD_EVENT: 00428 break; 00429 00430 case CHANGE_DISP_CMD_EVENT: 00431 case DUMP_WERD_CMD_EVENT: 00432 case SHOW_POINT_CMD_EVENT: 00433 case SHOW_BLN_WERD_CMD_EVENT: 00434 case RECOG_WERDS: 00435 case RECOG_PSEUDO: 00436 mode =(CMD_EVENTS) cmd_event; 00437 break; 00438 case DEBUG_WERD_CMD_EVENT: 00439 mode = DEBUG_WERD_CMD_EVENT; 00440 word_config_ = image_win->ShowInputDialog("Config File Name"); 00441 break; 00442 case BOUNDING_BOX_CMD_EVENT: 00443 if (new_value[0] == 'T') 00444 word_display_mode.turn_on_bit(DF_BOX); 00445 else 00446 word_display_mode.turn_off_bit(DF_BOX); 00447 mode = CHANGE_DISP_CMD_EVENT; 00448 break; 00449 case BLAMER_CMD_EVENT: 00450 if (new_value[0] == 'T') 00451 word_display_mode.turn_on_bit(DF_BLAMER); 00452 else 00453 word_display_mode.turn_off_bit(DF_BLAMER); 00454 do_re_display(&tesseract::Tesseract::word_display); 00455 mode = CHANGE_DISP_CMD_EVENT; 00456 break; 00457 case CORRECT_TEXT_CMD_EVENT: 00458 if (new_value[0] == 'T') 00459 word_display_mode.turn_on_bit(DF_TEXT); 00460 else 00461 word_display_mode.turn_off_bit(DF_TEXT); 00462 mode = CHANGE_DISP_CMD_EVENT; 00463 break; 00464 case POLYGONAL_CMD_EVENT: 00465 if (new_value[0] == 'T') 00466 word_display_mode.turn_on_bit(DF_POLYGONAL); 00467 else 00468 word_display_mode.turn_off_bit(DF_POLYGONAL); 00469 mode = CHANGE_DISP_CMD_EVENT; 00470 break; 00471 case BL_NORM_CMD_EVENT: 00472 if (new_value[0] == 'T') 00473 word_display_mode.turn_on_bit(DF_BN_POLYGONAL); 00474 else 00475 word_display_mode.turn_off_bit(DF_BN_POLYGONAL); 00476 mode = CHANGE_DISP_CMD_EVENT; 00477 break; 00478 case BITMAP_CMD_EVENT: 00479 if (new_value[0] == 'T') 00480 word_display_mode.turn_on_bit(DF_EDGE_STEP); 00481 else 00482 word_display_mode.turn_off_bit(DF_EDGE_STEP); 00483 mode = CHANGE_DISP_CMD_EVENT; 00484 break; 00485 case UNIFORM_DISP_CMD_EVENT: 00486 do_re_display(&tesseract::Tesseract::word_set_display); 00487 break; 00488 case IMAGE_CMD_EVENT: 00489 display_image =(new_value[0] == 'T'); 00490 do_re_display(&tesseract::Tesseract::word_display); 00491 break; 00492 case BLOCKS_CMD_EVENT: 00493 display_blocks =(new_value[0] == 'T'); 00494 do_re_display(&tesseract::Tesseract::word_display); 00495 break; 00496 case BASELINES_CMD_EVENT: 00497 display_baselines =(new_value[0] == 'T'); 00498 do_re_display(&tesseract::Tesseract::word_display); 00499 break; 00500 case SHOW_SUBSCRIPT_CMD_EVENT: 00501 color_mode = CM_SUBSCRIPT; 00502 do_re_display(&tesseract::Tesseract::word_display); 00503 break; 00504 case SHOW_SUPERSCRIPT_CMD_EVENT: 00505 color_mode = CM_SUPERSCRIPT; 00506 do_re_display(&tesseract::Tesseract::word_display); 00507 break; 00508 case SHOW_ITALIC_CMD_EVENT: 00509 color_mode = CM_ITALIC; 00510 do_re_display(&tesseract::Tesseract::word_display); 00511 break; 00512 case SHOW_BOLD_CMD_EVENT: 00513 color_mode = CM_BOLD; 00514 do_re_display(&tesseract::Tesseract::word_display); 00515 break; 00516 case SHOW_UNDERLINE_CMD_EVENT: 00517 color_mode = CM_UNDERLINE; 00518 do_re_display(&tesseract::Tesseract::word_display); 00519 break; 00520 case SHOW_FIXEDPITCH_CMD_EVENT: 00521 color_mode = CM_FIXEDPITCH; 00522 do_re_display(&tesseract::Tesseract::word_display); 00523 break; 00524 case SHOW_SERIF_CMD_EVENT: 00525 color_mode = CM_SERIF; 00526 do_re_display(&tesseract::Tesseract::word_display); 00527 break; 00528 case SHOW_SMALLCAPS_CMD_EVENT: 00529 color_mode = CM_SMALLCAPS; 00530 do_re_display(&tesseract::Tesseract::word_display); 00531 break; 00532 case SHOW_DROPCAPS_CMD_EVENT: 00533 color_mode = CM_DROPCAPS; 00534 do_re_display(&tesseract::Tesseract::word_display); 00535 break; 00536 case REFRESH_CMD_EVENT: 00537 do_re_display(&tesseract::Tesseract::word_display); 00538 break; 00539 case QUIT_CMD_EVENT: 00540 exit = TRUE; 00541 ScrollView::Exit(); 00542 break; 00543 00544 default: 00545 sprintf(msg, "Unrecognised event " INT32FORMAT "(%s)", 00546 cmd_event, new_value); 00547 image_win->AddMessage(msg); 00548 break; 00549 } 00550 return exit; 00551 } 00552 00553 00563 void Tesseract::process_image_event( // action in image win 00564 const SVEvent &event) { 00565 // The following variable should remain static, since it is used by 00566 // debug editor, which uses a single Tesseract instance. 00567 static ICOORD down; 00568 ICOORD up; 00569 TBOX selection_box; 00570 char msg[80]; 00571 00572 switch(event.type) { 00573 00574 case SVET_SELECTION: 00575 if (event.type == SVET_SELECTION) { 00576 down.set_x(event.x + event.x_size); 00577 down.set_y(event.y + event.y_size); 00578 if (mode == SHOW_POINT_CMD_EVENT) 00579 show_point(current_page_res, event.x, event.y); 00580 } 00581 00582 up.set_x(event.x); 00583 up.set_y(event.y); 00584 00585 selection_box = TBOX(down, up); 00586 00587 switch(mode) { 00588 case CHANGE_DISP_CMD_EVENT: 00589 process_selected_words( 00590 current_page_res, 00591 selection_box, 00592 &tesseract::Tesseract::word_blank_and_set_display); 00593 break; 00594 case DUMP_WERD_CMD_EVENT: 00595 process_selected_words(current_page_res, 00596 selection_box, 00597 &tesseract::Tesseract::word_dumper); 00598 break; 00599 case SHOW_BLN_WERD_CMD_EVENT: 00600 process_selected_words(current_page_res, 00601 selection_box, 00602 &tesseract::Tesseract::word_bln_display); 00603 break; 00604 case DEBUG_WERD_CMD_EVENT: 00605 debug_word(current_page_res, selection_box); 00606 break; 00607 case SHOW_POINT_CMD_EVENT: 00608 break; // ignore up event 00609 00610 case RECOG_WERDS: 00611 image_win->AddMessage("Recogging selected words"); 00612 this->process_selected_words(current_page_res, 00613 selection_box, 00614 &Tesseract::recog_interactive); 00615 break; 00616 case RECOG_PSEUDO: 00617 image_win->AddMessage("Recogging selected blobs"); 00618 recog_pseudo_word(current_page_res, selection_box); 00619 break; 00620 00621 default: 00622 sprintf(msg, "Mode %d not yet implemented", mode); 00623 image_win->AddMessage(msg); 00624 break; 00625 } 00626 default: 00627 break; 00628 } 00629 } 00630 00636 void Tesseract::debug_word(PAGE_RES* page_res, const TBOX &selection_box) { 00637 ResetAdaptiveClassifier(); 00638 recog_all_words(page_res, NULL, &selection_box, word_config_.string(), 0); 00639 } 00640 } // namespace tesseract 00641 00642 00650 void show_point(PAGE_RES* page_res, float x, float y) { 00651 FCOORD pt(x, y); 00652 PAGE_RES_IT pr_it(page_res); 00653 00654 char msg[160]; 00655 char *msg_ptr = msg; 00656 00657 msg_ptr += sprintf(msg_ptr, "Pt:(%0.3f, %0.3f) ", x, y); 00658 00659 for (WERD_RES* word = pr_it.word(); word != NULL; word = pr_it.forward()) { 00660 if (pr_it.row() != pr_it.prev_row() && 00661 pr_it.row()->row->bounding_box().contains(pt)) { 00662 msg_ptr += sprintf(msg_ptr, "BL(x)=%0.3f ", 00663 pr_it.row()->row->base_line(x)); 00664 } 00665 if (word->word->bounding_box().contains(pt)) { 00666 TBOX box = word->word->bounding_box(); 00667 msg_ptr += sprintf(msg_ptr, "Wd(%d, %d)/(%d, %d) ", 00668 box.left(), box.bottom(), 00669 box.right(), box.top()); 00670 C_BLOB_IT cblob_it(word->word->cblob_list()); 00671 for (cblob_it.mark_cycle_pt(); 00672 !cblob_it.cycled_list(); 00673 cblob_it.forward()) { 00674 C_BLOB* cblob = cblob_it.data(); 00675 box = cblob->bounding_box(); 00676 if (box.contains(pt)) { 00677 msg_ptr += sprintf(msg_ptr, 00678 "CBlb(%d, %d)/(%d, %d) ", 00679 box.left(), box.bottom(), 00680 box.right(), box.top()); 00681 } 00682 } 00683 } 00684 } 00685 image_win->AddMessage(msg); 00686 } 00687 00688 00689 /********************************************************************** 00690 * WERD PROCESSOR FUNCTIONS 00691 * ======================== 00692 * 00693 * These routines are invoked by one or more of: 00694 * process_all_words() 00695 * process_selected_words() 00696 * or 00697 * process_all_words_it() 00698 * process_selected_words_it() 00699 * for each word to be processed 00700 **********************************************************************/ 00701 00708 #endif // GRAPHICS_DISABLED 00709 namespace tesseract { 00710 #ifndef GRAPHICS_DISABLED 00711 BOOL8 Tesseract:: word_blank_and_set_display(BLOCK* block, ROW* row, 00712 WERD_RES* word_res) { 00713 word_res->word->bounding_box().plot(image_win, ScrollView::BLACK, 00714 ScrollView::BLACK); 00715 return word_set_display(block, row, word_res); 00716 } 00717 00718 00724 BOOL8 Tesseract::word_bln_display(BLOCK* block, ROW* row, WERD_RES* word_res) { 00725 TWERD *bln_word = word_res->chopped_word; 00726 if (bln_word == NULL) { 00727 word_res->SetupForTessRecognition(unicharset, this, BestPix(), false, 00728 this->textord_use_cjk_fp_model, 00729 row, block); 00730 bln_word = word_res->chopped_word; 00731 } 00732 bln_word_window_handle()->Clear(); 00733 display_bln_lines(bln_word_window_handle(), ScrollView::CYAN, 00734 1.0, 0.0f, -1000.0f, 1000.0f); 00735 bln_word->plot(bln_word_window_handle()); 00736 bln_word_window_handle()->Update(); 00737 return TRUE; 00738 } 00739 00740 00741 00747 BOOL8 Tesseract::word_display(BLOCK* block, ROW* row, WERD_RES* word_res) { 00748 WERD* word = word_res->word; 00749 TBOX word_bb; // word bounding box 00750 int word_height; // ht of word BB 00751 BOOL8 displayed_something = FALSE; 00752 float shift; // from bot left 00753 C_BLOB_IT c_it; // cblob iterator 00754 00755 if (color_mode != CM_RAINBOW && word_res->box_word != NULL) { 00756 BoxWord* box_word = word_res->box_word; 00757 int length = box_word->length(); 00758 if (word_res->fontinfo == NULL) return false; 00759 const FontInfo& font_info = *word_res->fontinfo; 00760 for (int i = 0; i < length; ++i) { 00761 ScrollView::Color color = ScrollView::GREEN; 00762 switch (color_mode) { 00763 case CM_SUBSCRIPT: 00764 if (box_word->BlobPosition(i) == SP_SUBSCRIPT) 00765 color = ScrollView::RED; 00766 break; 00767 case CM_SUPERSCRIPT: 00768 if (box_word->BlobPosition(i) == SP_SUPERSCRIPT) 00769 color = ScrollView::RED; 00770 break; 00771 case CM_ITALIC: 00772 if (font_info.is_italic()) 00773 color = ScrollView::RED; 00774 break; 00775 case CM_BOLD: 00776 if (font_info.is_bold()) 00777 color = ScrollView::RED; 00778 break; 00779 case CM_FIXEDPITCH: 00780 if (font_info.is_fixed_pitch()) 00781 color = ScrollView::RED; 00782 break; 00783 case CM_SERIF: 00784 if (font_info.is_serif()) 00785 color = ScrollView::RED; 00786 break; 00787 case CM_SMALLCAPS: 00788 if (word_res->small_caps) 00789 color = ScrollView::RED; 00790 break; 00791 case CM_DROPCAPS: 00792 if (box_word->BlobPosition(i) == SP_DROPCAP) 00793 color = ScrollView::RED; 00794 break; 00795 // TODO(rays) underline is currently completely unsupported. 00796 case CM_UNDERLINE: 00797 default: 00798 break; 00799 } 00800 image_win->Pen(color); 00801 TBOX box = box_word->BlobBox(i); 00802 image_win->Rectangle(box.left(), box.bottom(), box.right(), box.top()); 00803 } 00804 return true; 00805 } 00806 /* 00807 Note the double coercions of(COLOUR)((inT32)editor_image_word_bb_color) 00808 etc. are to keep the compiler happy. 00809 */ 00810 // display bounding box 00811 if (word->display_flag(DF_BOX)) { 00812 word->bounding_box().plot(image_win, 00813 (ScrollView::Color)((inT32) 00814 editor_image_word_bb_color), 00815 (ScrollView::Color)((inT32) 00816 editor_image_word_bb_color)); 00817 00818 ScrollView::Color c = (ScrollView::Color) 00819 ((inT32) editor_image_blob_bb_color); 00820 image_win->Pen(c); 00821 c_it.set_to_list(word->cblob_list()); 00822 for (c_it.mark_cycle_pt(); !c_it.cycled_list(); c_it.forward()) 00823 c_it.data()->bounding_box().plot(image_win); 00824 displayed_something = TRUE; 00825 } 00826 00827 // display edge steps 00828 if (word->display_flag(DF_EDGE_STEP)) { // edgesteps available 00829 word->plot(image_win); // rainbow colors 00830 displayed_something = TRUE; 00831 } 00832 00833 // display poly approx 00834 if (word->display_flag(DF_POLYGONAL)) { 00835 // need to convert 00836 TWERD* tword = TWERD::PolygonalCopy(word); 00837 tword->plot(image_win); 00838 delete tword; 00839 displayed_something = TRUE; 00840 } 00841 00842 // Display correct text and blamer information. 00843 STRING text; 00844 STRING blame; 00845 if (word->display_flag(DF_TEXT) && word->text() != NULL) { 00846 text = word->text(); 00847 } 00848 if (word->display_flag(DF_BLAMER) && 00849 !(word_res->blamer_bundle != NULL && 00850 word_res->blamer_bundle->incorrect_result_reason == IRR_CORRECT)) { 00851 text = ""; 00852 const BlamerBundle *blamer_bundle = word_res->blamer_bundle; 00853 if (blamer_bundle == NULL) { 00854 text += "NULL"; 00855 } else { 00856 for (int i = 0; i < blamer_bundle->truth_text.length(); ++i) { 00857 text += blamer_bundle->truth_text[i]; 00858 } 00859 } 00860 text += " -> "; 00861 STRING best_choice_str; 00862 if (word_res->best_choice == NULL) { 00863 best_choice_str = "NULL"; 00864 } else { 00865 word_res->best_choice->string_and_lengths(&best_choice_str, NULL); 00866 } 00867 text += best_choice_str; 00868 IncorrectResultReason reason = (blamer_bundle == NULL) ? 00869 IRR_PAGE_LAYOUT : blamer_bundle->incorrect_result_reason; 00870 ASSERT_HOST(reason < IRR_NUM_REASONS) 00871 blame += " ["; 00872 blame += BlamerBundle::IncorrectReasonName(reason); 00873 blame += "]"; 00874 } 00875 if (text.length() > 0) { 00876 word_bb = word->bounding_box(); 00877 image_win->Pen(ScrollView::RED); 00878 word_height = word_bb.height(); 00879 int text_height = 0.50 * word_height; 00880 if (text_height > 20) text_height = 20; 00881 image_win->TextAttributes("Arial", text_height, false, false, false); 00882 shift = (word_height < word_bb.width()) ? 0.25 * word_height : 0.0f; 00883 image_win->Text(word_bb.left() + shift, 00884 word_bb.bottom() + 0.25 * word_height, text.string()); 00885 if (blame.length() > 0) { 00886 image_win->Text(word_bb.left() + shift, 00887 word_bb.bottom() + 0.25 * word_height - text_height, 00888 blame.string()); 00889 } 00890 00891 displayed_something = TRUE; 00892 } 00893 00894 if (!displayed_something) // display BBox anyway 00895 word->bounding_box().plot(image_win, 00896 (ScrollView::Color)((inT32) editor_image_word_bb_color), 00897 (ScrollView::Color)((inT32) 00898 editor_image_word_bb_color)); 00899 return TRUE; 00900 } 00901 #endif // GRAPHICS_DISABLED 00902 00908 BOOL8 Tesseract::word_dumper(BLOCK* block, ROW* row, WERD_RES* word_res) { 00909 if (block != NULL) { 00910 tprintf("\nBlock data...\n"); 00911 block->print(NULL, FALSE); 00912 } 00913 tprintf("\nRow data...\n"); 00914 row->print(NULL); 00915 tprintf("\nWord data...\n"); 00916 word_res->word->print(); 00917 if (word_res->blamer_bundle != NULL && wordrec_debug_blamer && 00918 word_res->blamer_bundle->incorrect_result_reason != IRR_CORRECT) { 00919 tprintf("Current blamer debug: %s\n", 00920 word_res->blamer_bundle->debug.string()); 00921 } 00922 return TRUE; 00923 } 00924 00925 #ifndef GRAPHICS_DISABLED 00926 00931 BOOL8 Tesseract::word_set_display(BLOCK* block, ROW* row, WERD_RES* word_res) { 00932 WERD* word = word_res->word; 00933 word->set_display_flag(DF_BOX, word_display_mode.bit(DF_BOX)); 00934 word->set_display_flag(DF_TEXT, word_display_mode.bit(DF_TEXT)); 00935 word->set_display_flag(DF_POLYGONAL, word_display_mode.bit(DF_POLYGONAL)); 00936 word->set_display_flag(DF_EDGE_STEP, word_display_mode.bit(DF_EDGE_STEP)); 00937 word->set_display_flag(DF_BN_POLYGONAL, 00938 word_display_mode.bit(DF_BN_POLYGONAL)); 00939 word->set_display_flag(DF_BLAMER, word_display_mode.bit(DF_BLAMER)); 00940 return word_display(block, row, word_res); 00941 } 00942 #endif // GRAPHICS_DISABLED 00943 00944 } // namespace tesseract 00945 00946 00947