int main(int argc, char** argv) { int M1 = 2; int M2 = 2; int N1 = 2; int N2 = 2; // initialize A and B // CvMat* A = cvCreateMat(M1, N1, CV_32F); CvMat* B = cvCreateMat(M2, N2, A->type); // it is also possible to have only abs(M2-M1)+1×abs(N2-N1)+1 // part of the full convolution result CvMat* conv = cvCreateMat(A->rows + B->rows - 1, A->cols + B->cols - 1, A->type); int dft_M = cvGetOptimalDFTSize(A->rows + B->rows - 1); int dft_N = cvGetOptimalDFTSize(A->cols + B->cols - 1); CvMat* dft_A = cvCreateMat(dft_M, dft_N, A->type); CvMat* dft_B = cvCreateMat(dft_M, dft_N, B->type); CvMat tmp; // copy A to dft_A and pad dft_A with zeros // cvGetSubRect(dft_A, &tmp, cvRect(0, 0, A->cols, A->rows)); cvCopy(A, &tmp); cvGetSubRect(dft_A, &tmp, cvRect(A->cols, 0, dft_A->cols - A->cols, A->rows)); cvZero(&tmp); // no need to pad bottom part of dft_A with zeros because of // use nonzero_rows parameter in cvDFT() call below // cvDFT(dft_A, dft_A, CV_DXT_FORWARD, A->rows); // repeat the same with the second array // cvGetSubRect(dft_B, &tmp, cvRect(0, 0, B->cols, B->rows)); cvCopy(B, &tmp); cvGetSubRect(dft_B, &tmp, cvRect(B->cols, 0, dft_B->cols - B->cols, B->rows)); cvZero(&tmp); // no need to pad bottom part of dft_B with zeros because of // use nonzero_rows parameter in cvDFT() call below // cvDFT(dft_B, dft_B, CV_DXT_FORWARD, B->rows); // or CV_DXT_MUL_CONJ to get correlation rather than convolution // cvMulSpectrums(dft_A, dft_B, dft_A, 0); // calculate only the top part // cvDFT(dft_A, dft_A, CV_DXT_INV_SCALE, conv->rows); cvGetSubRect(dft_A, &tmp, cvRect(0, 0, conv->cols, conv->rows)); cvCopy(&tmp, conv); return 0; }
IplImage* fftImage(IplImage *img) { IplImage *realpart, *imgpart, *complexpart, *ret; CvMat *ft; int sizeM, sizeN; CvMat tmp; realpart = cvCreateImage(cvGetSize(img), IPL_DEPTH_64F, 1); imgpart = cvCreateImage(cvGetSize(img), IPL_DEPTH_64F, 1); complexpart = cvCreateImage(cvGetSize(img), IPL_DEPTH_64F, 2); cvScale(img, realpart, 1.0, 0.0); // copy grey input image to realpart cvZero(imgpart); // Set imaginary part to 0 cvMerge(realpart, imgpart, NULL, NULL, complexpart); // real+imag to complex /* Messy bit - fft needs sizes to be a power of 2, so the images have to be // embedded into a background of 0 pixels. */ sizeM = cvGetOptimalDFTSize(img->height - 1); sizeN = cvGetOptimalDFTSize(img->width - 1); printf("Size of image to be transformed is %dx%d\n", sizeM, sizeN); ft = cvCreateMat(sizeM, sizeN, CV_64FC2); origin_center(complexpart); // copy A to dft_A and pad dft_A with zeros cvGetSubRect(ft, &tmp, cvRect(0, 0, img->width, img->height)); // tmp points to sub of dft_A cvCopy(complexpart, &tmp, NULL); // Copy complex image into sub of dft_A cvGetSubRect(ft, &tmp, cvRect(img->width, 0, ft->cols - img->width, img->height)); // Get sub of dft_A on right side if ((ft->cols - img->width) > 0) cvZero(&tmp); // Set right margin to zero cvDFT(ft, ft, CV_DXT_FORWARD, complexpart->height); ret = cvMatToImage(ft); cvReleaseMat(&ft); cvReleaseImage(&realpart); cvReleaseImage(&imgpart); cvReleaseImage(&complexpart); return ret; }
static IplImage* get_convolution (const IplImage *image, const IplImage *filter) { CvSize dft_size; IplImage *reversed_image, *reversed_filter; IplImage *dft_image, *dft_filter, *dft_res; IplImage *res; dft_size.height = cvGetOptimalDFTSize(image->height + filter->height - 1); dft_size.width = cvGetOptimalDFTSize(image->width + filter->width - 1); res = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_32F, N_CHANNELS_GRAY); reversed_image = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, N_CHANNELS_GRAY); reversed_filter = cvCreateImage(cvGetSize(filter), IPL_DEPTH_8U, N_CHANNELS_GRAY); cvNot(image, reversed_image); cvNot(filter, reversed_filter); dft_image = cvCreateImage(dft_size, IPL_DEPTH_32F, N_CHANNELS_GRAY); cvSet(dft_image, cvScalar(0, 0, 0, 0), NULL); dft_filter = cvCreateImage(dft_size, IPL_DEPTH_32F, N_CHANNELS_GRAY); cvSet(dft_filter, cvScalar(0, 0, 0, 0), NULL); cvSetImageROI(dft_image, cvRect(0, 0, reversed_image->width, reversed_image->height)); cvSetImageROI(dft_filter, cvRect(0, 0, reversed_filter->width, reversed_filter->height)); double scaling_factor = 1.0/255; cvConvertScale(reversed_image, dft_image, scaling_factor, 0); cvConvertScale(reversed_filter, dft_filter, scaling_factor, 0); cvResetImageROI(dft_image); cvResetImageROI(dft_filter); cvDFT(dft_image, dft_image, CV_DXT_FORWARD, image->height); cvDFT(dft_filter, dft_filter, CV_DXT_FORWARD, filter->height); dft_res = cvCreateImage(dft_size, IPL_DEPTH_32F, N_CHANNELS_GRAY); cvMulSpectrums(dft_image, dft_filter, dft_res, 0); cvDFT(dft_res, dft_res, CV_DXT_INVERSE, res->height); cvSetImageROI(dft_res, cvRect(0, 0, res->width, res->height)); cvCopy(dft_res, res, NULL); cvResetImageROI(dft_res); cvReleaseImage(&reversed_filter); cvReleaseImage(&reversed_image); cvReleaseImage(&dft_image); cvReleaseImage(&dft_filter); cvReleaseImage(&dft_res); return res; }
int main(int argc, char ** argv) { int height,width,step,channels; uchar* data; uchar* data1; int i,j,k; float s; CvMat *dft_A; CvMat *dft_B; CvMat *dft_C; IplImage* im; IplImage* im1; IplImage* image_ReB; IplImage* image_ImB; IplImage* image_ReC; IplImage* image_ImC; IplImage* complex_ImC; IplImage* image_ReDen; IplImage* image_ImDen; FILE *fp; fp = fopen("test.txt","w+"); int dft_M,dft_N; int dft_M1,dft_N1; CvMat* cvShowDFT(); void cvShowInvDFT(); im1 = cvLoadImage( "kutty-1.jpg",1 ); cvNamedWindow("original-color", 0); cvShowImage("original-color", im1); im = cvLoadImage( "kutty-1.jpg", CV_LOAD_IMAGE_GRAYSCALE ); if( !im ) return -1; cvNamedWindow("original-gray", 0); cvShowImage("original-gray", im); // Create blur kernel (non-blind) //float vals[]={.000625,.000625,.000625,.003125,.003125,.003125,.000625,.000625,.000625}; //float vals[]={-0.167,0.333,0.167,-0.167,.333,.167,-0.167,.333,.167}; float vals[]={.055,.055,.055,.222,.222,.222,.055,.055,.055}; CvMat kernel = cvMat(3, // number of rows 3, // number of columns CV_32FC1, // matrix data type vals); IplImage* k_image_hdr; IplImage* k_image; k_image_hdr = cvCreateImageHeader(cvSize(3,3),IPL_DEPTH_64F,2); k_image = cvCreateImage(cvSize(3,3),IPL_DEPTH_64F,1); k_image = cvGetImage(&kernel,k_image_hdr); /*IplImage* k_image; k_image = cvLoadImage( "kernel4.bmp",0 );*/ cvNamedWindow("blur kernel", 0); height = k_image->height; width = k_image->width; step = k_image->widthStep; channels = k_image->nChannels; //data1 = (float *)(k_image->imageData); data1 = (uchar *)(k_image->imageData); cvShowImage("blur kernel", k_image); dft_M = cvGetOptimalDFTSize( im->height - 1 ); dft_N = cvGetOptimalDFTSize( im->width - 1 ); //dft_M1 = cvGetOptimalDFTSize( im->height+99 - 1 ); //dft_N1 = cvGetOptimalDFTSize( im->width+99 - 1 ); dft_M1 = cvGetOptimalDFTSize( im->height+3 - 1 ); dft_N1 = cvGetOptimalDFTSize( im->width+3 - 1 ); // Perform DFT of original image dft_A = cvShowDFT(im, dft_M1, dft_N1,"original"); //Perform inverse (check & comment out) - Commented as it overwrites dft_A //cvShowInvDFT(im,dft_A,dft_M1,dft_N1,fp, "original"); // Perform DFT of kernel dft_B = cvShowDFT(k_image,dft_M1,dft_N1,"kernel"); //Perform inverse of kernel (check & comment out) - commented as it overwrites dft_B //cvShowInvDFT(k_image,dft_B,dft_M1,dft_N1,fp, "kernel"); // Multiply numerator with complex conjugate dft_C = cvCreateMat( dft_M1, dft_N1, CV_64FC2 ); printf("%d %d %d %d\n",dft_M,dft_N,dft_M1,dft_N1); // Multiply DFT(blurred image) * complex conjugate of blur kernel cvMulSpectrums(dft_A,dft_B,dft_C,CV_DXT_MUL_CONJ); // Split Fourier in real and imaginary parts image_ReC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); image_ImC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); complex_ImC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 2); printf("%d %d %d %d\n",dft_M,dft_N,dft_M1,dft_N1); //cvSplit( dft_C, image_ReC, image_ImC, 0, 0 ); cvSplit( dft_C, image_ReC, image_ImC, 0, 0 ); // Compute A^2 + B^2 of denominator or blur kernel image_ReB = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); image_ImB = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); // Split Real and imaginary parts cvSplit( dft_B, image_ReB, image_ImB, 0, 0 ); cvPow( image_ReB, image_ReB, 2.0); cvPow( image_ImB, image_ImB, 2.0); cvAdd(image_ReB, image_ImB, image_ReB,0); //Divide Numerator/A^2 + B^2 cvDiv(image_ReC, image_ReB, image_ReC, 1.0); cvDiv(image_ImC, image_ReB, image_ImC, 1.0); // Merge Real and complex parts cvMerge(image_ReC, image_ImC, NULL, NULL, complex_ImC); // Perform Inverse cvShowInvDFT(im, complex_ImC,dft_M1,dft_N1,fp,"deblur"); cvWaitKey(-1); return 0; }
void icvCrossCorr( const CvArr* _img, const CvArr* _templ, CvArr* _corr, CvPoint anchor, double delta, int borderType ) { // disable OpenMP in the case of Visual Studio, // otherwise the performance drops significantly #undef USE_OPENMP #if !defined _MSC_VER || defined CV_ICC #define USE_OPENMP 1 #endif const double block_scale = 4.5; const int min_block_size = 256; cv::Ptr<CvMat> dft_img[CV_MAX_THREADS]; cv::Ptr<CvMat> dft_templ; std::vector<uchar> buf[CV_MAX_THREADS]; int k, num_threads = 0; CvMat istub, *img = (CvMat*)_img; CvMat tstub, *templ = (CvMat*)_templ; CvMat cstub, *corr = (CvMat*)_corr; CvSize dftsize, blocksize; int depth, templ_depth, corr_depth, max_depth = CV_32F, cn, templ_cn, corr_cn, buf_size = 0, tile_count_x, tile_count_y, tile_count; img = cvGetMat( img, &istub ); templ = cvGetMat( templ, &tstub ); corr = cvGetMat( corr, &cstub ); if( CV_MAT_DEPTH( img->type ) != CV_8U && CV_MAT_DEPTH( img->type ) != CV_16U && CV_MAT_DEPTH( img->type ) != CV_32F && CV_MAT_DEPTH( img->type ) != CV_64F ) CV_Error( CV_StsUnsupportedFormat, "The function supports only 8u, 16u and 32f data types" ); if( !CV_ARE_DEPTHS_EQ( img, templ ) && CV_MAT_DEPTH( templ->type ) != CV_32F ) CV_Error( CV_StsUnsupportedFormat, "Template (kernel) must be of the same depth as the input image, or be 32f" ); if( !CV_ARE_DEPTHS_EQ( img, corr ) && CV_MAT_DEPTH( corr->type ) != CV_32F && CV_MAT_DEPTH( corr->type ) != CV_64F ) CV_Error( CV_StsUnsupportedFormat, "The output image must have the same depth as the input image, or be 32f/64f" ); if( (!CV_ARE_CNS_EQ( img, corr ) || CV_MAT_CN(templ->type) > 1) && (CV_MAT_CN( corr->type ) > 1 || !CV_ARE_CNS_EQ( img, templ)) ) CV_Error( CV_StsUnsupportedFormat, "The output must have the same number of channels as the input (when the template has 1 channel), " "or the output must have 1 channel when the input and the template have the same number of channels" ); depth = CV_MAT_DEPTH(img->type); cn = CV_MAT_CN(img->type); templ_depth = CV_MAT_DEPTH(templ->type); templ_cn = CV_MAT_CN(templ->type); corr_depth = CV_MAT_DEPTH(corr->type); corr_cn = CV_MAT_CN(corr->type); CV_Assert( corr_cn == 1 || delta == 0 ); max_depth = MAX( max_depth, templ_depth ); max_depth = MAX( max_depth, depth ); max_depth = MAX( max_depth, corr_depth ); if( depth > CV_8U ) max_depth = CV_64F; /*if( img->cols < templ->cols || img->rows < templ->rows ) CV_Error( CV_StsUnmatchedSizes, "Such a combination of image and template/filter size is not supported" );*/ if( corr->rows > img->rows + templ->rows - 1 || corr->cols > img->cols + templ->cols - 1 ) CV_Error( CV_StsUnmatchedSizes, "output image should not be greater than (W + w - 1)x(H + h - 1)" ); blocksize.width = cvRound(templ->cols*block_scale); blocksize.width = MAX( blocksize.width, min_block_size - templ->cols + 1 ); blocksize.width = MIN( blocksize.width, corr->cols ); blocksize.height = cvRound(templ->rows*block_scale); blocksize.height = MAX( blocksize.height, min_block_size - templ->rows + 1 ); blocksize.height = MIN( blocksize.height, corr->rows ); dftsize.width = cvGetOptimalDFTSize(blocksize.width + templ->cols - 1); if( dftsize.width == 1 ) dftsize.width = 2; dftsize.height = cvGetOptimalDFTSize(blocksize.height + templ->rows - 1); if( dftsize.width <= 0 || dftsize.height <= 0 ) CV_Error( CV_StsOutOfRange, "the input arrays are too big" ); // recompute block size blocksize.width = dftsize.width - templ->cols + 1; blocksize.width = MIN( blocksize.width, corr->cols ); blocksize.height = dftsize.height - templ->rows + 1; blocksize.height = MIN( blocksize.height, corr->rows ); dft_templ = cvCreateMat( dftsize.height*templ_cn, dftsize.width, max_depth ); #ifdef USE_OPENMP num_threads = cvGetNumThreads(); #else num_threads = 1; #endif for( k = 0; k < num_threads; k++ ) dft_img[k] = cvCreateMat( dftsize.height, dftsize.width, max_depth ); if( templ_cn > 1 && templ_depth != max_depth ) buf_size = templ->cols*templ->rows*CV_ELEM_SIZE(templ_depth); if( cn > 1 && depth != max_depth ) buf_size = MAX( buf_size, (blocksize.width + templ->cols - 1)* (blocksize.height + templ->rows - 1)*CV_ELEM_SIZE(depth)); if( (corr_cn > 1 || cn > 1) && corr_depth != max_depth ) buf_size = MAX( buf_size, blocksize.width*blocksize.height*CV_ELEM_SIZE(corr_depth)); if( buf_size > 0 ) { for( k = 0; k < num_threads; k++ ) buf[k].resize(buf_size); } // compute DFT of each template plane for( k = 0; k < templ_cn; k++ ) { CvMat dstub, *src, *dst, temp; CvMat* planes[] = { 0, 0, 0, 0 }; int yofs = k*dftsize.height; src = templ; dst = cvGetSubRect( dft_templ, &dstub, cvRect(0,yofs,templ->cols,templ->rows)); if( templ_cn > 1 ) { planes[k] = templ_depth == max_depth ? dst : cvInitMatHeader( &temp, templ->rows, templ->cols, templ_depth, &buf[0][0] ); cvSplit( templ, planes[0], planes[1], planes[2], planes[3] ); src = planes[k]; planes[k] = 0; } if( dst != src ) cvConvert( src, dst ); if( dft_templ->cols > templ->cols ) { cvGetSubRect( dft_templ, dst, cvRect(templ->cols, yofs, dft_templ->cols - templ->cols, templ->rows) ); cvZero( dst ); } cvGetSubRect( dft_templ, dst, cvRect(0,yofs,dftsize.width,dftsize.height) ); cvDFT( dst, dst, CV_DXT_FORWARD + CV_DXT_SCALE, templ->rows ); } tile_count_x = (corr->cols + blocksize.width - 1)/blocksize.width; tile_count_y = (corr->rows + blocksize.height - 1)/blocksize.height; tile_count = tile_count_x*tile_count_y; #if defined _OPENMP && defined USE_OPENMP #pragma omp parallel for num_threads(num_threads) schedule(dynamic) #endif // calculate correlation by blocks for( k = 0; k < tile_count; k++ ) { #ifdef USE_OPENMP int thread_idx = cvGetThreadNum(); #else int thread_idx = 0; #endif int x = (k%tile_count_x)*blocksize.width; int y = (k/tile_count_x)*blocksize.height; int i, yofs; CvMat sstub, dstub, *src, *dst, temp; CvMat* planes[] = { 0, 0, 0, 0 }; CvMat* _dft_img = dft_img[thread_idx]; uchar* _buf = buf_size > 0 ? &buf[thread_idx][0] : 0; CvSize csz = { blocksize.width, blocksize.height }, isz; int x0 = x - anchor.x, y0 = y - anchor.y; int x1 = MAX( 0, x0 ), y1 = MAX( 0, y0 ), x2, y2; csz.width = MIN( csz.width, corr->cols - x ); csz.height = MIN( csz.height, corr->rows - y ); isz.width = csz.width + templ->cols - 1; isz.height = csz.height + templ->rows - 1; x2 = MIN( img->cols, x0 + isz.width ); y2 = MIN( img->rows, y0 + isz.height ); for( i = 0; i < cn; i++ ) { CvMat dstub1, *dst1; yofs = i*dftsize.height; src = cvGetSubRect( img, &sstub, cvRect(x1,y1,x2-x1,y2-y1) ); dst = cvGetSubRect( _dft_img, &dstub, cvRect(0,0,isz.width,isz.height) ); dst1 = dst; if( x2 - x1 < isz.width || y2 - y1 < isz.height ) dst1 = cvGetSubRect( _dft_img, &dstub1, cvRect( x1 - x0, y1 - y0, x2 - x1, y2 - y1 )); if( cn > 1 ) { planes[i] = dst1; if( depth != max_depth ) planes[i] = cvInitMatHeader( &temp, y2 - y1, x2 - x1, depth, _buf ); cvSplit( src, planes[0], planes[1], planes[2], planes[3] ); src = planes[i]; planes[i] = 0; } if( dst1 != src ) cvConvert( src, dst1 ); if( dst != dst1 ) cvCopyMakeBorder( dst1, dst, cvPoint(x1 - x0, y1 - y0), borderType ); if( dftsize.width > isz.width ) { cvGetSubRect( _dft_img, dst, cvRect(isz.width, 0, dftsize.width - isz.width,dftsize.height) ); cvZero( dst ); } cvDFT( _dft_img, _dft_img, CV_DXT_FORWARD, isz.height ); cvGetSubRect( dft_templ, dst, cvRect(0,(templ_cn>1?yofs:0),dftsize.width,dftsize.height) ); cvMulSpectrums( _dft_img, dst, _dft_img, CV_DXT_MUL_CONJ ); cvDFT( _dft_img, _dft_img, CV_DXT_INVERSE, csz.height ); src = cvGetSubRect( _dft_img, &sstub, cvRect(0,0,csz.width,csz.height) ); dst = cvGetSubRect( corr, &dstub, cvRect(x,y,csz.width,csz.height) ); if( corr_cn > 1 ) { planes[i] = src; if( corr_depth != max_depth ) { planes[i] = cvInitMatHeader( &temp, csz.height, csz.width, corr_depth, _buf ); cvConvertScale( src, planes[i], 1, delta ); } cvMerge( planes[0], planes[1], planes[2], planes[3], dst ); planes[i] = 0; } else { if( i == 0 ) cvConvertScale( src, dst, 1, delta ); else { if( max_depth > corr_depth ) { cvInitMatHeader( &temp, csz.height, csz.width, corr_depth, _buf ); cvConvert( src, &temp ); src = &temp; } cvAcc( src, dst ); } } } } }
int main(int argc, char ** argv) { int height,width,step,channels,depth; uchar* data1; CvMat *dft_A; CvMat *dft_B; CvMat *dft_C; IplImage* im; IplImage* im1; IplImage* image_ReB; IplImage* image_ImB; IplImage* image_ReC; IplImage* image_ImC; IplImage* complex_ImC; CvScalar val; IplImage* k_image_hdr; int i,j,k; FILE *fp; fp = fopen("test.txt","w+"); int dft_M,dft_N; int dft_M1,dft_N1; CvMat* cvShowDFT1(IplImage*, int, int,char*); void cvShowInvDFT1(IplImage*, CvMat*, int, int,char*); im1 = cvLoadImage( "../homer.jpg",1 ); cvNamedWindow("Original-color", 0); cvShowImage("Original-color", im1); im = cvLoadImage( "../homer.jpg", CV_LOAD_IMAGE_GRAYSCALE ); if( !im ) return -1; cvNamedWindow("Original-gray", 0); cvShowImage("Original-gray", im); // Create a random noise matrix fp = fopen("test.txt","w+"); int val_noise[357*383]; for(i=0; i <im->height;i++){ for(j=0;j<im->width;j++){ fprintf(fp, "%d ",(383*i+j)); val_noise[383*i+j] = rand() % 128; } fprintf(fp, "/n"); } CvMat noise = cvMat(im->height,im->width, CV_8UC1,val_noise); // Add the random noise matric to the image cvAdd(im,&noise,im, 0); cvNamedWindow("Original + Noise", 0); cvShowImage("Original + Noise", im); cvSmooth( im, im, CV_GAUSSIAN, 7, 7, 0.5, 0.5 ); cvNamedWindow("Gaussian Smooth", 0); cvShowImage("Gaussian Smooth", im); // Create a blur kernel IplImage* k_image; float r = rad; float radius=((int)(r)*2+1)/2.0; int rowLength=(int)(2*radius); printf("rowlength %d/n",rowLength); float kernels[rowLength*rowLength]; printf("rowl: %i",rowLength); int norm=0; //Normalization factor int x,y; CvMat kernel; for(x = 0; x < rowLength; x++) for (y = 0; y < rowLength; y++) if (sqrt((x - (int)(radius) ) * (x - (int)(radius) ) + (y - (int)(radius))* (y - (int)(radius))) <= (int)(radius)) norm++; // Populate matrix for (y = 0; y < rowLength; y++) //populate array with values { for (x = 0; x < rowLength; x++) { if (sqrt((x - (int)(radius) ) * (x - (int)(radius) ) + (y - (int)(radius)) * (y - (int)(radius))) <= (int)(radius)) { //kernels[y * rowLength + x] = 255; kernels[y * rowLength + x] =1.0/norm; printf("%f ",1.0/norm); } else{ kernels[y * rowLength + x] =0; } } } kernel= cvMat(rowLength, // number of rows rowLength, // number of columns CV_32FC1, // matrix data type &kernels); k_image_hdr = cvCreateImageHeader( cvSize(rowLength,rowLength), IPL_DEPTH_32F,1); k_image = cvGetImage(&kernel,k_image_hdr); height = k_image->height; width = k_image->width; step = k_image->widthStep/sizeof(float); depth = k_image->depth; channels = k_image->nChannels; //data1 = (float *)(k_image->imageData); data1 = (uchar *)(k_image->imageData); cvNamedWindow("blur kernel", 0); cvShowImage("blur kernel", k_image); dft_M = cvGetOptimalDFTSize( im->height - 1 ); dft_N = cvGetOptimalDFTSize( im->width - 1 ); //dft_M1 = cvGetOptimalDFTSize( im->height+99 - 1 ); //dft_N1 = cvGetOptimalDFTSize( im->width+99 - 1 ); dft_M1 = cvGetOptimalDFTSize( im->height+3 - 1 ); dft_N1 = cvGetOptimalDFTSize( im->width+3 - 1 ); printf("dft_N1=%d,dft_M1=%d/n",dft_N1,dft_M1); // Perform DFT of original image dft_A = cvShowDFT1(im, dft_M1, dft_N1,"original"); //Perform inverse (check) //cvShowInvDFT1(im,dft_A,dft_M1,dft_N1, "original"); - Commented as it overwrites the DFT // Perform DFT of kernel dft_B = cvShowDFT1(k_image,dft_M1,dft_N1,"kernel"); //Perform inverse of kernel (check) //cvShowInvDFT1(k_image,dft_B,dft_M1,dft_N1, "kernel");- Commented as it overwrites the DFT // Multiply numerator with complex conjugate dft_C = cvCreateMat( dft_M1, dft_N1, CV_64FC2 ); printf("%d %d %d %d/n",dft_M,dft_N,dft_M1,dft_N1); // Multiply DFT(blurred image) * complex conjugate of blur kernel cvMulSpectrums(dft_A,dft_B,dft_C,CV_DXT_MUL_CONJ); //cvShowInvDFT1(im,dft_C,dft_M1,dft_N1,"blur1"); // Split Fourier in real and imaginary parts image_ReC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); image_ImC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); complex_ImC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 2); printf("%d %d %d %d/n",dft_M,dft_N,dft_M1,dft_N1); //cvSplit( dft_C, image_ReC, image_ImC, 0, 0 ); cvSplit( dft_C, image_ReC, image_ImC, 0, 0 ); // Compute A^2 + B^2 of denominator or blur kernel image_ReB = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); image_ImB = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); // Split Real and imaginary parts cvSplit( dft_B, image_ReB, image_ImB, 0, 0 ); cvPow( image_ReB, image_ReB, 2.0); cvPow( image_ImB, image_ImB, 2.0); cvAdd(image_ReB, image_ImB, image_ReB,0); val = cvScalarAll(kappa); cvAddS(image_ReB,val,image_ReB,0); //Divide Numerator/A^2 + B^2 cvDiv(image_ReC, image_ReB, image_ReC, 1.0); cvDiv(image_ImC, image_ReB, image_ImC, 1.0); // Merge Real and complex parts cvMerge(image_ReC, image_ImC, NULL, NULL, complex_ImC); // Perform Inverse cvShowInvDFT1(im, (CvMat *)complex_ImC,dft_M1,dft_N1,"O/p Wiener k=1 rad=2"); cvWaitKey(-1); return 0; }
int main(int argc, char ** argv) { const char* filename = argc >=2 ? argv[1] : "lena.jpg"; IplImage * im; IplImage * realInput; IplImage * imaginaryInput; IplImage * complexInput; int dft_M, dft_N; CvMat* dft_A, tmp; IplImage * image_Re; IplImage * image_Im; double m, M; im = cvLoadImage( filename, CV_LOAD_IMAGE_GRAYSCALE ); if( !im ) return -1; realInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); imaginaryInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); complexInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 2); cvScale(im, realInput, 1.0, 0.0); cvZero(imaginaryInput); cvMerge(realInput, imaginaryInput, NULL, NULL, complexInput); dft_M = cvGetOptimalDFTSize( im->height - 1 ); dft_N = cvGetOptimalDFTSize( im->width - 1 ); dft_A = cvCreateMat( dft_M, dft_N, CV_64FC2 ); image_Re = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); image_Im = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); // copy A to dft_A and pad dft_A with zeros cvGetSubRect( dft_A, &tmp, cvRect(0,0, im->width, im->height)); cvCopy( complexInput, &tmp, NULL ); if( dft_A->cols > im->width ) { cvGetSubRect( dft_A, &tmp, cvRect(im->width,0, dft_A->cols - im->width, im->height)); cvZero( &tmp ); } // no need to pad bottom part of dft_A with zeros because of // use nonzero_rows parameter in cvDFT() call below cvDFT( dft_A, dft_A, CV_DXT_FORWARD, complexInput->height ); cvNamedWindow("win", 0); cvNamedWindow("magnitude", 0); cvShowImage("win", im); // Split Fourier in real and imaginary parts cvSplit( dft_A, image_Re, image_Im, 0, 0 ); // Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2) cvPow( image_Re, image_Re, 2.0); cvPow( image_Im, image_Im, 2.0); cvAdd( image_Re, image_Im, image_Re, NULL); cvPow( image_Re, image_Re, 0.5 ); // Compute log(1 + Mag) cvAddS( image_Re, cvScalarAll(1.0), image_Re, NULL ); // 1 + Mag cvLog( image_Re, image_Re ); // log(1 + Mag) // Rearrange the quadrants of Fourier image so that the origin is at // the image center cvShiftDFT( image_Re, image_Re ); cvMinMaxLoc(image_Re, &m, &M, NULL, NULL, NULL); cvScale(image_Re, image_Re, 1.0/(M-m), 1.0*(-m)/(M-m)); cvShowImage("magnitude", image_Re); cvWaitKey(-1); return 0; }
IplImage* create_fourier_image(const IplImage *im) { IplImage *realInput; IplImage *imaginaryInput; IplImage *complexInput; int dft_M, dft_N; CvMat *dft_A, tmp; IplImage *image_Re; IplImage *image_Im; realInput = rb_cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); imaginaryInput = rb_cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); complexInput = rb_cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 2); cvScale(im, realInput, 1.0, 0.0); cvZero(imaginaryInput); cvMerge(realInput, imaginaryInput, NULL, NULL, complexInput); dft_M = cvGetOptimalDFTSize( im->height - 1 ); dft_N = cvGetOptimalDFTSize( im->width - 1 ); dft_A = rb_cvCreateMat( dft_M, dft_N, CV_64FC2 ); image_Re = rb_cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); image_Im = rb_cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); // copy A to dft_A and pad dft_A with zeros cvGetSubRect( dft_A, &tmp, cvRect(0,0, im->width, im->height)); cvCopy( complexInput, &tmp, NULL ); if( dft_A->cols > im->width ) { cvGetSubRect( dft_A, &tmp, cvRect(im->width,0, dft_A->cols - im->width, im->height)); cvZero( &tmp ); } // no need to pad bottom part of dft_A with zeros because of // use nonzero_rows parameter in cvDFT() call below cvDFT( dft_A, dft_A, CV_DXT_FORWARD, complexInput->height ); // Split Fourier in real and imaginary parts cvSplit( dft_A, image_Re, image_Im, 0, 0 ); // Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2) cvPow( image_Re, image_Re, 2.0); cvPow( image_Im, image_Im, 2.0); cvAdd( image_Re, image_Im, image_Re, NULL); cvPow( image_Re, image_Re, 0.5 ); // Compute log(1 + Mag) cvAddS( image_Re, cvScalarAll(1.0), image_Re, NULL ); // 1 + Mag cvLog( image_Re, image_Re ); // log(1 + Mag) // Rearrange the quadrants of Fourier image so that the origin is at // the image center cvShiftDFT( image_Re, image_Re ); cvReleaseImage(&realInput); cvReleaseImage(&imaginaryInput); cvReleaseImage(&complexInput); cvReleaseImage(&image_Im); cvReleaseMat(&dft_A); return image_Re; }