fft_enhance_cubs.m
Upload User: chenghe_sh
Upload Date: 2007-04-21
Package Size: 412k
Code Size: 20k
Category:

Graph Recognize

Development Platform:

Matlab

  1. %--------------------------------------------------------------------------
  2. %fft_enhance_cubs
  3. %enhances the fingerprint image
  4. %syntax:
  5. %[oimg,fimg,bwimg,eimg,enhimg] =  fft_enhance_cubs(img)
  6. %oimg -  [OUT] block orientation image(can be viewed using
  7. %        view_orientation_image.m)
  8. %fimg  - [OUT] block frequency image(indicates ridge spacing)
  9. %bwimg - [OUT] shows angular bandwidth image(filter bandwidth adapts near the
  10. %        singular points)
  11. %eimg  - [OUT] energy image. Indicates the 'ridgeness' of a block (can be 
  12. %        used for fingerprint segmentation)
  13. %enhimg- [OUT] enhanced image
  14. %img   - [IN]  input fingerprint image (HAS to be of DOUBLE type)
  15. %Contact:
  16. %   ssc5@cubs.buffalo.edu sharat@mit.edu
  17. %   http://www.sharat.org
  18. %Reference:
  19. %1. S. Chikkerur, C.Wu and V. Govindaraju, "Systematic approach for feature
  20. %   extraction in Fingerprint Images", ICBA 2004
  21. %2. S. Chikkerur and V. Govindaraju, "Fingerprint Image Enhancement using 
  22. %   STFT Analysis", International Workshop on Pattern Recognition for Crime 
  23. %   Prevention, Security and Surveillance, ICAPR 2005
  24. %3. S. Chikkeur, "Online Fingerprint Verification", M. S. Thesis,
  25. %   University at Buffalo, 2005
  26. %4. T. Jea and V. Govindaraju, "A Minutia-Based Partial Fingerprint Recognition System", 
  27. %   to appear in Pattern Recognition 2005
  28. %5. S. Chikkerur, "K-plet and CBFS: A Graph based Fingerprint
  29. %   Representation and Matching Algorithm", submitted, ICB 2006
  30. % See also: cubs_visualize_template
  31. %--------------------------------------------------------------------------
  32. function [oimg,fimg,bwimg,eimg,enhimg] =  fft_enhance_cubs(img)
  33.     global NFFT;
  34.     NFFT            =   32;     %size of FFT
  35.     BLKSZ           =   12;      %size of the block
  36.     OVRLP           =   6;      %size of overlap
  37.     ALPHA           =   0.4;    %root filtering
  38.     RMIN            =   5;      %min allowable ridge spacing
  39.     RMAX            =   20;     %maximum allowable ridge spacing
  40.     do_prefiltering =   1;
  41.     [nHt,nWt]       =   size(img);  
  42.     img             =   im2double(img);    %convert to DOUBLE
  43.     
  44.     nBlkHt          =   floor((nHt-2*OVRLP)/BLKSZ);
  45.     nBlkWt          =   floor((nWt-2*OVRLP)/BLKSZ);
  46.     fftSrc          =   zeros(nBlkHt*nBlkWt,NFFT*NFFT); %stores FFT
  47.     nWndSz          =   BLKSZ+2*OVRLP; %size of analysis window. 
  48.     warning off MATLAB:divideByZero
  49.     %-------------------------
  50.     %allocate outputs
  51.     %-------------------------
  52.     oimg        =   zeros(nBlkHt,nBlkWt);
  53.     fimg        =   zeros(nBlkHt,nBlkWt);
  54.     bwimg       =   zeros(nBlkHt,nBlkWt);
  55.     eimg        =   zeros(nBlkHt,nBlkWt);
  56.     enhimg      =   zeros(nHt,nWt);
  57.     
  58.     %-------------------------
  59.     %precomputations
  60.     %-------------------------
  61.     [x,y]       =   meshgrid(0:nWndSz-1,0:nWndSz-1);
  62.     dMult       =   (-1).^(x+y); %used to center the FFT
  63.     [x,y]       =   meshgrid(-NFFT/2:NFFT/2-1,-NFFT/2:NFFT/2-1);
  64.     r           =   sqrt(x.^2+y.^2)+eps;
  65.     th          =   atan2(y,x);
  66.     th(th<0)    =   th(th<0)+pi;
  67.     w           =   raised_cosine_window(BLKSZ,OVRLP); %spectral window
  68.     
  69.     %-------------------------
  70.     %FFT Analysis
  71.     %-------------------------
  72.     for i = 0:nBlkHt-1
  73.         nRow = i*BLKSZ+OVRLP+1;  
  74.         for j = 0:nBlkWt-1
  75.             nCol = j*BLKSZ+OVRLP+1;
  76.             %extract local block
  77.             blk     =   img(nRow-OVRLP:nRow+BLKSZ+OVRLP-1,nCol-OVRLP:nCol+BLKSZ+OVRLP-1);
  78.             %remove dc
  79.             dAvg    =   sum(sum(blk))/(nWndSz*nWndSz);
  80.             blk     =   blk-dAvg;   %remove DC content
  81.             blk     =   blk.*w;     %multiply by spectral window
  82.             %--------------------------
  83.             %do pre filtering
  84.             %--------------------------
  85.             blkfft  =   fft2(blk.*dMult,NFFT,NFFT);
  86.             if(do_prefiltering)
  87.                 dEnergy =   abs(blkfft).^2;
  88.                 blkfft  =   blkfft.*sqrt(dEnergy);      %root filtering(for diffusion)
  89.             end;
  90.             fftSrc(nBlkWt*i+j+1,:) = transpose(blkfft(:));
  91.             dEnergy =   abs(blkfft).^2;             %----REDUCE THIS COMPUTATION----
  92.             %--------------------------
  93.             %compute statistics
  94.             %--------------------------
  95.             dTotal          =   sum(sum(dEnergy));%/(NFFT*NFFT);
  96.             fimg(i+1,j+1)   =   NFFT/(compute_mean_frequency(dEnergy,r)+eps); %ridge separation
  97.             oimg(i+1,j+1)   =   compute_mean_angle(dEnergy,th);         %ridge angle
  98.             eimg(i+1,j+1)   =   log(dTotal+eps);                        %used for segmentation
  99.         end;%for j
  100.     end;%for i
  101.     %-------------------------
  102.     %precomputations
  103.     %-------------------------
  104.     [x,y]       =   meshgrid(-NFFT/2:NFFT/2-1,-NFFT/2:NFFT/2-1);
  105.     dMult       =   (-1).^(x+y); %used to center the FFT
  106.     %-------------------------
  107.     %process the resulting maps
  108.     %-------------------------
  109.     for i = 1:3
  110.         oimg = smoothen_orientation_image(oimg);            %smoothen orientation image
  111.     end;
  112.     fimg    =   smoothen_frequency_image(fimg,RMIN,RMAX,5); %diffuse frequency image
  113.     cimg    =   compute_coherence(oimg);                    %coherence image for bandwidth
  114.     bwimg   =   get_angular_bw_image(cimg);                 %QUANTIZED bandwidth image
  115.     %-------------------------
  116.     %FFT reconstruction
  117.     %-------------------------
  118.     for i = 0:nBlkHt-1
  119.         for j = 0:nBlkWt-1
  120.             nRow = i*BLKSZ+OVRLP+1;            
  121.             nCol = j*BLKSZ+OVRLP+1;
  122.             %--------------------------
  123.             %apply the filters
  124.             %--------------------------
  125.             blkfft  =   reshape(transpose(fftSrc(nBlkWt*i+j+1,:)),NFFT,NFFT);
  126.             %--------------------------
  127.             %reconstruction
  128.             %--------------------------
  129.             af      =   get_angular_filter(oimg(i+1,j+1),bwimg(i+1,j+1));
  130.             rf      =   get_radial_filter(fimg(i+1,j+1));
  131.             blkfft  =   blkfft.*(af).*(rf); 
  132.             blk     =   real(ifft2(blkfft).*dMult);
  133.             enhimg(nRow:nRow+BLKSZ-1,nCol:nCol+BLKSZ-1)=blk(OVRLP+1:OVRLP+BLKSZ,OVRLP+1:OVRLP+BLKSZ);
  134.         end;%for j
  135.     end;%for i
  136.     %end block processing
  137.     %--------------------------
  138.     %contrast enhancement
  139.     %--------------------------
  140.     enhimg =sqrt(abs(enhimg)).*sign(enhimg);
  141.     enhimg =imscale(enhimg);
  142.     enhimg =im2uint8(enhimg);
  143.     
  144.     %--------------------------
  145.     %clean up the image
  146.     %--------------------------
  147.     emsk            = segment_print(enhimg,0);
  148.     enhimg(emsk==0) = 128;
  149. %end function fft_enhance_cubs
  150. %-----------------------------------
  151. %raised_cosine
  152. %returns 1D spectral window
  153. %syntax:
  154. %y = raised_cosine(nBlkSz,nOvrlp)
  155. %y      - [OUT] 1D raised cosine function
  156. %nBlkSz - [IN]  the window is constant here
  157. %nOvrlp - [IN]  the window has transition here
  158. %-----------------------------------
  159. function y = raised_cosine(nBlkSz,nOvrlp)
  160.     nWndSz  =   (nBlkSz+2*nOvrlp);
  161.     x       =   abs(-nWndSz/2:nWndSz/2-1);
  162.     y       =   0.5*(cos(pi*(x-nBlkSz/2)/nOvrlp)+1);
  163.     y(abs(x)<nBlkSz/2)=1;
  164. %end function raised_cosine
  165. %-----------------------------------
  166. %raised_cosine_window
  167. %returns 2D spectral window
  168. %syntax:
  169. %w = raised_cosine_window(blksz,ovrlp)
  170. %w      - [OUT] 1D raised cosine function
  171. %nBlkSz - [IN]  the window is constant here
  172. %nOvrlp - [IN]  the window has transition here
  173. %-----------------------------------
  174. function w = raised_cosine_window(blksz,ovrlp)
  175.     y = raised_cosine(blksz,ovrlp);
  176.     w = y(:)*y(:)';
  177. %end function raised_cosine_window
  178. %---------------------------------------------------------------------
  179. %get_angular_filter
  180. %generates an angular filter centered around 'th' and with bandwidth 'bw'
  181. %the filters in angf_xx are precomputed using angular_filter_bank.m
  182. %syntax:
  183. %r = get_angular_filter(t0,bw)
  184. %r - [OUT] angular filter of size NFFTxNFFT
  185. %t0- mean angle (obtained from orientation image)
  186. %bw- angular bandwidth(obtained from bandwidth image)
  187. %angf_xx - precomputed filters (using angular_filter_bank.m)
  188. %-----------------------------------------------------------------------
  189. function rmsk = get_angular_filter(t0,BW)
  190.      global NFFT;
  191.      [x,y]   =   meshgrid(-NFFT/2:NFFT/2-1,-NFFT/2:NFFT/2-1);
  192.      r       =   sqrt(x.^2+y.^2);
  193.      th      =   atan2(y,x);
  194.      th(th<0)=   th(th<0)+2*pi;  %unsigned
  195.      t1      =   mod(t0+pi,2*pi);
  196.      %-----------------
  197.      %first lobe
  198.      %-----------------
  199.      d          = angular_distance(th,t0);
  200.      msk        = 1+cos(d*pi/BW); 
  201.      msk(d>BW)  = 0;
  202.      rmsk       = msk;                              %save first lobe
  203.      %-----------------
  204.      %second lobe
  205.      %-----------------
  206.      d          = angular_distance(th,t1);
  207.      msk        = 1+cos(d*pi/BW); 
  208.      msk(d>BW)  = 0;
  209.      rmsk       = (rmsk+msk);
  210. %end function
  211. %---------------------------------------------------------------------
  212. %get_radial_filter
  213. %generates an radial filter
  214. %syntax:
  215. %r = get_radial_filter(r0)
  216. %r - [OUT] angular filter of size NFFTxNFFT
  217. %r0- center frequency
  218. %-----------------------------------------------------------------------
  219. function rmsk = get_radial_filter(r0)
  220.      global NFFT;
  221.      N          =   4;
  222.      r0         =   NFFT/r0;
  223.      BW         =   r0*1.75-r0/1.75;
  224.      [x,y]      =   meshgrid(-NFFT/2:NFFT/2-1,-NFFT/2:NFFT/2-1);
  225.      r          =   sqrt(x.^2+y.^2);
  226.      num        =   (r*BW).^(2*N);
  227.      den        =   (r*BW).^(2*N)+((r.^2-r0.^2)).^(2*N);
  228.      rmsk       =   sqrt(num./den);
  229. %end function get_radial_filter
  230. %-----------------------------------------------------------
  231. %get_angular_bw_image
  232. %the bandwidth allocation is currently based on heuristics
  233. %(domain knowledge :)). 
  234. %syntax:
  235. %bwimg = get_angular_bw_image(c)
  236. %-----------------------------------------------------------
  237. function bwimg = get_angular_bw_image(c)
  238.     bwimg   =   zeros(size(c));
  239.     bwimg(:,:)    = pi/2;                       %med bw
  240.     bwimg(c<=0.7) = pi;                         %high bw
  241.     bwimg(c>=0.9) = pi/6;                       %low bw
  242. %end function get_angular_bw
  243. %-----------------------------------------------------------
  244. %get_angular_bw_image
  245. %the bandwidth allocation is currently based on heuristics
  246. %(domain knowledge :)). 
  247. %syntax:
  248. %bwimg = get_angular_bw_image(c)
  249. %-----------------------------------------------------------
  250. function mth = compute_mean_angle(dEnergy,th)
  251.     global NFFT;
  252.     sth         =   sin(2*th);
  253.     cth         =   cos(2*th);
  254.     num         =   sum(sum(dEnergy.*sth));
  255.     den         =   sum(sum(dEnergy.*cth));
  256.     mth         =   0.5*atan2(num,den);
  257.     if(mth <0)
  258.         mth = mth+pi;
  259.     end;
  260. %end function compute_mean_angle
  261. %-----------------------------------------------------------
  262. %get_angular_bw_image
  263. %the bandwidth allocation is currently based on heuristics
  264. %(domain knowledge :)). 
  265. %syntax:
  266. %bwimg = get_angular_bw_image(c)
  267. %-----------------------------------------------------------
  268. function mr = compute_mean_frequency(dEnergy,r)
  269.     global NFFT;
  270.     num         =   sum(sum(dEnergy.*r));
  271.     den         =   sum(sum(dEnergy));
  272.     mr          =   num/(den+eps);
  273. %end function compute_mean_angle
  274. %-----------------------------------------
  275. %angular_distance
  276. %computes angular distance-acute angle 
  277. %-----------------------------------------
  278. function d = angular_distance(th,t0)
  279.     d = abs(th-t0);
  280.     d = min(d,2*pi-d);
  281. %end function angular_distance
  282. %-----------------------------------------------------
  283. %imscale
  284. %normalizes the image to range [0-1]
  285. %-----------------------------------------------------
  286. function y = imscale(x)
  287.     mn = min(min(x));
  288.     mx = max(max(x));
  289.     y  = (x-mn)/(mx-mn);
  290. %end function imscale
  291. %--------------------------------------------------------------------------
  292. %  Version 1.0 March 2005
  293. %  Copyright (c) 2005-2010 by Center for Unified Biometrics and Sensors
  294. %  www.cubs.buffalo.edu
  295. %
  296. %otsu_threshold
  297. %implements otsu's thresholding method
  298. %Contact:
  299. %   ssc5@eng.buffalo.edu
  300. %   www.eng.buffalo.edu/~ssc5
  301. %Reference:
  302. %Otsu, A Threshold Selection Method from Gray-Level Histogram, IEEE Trans.
  303. %on Systems, Man and Cybernetics, 1979
  304. %--------------------------------------------------------------------------
  305. function t = otsu_threshold(img)
  306.     %obtain probability
  307.     [ht,wt] = size(img);
  308.     [p,x]   = imhist(img,256);
  309.     p       = p/(ht*wt);
  310.     w       = zeros(1,256);
  311.     m       = zeros(1,256);
  312.     w(1)    = p(1);
  313.     m(1)    = p(1);
  314.     for i=2:256
  315.         w(i)= w(i-1)+p(i);
  316.         m(i)= i*p(i)+m(i-1);
  317.     end;
  318.     mt = m(end);
  319.     w  = w+eps;
  320.     sigma_b = ((mt*w-m).^2)./(w.*(1-w));
  321.     t       = find(sigma_b == max(sigma_b));
  322.     t       = x(t(1));
  323. %end function
  324. %--------------------------------------------------------------------------
  325. %  Version 1.0 March 2005
  326. %  Copyright (c) 2005-2010 by Center for Unified Biometrics and Sensors
  327. %  www.cubs.buffalo.edu
  328. %
  329. %segment_print
  330. %segments the fingerprint region from the background based on morphological
  331. %operations
  332. %syntax:
  333. % [msk]= segment_print(img,iters,verbose)
  334. % img       - original image 
  335. % verbose   - a value of 1 displays intermediate results
  336. %Contact:
  337. %   ssc5@cubs.buffalo.edu, sharat@mit.edu
  338. %   http://www.sharat.org
  339. %--------------------------------------------------------------------------
  340. function msk    =   segment_print(img,verbose)
  341.     [ht,wt]     =   size(img);
  342.     y           =   im2double(img);
  343.     img         =   im2double(img);
  344.     ITERS       =   4;
  345.     %-----------------
  346.     %compute the mask
  347.     %-----------------
  348.     for i=1:ITERS
  349.         y           =   imerode(y,ones(5,5));      %diffuse blob
  350.         c           =   y.^2;                       %enhance contrast
  351.         msk         =   ~im2bw(c,otsu_threshold(c)); %find mask
  352.         %---------------------------------------------------
  353.         %remove sections that might grow to join main blob
  354.         %---------------------------------------------------
  355.         if(i == 2)
  356.             small       =   msk & ~bwareaopen(msk,floor(0.1*ht*wt),4);
  357.             y(small==1) =   sum(sum(img))/(ht*wt);
  358.         end;
  359.         %---------------------------------------------------
  360.         %display intermediate result
  361.         %---------------------------------------------------
  362.         if(verbose==1)
  363.             subplot(1,4,1),imagesc(img),title('Original');
  364.             subplot(1,4,2),imagesc(y),title('Eroded');
  365.             subplot(1,4,3),imagesc(c);colormap('gray'),title('Enhanced');
  366.             subplot(1,4,4),imagesc(msk),title('Segmented');
  367.             pause;
  368.             drawnow;
  369.         end;
  370.     end;
  371.     %----------------------------------------
  372.     %get the largest blob as the fingerprint
  373.     %----------------------------------------
  374.     msk = bwareaopen(msk,round(0.15*ht*wt));
  375.     msk = imerode(msk,ones(7,7));           %erode boundary
  376.     msk = imfill(msk,'holes');              %fill holes
  377.     %---------------------------------------------------
  378.     %display final result
  379.     %---------------------------------------------------
  380.     if(verbose==1)
  381.         figure,imagesc(msk.*img),axis image,colormap('gray'),title('Final');
  382.     end;
  383. %end function isotropic_diffusion
  384. %------------------------------------------------------------------------
  385. %compute_coherence
  386. %Computes the coherence image. 
  387. %Usage:
  388. %[cimg] = compute_coherence(oimg)
  389. %oimg - orientation image
  390. %cimg - coherence image(0-low coherence,1-high coherence)
  391. %Contact:
  392. %   ssc5@cubs.buffalo.edu, sharat@mit.edu
  393. %   http://www.sharat.org
  394. %Reference:
  395. %A. Ravishankar Rao,"A taxonomy of texture description", Springer Verlag
  396. %------------------------------------------------------------------------
  397. function [cimg] = compute_coherence(oimg)
  398.     [h,w]   =   size(oimg);
  399.     cimg    =   zeros(h,w);
  400.     N       =   2;
  401.     %---------------
  402.     %pad the image
  403.     %---------------
  404.     oimg    =   [flipud(oimg(1:N,:));oimg;flipud(oimg(h-N+1:h,:))]; %pad the rows
  405.     oimg    =   [fliplr(oimg(:,1:N)),oimg,fliplr(oimg(:,w-N+1:w))]; %pad the cols
  406.     %compute coherence
  407.     for i=N+1:h+N
  408.         for j = N+1:w+N
  409.             th  = oimg(i,j);
  410.             blk = oimg(i-N:i+N,j-N:j+N);
  411.             cimg(i-N,j-N)=sum(sum(abs(cos(blk-th))))/((2*N+1).^2);
  412.         end;
  413.     end;
  414. %end function compute_coherence
  415. %------------------------------------------------------------------------
  416. %smoothen_frequency_image
  417. %smoothens the frequency image through a process of diffusion
  418. %Usage:
  419. %new_oimg = smoothen_frequency_image(fimg,RLOW,RHIGH,diff_cycles)
  420. %fimg       - frequency image image
  421. %nimg       - filtered frequency image
  422. %RLOW       - lowest allowed ridge separation
  423. %RHIGH      - highest allowed ridge separation
  424. %diff_cyles - number of diffusion cycles
  425. %Contact:
  426. %   ssc5@cubs.buffalo.edu sharat@mit.edu
  427. %   http://www.sharat.org
  428. %Reference:
  429. %1. S. Chikkerur, C.Wu and V. Govindaraju, "Systematic approach for feature
  430. %   extraction in Fingerprint Images", ICBA 2004
  431. %2. S. Chikkerur and V. Govindaraju, "Fingerprint Image Enhancement using 
  432. %   STFT Analysis", International Workshop on Pattern Recognition for Crime 
  433. %   Prevention, Security and Surveillance, ICAPR 2005
  434. %3. S. Chikkeur, "Online Fingerprint Verification", M. S. Thesis,
  435. %   University at Buffalo, 2005
  436. %4. T. Jea and V. Govindaraju, "A Minutia-Based Partial Fingerprint Recognition System", 
  437. %   to appear in Pattern Recognition 2005
  438. %5. S. Chikkerur, "K-plet and CBFS: A Graph based Fingerprint
  439. %   Representation and Matching Algorithm", submitted, ICB 2006
  440. % See also: cubs_visualize_template
  441. %------------------------------------------------------------------------
  442. function nfimg = smoothen_frequency_image(fimg,RLOW,RHIGH,diff_cycles)
  443.     valid_nbrs  =   3; %uses only pixels with more then valid_nbrs for diffusion
  444.     [ht,wt]     =   size(fimg);
  445.     nfimg       =   fimg;
  446.     N           =   1;
  447.     
  448.     %---------------------------------
  449.     %perform diffusion
  450.     %---------------------------------
  451.     h           =   fspecial('gaussian',2*N+1);
  452.     cycles      =   0;
  453.     invalid_cnt = sum(sum(fimg<RLOW | fimg>RHIGH));
  454.     while((invalid_cnt>0 &cycles < diff_cycles) | cycles < diff_cycles)
  455.         %---------------
  456.         %pad the image
  457.         %---------------
  458.         fimg    =   [flipud(fimg(1:N,:));fimg;flipud(fimg(ht-N+1:ht,:))]; %pad the rows
  459.         fimg    =   [fliplr(fimg(:,1:N)),fimg,fliplr(fimg(:,wt-N+1:wt))]; %pad the cols
  460.         %---------------
  461.         %perform diffusion
  462.         %---------------
  463.         for i=N+1:ht+N
  464.          for j = N+1:wt+N
  465.                 blk = fimg(i-N:i+N,j-N:j+N);
  466.                 msk = (blk>=RLOW & blk<=RHIGH);
  467.                 if(sum(sum(msk))>=valid_nbrs)
  468.                     blk           =blk.*msk;
  469.                     nfimg(i-N,j-N)=sum(sum(blk.*h))/sum(sum(h.*msk));
  470.                 else
  471.                     nfimg(i-N,j-N)=-1; %invalid value
  472.                 end;
  473.          end;
  474.         end;
  475.         %---------------
  476.         %prepare for next iteration
  477.         %---------------
  478.         fimg        =   nfimg;
  479.         invalid_cnt =   sum(sum(fimg<RLOW | fimg>RHIGH));
  480.         cycles      =   cycles+1;
  481.     end;
  482.     cycles
  483. %end function smoothen_orientation_image
  484. %------------------------------------------------------------------------
  485. %smoothen_orientation_image
  486. %smoothens the orientation image through vectorial gaussian filtering
  487. %Usage:
  488. %new_oimg = smoothen_orientation_image(oimg)
  489. %oimg     - orientation image
  490. %new_oimg - filtered orientation image
  491. %Contact:
  492. %   ssc5@cubs.buffalo.edu,sharat@mit.edu
  493. %   http://www.sharat.org
  494. %Reference:
  495. %M. Kaas and A. Witkin, "Analyzing oriented patterns", Computer Vision
  496. %Graphics Image Processing 37(4), pp 362--385, 1987
  497. %------------------------------------------------------------------------
  498. function noimg = smoothen_orientation_image(oimg)
  499.     %---------------------------
  500.     %smoothen the image
  501.     %---------------------------
  502.     gx      =   cos(2*oimg);
  503.     gy      =   sin(2*oimg);
  504.     
  505.     msk     =   fspecial('gaussian',5);
  506.     gfx     =   imfilter(gx,msk,'symmetric','same');
  507.     gfy     =   imfilter(gy,msk,'symmetric','same');
  508.     noimg   =   atan2(gfy,gfx);
  509.     noimg(noimg<0) = noimg(noimg<0)+2*pi;
  510.     noimg   =   0.5*noimg;
  511. %end function smoothen_orientation_image