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