// Author: Ce Liu (c) Dec, 2009; celiu@mit.edu // Modified By: Deepak Pathak (c) 2016; pathak@berkeley.edu #ifndef _ImageProcessing_h #define _ImageProcessing_h #include "math.h" #include "stdio.h" #include "stdlib.h" #include //---------------------------------------------------------------------------------- // class to handle basic image processing functions // this is a collection of template functions. These template functions are // used in other image classes such as BiImage, IntImage and FImage //---------------------------------------------------------------------------------- class ImageProcessing { public: ImageProcessing(void); ~ImageProcessing(void); public: // basic functions template static inline T EnforceRange(const T& x,const int& MaxValue) {return __min(__max(x,0),MaxValue-1);}; //--------------------------------------------------------------------------------- // function to interpolate the image plane //--------------------------------------------------------------------------------- template static inline void BilinearInterpolate(const T1* pImage,int width,int height,int nChannels,double x,double y,T2* result); template static inline T1 BilinearInterpolate(const T1* pImage,int width,int height,double x,double y); // the transpose of bilinear interpolation template static inline void BilinearInterpolate_transpose(const T1* pImage,int width,int height,int nChannels,double x,double y,T2* result); template static inline T1 BilinearInterpolate_transpose(const T1* pImage,int width,int height,double x,double y); template static void ResizeImage(const T1* pSrcImage,T2* pDstImage,int SrcWidth,int SrcHeight,int nChannels,double Ratio); template static void ResizeImage(const T1* pSrcImage,T2* pDstImage,int SrcWidth,int SrcHeight,int nChannels,int DstWidth,int DstHeight); //--------------------------------------------------------------------------------- // functions for 1D filtering //--------------------------------------------------------------------------------- template static void hfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter1D,int fsize); template static void vfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter1D,int fsize); template static void hfiltering_transpose(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter1D,int fsize); template static void vfiltering_transpose(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter1D,int fsize); //--------------------------------------------------------------------------------- // functions for 2D filtering //--------------------------------------------------------------------------------- template static void filtering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter2D,int fsize); template static void filtering_transpose(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter2D,int fsize); template static void Laplacian(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels); //--------------------------------------------------------------------------------- // functions for sample a patch from the image //--------------------------------------------------------------------------------- template static void getPatch(const T1* pSrcImgae,T2* pPatch,int width,int height,int nChannels,double x,double y,int wsize); //--------------------------------------------------------------------------------- // function to warp image //--------------------------------------------------------------------------------- template static void warpImage(T1* pWarpIm2,const T1* pIm1,const T1* pIm2,const T2* pVx,const T2* pVy,int width,int height,int nChannels); template static void warpImageFlow(T1* pWarpIm2,const T1* pIm1,const T1* pIm2,const T2* pFlow,int width,int height,int nChannels); template static void warpImage(T1* pWarpIm2,const T1* pIm2,const T2* pVx,const T2* pVy,int width,int height,int nChannels); template static void warpImage_transpose(T1* pWarpIm2,const T1* pIm2,const T2* pVx,const T2* pVy,int width,int height,int nChannels); template static void warpImage(T1* pWarpIm2,const T1* pIm2,const T2*flow,int width,int height,int nChannels); template static void warpImage_transpose(T1* pWarpIm2,const T1* pIm2,const T2* flow,int width,int height,int nChannels); template static void warpImage(T1 *pWarpIm2, T3* pMask,const T1 *pIm1, const T1 *pIm2, const T2 *pVx, const T2 *pVy, int width, int height, int nChannels); //--------------------------------------------------------------------------------- // function to crop an image //--------------------------------------------------------------------------------- template static void cropImage(const T1* pSrcImage,int SrcWidth,int SrcHeight,int nChannels,T2* pDstImage,int Left,int Top,int DstWidth,int DstHeight); //--------------------------------------------------------------------------------- //--------------------------------------------------------------------------------- // function to generate a 2D Gaussian //--------------------------------------------------------------------------------- template static void generate2DGaussian(T*& pImage,int wsize,double sigma=-1); template static void generate1DGaussian(T*& pImage,int wsize,double sigma=-1); }; //-------------------------------------------------------------------------------------------------- // function to interplate multi-channel image plane for (x,y) // -------------------------------------------------------------------------------------------------- template inline void ImageProcessing::BilinearInterpolate(const T1* pImage,int width,int height,int nChannels,double x,double y,T2* result) { int xx,yy,m,n,u,v,l,offset; xx=x; yy=y; double dx,dy,s; dx=__max(__min(x-xx,1),0); dy=__max(__min(y-yy,1),0); for(m=0;m<=1;m++) for(n=0;n<=1;n++) { u=EnforceRange(xx+m,width); v=EnforceRange(yy+n,height); offset=(v*width+u)*nChannels; s=fabs(1-m-dx)*fabs(1-n-dy); for(l=0;l inline T1 ImageProcessing::BilinearInterpolate(const T1* pImage,int width,int height,double x,double y) { int xx,yy,m,n,u,v,l,offset; xx=x; yy=y; double dx,dy,s; dx=__max(__min(x-xx,1),0); dy=__max(__min(y-yy,1),0); T1 result=0; for(m=0;m<=1;m++) for(n=0;n<=1;n++) { u=EnforceRange(xx+m,width); v=EnforceRange(yy+n,height); offset=v*width+u; s=fabs(1-m-dx)*fabs(1-n-dy); result+=pImage[offset]*s; } return result; } //-------------------------------------------------------------------------------------------------- // function to interplate multi-channel image plane for (x,y) // -------------------------------------------------------------------------------------------------- template inline void ImageProcessing::BilinearInterpolate_transpose(const T1* pInput,int width,int height,int nChannels,double x,double y,T2* pDstImage) { int xx,yy,m,n,u,v,l,offset; xx=x; yy=y; double dx,dy,s; dx=__max(__min(x-xx,1),0); dy=__max(__min(y-yy,1),0); for(m=0;m<=1;m++) for(n=0;n<=1;n++) { u=EnforceRange(xx+m,width); v=EnforceRange(yy+n,height); offset=(v*width+u)*nChannels; s=fabs(1-m-dx)*fabs(1-n-dy); for(l=0;l void ImageProcessing::ResizeImage(const T1* pSrcImage,T2* pDstImage,int SrcWidth,int SrcHeight,int nChannels,double Ratio) { int DstWidth,DstHeight; DstWidth=(double)SrcWidth*Ratio; DstHeight=(double)SrcHeight*Ratio; memset(pDstImage,0,sizeof(T2)*DstWidth*DstHeight*nChannels); double x,y; for(int i=0;i void ImageProcessing::ResizeImage(const T1 *pSrcImage, T2 *pDstImage, int SrcWidth, int SrcHeight, int nChannels, int DstWidth, int DstHeight) { double xRatio=(double)DstWidth/SrcWidth; double yRatio=(double)DstHeight/SrcHeight; memset(pDstImage,sizeof(T2)*DstWidth*DstHeight*nChannels,0); double x,y; for(int i=0;i void ImageProcessing::hfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter1D,int fsize) { memset(pDstImage,0,sizeof(T2)*width*height*nChannels); T2* pBuffer; double w; int i,j,l,k,offset,jj; for(i=0;i void ImageProcessing::hfiltering_transpose(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter1D,int fsize) { memset(pDstImage,0,sizeof(T2)*width*height*nChannels); const T1* pBuffer; double w; int i,j,l,k,offset,jj; for(i=0;i void ImageProcessing::Laplacian(const T1 *pSrcImage, T2 *pDstImage, int width, int height, int nChannels) { int LineWidth=width*nChannels; int nElements=width*height*nChannels; // first treat the corners for(int k=0;k void ImageProcessing::vfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter1D,int fsize) { memset(pDstImage,0,sizeof(T2)*width*height*nChannels); T2* pBuffer; double w; int i,j,l,k,offset,ii; for(i=0;i void ImageProcessing::vfiltering_transpose(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter1D,int fsize) { memset(pDstImage,0,sizeof(T2)*width*height*nChannels); const T1* pBuffer; double w; int i,j,l,k,offset,ii; for(i=0;i void ImageProcessing::filtering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter2D,int fsize) { double w; int i,j,u,v,k,ii,jj,wsize,offset; wsize=fsize*2+1; double* pBuffer=new double[nChannels]; for(i=0;i void ImageProcessing::filtering_transpose(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,const double* pfilter2D,int fsize) { double w; int i,j,u,v,k,ii,jj,wsize,offset; wsize=fsize*2+1; memset(pDstImage,0,sizeof(T2)*width*height*nChannels); for(i=0;i void ImageProcessing::getPatch(const T1* pSrcImage,T2* pPatch,int width,int height,int nChannels,double x0,double y0,int wsize) { // suppose pPatch has been allocated and cleared before calling the function int wlength=wsize*2+1; double x,y; for(int i=-wsize;i<=wsize;i++) for(int j=-wsize;j<=wsize;j++) { y=y0+i; x=x0+j; if(x<0 || x>width-1 || y<0 || y>height-1) continue; BilinearInterpolate(pSrcImage,width,height,nChannels,x,y,pPatch+((i+wsize)*wlength+j+wsize)*nChannels); } } //------------------------------------------------------------------------------------------------------------ // function to warp an image with respect to flow field // pWarpIm2 has to be allocated before hands //------------------------------------------------------------------------------------------------------------ template void ImageProcessing::warpImage(T1 *pWarpIm2, const T1 *pIm1, const T1 *pIm2, const T2 *pVx, const T2 *pVy, int width, int height, int nChannels) { memset(pWarpIm2,0,sizeof(T1)*width*height*nChannels); for(int i=0;iwidth-1 || y<0 || y>height-1) { for(int k=0;k void ImageProcessing::warpImageFlow(T1 *pWarpIm2, const T1 *pIm1, const T1 *pIm2, const T2 *pFlow, int width, int height, int nChannels) { memset(pWarpIm2,0,sizeof(T1)*width*height*nChannels); for(int i=0;iwidth-1 || y<0 || y>height-1) { for(int k=0;k void ImageProcessing::warpImage(T1 *pWarpIm2,const T1 *pIm2, const T2 *pVx, const T2 *pVy, int width, int height, int nChannels) { memset(pWarpIm2,0,sizeof(T1)*width*height*nChannels); for(int i=0;iwidth-1 || y<0 || y>height-1) continue; BilinearInterpolate(pIm2,width,height,nChannels,x,y,pWarpIm2+offset); } } template void ImageProcessing::warpImage_transpose(T1 *pWarpIm2,const T1 *pIm2, const T2 *pVx, const T2 *pVy, int width, int height, int nChannels) { memset(pWarpIm2,0,sizeof(T1)*width*height*nChannels); for(int i=0;iwidth-1 || y<0 || y>height-1) continue; //BilinearInterpolate(pIm2,width,height,nChannels,x,y,pWarpIm2+offset); BilinearInterpolate_transpose(pIm2+offset,width,height,nChannels,x,y,pWarpIm2); } } ////////////////////////////////////////////////////////////////////////////////////// // different format ////////////////////////////////////////////////////////////////////////////////////// template void ImageProcessing::warpImage(T1 *pWarpIm2,const T1 *pIm2, const T2 *flow, int width, int height, int nChannels) { memset(pWarpIm2,0,sizeof(T1)*width*height*nChannels); for(int i=0;iwidth-1 || y<0 || y>height-1) continue; BilinearInterpolate(pIm2,width,height,nChannels,x,y,pWarpIm2+offset); } } template void ImageProcessing::warpImage_transpose(T1 *pWarpIm2,const T1 *pIm2, const T2 *flow, int width, int height, int nChannels) { memset(pWarpIm2,0,sizeof(T1)*width*height*nChannels); for(int i=0;iwidth-1 || y<0 || y>height-1) continue; //BilinearInterpolate(pIm2,width,height,nChannels,x,y,pWarpIm2+offset); BilinearInterpolate_transpose(pIm2+offset,width,height,nChannels,x,y,pWarpIm2); } } template void ImageProcessing::warpImage(T1 *pWarpIm2, T3* pMask,const T1 *pIm1, const T1 *pIm2, const T2 *pVx, const T2 *pVy, int width, int height, int nChannels) { memset(pWarpIm2,0,sizeof(T1)*width*height*nChannels); for(int i=0;iwidth-1 || y<0 || y>height-1) { for(int k=0;k void ImageProcessing::cropImage(const T1 *pSrcImage, int SrcWidth, int SrcHeight, int nChannels, T2 *pDstImage, int Left, int Top, int DstWidth, int DstHeight) { if(typeid(T1)==typeid(T2)) { for(int i=0;i void ImageProcessing::generate2DGaussian(T*& pImage, int wsize, double sigma) { if(sigma==-1) sigma=wsize/2; double alpha=1/(2*sigma*sigma); int winlength=wsize*2+1; if(pImage==NULL) pImage=new T[winlength*winlength]; double total = 0; for(int i=-wsize;i<=wsize;i++) for(int j=-wsize;j<=wsize;j++) { pImage[(i+wsize)*winlength+j+wsize]=exp(-(double)(i*i+j*j)*alpha); total += pImage[(i+wsize)*winlength+j+wsize]; } for(int i = 0;i void ImageProcessing::generate1DGaussian(T*& pImage, int wsize, double sigma) { if(sigma==-1) sigma=wsize/2; double alpha=1/(2*sigma*sigma); int winlength=wsize*2+1; if(pImage==NULL) pImage=new T[winlength]; double total = 0; for(int i=-wsize;i<=wsize;i++) { pImage[i+wsize]=exp(-(double)(i*i)*alpha); total += pImage[i+wsize]; } for(int i = 0;i