├── README.md └── deconvolution.cpp /README.md: -------------------------------------------------------------------------------- 1 | # deconv 2 | Deblurring through deconvolution in OpenCV 3 | 4 | For details please see my post https://gigadom.wordpress.com/2011/11/09/experiments-with-deblurring-using-opencv/. 5 | 6 | 1. [Re-working the Lucy-Richardson Algorithm in OpenCV/](https://gigadom.wordpress.com/2012/05/14/re-working-the-lucy-richardson-algorithm-in-opencv/) 7 | 2. [Deblurring with OpenCV: Wiener filter reloaded](https://gigadom.wordpress.com/2012/05/11/deblurring-with-opencv-weiner-filter-reloaded/) 8 | 3. [Dabbling with Wiener filter using OpenCV](https://gigadom.wordpress.com/2011/11/14/dabbling-with-wiener-filter-using-opencv/) 9 | 4. [Experiments with deblurring using OpenCV](https://gigadom.wordpress.com/2011/11/09/experiments-with-deblurring-using-opencv/) 10 | 5. [De-blurring revisited with Wiener filter using OpenCV](https://gigadom.wordpress.com/2011/11/22/de-blurring-revisited-with-wiener-filter-using-opencv/) 11 | 12 | For more similar posts visit my blog https://gigadom.wordpress.com/ 13 | -------------------------------------------------------------------------------- /deconvolution.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================ 3 | Name : deconv.c 4 | Author : Tinniam V Ganesh 5 | Version : 6 | Copyright : 7 | Description : Deconvolution in OpenCV 8 | ============================================================================ 9 | */ 10 | 11 | #include 12 | #include 13 | #include "cxcore.h" 14 | #include "cv.h" 15 | #include "highgui.h" 16 | 17 | int main(int argc, char ** argv) 18 | { 19 | int height,width,step,channels; 20 | uchar* data; 21 | uchar* data1; 22 | int i,j,k; 23 | float s; 24 | 25 | CvMat *dft_A; 26 | CvMat *dft_B; 27 | CvMat *dft_C; 28 | IplImage* im; 29 | IplImage* im1; 30 | 31 | IplImage* image_ReB; 32 | IplImage* image_ImB; 33 | 34 | IplImage* image_ReC; 35 | IplImage* image_ImC; 36 | IplImage* complex_ImC; 37 | 38 | IplImage* image_ReDen; 39 | IplImage* image_ImDen; 40 | 41 | FILE *fp; 42 | fp = fopen("test.txt","w+"); 43 | 44 | int dft_M,dft_N; 45 | int dft_M1,dft_N1; 46 | CvMat* cvShowDFT(); 47 | void cvShowInvDFT(); 48 | 49 | im1 = cvLoadImage( "kutty-1.jpg",1 ); 50 | cvNamedWindow("original-color", 0); 51 | cvShowImage("original-color", im1); 52 | im = cvLoadImage( "kutty-1.jpg", CV_LOAD_IMAGE_GRAYSCALE ); 53 | if( !im ) 54 | return -1; 55 | 56 | cvNamedWindow("original-gray", 0); 57 | cvShowImage("original-gray", im); 58 | // Create blur kernel (non-blind) 59 | //float vals[]={.000625,.000625,.000625,.003125,.003125,.003125,.000625,.000625,.000625}; 60 | //float vals[]={-0.167,0.333,0.167,-0.167,.333,.167,-0.167,.333,.167}; 61 | 62 | float vals[]={.055,.055,.055,.222,.222,.222,.055,.055,.055}; 63 | CvMat kernel = cvMat(3, // number of rows 64 | 3, // number of columns 65 | CV_32FC1, // matrix data type 66 | vals); 67 | IplImage* k_image_hdr; 68 | IplImage* k_image; 69 | 70 | k_image_hdr = cvCreateImageHeader(cvSize(3,3),IPL_DEPTH_64F,2); 71 | k_image = cvCreateImage(cvSize(3,3),IPL_DEPTH_64F,1); 72 | k_image = cvGetImage(&kernel,k_image_hdr); 73 | 74 | /*IplImage* k_image; 75 | k_image = cvLoadImage( "kernel4.bmp",0 );*/ 76 | cvNamedWindow("blur kernel", 0); 77 | 78 | height = k_image->height; 79 | width = k_image->width; 80 | step = k_image->widthStep; 81 | 82 | channels = k_image->nChannels; 83 | //data1 = (float *)(k_image->imageData); 84 | data1 = (uchar *)(k_image->imageData); 85 | 86 | cvShowImage("blur kernel", k_image); 87 | 88 | dft_M = cvGetOptimalDFTSize( im->height - 1 ); 89 | dft_N = cvGetOptimalDFTSize( im->width - 1 ); 90 | 91 | //dft_M1 = cvGetOptimalDFTSize( im->height+99 - 1 ); 92 | //dft_N1 = cvGetOptimalDFTSize( im->width+99 - 1 ); 93 | 94 | dft_M1 = cvGetOptimalDFTSize( im->height+3 - 1 ); 95 | dft_N1 = cvGetOptimalDFTSize( im->width+3 - 1 ); 96 | 97 | // Perform DFT of original image 98 | dft_A = cvShowDFT(im, dft_M1, dft_N1,"original"); 99 | //Perform inverse (check & comment out) - Commented as it overwrites dft_A 100 | //cvShowInvDFT(im,dft_A,dft_M1,dft_N1,fp, "original"); 101 | 102 | // Perform DFT of kernel 103 | dft_B = cvShowDFT(k_image,dft_M1,dft_N1,"kernel"); 104 | //Perform inverse of kernel (check & comment out) - commented as it overwrites dft_B 105 | //cvShowInvDFT(k_image,dft_B,dft_M1,dft_N1,fp, "kernel"); 106 | 107 | // Multiply numerator with complex conjugate 108 | dft_C = cvCreateMat( dft_M1, dft_N1, CV_64FC2 ); 109 | 110 | printf("%d %d %d %d\n",dft_M,dft_N,dft_M1,dft_N1); 111 | 112 | // Multiply DFT(blurred image) * complex conjugate of blur kernel 113 | cvMulSpectrums(dft_A,dft_B,dft_C,CV_DXT_MUL_CONJ); 114 | 115 | // Split Fourier in real and imaginary parts 116 | image_ReC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); 117 | image_ImC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); 118 | complex_ImC = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 2); 119 | 120 | printf("%d %d %d %d\n",dft_M,dft_N,dft_M1,dft_N1); 121 | 122 | //cvSplit( dft_C, image_ReC, image_ImC, 0, 0 ); 123 | cvSplit( dft_C, image_ReC, image_ImC, 0, 0 ); 124 | 125 | // Compute A^2 + B^2 of denominator or blur kernel 126 | image_ReB = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); 127 | image_ImB = cvCreateImage( cvSize(dft_N1, dft_M1), IPL_DEPTH_64F, 1); 128 | 129 | // Split Real and imaginary parts 130 | cvSplit( dft_B, image_ReB, image_ImB, 0, 0 ); 131 | cvPow( image_ReB, image_ReB, 2.0); 132 | cvPow( image_ImB, image_ImB, 2.0); 133 | cvAdd(image_ReB, image_ImB, image_ReB,0); 134 | 135 | //Divide Numerator/A^2 + B^2 136 | cvDiv(image_ReC, image_ReB, image_ReC, 1.0); 137 | cvDiv(image_ImC, image_ReB, image_ImC, 1.0); 138 | 139 | // Merge Real and complex parts 140 | cvMerge(image_ReC, image_ImC, NULL, NULL, complex_ImC); 141 | 142 | // Perform Inverse 143 | cvShowInvDFT(im, complex_ImC,dft_M1,dft_N1,fp,"deblur"); 144 | cvWaitKey(-1); 145 | return 0; 146 | } 147 | 148 | CvMat* cvShowDFT(im, dft_M, dft_N,src) 149 | IplImage* im; 150 | int dft_M, dft_N; 151 | char* src; 152 | { 153 | IplImage* realInput; 154 | IplImage* imaginaryInput; 155 | IplImage* complexInput; 156 | 157 | CvMat* dft_A, tmp; 158 | 159 | IplImage* image_Re; 160 | IplImage* image_Im; 161 | 162 | char str[80]; 163 | 164 | double m, M; 165 | 166 | realInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); 167 | imaginaryInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); 168 | complexInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 2); 169 | 170 | cvScale(im, realInput, 1.0, 0.0); 171 | cvZero(imaginaryInput); 172 | cvMerge(realInput, imaginaryInput, NULL, NULL, complexInput); 173 | 174 | dft_A = cvCreateMat( dft_M, dft_N, CV_64FC2 ); 175 | image_Re = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); 176 | image_Im = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); 177 | 178 | // copy A to dft_A and pad dft_A with zeros 179 | cvGetSubRect( dft_A, &tmp, cvRect(0,0, im->width, im->height)); 180 | cvCopy( complexInput, &tmp, NULL ); 181 | if( dft_A->cols > im->width ) 182 | { 183 | cvGetSubRect( dft_A, &tmp, cvRect(im->width,0, dft_A->cols - im->width, im->height)); 184 | cvZero( &tmp ); 185 | } 186 | 187 | // no need to pad bottom part of dft_A with zeros because of 188 | // use nonzero_rows parameter in cvDFT() call below 189 | 190 | cvDFT( dft_A, dft_A, CV_DXT_FORWARD, complexInput->height ); 191 | 192 | strcpy(str,"DFT -"); 193 | strcat(str,src); 194 | cvNamedWindow(str, 0); 195 | 196 | // Split Fourier in real and imaginary parts 197 | cvSplit( dft_A, image_Re, image_Im, 0, 0 ); 198 | 199 | // Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2) 200 | cvPow( image_Re, image_Re, 2.0); 201 | cvPow( image_Im, image_Im, 2.0); 202 | cvAdd( image_Re, image_Im, image_Re, NULL); 203 | cvPow( image_Re, image_Re, 0.5 ); 204 | 205 | // Compute log(1 + Mag) 206 | cvAddS( image_Re, cvScalarAll(1.0), image_Re, NULL ); // 1 + Mag 207 | cvLog( image_Re, image_Re ); // log(1 + Mag) 208 | 209 | cvMinMaxLoc(image_Re, &m, &M, NULL, NULL, NULL); 210 | cvScale(image_Re, image_Re, 1.0/(M-m), 1.0*(-m)/(M-m)); 211 | cvShowImage(str, image_Re); 212 | return(dft_A); 213 | } 214 | 215 | void cvShowInvDFT(im, dft_A, dft_M, dft_N,fp, src) 216 | IplImage* im; 217 | CvMat* dft_A; 218 | int dft_M,dft_N; 219 | FILE *fp; 220 | char* src; 221 | { 222 | 223 | IplImage* realInput; 224 | IplImage* imaginaryInput; 225 | IplImage* complexInput; 226 | 227 | IplImage * image_Re; 228 | IplImage * image_Im; 229 | 230 | double m, M; 231 | char str[80]; 232 | 233 | realInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); 234 | imaginaryInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1); 235 | complexInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 2); 236 | 237 | image_Re = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); 238 | image_Im = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1); 239 | 240 | //cvDFT( dft_A, dft_A, CV_DXT_INV_SCALE, complexInput->height ); 241 | cvDFT( dft_A, dft_A, CV_DXT_INV_SCALE, dft_M); 242 | strcpy(str,"DFT INVERSE - "); 243 | strcat(str,src); 244 | cvNamedWindow(str, 0); 245 | 246 | // Split Fourier in real and imaginary parts 247 | cvSplit( dft_A, image_Re, image_Im, 0, 0 ); 248 | 249 | // Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2) 250 | cvPow( image_Re, image_Re, 2.0); 251 | cvPow( image_Im, image_Im, 2.0); 252 | cvAdd( image_Re, image_Im, image_Re, NULL); 253 | cvPow( image_Re, image_Re, 0.5 ); 254 | 255 | // Compute log(1 + Mag) 256 | cvAddS( image_Re, cvScalarAll(1.0), image_Re, NULL ); // 1 + Mag 257 | cvLog( image_Re, image_Re ); // log(1 + Mag) 258 | 259 | cvMinMaxLoc(image_Re, &m, &M, NULL, NULL, NULL); 260 | cvScale(image_Re, image_Re, 1.0/(M-m), 1.0*(-m)/(M-m)); 261 | //cvCvtColor(image_Re, image_Re, CV_GRAY2RGBA); 262 | 263 | cvShowImage(str, image_Re); 264 | } 265 | 266 | 267 | --------------------------------------------------------------------------------