/********************************************************************** * choose_best_seam * * Choose the best seam that can be created by assembling this a * collection of splits. A queue of all the possible seams is * maintained. Each new split received is placed in that queue with * its partial priority value. These values in the seam queue are * evaluated and combined until a good enough seam is found. If no * further good seams are being found then this function returns to the * caller, who will send more splits. If this function is called with * a split of NULL, then no further splits can be supplied by the * caller. **********************************************************************/ void Wordrec::choose_best_seam(SeamQueue *seam_queue, const SPLIT *split, PRIORITY priority, SEAM **seam_result, TBLOB *blob, SeamPile *seam_pile) { SEAM *seam; char str[80]; float my_priority; /* Add seam of split */ my_priority = priority; if (split != NULL) { TPOINT split_point = split->point1->pos; split_point += split->point2->pos; split_point /= 2; seam = new SEAM(my_priority, split_point, *split); if (chop_debug > 1) seam->Print("Partial priority "); add_seam_to_queue(my_priority, seam, seam_queue); if (my_priority > chop_good_split) return; } TBOX bbox = blob->bounding_box(); /* Queue loop */ while (!seam_queue->empty()) { SeamPair seam_pair; seam_queue->Pop(&seam_pair); seam = seam_pair.extract_data(); /* Set full priority */ my_priority = seam->FullPriority(bbox.left(), bbox.right(), chop_overlap_knob, chop_centered_maxwidth, chop_center_knob, chop_width_change_knob); if (chop_debug) { sprintf (str, "Full my_priority %0.0f, ", my_priority); seam->Print(str); } if ((*seam_result == NULL || (*seam_result)->priority() > my_priority) && my_priority < chop_ok_split) { /* No crossing */ if (seam->IsHealthy(*blob, chop_min_outline_points, chop_min_outline_area)) { delete *seam_result; *seam_result = new SEAM(*seam); (*seam_result)->set_priority(my_priority); } else { delete seam; seam = NULL; my_priority = BAD_PRIORITY; } } if (my_priority < chop_good_split) { if (seam) delete seam; return; /* Made good answer */ } if (seam) { /* Combine with others */ if (seam_pile->size() < chop_seam_pile_size) { combine_seam(*seam_pile, seam, seam_queue); SeamDecPair pair(seam_pair.key(), seam); seam_pile->Push(&pair); } else if (chop_new_seam_pile && seam_pile->size() == chop_seam_pile_size && seam_pile->PeekTop().key() > seam_pair.key()) { combine_seam(*seam_pile, seam, seam_queue); SeamDecPair pair; seam_pile->Pop(&pair); // pop the worst. // Replace the seam in pair (deleting the old one) with // the new seam and score, then push back into the heap. pair.set_key(seam_pair.key()); pair.set_data(seam); seam_pile->Push(&pair); } else { delete seam; } } my_priority = seam_queue->empty() ? NO_FULL_PRIORITY : seam_queue->PeekTop().key(); if ((my_priority > chop_ok_split) || (my_priority > chop_good_split && split)) return; } }
/********************************************************************** * choose_best_seam * * Choose the best seam that can be created by assembling this a * collection of splits. A queue of all the possible seams is * maintained. Each new split received is placed in that queue with * its partial priority value. These values in the seam queue are * evaluated and combined until a good enough seam is found. If no * further good seams are being found then this function returns to the * caller, who will send more splits. If this function is called with * a split of NULL, then no further splits can be supplied by the * caller. **********************************************************************/ void choose_best_seam(SEAM_QUEUE seam_queue, SEAM_PILE *seam_pile, SPLIT *split, PRIORITY priority, SEAM **seam_result, TBLOB *blob) { SEAM *seam; TPOINT topleft; TPOINT botright; char str[80]; float my_priority; /* Add seam of split */ my_priority = priority; if (split != NULL) { seam = new_seam (my_priority, (split->point1->pos.x + split->point1->pos.x) / 2, split, NULL, NULL); if (chop_debug > 1) print_seam ("Partial priority ", seam); add_seam_to_queue (seam_queue, seam, (float) my_priority); if (my_priority > chop_good_split) return; } blob_bounding_box(blob, &topleft, &botright); /* Queue loop */ while (pop_next_seam (seam_queue, seam, my_priority)) { /* Set full priority */ my_priority = seam_priority (seam, topleft.x, botright.x); if (chop_debug) { sprintf (str, "Full my_priority %0.0f, ", my_priority); print_seam(str, seam); } if ((*seam_result == NULL || /* Replace answer */ (*seam_result)->priority > my_priority) && my_priority < chop_ok_split) { /* No crossing */ if (constrained_split (seam->split1, blob)) { delete_seam(*seam_result); clone_seam(*seam_result, seam); (*seam_result)->priority = my_priority; } else { delete_seam(seam); seam = NULL; my_priority = BAD_PRIORITY; } } if (my_priority < chop_good_split) { if (seam) delete_seam(seam); return; /* Made good answer */ } if (seam) { /* Combine with others */ if (array_count (*seam_pile) < MAX_NUM_SEAMS /*|| tessedit_truncate_chopper==0 */ ) { combine_seam(seam_queue, *seam_pile, seam); *seam_pile = array_push (*seam_pile, seam); } else delete_seam(seam); } my_priority = best_seam_priority (seam_queue); if ((my_priority > chop_ok_split) || (my_priority > chop_good_split && split)) return; } }