#include #include #include #include #include #include "common.h" #include "memmgr.h" #include "bboxfeat.h" #define OverlapBins 1 //#define OverlapBins 2 #define RatioBins 11 #define StrokeBins 8 #define SpaceBins 1 //#define SpaceBins 5 // All unary feature bins should fall in the range 0<=bin=0); ASSERT(denom>=0); if (denom>num*8) return 0; if (denom>num*4) return 1; if (denom>num*3) return 2; if (denom>num*2) return 3; if (denom*2>num*3) return 4; if (num>denom*8) return 10; if (num>denom*4) return 9; if (num>denom*3) return 8; if (num>denom*2) return 7; if (num*2>denom*3) return 6; return 5; } /* int ScoreToFeature(FLOAT score) { int iScore=(int)floor(-score); if (iScore<0) iScore=0; if (iScore>=ScoreBins) iScore=ScoreBins-1; return iScore; } */ // Convert a stroke count to a feature number from 0 to 6 (inclusive) int StrokeCountToFeature(int nStrokes) { ASSERT(nStrokes>=1); if (nStrokes==1) return 0; if (nStrokes==2) return 1; if (nStrokes==3) return 2; if (nStrokes==4) return 3; if (nStrokes<=8) return 4; if (nStrokes<=16) return 5; if (nStrokes<=32) return 6; return 7; } // Convert an aspect ratio to a feature number int AspectRatioToFeature(RECT r) { ASSERT(r.left<=r.right); ASSERT(r.top<=r.bottom); return RatioToFeature((float)r.right-r.left+1,(float)r.bottom-r.top+1); } // Convert a ratio which has the range 0 to 1 to a feature number of 0 to 4 inclusive int FractionToFeature(int num, int denom) { return 0; if (5*num<=1*denom) return 0; if (5*num<=2*denom) return 1; if (5*num<=3*denom) return 2; if (5*num<=4*denom) return 3; return 4; } // A binary overlap feature: 1 if overlapped, 0 otherwise int OverlapRatioToFeature(RECT r1, RECT r2) { return 0; if (r1.left>r2.right || r1.rightr2.bottom || r1.bottom=0 && matchSpace<32); if (iScore<0) iScore=0; if (nStrokes<3) iScore/=10; if (iScore>=ScoreBins) iScore=ScoreBins-1; if (nStrokes<3) return matchSpace*ScoreBins+iScore; else return (matchSpace+32)*ScoreBins+iScore; } // Returns the unary feature bin of one range of the ink, from index iStart<=index0); bin=StrokeBins*RatioBins*FractionToFeature(stats->space,stats->area)+StrokeBins*AspectRatioToFeature(stats->rect)+StrokeCountToFeature(nStrokes); ASSERT(bin>=0 && bin0); ASSERT(nStrokes2>0); bin= RatioBins*StrokeBins*StrokeBins*OverlapBins*RatioBins*FractionToFeature(stats2->space,stats2->area)+ RatioBins*StrokeBins*StrokeBins*OverlapBins*AspectRatioToFeature(stats2->rect)+ RatioBins*StrokeBins*StrokeBins*OverlapRatioToFeature(stats1->rect,stats2->rect)+ StrokeBins*StrokeBins*SizeRatioToFeature(stats1->rect,stats2->rect)+ StrokeBins*StrokeCountToFeature(nStrokes1)+ StrokeCountToFeature(nStrokes2); ASSERT(bin>=0 && bin=0); ASSERT(denom>=0); if (denom==0) return Log2Range; if (num==0) return Log2Range; ratio=(double)num/(double)denom; val=log(ratio)/log(2.0); if (val0) val=0; return (int)floor(val+0.5); } PROB ClippedLog2Threshold(COUNTER num, COUNTER denom, COUNTER threshold) { ASSERT(num>=0); ASSERT(denom>=0); if (numnumIntervals=0; intervals->minRange=min; intervals->maxRange=max; } // Add a given range of ink to the interval structure. void ExpandIntervalsRange(INTERVALS *intervals, int min, int max) { int i; ASSERT(intervals!=NULL); ASSERT(min<=max); // If the added range extends beyond the minimum of the current range, then // extend. if (minminRange) { // Find the free interval that touches the current minimum BOOL minFound=FALSE; for (i=0; inumIntervals; i++) { if (intervals->min[i]==intervals->minRange) { // When found, extend it. intervals->min[i]=min; minFound=TRUE; } } // If there wasn't a free interval touching the boundary, then // make one to account for the extra space if (!minFound) { intervals->min[intervals->numIntervals]=min; intervals->max[intervals->numIntervals]=intervals->minRange-1; intervals->numIntervals++; } // Extend the range of the interval set. intervals->minRange=min; } // If the added range extends beyond the maximum of the current range, // then extend. if (max>intervals->maxRange) { // Find the free interval that touches the current maximum BOOL maxFound=FALSE; for (i=0; inumIntervals; i++) { if (intervals->max[i]==intervals->maxRange) { // When found, extend it. intervals->max[i]=max; maxFound=TRUE; } } // If there wasnt' a free interval touching the boundary, then // make one to accoutn for the extra space. if (!maxFound) { intervals->min[intervals->numIntervals]=intervals->maxRange+1; intervals->max[intervals->numIntervals]=max; intervals->numIntervals++; } // Extend the range of the interval set. intervals->maxRange=max; } } // Remove a given range of ink from the interval structure. void RemoveInterval(INTERVALS *intervals, int min, int max) { int i; ASSERT(intervals!=NULL); ASSERT(min<=max); // Scan through all the free intervals currently in the set. for (i=0; inumIntervals; i++) { // No overlap case if (min>intervals->max[i] || maxmin[i]) { continue; } // Complete overlap case: delete interval if (min<=intervals->min[i] && max>=intervals->max[i]) { int nMove=intervals->numIntervals-i-1; if (nMove>0) { memmove(intervals->min+i,intervals->min+i+1,nMove*sizeof(int)); memmove(intervals->max+i,intervals->max+i+1,nMove*sizeof(int)); } intervals->numIntervals--; i--; continue; } // Complete overlap case: break free interval in two if (min>intervals->min[i] && maxmax[i]) { intervals->min[intervals->numIntervals]=max+1; intervals->max[intervals->numIntervals]=intervals->max[i]; intervals->max[i]=min-1; intervals->numIntervals++; continue; } // Min side overlapped if (min<=intervals->min[i] && maxmax[i]) { intervals->min[i]=max+1; continue; } // Max side overlapped if (min>intervals->min[i] && max>=intervals->max[i]) { intervals->max[i]=min-1; continue; } } #ifdef DBG for (i=0; inumIntervals; i++) { ASSERT(min>intervals->max[i] || maxmin[i]); } #endif } // Get the total range of the interval set int TotalRange(INTERVALS *intervals) { ASSERT(intervals!=NULL); return intervals->maxRange-intervals->minRange+1; } // Get the total amount of free space in the interval set int TotalPresent(INTERVALS *intervals) { int i, total; ASSERT(intervals!=NULL); total=0; for (i=0; inumIntervals; i++) { total += intervals->max[i]-intervals->min[i]+1; } return total; } // Test two rectangles for overlap (duplicates a system provided function) BOOL Overlapping(RECT r1, RECT r2) { if (r1.left>r2.right || r1.rightr2.bottom || r1.bottom