tesseract
3.03
|
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