void GaussianPyramid::ConstructPyramidLevels(const DImage &image, double ratio, int _nLevels) { // the ratio cannot be arbitrary numbers if(ratio>0.98 || ratio<0.4) ratio=0.75; nLevels = _nLevels; if(ImPyramid!=NULL) delete []ImPyramid; ImPyramid=new DImage[nLevels]; ImPyramid[0].copyData(image); double baseSigma=(1/ratio-1); int n=log(0.25)/log(ratio); double nSigma=baseSigma*n; for(int i=1;i<nLevels;i++) { DImage foo; if(i<=n) { double sigma=baseSigma*i; image.GaussianSmoothing(foo,sigma,sigma*3); foo.imresize(ImPyramid[i],pow(ratio,i)); } else { ImPyramid[i-n].GaussianSmoothing(foo,nSigma,nSigma*3); double rate=(double)pow(ratio,i)*image.width()/foo.width(); foo.imresize(ImPyramid[i],rate); } } }
//-------------------------------------------------------------------------------------- // function to perfomr coarse to fine optical flow estimation //-------------------------------------------------------------------------------------- void OpticalFlow::Coarse2FineFlow(DImage &vx, DImage &vy, DImage &warpI2,const DImage &Im1, const DImage &Im2, double alpha, double ratio, int minWidth, int nOuterFPIterations, int nInnerFPIterations, int nCGIterations) { // first build the pyramid of the two images GaussianPyramid GPyramid1; GaussianPyramid GPyramid2; if(IsDisplay) cout<<"Constructing pyramid..."; GPyramid1.ConstructPyramid(Im1,ratio,minWidth); GPyramid2.ConstructPyramid(Im2,ratio,minWidth); if(IsDisplay) cout<<"done!"<<endl; // now iterate from the top level to the bottom DImage Image1,Image2,WarpImage2; for(int k=GPyramid1.nlevels()-1; k>=0; k--) { if(IsDisplay) cout<<"Pyramid level "<<k; int width=GPyramid1.Image(k).width(); int height=GPyramid1.Image(k).height(); im2feature(Image1,GPyramid1.Image(k)); im2feature(Image2,GPyramid2.Image(k)); if(k==GPyramid1.nlevels()-1) // if at the top level { vx.allocate(width,height); vy.allocate(width,height); //warpI2.copyData(Image2); WarpImage2.copyData(Image2); } else { vx.imresize(width,height); vx.Multiplywith(1/ratio); vy.imresize(width,height); vy.Multiplywith(1/ratio); //warpFL(warpI2,GPyramid1.Image(k),GPyramid2.Image(k),vx,vy); warpFL(WarpImage2,Image1,Image2,vx,vy); } //SmoothFlowPDE(GPyramid1.Image(k),GPyramid2.Image(k),warpI2,vx,vy,alpha,nOuterFPIterations,nInnerFPIterations,nCGIterations); //SmoothFlowPDE(Image1,Image2,WarpImage2,vx,vy,alpha*pow((1/ratio),k),nOuterFPIterations,nInnerFPIterations,nCGIterations); SmoothFlowPDE(Image1,Image2,WarpImage2,vx,vy,alpha,nOuterFPIterations,nInnerFPIterations,nCGIterations); if(IsDisplay) cout<<endl; } warpFL(warpI2,Im1,Im2,vx,vy); }
//-------------------------------------------------------------------------------------- // function to perfomr coarse to fine optical flow estimation //-------------------------------------------------------------------------------------- void OpticalFlow::Coarse2FineFlow(DImage &vx, DImage &vy, DImage &warpI2,const DImage &Im1, const DImage &Im2, double alpha, double ratio, int minWidth, int nOuterFPIterations, int nInnerFPIterations, int nCGIterations) { // first build the pyramid of the two images GaussianPyramid GPyramid1; GaussianPyramid GPyramid2; if(IsDisplay) cout<<"Constructing pyramid..."; GPyramid1.ConstructPyramid(Im1,ratio,minWidth); GPyramid2.ConstructPyramid(Im2,ratio,minWidth); if(IsDisplay) cout<<"done!"<<endl; // now iterate from the top level to the bottom DImage Image1,Image2,WarpImage2; // initialize noise // cout << GPyramid1.nlevels() << " pyramid levels\n"; for(int k=GPyramid1.nlevels()-1;k>=0;k--) { if(IsDisplay) cout<<"Pyramid level "<<k+1; int width=GPyramid1.Image(k).width(); int height=GPyramid1.Image(k).height(); im2feature(Image1,GPyramid1.Image(k)); im2feature(Image2,GPyramid2.Image(k)); // cout << "\t- level " << k+1 << " size " << width <<"x" << height <<endl; if(k==GPyramid1.nlevels()-1) // if at the top level { vx.allocate(width,height); vy.allocate(width,height); WarpImage2.copyData(Image2); } else { vx.imresize(width,height); vx.Multiplywith(1/ratio); vy.imresize(width,height); vy.Multiplywith(1/ratio); if(interpolation == Bilinear) warpFL(WarpImage2,Image1,Image2,vx,vy); else Image2.warpImageBicubicRef(Image1,WarpImage2,vx,vy); } SmoothFlowSOR(Image1,Image2,WarpImage2,vx,vy,alpha,nOuterFPIterations+k,nInnerFPIterations,nCGIterations+k*3); //GMPara.display(); if(IsDisplay) cout<<endl; } //warpFL(warpI2,Im1,Im2,vx,vy); Im2.warpImageBicubicRef(Im1,warpI2,vx,vy); warpI2.threshold(); }
//------------------------------------------------------------------------------------------------ // multi-grid belie propagation //------------------------------------------------------------------------------------------------ void BPFlow::generateCoarserLevel(BPFlow &bp) { //------------------------------------------------------------------------------------------------ // set the dimensions and parameters //------------------------------------------------------------------------------------------------ bp.Width=Width/2; if(Width%2==1) bp.Width++; bp.Height=Height/2; if(Height%2==1) bp.Height++; bp.Area=bp.Width*bp.Height; bp.s=s; bp.d=d; DImage foo; Im_s.smoothing(foo); foo.imresize(bp.Im_s,bp.Width,bp.Height); Im_d.smoothing(foo); foo.imresize(bp.Im_d,bp.Width,bp.Height); bp.IsDisplay=IsDisplay; bp.nNeighbors=nNeighbors; //------------------------------------------------------------------------------------------------ // allocate buffers //------------------------------------------------------------------------------------------------ for(int i=0;i<2;i++) { bp.pOffset[i]=new int[bp.Area]; bp.pWinSize[i]=new int[bp.Area]; ReduceImage(bp.pOffset[i],Width,Height,pOffset[i]); ReduceImage(bp.pWinSize[i],Width,Height,pWinSize[i]); for(int j = 0;j<bp.Area;j++) bp.pWinSize[i][j] = __max(bp.pWinSize[i][j],1); } //------------------------------------------------------------------------------------------------ // generate data term //------------------------------------------------------------------------------------------------ bp.nTotalMatches=bp.AllocateBuffer(bp.pDataTerm,bp.ptrDataTerm,bp.pWinSize[0],bp.pWinSize[1]); for(int i=0;i<bp.Height;i++) for(int j=0;j<bp.Width;j++) { int offset=i*bp.Width+j; for(int ii=0;ii<2;ii++) for(int jj=0;jj<2;jj++) { int y=i*2+ii; int x=j*2+jj; if(y<Height && x<Width) { int nStates=(bp.pWinSize[0][offset]*2+1)*(bp.pWinSize[1][offset]*2+1); for(int k=0;k<nStates;k++) bp.pDataTerm[offset].data()[k]+=pDataTerm[y*Width+x].data()[k]; } } } //------------------------------------------------------------------------------------------------ // generate range term //------------------------------------------------------------------------------------------------ bp.ComputeRangeTerm(gamma/2); }
//-------------------------------------------------------------------------------------- // function to perfomr coarse to fine optical flow estimation //-------------------------------------------------------------------------------------- void OpticalFlow::Coarse2FineFlow(DImage &vx, DImage &vy, DImage &warpI2,const DImage &Im1, const DImage &Im2, double alpha, double ratio, int minWidth, int nOuterFPIterations, int nInnerFPIterations, int nCGIterations) { // first build the pyramid of the two images GaussianPyramid GPyramid1; GaussianPyramid GPyramid2; if(IsDisplay) cout<<"Constructing pyramid..."; GPyramid1.ConstructPyramid(Im1,ratio,minWidth); GPyramid2.ConstructPyramid(Im2,ratio,minWidth); if(IsDisplay) cout<<"done!"<<endl; // now iterate from the top level to the bottom DImage Image1,Image2,WarpImage2; //GaussianMixture GMPara(Im1.nchannels()+2); // initialize noise switch(noiseModel){ case GMixture: GMPara.reset(Im1.nchannels()+2); break; case Lap: LapPara.allocate(Im1.nchannels()+2); for(int i = 0;i<LapPara.dim();i++) LapPara[i] = 0.02; break; } for(int k=GPyramid1.nlevels()-1;k>=0;k--) { if(IsDisplay) cout<<"Pyramid level "<<k; int width=GPyramid1.Image(k).width(); int height=GPyramid1.Image(k).height(); im2feature(Image1,GPyramid1.Image(k)); im2feature(Image2,GPyramid2.Image(k)); if(k==GPyramid1.nlevels()-1) // if at the top level { vx.allocate(width,height); vy.allocate(width,height); //warpI2.copyData(Image2); WarpImage2.copyData(Image2); } else { vx.imresize(width,height); vx.Multiplywith(1/ratio); vy.imresize(width,height); vy.Multiplywith(1/ratio); //warpFL(warpI2,GPyramid1.Image(k),GPyramid2.Image(k),vx,vy); if(interpolation == Bilinear) warpFL(WarpImage2,Image1,Image2,vx,vy); else Image2.warpImageBicubicRef(Image1,WarpImage2,vx,vy); } //SmoothFlowPDE(GPyramid1.Image(k),GPyramid2.Image(k),warpI2,vx,vy,alpha,nOuterFPIterations,nInnerFPIterations,nCGIterations); //SmoothFlowPDE(Image1,Image2,WarpImage2,vx,vy,alpha*pow((1/ratio),k),nOuterFPIterations,nInnerFPIterations,nCGIterations,GMPara); //SmoothFlowPDE(Image1,Image2,WarpImage2,vx,vy,alpha,nOuterFPIterations,nInnerFPIterations,nCGIterations); SmoothFlowSOR(Image1,Image2,WarpImage2,vx,vy,alpha,nOuterFPIterations+k,nInnerFPIterations,nCGIterations+k*3); //GMPara.display(); if(IsDisplay) cout<<endl; } //warpFL(warpI2,Im1,Im2,vx,vy); Im2.warpImageBicubicRef(Im1,warpI2,vx,vy); warpI2.threshold(); }