// Draws the data in a new window. void ImageData::Display() const { #ifndef GRAPHICS_DISABLED const int kTextSize = 64; // Draw the image. Pix* pix = GetPix(); if (pix == NULL) return; int width = pixGetWidth(pix); int height = pixGetHeight(pix); ScrollView* win = new ScrollView("Imagedata", 100, 100, 2 * (width + 2 * kTextSize), 2 * (height + 4 * kTextSize), width + 10, height + 3 * kTextSize, true); win->Image(pix, 0, height - 1); pixDestroy(&pix); // Draw the boxes. win->Pen(ScrollView::RED); win->Brush(ScrollView::NONE); win->TextAttributes("Arial", kTextSize, false, false, false); for (int b = 0; b < boxes_.size(); ++b) { boxes_[b].plot(win); win->Text(boxes_[b].left(), height + kTextSize, box_texts_[b].string()); TBOX scaled(boxes_[b]); scaled.scale(256.0 / height); scaled.plot(win); } // The full transcription. win->Pen(ScrollView::CYAN); win->Text(0, height + kTextSize * 2, transcription_.string()); // Add the features. win->Pen(ScrollView::GREEN); win->Update(); window_wait(win); #endif }
/** * @name classify_blob * * Classify the this blob if it is not already recorded in the match * table. Attempt to recognize this blob as a character. The recognition * rating for this blob will be stored as a part of the blob. This value * will also be returned to the caller. * @param blob Current blob * @param string The string to display in ScrollView * @param color The colour to use when displayed with ScrollView */ BLOB_CHOICE_LIST *Wordrec::classify_blob(TBLOB *blob, const char *string, C_COL color, BlamerBundle *blamer_bundle) { #ifndef GRAPHICS_DISABLED if (wordrec_display_all_blobs) display_blob(blob, color); #endif // TODO(rays) collapse with call_matcher and move all to wordrec.cpp. BLOB_CHOICE_LIST* choices = call_matcher(blob); // If a blob with the same bounding box as one of the truth character // bounding boxes is not classified as the corresponding truth character // blame character classifier for incorrect answer. if (blamer_bundle != NULL) { blamer_bundle->BlameClassifier(getDict().getUnicharset(), blob->bounding_box(), *choices, wordrec_debug_blamer); } #ifndef GRAPHICS_DISABLED if (classify_debug_level && string) print_ratings_list(string, choices, getDict().getUnicharset()); if (wordrec_blob_pause) window_wait(blob_window); #endif return choices; }
BLOB_CHOICE_LIST *Wordrec::classify_piece(TBLOB *pieces, const DENORM& denorm, SEAMS seams, inT16 start, inT16 end, BlamerBundle *blamer_bundle) { BLOB_CHOICE_LIST *choices; TBLOB *blob; inT16 x; join_pieces(pieces, seams, start, end); for (blob = pieces, x = 0; x < start; x++) { blob = blob->next; } choices = classify_blob(blob, denorm, "pieces:", White, blamer_bundle); break_pieces(blob, seams, start, end); #ifndef GRAPHICS_DISABLED if (wordrec_display_segmentations > 2) { STATE current_state; SEARCH_STATE chunk_groups; set_n_ones (¤t_state, array_count(seams)); chunk_groups = bin_to_chunks(¤t_state, array_count(seams)); display_segmentation(pieces, chunk_groups); window_wait(segm_window); memfree(chunk_groups); } #endif return (choices); }
BLOB_CHOICE_LIST *Wordrec::classify_piece(TBLOB *pieces, SEAMS seams, inT16 start, inT16 end) { STATE current_state; BLOB_CHOICE_LIST *choices; TBLOB *pblob; TBLOB *blob; TBLOB *nblob; inT16 x; SEARCH_STATE chunk_groups; set_n_ones (¤t_state, array_count (seams)); join_pieces(pieces, seams, start, end); for (blob = pieces, pblob = NULL, x = 0; x < start; x++) { pblob = blob; blob = blob->next; } for (nblob = blob->next; x < end; x++) nblob = nblob->next; choices = classify_blob (pblob, blob, nblob, NULL, "pieces:", White); break_pieces(blob, seams, start, end); #ifndef GRAPHICS_DISABLED if (wordrec_display_segmentations > 2) { chunk_groups = bin_to_chunks (¤t_state, array_count (seams)); display_segmentation(pieces, chunk_groups); window_wait(segm_window); memfree(chunk_groups); } #endif return (choices); }
/********************************************************************** * save_best_state * * Save this state away to be compared later. **********************************************************************/ void save_best_state(CHUNKS_RECORD *chunks_record) { STATE state; SEARCH_STATE chunk_groups; int num_joints; if (save_priorities) { num_joints = chunks_record->ratings->dimension() - 1; state.part1 = 0xffffffff; state.part2 = 0xffffffff; chunk_groups = bin_to_chunks (&state, num_joints); display_segmentation (chunks_record->chunks, chunk_groups); memfree(chunk_groups); cprintf ("Enter the correct segmentation > "); fflush(stdout); state.part1 = 0; scanf ("%x", &state.part2); chunk_groups = bin_to_chunks (&state, num_joints); display_segmentation (chunks_record->chunks, chunk_groups); memfree(chunk_groups); window_wait(segm_window); /* == 'n') */ if (known_best_state) free_state(known_best_state); known_best_state = new_state (&state); } }
/** * @name evaluate_state * * Evaluate the segmentation that is represented by this state in the * best first search. Add this state to the "states_seen" list. */ inT16 Wordrec::evaluate_state(CHUNKS_RECORD *chunks_record, SEARCH_RECORD *the_search, DANGERR *fixpt) { BLOB_CHOICE_LIST_VECTOR *char_choices; SEARCH_STATE chunk_groups; float rating_limit = the_search->best_choice->rating(); inT16 keep_going = TRUE; PIECES_STATE widths; the_search->num_states++; chunk_groups = bin_to_chunks(the_search->this_state, the_search->num_joints); bin_to_pieces (the_search->this_state, the_search->num_joints, widths); getDict().LogNewSegmentation(widths); char_choices = evaluate_chunks(chunks_record, chunk_groups); wordseg_rating_adjust_factor = -1.0f; if (char_choices != NULL && char_choices->length() > 0) { // Compute the segmentation cost and include the cost in word rating. // TODO(dsl): We should change the SEARCH_RECORD to store this cost // from state evaluation and avoid recomputing it here. prioritize_state(chunks_record, the_search); wordseg_rating_adjust_factor = the_search->segcost_bias; getDict().permute_characters(*char_choices, rating_limit, the_search->best_choice, the_search->raw_choice); bool replaced = false; if (getDict().AcceptableChoice(char_choices, the_search->best_choice, *(the_search->raw_choice), fixpt, ASSOCIATOR_CALLER, &replaced)) { keep_going = FALSE; } } wordseg_rating_adjust_factor = -1.0f; #ifndef GRAPHICS_DISABLED if (wordrec_display_segmentations) { display_segmentation (chunks_record->chunks, chunk_groups); if (wordrec_display_segmentations > 1) window_wait(segm_window); } #endif if (rating_limit != the_search->best_choice->rating()) { the_search->before_best = the_search->num_states; the_search->best_state->part1 = the_search->this_state->part1; the_search->best_state->part2 = the_search->this_state->part2; replace_char_widths(chunks_record, chunk_groups); } else if (char_choices != NULL) fixpt->index = -1; if (char_choices != NULL) delete char_choices; memfree(chunk_groups); return (keep_going); }
/********************************************************************** * classify_blob * * Classify the this blob if it is not already recorded in the match * table. Attempt to recognize this blob as a character. The recognition * rating (probability) for this blob will be stored as a part of the * blob. This value will also be returned to the caller. **********************************************************************/ CHOICES classify_blob(TBLOB *pblob, TBLOB *blob, TBLOB *nblob, TEXTROW *row, int fx, const char *string, C_COL color, STATE *this_state, STATE *best_state, INT32 pass, INT32 blob_index) { CHOICES rating; INT32 old_index; chars_classified++; /* Global value */ if (blob_skip) return (NIL); #ifndef GRAPHICS_DISABLED if (display_all_blobs) display_blob(blob, color); #endif rating = get_match (blob); if (rating == NIL) { if (pass) { old_index = blob_index; //?cast to int* blob_type = compare_states (best_state, this_state, (int *) &blob_index); blob_answer = word_answer[blob_index]; if (blob_answer < '!') fprintf (matcher_fp, "Bad compare states: best state=0x%x%x, this=0x%x%x, bits=" INT32FORMAT ", index=" INT32FORMAT ", outdex=" INT32FORMAT ", word=%s\n", best_state->part1, best_state->part2, this_state->part1, this_state->part2, bits_in_states, old_index, blob_index, word_answer); } else blob_type = 0; rating = /*(*blob_matchers [fx]) */ (CHOICES) call_matcher (pblob, blob, nblob, NULL, row); put_match(blob, rating); } #ifndef GRAPHICS_DISABLED if (display_ratings && string) print_choices(string, rating); if (blob_pause) window_wait(blob_window); #endif return (rating); }
/********************************************************************** * classify_piece * * Create a larger piece from a collection of smaller ones. Classify * it and return the results. Take the large piece apart to leave * the collection of small pieces un modified. **********************************************************************/ CHOICES classify_piece(TBLOB *pieces, SEAMS seams, INT16 start, INT16 end, INT32 fx, STATE *this_state, STATE *best_state, INT32 pass, INT32 blob_index) { STATE current_state; CHOICES choices; TBLOB *pblob; TBLOB *blob; TBLOB *nblob; INT16 x; SEARCH_STATE chunk_groups; set_n_ones (¤t_state, array_count (seams)); join_pieces(pieces, seams, start, end); for (blob = pieces, pblob = NULL, x = 0; x < start; x++) { pblob = blob; blob = blob->next; } for (nblob = blob->next; x < end; x++) nblob = nblob->next; choices = classify_blob (pblob, blob, nblob, NULL, fx, "pieces:", White, this_state, best_state, pass, blob_index); break_pieces(blob, seams, start, end); #ifndef GRAPHICS_DISABLED if (display_segmentations > 2) { chunk_groups = bin_to_chunks (¤t_state, array_count (seams)); display_segmentation(pieces, chunk_groups); window_wait(segm_window); memfree(chunk_groups); } #endif return (choices); }
// Draws the data in a new window. void ImageData::Display() const { const int kTextSize = 64; int x_max, y_max; WordFeature::ComputeSize(features_, &x_max, &y_max); ScrollView* win = new ScrollView("Imagedata", 100, 100, 2 * (x_max + 2 * kTextSize), 2 * (y_max + 4 * kTextSize), x_max + 10, y_max + 3 * kTextSize, true); // Draw the image. Pix* pix = GetPix(); int height = 256; if (pix != NULL) { height = pixGetHeight(pix); win->Image(pix, 0, height - 1); pixDestroy(&pix); } // Draw the boxes. win->Pen(ScrollView::RED); win->Brush(ScrollView::NONE); win->TextAttributes("Arial", kTextSize, false, false, false); for (int b = 0; b < boxes_.size(); ++b) { boxes_[b].plot(win); win->Text(boxes_[b].left(), y_max + kTextSize, box_texts_[b].string()); TBOX scaled(boxes_[b]); scaled.scale(256.0 / height); scaled.plot(win); } // The full transcription. win->Pen(ScrollView::CYAN); win->Text(0, y_max + kTextSize * 2, transcription_.string()); // Add the features. win->Pen(ScrollView::GREEN); WordFeature::Draw(features_, win); win->Update(); window_wait(win); }
/** * @name evaluate_state * * Evaluate the segmentation that is represented by this state in the * best first search. Add this state to the "states_seen" list. */ inT16 Wordrec::evaluate_state(CHUNKS_RECORD *chunks_record, SEARCH_RECORD *the_search, DANGERR *fixpt, BlamerBundle *blamer_bundle) { BLOB_CHOICE_LIST_VECTOR *char_choices; SEARCH_STATE chunk_groups; float rating_limit = the_search->best_choice->rating(); bool keep_going = true; PIECES_STATE widths; the_search->num_states++; chunk_groups = bin_to_chunks(the_search->this_state, the_search->num_joints); bin_to_pieces (the_search->this_state, the_search->num_joints, widths); if (wordrec_debug_level > 1) { log_state("Evaluating state", the_search->num_joints, the_search->this_state); } getDict().LogNewSegmentation(widths); char_choices = evaluate_chunks(chunks_record, chunk_groups, blamer_bundle); getDict().SetWordsegRatingAdjustFactor(-1.0f); bool updated_best_choice = false; if (char_choices != NULL && char_choices->length() > 0) { // Compute the segmentation cost and include the cost in word rating. // TODO(dsl): We should change the SEARCH_RECORD to store this cost // from state evaluation and avoid recomputing it here. prioritize_state(chunks_record, the_search); getDict().SetWordsegRatingAdjustFactor(the_search->segcost_bias); updated_best_choice = getDict().permute_characters(*char_choices, the_search->best_choice, the_search->raw_choice); bool replaced = false; if (updated_best_choice) { if (getDict().AcceptableChoice(char_choices, the_search->best_choice, NULL, ASSOCIATOR_CALLER, &replaced)) { keep_going = false; } CopyCharChoices(*char_choices, the_search->best_char_choices); } } getDict().SetWordsegRatingAdjustFactor(-1.0f); #ifndef GRAPHICS_DISABLED if (wordrec_display_segmentations) { display_segmentation (chunks_record->chunks, chunk_groups); if (wordrec_display_segmentations > 1) window_wait(segm_window); } #endif if (rating_limit != the_search->best_choice->rating()) { ASSERT_HOST(updated_best_choice); the_search->before_best = the_search->num_states; the_search->best_state->part1 = the_search->this_state->part1; the_search->best_state->part2 = the_search->this_state->part2; replace_char_widths(chunks_record, chunk_groups); } else { ASSERT_HOST(!updated_best_choice); if (char_choices != NULL) fixpt->clear(); } if (char_choices != NULL) delete char_choices; memfree(chunk_groups); return (keep_going); }