// Rasterizor.cpp -- Analysis of 1D Mondrian scenes // // // DESCRIPTION // // Copyright © Tim Bahls, Daniel Scharstien 2003. // /////////////////////////////////////////////////////////////////////////// #pragma once #include "Error.h" #include "Image.h" #include "Color.h" #include "Rasterizor.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 MAXSIMILARITY 15.0f; #define MINVEL -4 #define MAXVEL 4 #define MINLEN 6 #define MAXLEN 399 /////////////////////////////////////////////////////////////////////////// // class CRegRast - a single region CRegRast::CRegRast(int iid, int inFrames, int iwidth) { id = iid; minVel=MINVEL; maxVel=MAXVEL; bool*possVelInit=new bool[MAXVEL-MINVEL+1]; possVels=possVelInit-MINVEL; for(int v=MINVEL;v<=MAXVEL;v++){ possVels[v]=true; } nFrames=inFrames; xmins=new int[nFrames]; for(int i=0; i=maxWidth) continue; if(data[f2][testX]==contradict){ possVels[v]=false; a=true; } } } if(a){ for(int i=MINVEL;i<=MAXVEL;i++){ if(possVels[i]){ minVel=i; break; } } if(i>MAXVEL){ throw CError("Region %d can have no velocity from MINVEL to MAXVEL\n",i); } for(int i=MAXVEL;i>=MINVEL;i--){ if(possVels[i]){ maxVel=i; break; } } } return a; } bool CRegRast::restrictVel() { if(minVel==maxVel) return false; bool change=false; for(int f1=0; f1=maxWidth){ allYes=false; allNo=false; break; } int curr=data[f2][currX]; if (curr==0){ allYes=false; allNo=false; break; }else if(curr==1){ allNo=false; }else if(curr==-1){ allYes=false; }else{ throw CError("Wrong value"); } } if(allNo){ data[f1][x1]=-1; a=true; } if(allYes){ data[f1][x1]=1; a=true; }else{ } } return a; } bool CRegRast::restrictPosition() { bool change=false; for(int f=0; f=0;k--){ if(data[f][k]==1){ minmax=k; break; } } for(int x=maxmin;x<=minmax;x++){ if(data[f][x]==1){ //do nothing }else if(data[f][x]==0){ data[f][x]=1; a=true; }else if(data[f][x]==-1){ throw CError("This region is not convex: %d",id); }else{ printf("Screwy value for region[%d].data[%d][%d]=%d\n",id,f,x,data[f][x]); } } int minmin=maxmin-1; while(minmin>=0&&data[f][minmin]!=-1){ minmin--; } for(;minmin>=0;minmin--){ if(data[f][minmin]==-1){ //do nothing }else if(data[f][minmin]==0){ data[f][minmin]=-1; a=true; }else if(data[f][x]==1){ throw CError("This region is not convex: %d",id); }else{ printf("cScrewy value for region[%d].data[%d][%d]=%d\n",id,f,minmin,data[f][minmin]); } } int maxmax=minmax+1; while(maxmax=maxWidth||lineAt0+v*f<0){ continue; } if(data[f][lineAt0+v*f]==1){ maxmin=f; break; } } if(maxmin!=UNKNOWN){ for(int f=nFrames-1;f>=0;f--){ if(lineAt0+v*f>=maxWidth||lineAt0+v*f<0){ continue; } if(data[f][lineAt0+v*f]==1){ minmax=f; break; } } for(int f=maxmin;f<=minmax;f++){ if(data[f][lineAt0+v*f]==1){ //do nothing }else if(data[f][lineAt0+v*f]==0){ data[f][lineAt0+v*f]=1; a=true; }else if(data[f][lineAt0+v*f]==-1){ throw CError("This region is not convex: %d\n",id); }else{ printf("Screwy value for region[%d].data[%d][%d]=%d in ABA analysis\n" ,id,f,lineAt0+v*f,data[f][lineAt0+v*f]); } } int minmin=maxmin-1; while(minmin>=0&&data[minmin][lineAt0+minmin*v]!=-1){ minmin--; } for(;minmin>=0;minmin--){ if(lineAt0+v*minmin>=maxWidth||lineAt0+v*minmin<0){ continue; } if(data[minmin][lineAt0+v*minmin]==-1){ //do nothing }else if(data[minmin][lineAt0+v*minmin]==0){ data[minmin][lineAt0+v*minmin]=-1; a=true; }else if(data[minmin][lineAt0+v*minmin]==1){ throw CError("This region is not convex: %d\n",id); }else{ printf("Screwy value for region[%d].data[%d][%d]=%d in minmin Analysis\n", id,minmin,lineAt0+v*minmin,data[f][minmin]); } } int maxmax=minmax+1; while(maxmax=maxWidth||lineAt0+v*maxmax<0){ continue; } if(data[maxmax][lineAt0+v*maxmax]==-1){ //do nothing }else if(data[maxmax][lineAt0+v*maxmax]==0){ data[maxmax][lineAt0+v*maxmax]=-1; a=true; }else if(data[maxmax][lineAt0+v*maxmax]==1){ throw CError("This region is not convex: %d\n",id); }else{ printf("lineAt0=%d v=%d maxmax=%d\n",lineAt0,v,maxmax); printf("Screwy value for region[%d].data[%d][%d]=%d in maxmax Analysis\n", id,maxmax,lineAt0+v*maxmax,data[maxmax][lineAt0+v*maxmax]); } } } } } return a; } bool CRegRast::operator == (CRegRast param) { return (param.id==id); } void CRegRast::printStuff(){ CRegRast reg=*this; //CRegRast reg=regp; CCol(id).printName(); printf("'s possVels is "); for(int v=MINVEL;v<=MAXVEL;v++){ if(reg.possVels[v]){ printf("0"); }else{ printf("X"); } } printf("\n"); for(int f=0;f0){ //delete [] relative; //} relative=c; } //returns the id of the color int CRasterizor::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]=CRegRast(a,nFrames,maxWidth); nRegions++; } return a; } // create new region if necessary, add a new component, and record its left edge void CRasterizor::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; } } // record right boundary of current region void CRasterizor::endRegion(int id, int frame, int x, int nextID) { region[id].xmaxes[frame]=x; region[id].rightIDs[frame]=nextID; } // read a frame: look at all pixels in center scanline and initialize / update // regions and their edges void CRasterizor::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; region[oldid].data[frame][0]=1; for (int x = 1; x < w; x++) { int newid = getPixID(row,x); data[frame][x]=newid; region[newid].data[frame][x]=1; 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 CRasterizor::printData() { printf("%d regions observed\n", nRegions); for (int i=0; i <= maxID; i++) { if (region[i]==null) continue; printf(" "); p(i); printf(":"); CRegRast 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 CRasterizor::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)//if motion is inconsistant return; int edgeVel = x21/f21; int id1=rightleft[f1]; int id2=rightleft[f2]; int id3=rightleft[f3]; if (id1 < 0 || id2 < 0 || id3 < 0)//if they are off the edge return; if (id1 == id2 && id2 != id3){ for(int f4=f3+1;f4=nFrames||r2.rightIDs[f1]!=i||r2.rightIDs[f2]!=i) //if there is no two frames that have these regions adjacent 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){//We don't need to check that id1!=j change|=setCloser(id1,i); change|=setCloser(id1,j); } } } } } void CRasterizor::possibilityElimination(){ for (int i=0; i <= maxID; i++) { CRegRast r=region[i]; if (r==null) continue; bool change2=true; while(change2==true){ change2=false; change2|=region[i].restrictPosition(); change2|=region[i].restrictVel(); if(!concave){ change2|=region[i].convexHull(); } change|=change2; } } } void CRasterizor::occlusionDetection() { if(verbose) printf("Occlusion Detection:\n"); for (int i=0; i <= maxID; i++) { CRegRast r=region[i]; if (r==null) continue; for(int f=0; freg.maxVel||rect.vel.xrect2.z){ verbose=true; printf("ERROR! "); p(i); printf(" doesn't beat "); p(j); printf("!\n"); throw CError("Relative Distances incorrect\n"); } } if(compare(0,i)==2){ verbose=true; printf("ERROR! "); p(i); printf(" doesn't beat "); p(0); throw CError("Nothing behind white\n"); } } if(verbose) printf("All true\n"); }