📄 chopper.cpp
字号:
/* -*-C-*- ******************************************************************************** * * File: chopper.c (Formerly chopper.c) * Description: * Author: Mark Seaman, OCR Technology * Created: Fri Oct 16 14:37:00 1987 * Modified: Tue Jul 30 16:18:52 1991 (Mark Seaman) marks@hpgrlt * Language: C * Package: N/A * Status: Reusable Software Component * * (c) Copyright 1987, Hewlett-Packard Company. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** http://www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. * **************************************************************************//*---------------------------------------------------------------------- I n c l u d e s----------------------------------------------------------------------*/#include "chopper.h"#include "wordclass.h"#include "makechop.h"#include "associate.h"#include "metrics.h"#include "tordvars.h"#include "stopper.h"#include "callcpp.h"#include "structures.h"#include "findseam.h"#include "render.h"#include "seam.h"#include "const.h"#include "freelist.h"#include "pieces.h"#include "permute.h"//#include "tessvars.h"#include <math.h>extern int blob_skip;INT_VAR (repair_unchopped_blobs, 1, "Fix blobs that aren't chopped");//?extern int tessedit_dangambigs_chop;double_VAR (tessedit_certainty_threshold, -2.25, "Good blob limit");/*---------------------------------------------------------------------- M a c r o s----------------------------------------------------------------------*//********************************************************************** * bounds_inside * * Check to see if the bounding box of one thing is inside the * bounding box of another. **********************************************************************/#define bounds_inside(inner_tl,inner_br,outer_tl,outer_br) \((inner_tl.x >= outer_tl.x) && \(inner_tl.y <= outer_tl.y) && \(inner_br.x <= outer_br.x) && \(inner_br.y >= outer_br.y)) \/********************************************************************** * set_null_choice * * Set the fields in this choice to be defaulted bad initial values. **********************************************************************/#define set_null_choice(choice) \(class_string (choice) = NULL, \class_probability (choice) = MAX_FLOAT32, \class_certainty (choice) = -MAX_FLOAT32) \/*---------------------------------------------------------------------- F u n c t i o n s----------------------------------------------------------------------*//********************************************************************** * preserve_outline_tree * * Copy the list of outlines. **********************************************************************/void preserve_outline(EDGEPT *start) { EDGEPT *srcpt; if (start == NULL) return; srcpt = start; do { srcpt->flags[1] = 1; srcpt = srcpt->next; } while (srcpt != start); srcpt->flags[1] = 2;}/**************************************************************************/void preserve_outline_tree(TESSLINE *srcline) { TESSLINE *outline; for (outline = srcline; outline != NULL; outline = outline->next) { preserve_outline (outline->loop); } if (srcline->child != NULL) preserve_outline_tree (srcline->child);}/********************************************************************** * restore_outline_tree * * Copy the list of outlines. **********************************************************************/EDGEPT *restore_outline(EDGEPT *start) { EDGEPT *srcpt; EDGEPT *real_start; EDGEPT *deadpt; if (start == NULL) return NULL; srcpt = start; do { if (srcpt->flags[1] == 2) break; srcpt = srcpt->next; } while (srcpt != start); real_start = srcpt; do { if (srcpt->flags[1] == 0) { deadpt = srcpt; srcpt = srcpt->next; srcpt->prev = deadpt->prev; deadpt->prev->next = srcpt; deadpt->prev->vec.x = srcpt->pos.x - deadpt->prev->pos.x; deadpt->prev->vec.y = srcpt->pos.y - deadpt->prev->pos.y; oldedgept(deadpt); } else srcpt = srcpt->next; } while (srcpt != real_start); return real_start;}/******************************************************************************/void restore_outline_tree(TESSLINE *srcline) { TESSLINE *outline; for (outline = srcline; outline != NULL; outline = outline->next) { outline->loop = restore_outline (outline->loop); outline->start = outline->loop->pos; } if (srcline->child != NULL) restore_outline_tree (srcline->child);}/********************************************************************** * attempt_blob_chop * * Try to split the this blob after this one. Check to make sure that * it was successful. **********************************************************************/SEAM *attempt_blob_chop(TWERD *word, INT32 blob_number, SEAMS seam_list) { TBLOB *blob; TBLOB *other_blob; SEAM *seam; TBLOB *last_blob; TBLOB *next_blob; INT16 x; if (first_pass) chops_attempted1++; else chops_attempted2++; last_blob = NULL; blob = word->blobs; for (x = 0; x < blob_number; x++) { last_blob = blob; blob = blob->next; } next_blob = blob->next; if (repair_unchopped_blobs) preserve_outline_tree (blob->outlines); other_blob = newblob (); /* Make new blob */ other_blob->next = blob->next; other_blob->outlines = NULL; blob->next = other_blob; seam = pick_good_seam (blob); if (chop_debug) { if (seam != NULL) { print_seam ("Good seam picked=", seam); } else cprintf ("\n** no seam picked *** \n"); } if (seam) { apply_seam(blob, other_blob, seam); } if ((seam == NULL) || (blob->outlines == NULL) || (other_blob->outlines == NULL) || total_containment (blob, other_blob) || check_blob (other_blob) || !(check_seam_order (blob, seam) && check_seam_order (other_blob, seam)) || any_shared_split_points (seam_list, seam) || !test_insert_seam(seam_list, blob_number, blob, word->blobs)) { blob->next = next_blob; if (seam) { undo_seam(blob, other_blob, seam); delete_seam(seam);#ifndef GRAPHICS_DISABLED if (chop_debug) { display_blob(blob, Red); cprintf ("\n** seam being removed ** \n"); }#endif } else { oldblob(other_blob); } if (repair_unchopped_blobs) restore_outline_tree (blob->outlines); return (NULL); } return (seam);}/********************************************************************** * any_shared_split_points * * Return true if any of the splits share a point with this one. **********************************************************************/int any_shared_split_points(SEAMS seam_list, SEAM *seam) { int length; int index; length = array_count (seam_list); for (index = 0; index < length; index++) if (shared_split_points ((SEAM *) array_value (seam_list, index), seam)) return TRUE; return FALSE;}/********************************************************************** * check_blob * * Return true if blob has a non whole outline. **********************************************************************/int check_blob(TBLOB *blob) { TESSLINE *outline; EDGEPT *edgept; for (outline = blob->outlines; outline != NULL; outline = outline->next) { edgept = outline->loop; do { if (edgept == NULL) break; edgept = edgept->next; } while (edgept != outline->loop); if (edgept == NULL) return 1; } return 0;}/********************************************************************** * improve_one_blob * * Start with the current word of blobs and its classification. Find * the worst blobs and try to divide it up to improve the ratings. *********************************************************************/CHOICES_LIST improve_one_blob(TWERD *word, CHOICES_LIST char_choices, int fx, INT32 *blob_number, SEAMS *seam_list, DANGERR *fixpt, STATE *this_state, STATE *correct_state, INT32 pass) { TBLOB *pblob; TBLOB *blob; INT16 x = 0; float rating_ceiling = MAX_FLOAT32; CHOICES answer; SEAM *seam; do { *blob_number = select_blob_to_split (char_choices, rating_ceiling); if (*blob_number == -1) return (NULL); seam = attempt_blob_chop (word, *blob_number, *seam_list); if (seam != NULL) break; /* Must split null blobs */ answer = (CHOICES) array_value (char_choices, *blob_number); if (answer == NIL) return (NULL); /* Try different blob */ rating_ceiling = best_probability (answer); } while (!blob_skip); /* Split OK */ for (blob = word->blobs, pblob = NULL; x < *blob_number; x++) { pblob = blob; blob = blob->next; } *seam_list = insert_seam (*seam_list, *blob_number, seam, blob, word->blobs); free_choices ((CHOICES) array_value (char_choices, *blob_number)); answer = classify_blob (pblob, blob, blob->next, NULL, fx, "improve 1:", Red, this_state, correct_state, pass, *blob_number); char_choices = array_insert (char_choices, *blob_number, answer); answer = classify_blob (blob, blob->next, blob->next->next, NULL, fx, "improve 2:", Yellow, this_state, correct_state, pass, *blob_number + 1); array_value (char_choices, *blob_number + 1) = (char *) answer; return (char_choices);}/********************************************************************** * check_seam_order * * Make sure that each of the splits in this seam match to outlines * in this blob. If any of the splits could not correspond to this * blob then there is a problem (and FALSE should be returned to the * caller). **********************************************************************/INT16 check_seam_order(TBLOB *blob, SEAM *seam) { TESSLINE *outline; TESSLINE *last_outline; INT8 found_em[3]; if (seam->split1 == NULL || seam->split1 == NULL || blob == NULL) return (TRUE); found_em[0] = found_em[1] = found_em[2] = FALSE; for (outline = blob->outlines; outline; outline = outline->next) { if (!found_em[0] && ((seam->split1 == NULL) || is_split_outline (outline, seam->split1))) { found_em[0] = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -