00001 #include "BrickOps.h"
00002 #include "visops.h"
00003
00004 using namespace std;
00005
00006 namespace DualCoding {
00007
00008
00009
00010
00011
00012 Point findEdgePoint(Point start, Point end, Sketch<bool>& rendering)
00013 {
00014 int gap_tolerance=2;
00015
00016 float startx = start.coordX();
00017 float starty = start.coordY();
00018 float dx = end.coordX() - startx;
00019 float dy = end.coordY() - starty;
00020
00021 float dist = sqrt(dx*dx + dy*dy);
00022 dx = dx/dist;
00023 dy = dy/dist;
00024 int maxi=0, gap=0;
00025 int x,y;
00026 for (int i=0; i<dist; i++) {
00027 x = (int)(startx+i*dx);
00028 y = (int)(starty+i*dy);
00029 if (rendering(x,y)) {
00030 maxi = i;
00031 gap = 0;
00032 }
00033 else
00034 gap++;
00035 if (gap>gap_tolerance)
00036 break;
00037 }
00038 float fx = startx+maxi*dx;
00039 float fy = starty+maxi*dy;
00040 Point result(fx,fy);
00041 return result;
00042 }
00043
00044
00045
00046
00047
00048
00049
00050 int findRadialDistancesFromPoint(Point center, float radius,
00051 Sketch<bool>& rendering,
00052 float distances[],
00053 std::vector<Point>& points)
00054 {
00055 NEW_SKETCH(circle, bool, visops::zeros(rendering));
00056
00057 int maxi = 0, origmaxi = 0;
00058 float max = -1;
00059 bool stillmax = false;
00060 Point edge;
00061 for (int i=0; i<2*M_PI*radius; i++){
00062 float x = center.coordX()+radius*cos(i/radius);
00063 float y = center.coordY()+radius*sin(i/radius);
00064 if (x<0) x = 0;
00065 else if (x>=rendering->getWidth()) x = rendering->getWidth()-1;
00066 if (y<0) y = 0;
00067 else if (y>=rendering->getHeight()) y = rendering->getHeight()-1;
00068 edge.setCoords(x,y,0);
00069 circle->at((int)(edge.coordX()), (int)(edge.coordY())) = 1;
00070 points[i] = findEdgePoint(center,edge, rendering);
00071 distances[i] = points[i].distanceFrom(center);
00072 if (distances[i] > max) {
00073 max = distances[i];
00074 maxi = i;
00075 origmaxi = i;
00076 stillmax = true;
00077 }
00078 else if (distances[i] == max && stillmax) {
00079 maxi = (origmaxi + i) / 2;
00080 }
00081 else {
00082 stillmax = false;
00083 }
00084
00085 }
00086
00087 return maxi;
00088 }
00089
00090
00091
00092
00093
00094 void takeDerivative(float x[], float dx[], int len)
00095 {
00096 for (int i=0; i<len; i++) {
00097 dx[i] = x[(i+1)%len]+x[(i+2)%len]-x[(i-1+len)%len]-x[(i-2+len)%len];
00098 }
00099 }
00100
00101
00102
00103
00104 void applyGaussian(float x[], float gx[], int len)
00105 {
00106 int smooth_n = 5;
00107 float smooth_x = .2f;
00108 for (int i=0; i<len; i++) {
00109 gx[i] = 0;
00110 for (int j=0; j<smooth_n; j++) {
00111 gx[i]+=x[(i+len+j-smooth_n/2)%len]*smooth_x;
00112 }
00113 }
00114 }
00115
00116
00117
00118
00119
00120
00121 void drawHist(float distances[], unsigned int len, Sketch<bool>& parent)
00122 {
00123 float xscale = 1;
00124 if (len > parent->getWidth() - 20) xscale = (parent->getWidth()-20)/(1.0f*len);
00125 float ymax = 0;
00126 for (unsigned int i=0; i<len; i++)
00127 ymax = max(ymax,abs(distances[i]));
00128 int const yscale = 2;
00129 ymax *= yscale;
00130 int const maxheight = 70;
00131 float const yshrink = (ymax > maxheight) ? maxheight/ymax : 1.0f;
00132
00133 NEW_SKETCH(hist,bool, visops::zeros(parent));
00134 for(unsigned int i=0; i<len; i++) {
00135 if (distances[i] > 0) {
00136 for (unsigned int j=0; j<yscale*distances[i]; j++) {
00137 hist->at((int)(i*xscale+10), (int)(maxheight - j*yshrink + 5)) = 1;
00138 }
00139 }
00140 else {
00141 for (int j=-1; j>yscale*distances[i]; j--) {
00142 hist->at((int)(i*xscale+10), (int)(maxheight - j*yshrink + 5)) = 1;
00143 }
00144 }
00145 }
00146
00147 hist->at(5,(int)(maxheight*(1-yshrink)+5)) = 1;
00148 hist->at(5,(int)(maxheight*(1+yshrink)+5)) = 1;
00149 hist->at(203,(int)(maxheight*(1-yshrink)+5)) = 1;
00150 hist->at(203,(int)(maxheight*(1+yshrink)+5)) = 1;
00151
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 float getBoundingQuadrilateralScore(BlobData &blob, vector<Point>& corners,
00167 Sketch<bool> edgeImage,
00168 int& borderCount, ShapeSpace &space)
00169 {
00170 const float EDGE_SCALAR = 50;
00171
00172 borderCount = countBorderPixelFit(blob, corners, edgeImage, space);
00173 return getQuadrilateralArea(corners) - EDGE_SCALAR*borderCount;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 float getQuadrilateralArea(vector<Point>& corners)
00186 {
00187 float totalArea = 0;
00188 for (unsigned int i=2; i<corners.size(); i++) {
00189 float e1 = corners[0].distanceFrom(corners[i-1]);
00190 float e2 = corners[i-1].distanceFrom(corners[i]);
00191 float diag = corners[0].distanceFrom(corners[i]);
00192 float s1 = (e1+e2+diag)/2.0f;
00193 totalArea += sqrt(s1*(s1-e1)*(s1-e2)*(s1-diag));
00194 }
00195
00196 return totalArea;
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206 float getBoundingQuadrilateralInteriorPointRatio(BlobData &blob,
00207 vector<Point>& corners,
00208 ShapeSpace &space)
00209 {
00210 int ncorners = corners.size();
00211
00212 vector<LineData> lines;
00213 for (int i=0; i<ncorners; i++) {
00214 lines.push_back(LineData(space,corners[(i+1)%ncorners], corners[(i+2)%ncorners]));
00215 }
00216
00217 int totalInside = 0;
00218 int totalPixelArea = 0;
00219
00220 for ( std::vector<BlobData::run>::const_iterator it = blob.runvec.begin();
00221 it != blob.runvec.end(); it++ ) {
00222 const BlobData::run &r = *it;
00223 int const xstop = r.x + r.width;
00224
00225 totalPixelArea += r.width;
00226
00227 Point p1(r.x,r.y);
00228 Point p2(xstop, r.y);
00229
00230
00231 bool pt1Inside = true, pt2Inside = true;
00232 for (int i=0; i<ncorners; i++) {
00233 if (!lines[i].pointsOnSameSide(p1,corners[i])) {
00234 pt1Inside = false;
00235 break;
00236 }
00237 }
00238 for (int i=0; i<ncorners; i++) {
00239 if (!lines[i].pointsOnSameSide(p2,corners[i])) {
00240 pt2Inside = false;
00241 break;
00242 }
00243 }
00244
00245
00246 if (pt1Inside) {
00247 if (pt2Inside) {
00248 totalInside += r.width;
00249 }
00250 else {
00251
00252
00253
00254 totalInside++;
00255 for (int x=xstop-1; x>r.x; x--) {
00256 Point p(x,r.y);
00257 bool ptInside = true;
00258 for (int i=0; i<ncorners; i++) {
00259 if (!lines[i].pointsOnSameSide(p,corners[i])) {
00260 ptInside = false;
00261 break;
00262 }
00263 }
00264 if (ptInside) {
00265 totalInside+=x-r.x;
00266 break;
00267 }
00268 }
00269 }
00270 }
00271 else {
00272
00273 if (pt2Inside) {
00274 totalInside++;
00275 for (int x=r.x+1; x<xstop; x++) {
00276 Point p(x,r.y);
00277 bool ptInside = true;
00278 for (int i=0; i<ncorners; i++) {
00279 if (!lines[i].pointsOnSameSide(p,corners[i])) {
00280 ptInside = false;
00281 break;
00282 }
00283 }
00284 if (ptInside) {
00285 totalInside+=xstop-x;
00286 break;
00287 }
00288 }
00289 }
00290 else {
00291
00292 bool beenInside = false;
00293 int xstart = xstop;
00294 for (int x=r.x+1; x<xstop; x++) {
00295 Point p(x,r.y);
00296 bool ptInside = true;
00297 for (int i=0; i<ncorners; i++) {
00298 if (!lines[i].pointsOnSameSide(p,corners[i])) {
00299 ptInside = false;
00300 break;
00301 }
00302 }
00303 if (ptInside) {
00304 xstart = x;
00305 beenInside = true;
00306 break;
00307 }
00308 }
00309 if (beenInside) {
00310 for (int x=xstop-1; x>=xstart; x--) {
00311 Point p(x,r.y);
00312 bool ptInside = true;
00313 for (int i=0; i<ncorners; i++) {
00314 if (!lines[i].pointsOnSameSide(p,corners[i])) {
00315 ptInside = false;
00316 break;
00317 }
00318 }
00319 if (ptInside) {
00320 totalInside+=x-xstart+1;
00321 break;
00322 }
00323 }
00324 }
00325 }
00326 }
00327
00328 }
00329
00330
00331 return totalInside*1.0f/totalPixelArea;
00332 }
00333
00334
00335
00336
00337
00338 int countBorderPixelFit(BlobData &blob, const vector<Point> &corners,
00339 Sketch<bool> edges, ShapeSpace &space)
00340 {
00341 int ncorners = corners.size();
00342
00343 vector<LineData> lines;
00344 vector<float> dx, dy;
00345 for (int i=0; i<ncorners; i++) {
00346 lines.push_back(LineData(space, corners[(i+1)%ncorners], corners[(i+2)%ncorners]));
00347 }
00348
00349 int count = 0;
00350
00351 for (int x=max((int)blob.topLeft.coordX()-5,0); x<=min((int)blob.topRight.coordX()+5,edges.width); x++) {
00352 for (int y=max((int)blob.topLeft.coordY()-5,0); y<=min((int)blob.bottomRight.coordY()+5,edges.height); y++) {
00353 if (edges(x,y)) {
00354 Point p(x,y);
00355 bool onLine = false;
00356 for (int i=0; i<ncorners; i++) {
00357 if (lines[i].pointOnLine(p)) {
00358 onLine = true;
00359 break;
00360 }
00361 }
00362 if (onLine)
00363 count++;
00364 }
00365 }
00366 }
00367
00368 return count;
00369 }
00370
00371
00372
00373
00374
00375
00376 int pickMove(vector<float> scores, float weight)
00377 {
00378 unsigned int i;
00379 float min = scores[0], max = scores[0];
00380 for (i=1; i<scores.size(); i++) {
00381 if (scores[i] < min)
00382 min = scores[i];
00383 else if (scores[i] > max)
00384 max = scores[i];
00385 }
00386
00387 max -= min;
00388 for (i=0; i<scores.size(); i++) {
00389 scores[i]-=min;
00390 if (max > 0) {
00391 scores[i]*=weight/max;
00392 }
00393 }
00394
00395 vector<float> exps;
00396 float expsum = 0;
00397 for (i=0; i<scores.size(); i++) {
00398 float curexp = exp(-scores[i]);
00399 exps.push_back(curexp);
00400 expsum+=curexp;
00401 }
00402
00403 for (i=0; i<scores.size(); i++) {
00404 exps[i]/=expsum;
00405 }
00406
00407 float randval = (rand()%1000000)/1000000.0f;
00408
00409 for (i=0; i<scores.size(); i++) {
00410 randval -= exps[i];
00411 if (randval <= 0)
00412 return i;
00413 }
00414
00415 return -1;
00416 }
00417
00418
00419 }
00420