/home/neoflo/smb4k/SERVEUR/Millie/trunk/src/operator/InpaintOperator.cpp

Aller à la documentation de ce fichier.
00001 /******************************************************************************
00002  *       __    _    _   _       _       _   _____                             *
00003  *       | \  / |  | | | |     | |     | |  | ___|                            *
00004  *       |  \/  |  | | | |     | |     | |  | |_                              *
00005  *       |      |  | | | |     | |     | |  |  _|                             *
00006  *       | |\/| |  | | | |__   | |__   | |  | |__                             *
00007  *       |_|  |_|  |_| |____|  |____|  |_|  |____|                            *
00008  * __________________________________________________________________________ *
00009  *                 Multifunctional Library For Image Processing               *
00010  *                                                                            *
00011  *                                                                            *
00012  *                                                                            *
00013  *      (c) Copyright 2007 by Humbert Florent                                 *
00014  *                                                                            *
00015  *      This program is free software; you can redistribute it and/or modify  *
00016  *      it under the terms of the GNU General Public License as published by  *
00017  *      the Free Software Foundation; only version 2 of the License.          *
00018  *                                                                            *
00019  *      This program is distributed in the hope that it will be useful,       *
00020  *      but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00021  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00022  *      GNU General Public License for more details.                          *
00023  *                                                                            *
00024  *      You should have received a copy of the GNU General Public License     *
00025  *      along with this program; if not, write to the Free Software           *
00026  *      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA             *
00027  *      02111-1307, USA.                                                      *
00028  ******************************************************************************/
00029 
00040 #include "InpaintOperator.hpp"
00041 
00042 #include <cmath>
00043 #include <iostream>
00044 
00045 using namespace Millie;
00046 
00047 static float absolue(float a);
00048 
00049 inline float absolue(float a)
00050 {
00051   if(a<=0)
00052     return -a;
00053   else
00054     return a;
00055 }
00056 
00057 
00058 
00059 
00060 void  InpaintOperator::compute(Image & out, const Image & c,  Image& mask)
00061 {
00062   int width = c.getWidth();
00063   int height = c.getHeight();
00064 
00065   if(out.getNumComponents() != c.getNumComponents())
00066     throw Millie::IllegalArgument("InpaintOperator::compute");
00067 
00068   if(mask.getHeight() != c.getHeight() || mask.getWidth() != c.getWidth())
00069     throw Millie::IllegalArgument("InpaintOperator::compute");
00070 
00071 
00072 
00073   /*taille des vecteurs dx et dy*/
00074   static const int n = 8;
00075   static const int dx [n] =
00076     {
00077       -1,0,1,1,1,0,-1,-1
00078     };
00079   static const int dy [n]  =
00080     {
00081       -1,-1,-1,0,1,1,1,0
00082     };
00083 
00084 
00085   out = c;
00086 
00087   std::vector<int> contourInt1;
00088   std::vector<int> contourInt2;
00089 
00090   for(int canal = 0; canal < c.getNumComponents(); canal++)
00091   {
00092 
00093     while(true)
00094     {
00095 
00096       /*vide les listes*/
00097       contourInt1.clear();
00098       contourInt2.clear();
00099       //            assert(contourInt1.size() == 0);
00100       //            assert(contourInt2.size() == 0);
00101       // front-line masked/unmasked
00102       for (int y = 0; y < height; y++)
00103       {
00104         for (int x = 0; x < width; x++)
00105         {
00106           if (absolue(mask.getPixel(x,y, canal))<0.01)
00107             continue;
00108           for (int i = 0; i < n; i++)
00109           {
00110             int xk = x + dx[i];
00111             int yk = y + dy[i];
00112             if (xk<0 || xk>=width)
00113               continue;
00114             if (yk<0 || yk>=height)
00115               continue;
00116             if (mask.getPixel(xk,yk, canal)>0.1)
00117               continue;
00118             contourInt1.push_back(x);
00119             contourInt2.push_back(y);
00120             break;
00121           }
00122         }
00123       }
00124 
00125       // exit when no front-line
00126       if (contourInt1.empty())
00127         break;
00128 
00129       // isophotes continuation
00130       for(unsigned int j=0;j<contourInt1.size();j++)
00131       {
00132         int x = contourInt1[j];
00133         int y = contourInt2[j];
00134 
00135         mask.setPixel(x,y,canal, 0.0f);
00136 
00137 
00138         float value=0.0f;
00139         float wsum=0.0f;
00140         float w = 0.0f;
00141 
00142 
00143         for (int i = 0; i < n; i++)
00144         {
00145           int xk = x + dx[i];
00146           int yk = y + dy[i];
00147           if (xk<0 || xk>=width)
00148             continue;
00149           if (yk<0 || yk>=height)
00150             continue;
00151           if (mask.getPixel(xk,yk, canal)>0.1f)
00152             continue;
00153 
00154           // gradient
00155           float norme = 0;
00156           float angle = 0;
00157 
00158           InpaintOperator::gradient(c, xk, yk, canal, &norme, &angle);
00159           // gradient normal = isophote direction
00160           angle+=  M_PI /2.0f;
00161 
00162 
00163           // Weight of the propagation:
00164 
00165           // 1. dotproduct ( gradient normal . propagation vector )
00166           float pscal;
00167           pscal = cos(angle)*(static_cast<float>(dx[i])) + (-sin(angle))*(static_cast<float>(dy[i]));
00168           pscal/=sqrt(static_cast<float> (dx[i]*dx[i]+dy[i]*dy[i])); //ne peut pas être nul !
00169 
00170           // 2. gradient magnitude  (O -> omnidirectionnal)
00171           //                    float w = (norme)*absolue(pscal)+(1-norme)*1;
00172           w = norme*(absolue(pscal)-1)+1;
00173 
00174           value += w*c.getPixel(xk,yk, canal);
00175           wsum  += w;
00176         }
00177 
00178         if (wsum<=0)
00179         {
00180           std::cout<<"d "<<wsum<<std::endl;
00181           continue;
00182         }
00183         value/=wsum;
00184         // set new value
00185         out.setPixel(x,y, canal, static_cast<int>(value));
00186 
00187 
00188       }
00189 
00190     }
00191 
00192   }
00193 
00194 }
00195 
00196 
00197 
00198 
00199 void InpaintOperator::gradient(const Image& c, int x, int y, int canal, float * norme, float * angle)
00200 {
00201   int width = c.getWidth();
00202   int height = c.getHeight();
00203 
00204   const float cst1 = (0.25f*(2-sqrt(2.0f)));
00205   const float cst2 = (0.5f*(sqrt(2.0f)-1.0f));
00206 
00207   int px = x-1;
00208   int nx = x+1;
00209   int py = y-1;
00210   int ny = y+1;
00211   if (px<0)
00212     px=0;
00213   if (nx>=width)
00214     nx=width-1;
00215   if (py<0)
00216     py=0;
00217   if (ny>=height)
00218     ny=height-1;
00219 
00220   float Ipp=c.getPixel(px,py, canal);
00221   float Ipc=c.getPixel(px,y, canal) ;
00222   float Ipn=c.getPixel(px,ny, canal);
00223   float Icp=c.getPixel(x,py, canal);
00224   float Icn=c.getPixel(x,ny, canal);
00225   float Inp=c.getPixel(nx,py, canal);
00226   float Inc=c.getPixel(nx,y, canal) ;
00227   float Inn=c.getPixel(nx,ny, canal);
00228 
00229   float IppInn = cst1*(Inn-Ipp);
00230   float IpnInp = cst1*(Ipn-Inp);
00231   float gradx = (IppInn-IpnInp-cst2*Ipc+cst2*Inc);
00232   float grady = (IppInn+IpnInp-cst2*Icp+cst2*Icn);
00233 
00234   *norme = sqrt( gradx*gradx + grady*grady );
00235 
00236   *angle = 0.0f;
00237   if (*norme>0.01f)
00238   {
00239     *angle = acos(gradx/ *norme);
00240     if (grady>0.01f)
00241       *angle = 2.0f*M_PI - *angle;
00242   }
00243 
00244   *norme/=255.0f;
00245 
00246 }
00247 
00248 
00249 

Généré le Fri May 18 23:24:40 2007 pour Millie par  doxygen 1.5.1