// page_res is non-const because the iterator doesn't know if you are going // to change the items it points to! Really a const here though. void Tesseract::blob_feature_display(PAGE_RES* page_res, const TBOX& selection_box) { ROW* row; // row of word BLOCK* block; // block of word WERD* word = make_pseudo_word(page_res, selection_box, block, row); if (word != NULL) { WERD_RES word_res(word); word_res.x_height = row->x_height(); word_res.SetupForRecognition(unicharset, this, BestPix(), tessedit_ocr_engine_mode, NULL, classify_bln_numeric_mode, textord_use_cjk_fp_model, poly_allow_detailed_fx, row, block); TWERD* bln_word = word_res.chopped_word; TBLOB* bln_blob = bln_word->blobs[0]; INT_FX_RESULT_STRUCT fx_info; GenericVector<INT_FEATURE_STRUCT> bl_features; GenericVector<INT_FEATURE_STRUCT> cn_features; Classify::ExtractFeatures(*bln_blob, classify_nonlinear_norm, &bl_features, &cn_features, &fx_info, NULL); // Display baseline features. ScrollView* bl_win = CreateFeatureSpaceWindow("BL Features", 512, 0); ClearFeatureSpaceWindow(baseline, bl_win); for (int f = 0; f < bl_features.size(); ++f) RenderIntFeature(bl_win, &bl_features[f], ScrollView::GREEN); bl_win->Update(); // Display cn features. ScrollView* cn_win = CreateFeatureSpaceWindow("CN Features", 512, 0); ClearFeatureSpaceWindow(character, cn_win); for (int f = 0; f < cn_features.size(); ++f) RenderIntFeature(cn_win, &cn_features[f], ScrollView::GREEN); cn_win->Update(); delete word; } }
// Visual debugger classifies the given sample, displays the results and // solicits user input to display other classifications. Returns when // the user has finished with debugging the sample. // Probably doesn't need to be overridden if the subclass provides // DisplayClassifyAs. void ShapeClassifier::DebugDisplay(const TrainingSample& sample, Pix* page_pix, UNICHAR_ID unichar_id) { #ifndef GRAPHICS_DISABLED static ScrollView* terminator = NULL; if (terminator == NULL) { terminator = new ScrollView("XIT", 0, 0, 50, 50, 50, 50, true); } ScrollView* debug_win = CreateFeatureSpaceWindow("ClassifierDebug", 0, 0); // Provide a right-click menu to choose the class. SVMenuNode* popup_menu = new SVMenuNode(); popup_menu->AddChild("Choose class to debug", 0, "x", "Class to debug"); popup_menu->BuildMenu(debug_win, false); // Display the features in green. const INT_FEATURE_STRUCT* features = sample.features(); int num_features = sample.num_features(); for (int f = 0; f < num_features; ++f) { RenderIntFeature(debug_win, &features[f], ScrollView::GREEN); } debug_win->Update(); GenericVector<UnicharRating> results; // Debug classification until the user quits. const UNICHARSET& unicharset = GetUnicharset(); SVEvent* ev; SVEventType ev_type; do { PointerVector<ScrollView> windows; if (unichar_id >= 0) { tprintf("Debugging class %d = %s\n", unichar_id, unicharset.id_to_unichar(unichar_id)); UnicharClassifySample(sample, page_pix, 1, unichar_id, &results); DisplayClassifyAs(sample, page_pix, unichar_id, 1, &windows); } else { tprintf("Invalid unichar_id: %d\n", unichar_id); UnicharClassifySample(sample, page_pix, 1, -1, &results); } if (unichar_id >= 0) { tprintf("Debugged class %d = %s\n", unichar_id, unicharset.id_to_unichar(unichar_id)); } tprintf("Right-click in ClassifierDebug window to choose debug class,"); tprintf(" Left-click or close window to quit...\n"); UNICHAR_ID old_unichar_id; do { old_unichar_id = unichar_id; ev = debug_win->AwaitEvent(SVET_ANY); ev_type = ev->type; if (ev_type == SVET_POPUP) { if (unicharset.contains_unichar(ev->parameter)) { unichar_id = unicharset.unichar_to_id(ev->parameter); } else { tprintf("Char class '%s' not found in unicharset", ev->parameter); } } delete ev; } while (unichar_id == old_unichar_id && ev_type != SVET_CLICK && ev_type != SVET_DESTROY); } while (ev_type != SVET_CLICK && ev_type != SVET_DESTROY); delete debug_win; #endif // GRAPHICS_DISABLED }