//-------------------------------------------------------------------------------------- // 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); }
void OpticalFlow::genInImageMask(DImage &mask, const DImage &flow,int interval) { int imWidth,imHeight; imWidth=flow.width(); imHeight=flow.height(); if(mask.matchDimension(flow.width(),flow.height(),1)==false) mask.allocate(imWidth,imHeight); else mask.reset(); const _FlowPrecision *pFlow; _FlowPrecision *pMask; pFlow = flow.data();; pMask=mask.data(); double x,y; for(int i=0;i<imHeight;i++) for(int j=0;j<imWidth;j++) { int offset=i*imWidth+j; y=i+pFlow[offset*2+1]; x=j+pFlow[offset*2]; if(x<interval || x>imWidth-1-interval || y<interval || y>imHeight-1-interval) continue; pMask[offset]=1; } }
//-------------------------------------------------------------------------------------------------------- // function to generate mask of the pixels that move inside the image boundary //-------------------------------------------------------------------------------------------------------- void OpticalFlow::genInImageMask(DImage &mask, const DImage &vx, const DImage &vy,int interval) { int imWidth,imHeight; imWidth=vx.width(); imHeight=vx.height(); if(mask.matchDimension(vx)==false) mask.allocate(imWidth,imHeight); const _FlowPrecision *pVx,*pVy; _FlowPrecision *pMask; pVx=vx.data(); pVy=vy.data(); mask.reset(); pMask=mask.data(); double x,y; for(int i=0;i<imHeight;i++) for(int j=0;j<imWidth;j++) { int offset=i*imWidth+j; y=i+pVx[offset]; x=j+pVy[offset]; if(x<interval || x>imWidth-1-interval || y<interval || y>imHeight-1-interval) continue; pMask[offset]=1; } }
//--------------------------------------------------------------------------------------- // function to convert image to feature image //--------------------------------------------------------------------------------------- void OpticalFlow::im2feature(DImage &imfeature, const DImage &im) { int width=im.width(); int height=im.height(); int nchannels=im.nchannels(); if(nchannels==1) { imfeature.allocate(im.width(),im.height(),3); DImage imdx,imdy; im.dx(imdx,true); im.dy(imdy,true); _FlowPrecision* data=imfeature.data(); for(int i=0;i<height;i++) for(int j=0;j<width;j++) { int offset=i*width+j; data[offset*3]=im.data()[offset]; data[offset*3+1]=imdx.data()[offset]; data[offset*3+2]=imdy.data()[offset]; } } else if(nchannels==3) { DImage grayImage; im.desaturate(grayImage); imfeature.allocate(im.width(),im.height(),5); DImage imdx,imdy; grayImage.dx(imdx,true); grayImage.dy(imdy,true); _FlowPrecision* data=imfeature.data(); for(int i=0;i<height;i++) for(int j=0;j<width;j++) { int offset=i*width+j; data[offset*5]=grayImage.data()[offset]; data[offset*5+1]=imdx.data()[offset]; data[offset*5+2]=imdy.data()[offset]; data[offset*5+3]=im.data()[offset*3+1]-im.data()[offset*3]; data[offset*5+4]=im.data()[offset*3+1]-im.data()[offset*3+2]; } } else imfeature.copyData(im); }
void OpticalFlow::Laplacian(DImage &output, const DImage &input, const DImage& weight) { if(output.matchDimension(input)==false) output.allocate(input); output.reset(); if(input.matchDimension(weight)==false) { cout<<"Error in image dimension matching OpticalFlow::Laplacian()!"<<endl; return; } const _FlowPrecision *inputData=input.data(),*weightData=weight.data(); int width=input.width(),height=input.height(); DImage foo(width,height); _FlowPrecision *fooData=foo.data(),*outputData=output.data(); // horizontal filtering for(int i=0;i<height;i++) for(int j=0;j<width-1;j++) { int offset=i*width+j; fooData[offset]=(inputData[offset+1]-inputData[offset])*weightData[offset]; } for(int i=0;i<height;i++) for(int j=0;j<width;j++) { int offset=i*width+j; if(j<width-1) outputData[offset]-=fooData[offset]; if(j>0) outputData[offset]+=fooData[offset-1]; } foo.reset(); // vertical filtering for(int i=0;i<height-1;i++) for(int j=0;j<width;j++) { int offset=i*width+j; fooData[offset]=(inputData[offset+width]-inputData[offset])*weightData[offset]; } for(int i=0;i<height;i++) for(int j=0;j<width;j++) { int offset=i*width+j; if(i<height-1) outputData[offset]-=fooData[offset]; if(i>0) outputData[offset]+=fooData[offset-width]; } }
bool OpticalFlow::LoadOpticalFlow(ifstream& myfile,DImage& flow) { Image<unsigned short int> foo; if(foo.loadImage(myfile) == false) return false; if(!flow.matchDimension(foo)) flow.allocate(foo); for(int i = 0;i<flow.npixels();i++) { flow.data()[i*2] = (double)foo.data()[i*2]/160-200; flow.data()[i*2+1] = (double)foo.data()[i*2+1]/160-200; } return true; }
//-------------------------------------------------------------------------------------- // 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(); }
void OpticalFlow::warpFL(DImage &warpIm2, const DImage &Im1, const DImage &Im2, const DImage &Flow) { if(warpIm2.matchDimension(Im2)==false) warpIm2.allocate(Im2.width(),Im2.height(),Im2.nchannels()); ImageProcessing::warpImageFlow(warpIm2.data(),Im1.data(),Im2.data(),Flow.data(),Im2.width(),Im2.height(),Im2.nchannels()); }
//-------------------------------------------------------------------------------------- // 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(); }