// -*- C++ -*- // Copyright 2006-2008 Deutsches Forschungszentrum fuer Kuenstliche Intelligenz // or its licensors, as applicable. // // You may not use this file except under the terms of the accompanying license. // // 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. // // Project: OCRopus // File: ocr-char-stats.cc // Purpose: calculate character statistics from bounding boxes // Responsible: Faisal Shafait (faisal.shafait@dfki.de) // Reviewer: // Primary Repository: // Web Sites: www.iupr.org, www.dfki.de #include "colib.h" #include "imgio.h" #include "imglib.h" #include "quicksort.h" #include "ocr-layout-rast.h" using namespace ocropus; using namespace iulib; using namespace colib; namespace ocropus { extern param_int debug_layout; void sort_boxes_by_x0(rectarray &boxes) { int len = boxes.length(); if(!len) return; intarray values,index; makelike(values,boxes); for(int i=0; i=maxval) continue; hist[int(distances[i])]++; } } static void calc_hist(floatarray &hist, floatarray &distances){ float maxval=-10000; int len = distances.length(); for(int i=0; i= b.x0) && (b.x1 >= a.x0) ); } static inline bool y_overlap(rectangle a, rectangle b){ return ( (a.y1 >= b.y0) && (b.y1 >= a.y0) ); } static void calc_distances(floatarray &hdist, floatarray &vdist, rectarray &cboxes){ int num_chars = cboxes.length(); float maxdist = 200; float temp = 0,minhdist,minvdist; int start; //Start with i=1 to skip first bounding box which is page size. start = ( (cboxes[0].x0==0) && (cboxes[0].y0==0) ) ? 1 : 0; for(int i=start; i< num_chars; i++){ rectangle r = cboxes[i]; minhdist = 10000; minvdist = 10000; for(int j=start; j< num_chars; j++){ rectangle cand = cboxes[j]; if(y_overlap(r,cand) && (cand.x0 > r.x1)){ temp = cand.x0 - r.x1; if(temp < minhdist) minhdist = temp; } if(x_overlap(r,cand) && (cand.y0 > r.y1)){ temp = cand.y0 - r.y1; if(temp < minvdist) minvdist = temp; } } if(minhdist && (minhdist=2){ printf("x-mode = %d, y-mode =%d, x-peak = %.2f, y-peak=%.2f\n", xmode,ymode,xhist[xmode],yhist[ymode]); } int minarea = ymode*2; int mindotarea = ymode/3; int maxaspect = 10; int maxheight = ymode*10; int maxwidth = xmode*10; int minheight = ymode>>1; int minwidth = xmode>>1; for(int i=0;imindotarea) dot_boxes.push(concomps[i]); continue; } if(bwmaxaspect || bh/bw>maxaspect || bw>maxwidth || bh>maxheight){ large_boxes.push(concomps[i]); continue; } char_boxes.push(rectangle(concomps[i])); } } void CharStats::calcCharStats(){ calcCharStats(char_boxes); } void CharStats::calcCharStats(rectarray &cboxes){ if(!cboxes.length()){ fprintf(stderr,"No character boxes found! ...\n"); return ; } xheight = calc_xheight(cboxes); sort_boxes_by_y0(cboxes); floatarray vdist,hdist; floatarray vhist,hhist; float maxdist = 200; float smooth = 2.0; calc_distances(hdist, vdist, cboxes); calc_hist(hhist, hdist); calc_hist(vhist, vdist); gauss1d(hhist,smooth); gauss1d(vhist,smooth); intarray modes; peaks(modes, hhist, 1, int(maxdist)); if(modes.length()<2){ if(debug_layout) fprintf(stderr,"Warning: No peaks found in character spacing histogram!\n"); char_spacing = xheight / 4; word_spacing = xheight / 2; } else{ char_spacing = modes[0]; word_spacing = modes[1]; } float mv = -1; for(int i=0, l=vhist.length(); i mv){ mv = vhist[i]; line_spacing = i; } } } void CharStats::calcCharStatsForOneLine(){ calcCharStatsForOneLine(char_boxes); } void CharStats::calcCharStatsForOneLine(rectarray &cboxes){ if(!cboxes.length()){ fprintf(stderr,"No character boxes found! ...\n"); return ; } xheight = calc_xheight(cboxes); sort_boxes_by_x0(cboxes); floatarray hdist,vdist; floatarray hhist; float maxdist = 200; calc_distances(hdist, vdist, cboxes); calc_hist(hhist, hdist); intarray modes; peaks(modes, hhist, 1, int(maxdist)); if(modes.length()<2){ if(debug_layout) fprintf(stderr,"Warning: No peaks found in character spacing histogram!\n"); char_spacing = xheight / 4; word_spacing = xheight / 2; } else{ char_spacing = modes[0]; word_spacing = modes[1]; } } void CharStats::print() { printf("Image Size = %d x %d\n",img_width,img_height); printf("xheight = %d\n",xheight); printf("Char spacing = %d\n",char_spacing); printf("Word spacing = %d\n",word_spacing); printf("Line spacing = %d\n",line_spacing); printf("Number of Characters = %d\n",char_boxes.length()); printf("Number of dots = %d\n",dot_boxes.length()); printf("Number of large components = %d\n",large_boxes.length()); } CharStats *make_CharStats() { return new CharStats(); } CharStats *make_CharStats(CharStats &c) { return new CharStats(c); } }