75 for (
int blob_id = 0; blob_id < num_blobs; ++blob_id) {
83 int min_bottom, max_bottom, min_top, max_top;
89 top < min_top - x_ht_acceptance_tolerance || top > max_top + x_ht_acceptance_tolerance;
93 if (debug_x_ht_level >= 1) {
94 tprintf(
"Class %s is %s with top %d vs limits of %d->%d, +/-%d\n",
96 static_cast<int>(x_ht_acceptance_tolerance));
106 STATS top_stats(0, UINT8_MAX - 1);
107 STATS shift_stats(-UINT8_MAX, UINT8_MAX - 1);
108 int bottom_shift = 0;
113 for (
int blob_id = 0; blob_id < num_blobs; ++blob_id) {
123 int min_bottom, max_bottom, min_top, max_top;
129 int misfit_dist = std::max((min_top - x_ht_acceptance_tolerance) - top,
130 top - (max_top + x_ht_acceptance_tolerance));
132 if (debug_x_ht_level >= 2) {
133 tprintf(
"Class %s: height=%d, bottom=%d,%d top=%d,%d, actual=%d,%d: ",
135 max_top, bottom, top);
139 if (min_bottom <= bottom + x_ht_acceptance_tolerance &&
146 if (debug_x_ht_level >= 2) {
147 tprintf(
" xht range min=%d, max=%d\n", min_xht, max_xht);
151 for (
int y = min_xht;
y <= max_xht; ++
y) {
152 top_stats.
add(
y, misfit_dist);
154 }
else if ((min_bottom > bottom + x_ht_acceptance_tolerance ||
155 bottom - x_ht_acceptance_tolerance > max_bottom) &&
158 int min_shift = min_bottom - bottom;
159 int max_shift = max_bottom - bottom;
160 if (debug_x_ht_level >= 2) {
161 tprintf(
" bottom shift min=%d, max=%d\n", min_shift, max_shift);
166 int misfit_weight = abs(min_shift);
167 if (max_shift > min_shift) {
168 misfit_weight /= max_shift - min_shift;
170 for (
int y = min_shift;
y <= max_shift; ++
y) {
171 shift_stats.
add(
y, misfit_weight);
174 if (bottom_shift == 0) {
179 if (debug_x_ht_level >= 2) {
187 if (debug_x_ht_level >= 2) {
188 tprintf(
"Applying bottom shift=%d\n", bottom_shift);
193 *baseline_shift = -bottom_shift / word_res->
denorm.
y_scale();
194 if (debug_x_ht_level >= 2) {
195 tprintf(
"baseline shift=%g\n", *baseline_shift);
198 return bottom_shift != 0 ? word_res->
x_height : 0.0f;
202 float new_xht = top_stats.
median();
203 if (debug_x_ht_level >= 2) {
204 tprintf(
"Median xht=%f\n", new_xht);
205 tprintf(
"Mode20:A: New x-height = %f (norm), %f (orig)\n", new_xht,
209 if (std::fabs(new_xht -
kBlnXHeight) >= x_ht_min_change) {
212 return bottom_shift != 0 ? word_res->
x_height : 0.0f;
void tprintf(const char *format,...)
int IntCastRounded(double x)
int DivRounded(int a, int b)
const int kMaxCharTopRange
const int kBlnBaselineOffset
float ComputeCompatibleXheight(WERD_RES *word_res, float *baseline_shift)
int CountMisfitTops(WERD_RES *word_res)
TBOX bounding_box() const
std::vector< TBLOB * > blobs
unsigned NumBlobs() const
WERD_CHOICE * best_choice
UNICHAR_ID unichar_id(unsigned index) const
TDimension bottom() const
void add(int32_t value, int32_t count)
int32_t get_total() const
bool get_isalpha(UNICHAR_ID unichar_id) const
const char * id_to_unichar(UNICHAR_ID id) const
void get_top_bottom(UNICHAR_ID unichar_id, int *min_bottom, int *max_bottom, int *min_top, int *max_top) const
bool get_isdigit(UNICHAR_ID unichar_id) const