// Deductor.cpp -- Analysis of 1D Mondrian scenes with integer values using an interval approach // // // DESCRIPTION // // Copyright © Tim Bahls, Daniel Scharstien 2003. // /////////////////////////////////////////////////////////////////////////// #pragma once #include "Error.h" #include "Image.h" #include "Color.h" #include "Deductor.h" #ifndef UNKNOWN #define UNKNOWN -9876 #define UNKNOWNF -9876.5f #define MAX 1234.5f #define MIN -1234.5f #ifndef WIN32 #define __max(a,b) (((a) > (b)) ? (a) : (b)) #define __min(a,b) (((a) < (b)) ? (a) : (b)) #endif #endif #define MINVEL -4 #define MAXVEL 4 #define MINLEN 6 #define MAXLEN 299 /////////////////////////////////////////////////////////////////////////// // class CRegion - a single region CRegion::CRegion(int iid, int inFrames) { id = iid; minVel=MINVEL; maxVel=MAXVEL; minLen=MINLEN; maxLen=MAXLEN; nFrames=inFrames; xmins=new int[nFrames]; for(int i=0; i0){ //delete [] relative; //} relative=c; } //returns the id of the color int CDeductor::getPixID(int row, int col){ CCol *c=(CCol*)&im.Pixel(col,row,0); //notice switch CCol cc=*c; int a= cc.getId(); if (a>maxID){ addid(a); } if(region[a]==null){ region[a]=CRegion(a,nFrames); nRegions++; } return a; } // create new region if necessary, add a new component, and record its left edge void CDeductor::startRegion(int id, int frame, int x, int prevID) { if(region[id].xmins[frame]==UNKNOWN){ region[id].xmins[frame]=x; region[id].leftIDs[frame]=prevID; region[id].maxmin[frame]=(float)x; } } // record right boundary of current region void CDeductor::endRegion(int id, int frame, int x, int nextID) { region[id].xmaxes[frame]=x; region[id].rightIDs[frame]=nextID; region[id].minmax[frame]=(float)x; } // read a frame: look at all pixels in center scanline and initialize / update // regions and their edges void CDeductor::readFrame(CByteImage iim, int frame) { im=iim; CShape sh = im.Shape(); int w = sh.width, h = sh.height; maxWidth=w; data[frame]=new int[w]; int row=h/2; int oldid = getPixID(row,0); startRegion(oldid, frame, 0, -1); data[frame][0]=oldid; for (int x = 1; x < w; x++) { int newid = getPixID(row,x); data[frame][x]=newid; if(newid!=oldid){ endRegion(oldid, frame, x-1, newid); startRegion(newid, frame, x, oldid); oldid = newid; } } //update last extent: endRegion(oldid, frame, w-1, -1); } void CDeductor::printData() { printf("%d regions observed\n", nRegions); for (int i=0; i <= maxID; i++) { if (region[i]==null) continue; printf(" "); p(i); printf(":"); CRegion r = region[i]; for (int f=0; f < nFrames; f++) { printf(" f%d:", f); if(r.xmins[f]==UNKNOWN) continue; printf("%d-%d,", r.xmins[f],r.xmaxes[f]); } printf("\n"); } } void CDeductor::checkTripletForQuadT(int i, int f1, int f2,int f3, int *minmax,int*rightleft) { int x1=minmax[f1]; int x2=minmax[f2]; int x3=minmax[f3]; // check if motion is consistent over three frames int x21 = x2-x1; int x31 = x3-x1; int f21 = f2-f1; int f31 = f3-f1; if (f21*x31 != f31*x21) return; int edgeVel = x21/f21; int id1=rightleft[f1]; int id2=rightleft[f2]; int id3=rightleft[f3]; if (id1 < 0 || id2 < 0 || id3 < 0) return; if (id1 == id2 && id2 != id3){ for(int f4=f3+1;f4=nFrames||r2.rightIDs[f1]!=i||r2.rightIDs[f2]!=i) continue; float edgeVel=(float)(r1.xmins[f2]-r1.xmins[f1])/(float)(f2-f1); int pos=r1.xmins[f1]; for(int f=0;f=maxWidth)// so both x2 and x2-1 are on image continue; int id1=data[f][loc-1]; int id2=data[f][loc]; if(id1==id2&&id2!=i){ change|=setCloser(id1,i); change|=setCloser(id1,j); } } } } } void CDeductor::possibilityElimination(){ //if(verbose) //printf("Possibility Elimination:\n"); for (int i=0; i <= maxID; i++) { CRegion r=region[i]; if (r==null) continue; bool change2=true; while(change2==true){ change2=false; change2|=region[i].restrictPosition(); change2|=region[i].restrictVel(); change2|=region[i].restrictLen(); change|=change; } } } void CDeductor::occlusionDetection(){ if(verbose) printf("Occlusion Detection:\n"); for (int i=0; i <= maxID; i++) { CRegion r=region[i]; if (r==null) continue; for(int f=0; f=end1;x--){ if(compare(i,data[f][x])==2){ r.minmin[f]=(float)(x+1);//if i extended this far, it would've been found. Thus it doesn't. change=true; break; } } int start2=(int)r.minmax[f]; start2=__max(start2,0); start2=__max(start2,(int)r.maxmin[f]); int end2=(int)r.maxmax[f]; end2=__min(end2,(int)maxWidth-1); for(int x=start2;x<=end2;x++){ if(compare(i,data[f][x])==2){ r.maxmax[f]=(float)(x-1);//if i extended this far, it would've been found. Thus it doesn't. change=true; break; } } if(r.maxmin[f]==MAX||r.maxmin[f]==MIN) continue; for(int x=__max(0,(int)(r.maxmin[f]));x<=__min((int)(r.minmax[f]),maxWidth-1);x++){ int id=data[f][x]; if(id!=i){ change|=setCloser(id,i); } } } } } //like it sounds void CDeductor::transitiveClosure() { if(verbose) printf("Computing Transitive closure:\n"); bool newEdge = true; while (newEdge) { newEdge = false; for (int i=0; i <= maxID; i++) { if (region[i]==null) continue; for (int j=0; j <= maxID; j++) { if(compare(i,j)==2){//definite for (int k=0; k <= maxID; k++) { if(compare(j,k)==2&&i!=k){//definite newEdge |= setCloser(i,k);//definite change |=newEdge; } } } } } } } void CDeductor::reportResults() { printf("\nResults: %d regions observed\n", nRegions); for (int i=0; i <= maxID; i++) { CRegion r=region[i]; if (r==null) continue; printf(" "); p(i); printf(": v"); if(r.minVel==r.maxVel){ printf(":%2d=%2d", (int)r.minVel,(int)r.maxVel); }else{ printf(":%2d~%2d",(int)r.minVel,(int)r.maxVel); } printf(" l"); if(r.minLen==r.maxLen){ printf(":%3d=%3d", (int)r.minLen,(int)r.maxLen); }else{ printf(":%3d~%3d",(int)r.minLen,(int)r.maxLen); } printf(" Over: "); for (int j=0; j <= maxID; j++) { if(compare(i,j)==2){ p(j); printf(" "); } } printf("\n"); } } // infer depth ordering, lengths and motion int CDeductor::goGoGo() { times=0; quadT(); extendedT(); while (change) { change = false; occlusionDetection(); possibilityElimination(); transitiveClosure(); } for (int i=0; i <= maxID; i++) { for (int j=0; j <= maxID; j++) { if(compare(i,j)==2) times++; } } if(verbose) reportResults(); return times; } void CDeductor::checkAccuracy(CScene scene) { for (int i=1; i <= maxID; i++) { CRegion reg=region[i]; if (reg==null) continue; CRect rect=scene.getByID(i); if(rect.vel.x>reg.maxVel||rect.vel.xreg.maxLen||rect.diag.xrect2.z){ verbose=true; printf("ERROR! "); p(i); printf(" doesn't beat "); p(j); printf("!\n"); throw CError("Relative Distances incorrect"); } } if(compare(0,i)==2){ verbose=true; printf("ERROR! "); p(i); printf(" doesn't beat "); p(0); throw CError("Nothing behind white"); } } if(verbose) printf("All true\n"); }