Browse Source

Ajout d'un programme cpp pour génération des fichiers .csv

Jerome Buisine 4 years ago
parent
commit
1592e72359

+ 12 - 0
.gitignore

@@ -0,0 +1,12 @@
+# generated images
+*.png
+*.csv
+
+# visual studio code
+.vscode/
+
+# model information
+*.coeff
+*.model
+
+.python-version

+ 2243 - 0
classeImage/Image.1.cpp

@@ -0,0 +1,2243 @@
+#include "Image.hpp"
+
+
+Lisic::Image::Image(const unsigned int& tailleX, const unsigned int& tailleY, const unsigned int& profondeurCouleur)
+{
+  assert(tailleX!=0);
+  assert(tailleY!=0);
+  _profondeurCouleur=profondeurCouleur;
+  _tailleX=tailleX;
+  _tailleY=tailleY;
+
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    _pixels.push_back(Lisic::Pixel());
+
+  normaliserA255();
+}
+
+
+Lisic::Image::Image(const unsigned int& tailleX, const unsigned int& tailleY, const unsigned int& profondeurCouleur, std::vector<unsigned int> canal1, std::vector<unsigned int> canal2, std::vector<unsigned int> canal3)
+{
+  assert(tailleX!=0);
+  assert(tailleY!=0);
+  _profondeurCouleur=profondeurCouleur;
+  _tailleX=tailleX;
+  _tailleY=tailleY;
+  
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    _pixels.push_back(Lisic::Pixel(canal1[i],canal2[i],canal3[i]));
+
+  normaliserA255();
+}
+
+//imagemagick V6
+#ifdef IM6
+Lisic::Image::Image(const char *chemin)
+{
+  _profondeurCouleur = (1<<QuantumDepth) - 1;
+  Magick::Image magickimg(chemin);
+  
+  _tailleX=magickimg.columns();
+  _tailleY=magickimg.rows();
+  
+  for(unsigned int j = 0; j < magickimg.rows(); j++ )
+    {
+      const Magick::PixelPacket *magickpixels = magickimg.getConstPixels( 0, j, magickimg.columns(), 1 );
+
+      
+      for(unsigned int i = 0; i < magickimg.columns(); i++ ){
+	//std::cout << magickpixels[i].red << " " << magickpixels[i].green <<" " << magickpixels[i].blue << std::endl;
+	_pixels.push_back(Lisic::Pixel(magickpixels[i].red,magickpixels[i].green,magickpixels[i].blue));
+      }
+    }
+
+  normaliserA255();
+}
+#endif
+
+//Imagemagick V7
+#ifdef IM7
+Lisic::Image::Image(const char *chemin)
+{
+  Magick::Image magickimg(chemin);
+  _profondeurCouleur=(1<<magickimg.depth()) - 1;
+  
+  _tailleX=magickimg.columns();
+  _tailleY=magickimg.rows();
+  
+  for(unsigned int j = 0; j < magickimg.rows(); j++ )
+    for(unsigned int i = 0; i < magickimg.columns(); i++ ){ 
+      const MagickCore::Quantum *magickpixels = magickimg.getConstPixels( i, j, 1, 1 );
+      MagickCore::PixelInfo packet;
+      MagickCore::GetPixelInfoPixel(magickimg.constImage(),magickpixels,&packet);
+      //std::cout << packet.red << " " << packet.green <<" " << packet.blue << std::endl;
+      _pixels.push_back(Lisic::Pixel(packet.red, packet.green, packet.blue));
+      //std::cout << _pixels[_pixels.size()-1][0] << std::endl;
+      //std::cout << "(" << i  << "," << j << ") : (" << packet.red << "," << packet.green << "," << packet.blue << ")" << std::endl << std::endl;
+    }
+  
+  // On va tester la valeur de tous les pixels pour voir si une valeur dépasse 255
+  // donc image qui n'est pas en 8bits
+  // dans ce cas, on va diviser par 257 (257=65535/255)
+  bool diviser=false;
+  for(unsigned int i = 0; i < _pixels.size() ; i++){
+    if(_pixels[i][0]>255){
+      diviser=true;
+      i=_pixels.size();
+    }
+  }
+  if(diviser){
+    for(unsigned int i = 0; i < _pixels.size() ; i++){
+      _pixels[i][0]/=257;_pixels[i][1]/=257;_pixels[i][2]/=257;
+    }
+  }
+
+  //std::cout << "profondeur couleur : " << _profondeurCouleur << std::endl;
+
+  _profondeurCouleur=255;
+  
+  normaliserA255();
+}
+#endif
+
+Lisic::Image::Image(const Lisic::Image& im1, const unsigned int& numeroCanal1, const Lisic::Image& im2, const unsigned int& numeroCanal2, const Lisic::Image& im3, const unsigned int& numeroCanal3)
+{
+  assert(im1._tailleX==im2._tailleX && im1._tailleX==im3._tailleX &&
+	 im1._tailleY==im2._tailleY && im1._tailleY==im3._tailleY &&
+	 im2._tailleX==im3._tailleX && im2._tailleY==im3._tailleY &&
+	 im1._profondeurCouleur==im2._profondeurCouleur && im2._profondeurCouleur==im3._profondeurCouleur);
+  
+  std::vector<unsigned int> can1=im1.extraireCanal(numeroCanal1);
+  std::vector<unsigned int> can2=im2.extraireCanal(numeroCanal2);
+  std::vector<unsigned int> can3=im3.extraireCanal(numeroCanal3);
+  
+  _profondeurCouleur=im1._profondeurCouleur;
+  _tailleX=im1._tailleX;
+  _tailleY=im1._tailleY;
+  
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    _pixels.push_back(Lisic::Pixel(can1[i],can2[i],can3[i]));
+
+  normaliserA255();
+}
+
+Lisic::Image::Image(const std::vector<Lisic::Image>& vec, const unsigned int& x, const unsigned int& y)
+{
+  assert(vec.size()==x*y);
+  
+  /*Vérifier que les tailles d'images sont bien compatibles pour assemblage*/
+  for(unsigned int i=0;i<x;i++)
+    for(unsigned int j=1;j<y;j++)
+      assert(vec[i]._tailleX==vec[j*x+i]._tailleX);
+  
+  for(unsigned int j=0;j<y;j++)
+    for(unsigned int i=1;i<x;i++)
+      assert(vec[j*x]._tailleY==vec[j*x+i]._tailleY);	
+
+  /*Vérifier que les profondeurCouleur soient bien les mêmes partout*/
+  for(unsigned int i=1;i<x*y;i++)
+    assert(vec[i]._profondeurCouleur==vec[0]._profondeurCouleur);
+  
+  /*retrouver la taille finale de l'image*/
+  std::vector<unsigned int> tab_taillex,tab_tailley;
+  _tailleX=0;
+  _tailleY=0;
+  _profondeurCouleur=vec[0]._profondeurCouleur;
+
+  for(unsigned int i=0;i<x;i++)
+    {
+      tab_taillex.push_back(_tailleX);
+      _tailleX+=vec[i]._tailleX;
+    }
+  for(unsigned int j=0;j<y;j++)
+    {
+      tab_tailley.push_back(_tailleY);
+      _tailleY+=vec[j*x]._tailleY;
+    }
+
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    _pixels.push_back(Lisic::Pixel());
+
+  for(unsigned int j=0;j<y;j++)
+    for(unsigned int i=0;i<x;i++)
+      for(unsigned int jj=0;jj<vec[j*x+i]._tailleY;jj++)
+	for(unsigned int ii=0;ii<vec[j*x+i]._tailleX;ii++)
+	  setPixel(tab_taillex[i]+ii,tab_tailley[j]+jj,vec[j*x+i]._pixels[jj*vec[j*x+i]._tailleX+ii][0],vec[j*x+i]._pixels[jj*vec[j*x+i]._tailleX+ii][1],vec[j*x+i]._pixels[jj*vec[j*x+i]._tailleX+ii][2]);
+
+  normaliserA255();
+}
+
+Lisic::Image::Image(const Lisic::Image& im)
+{
+  _profondeurCouleur=im._profondeurCouleur;
+  _tailleX=im._tailleX;
+  _tailleY=im._tailleY;
+  
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    _pixels.push_back(Lisic::Pixel(im._pixels[i]));
+}
+
+void Lisic::Image::normaliserA255()
+{
+  assert(_profondeurCouleur==255 || _profondeurCouleur==65535);
+  if(_profondeurCouleur==65535){
+    for(unsigned int i=0;i<_pixels.size();i++){
+      _pixels[i].r()/=257;
+      _pixels[i].v()/=257;
+      _pixels[i].b()/=257;
+    }
+  }
+  _profondeurCouleur=255;
+}
+
+//Imagemagick V6
+#ifdef IM6
+void Lisic::Image::sauver(const char *chemin) const
+{ 
+  Magick::Image magickimg(Magick::Geometry(_tailleX,_tailleY), "white");
+  magickimg.modifyImage();
+  Magick::Pixels view(magickimg);
+  Magick::PixelPacket *magickpixels=view.get(0,0,_tailleX,_tailleY);
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      *magickpixels++=Magick::ColorRGB(((_pixels[j*_tailleX+i][0])*1.0)/(_profondeurCouleur*1.0),
+				       ((_pixels[j*_tailleX+i][1])*1.0)/(_profondeurCouleur*1.0),
+				       ((_pixels[j*_tailleX+i][2])*1.0)/(_profondeurCouleur*1.0));
+  
+  view.sync();
+  
+  magickimg.write(chemin);
+}
+#endif
+
+//Imagemagick V7
+#ifdef IM7
+void Lisic::Image::sauver(const char *chemin) const
+{ 
+  Magick::Image magickimg(Magick::Geometry(_tailleX,_tailleY), "white");
+  magickimg.modifyImage();
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++){
+      MagickCore::Quantum *magickpixels = magickimg.getPixels( i, j, 1, 1 );
+      MagickCore::SetPixelRed(magickimg.constImage(),MagickCore::Quantum(_pixels[j*_tailleX+i][0]),magickpixels);
+      MagickCore::SetPixelGreen(magickimg.constImage(),MagickCore::Quantum(_pixels[j*_tailleX+i][1]),magickpixels);
+      MagickCore::SetPixelBlue(magickimg.constImage(),MagickCore::Quantum(_pixels[j*_tailleX+i][2]),magickpixels);
+    }
+  
+  magickimg.write(chemin);
+}
+#endif
+
+void Lisic::Image::sauver(const std::string chemin) const
+{
+  sauver(chemin.c_str());
+}
+
+void Lisic::Image::sauverSVG(const char *chemin) const
+{ 
+  std::cout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl << std::endl;
+  std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"" << _tailleX <<"\" height=\"" << _tailleY << "\">" << std::endl << std::endl;
+
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      std::cout << "<rect x=\"" << i << "\" y=\"" << j << "\" width=\"1\" height=\"1\" style=\"fill:rgb(" << (int)((_pixels[j*_tailleX+i][0]*1.0)/(_profondeurCouleur)*255.0) << "," << (int)((_pixels[j*_tailleX+i][1]*1.0)/(_profondeurCouleur)*255.0) << "," << (int)((_pixels[j*_tailleX+i][2]*1.0)/(_profondeurCouleur)*255.0) << ")\" />" << std::endl;
+  
+  std::cout << "</svg>" << std::endl;
+}
+
+void Lisic::Image::sauverSVG(const std::string chemin) const
+{
+  sauverSVG(chemin.c_str());
+}
+
+Lisic::Image Lisic::Image::getSousPartie(const unsigned int& imin, const unsigned int& jmin, const unsigned int& tailleXSousPartie, const unsigned int& tailleYSousPartie) const
+{
+  assert(imin+tailleXSousPartie<=_tailleX);
+  assert(jmin+tailleYSousPartie<=_tailleY);
+
+  Lisic::Image retour=Lisic::Image(tailleXSousPartie,tailleYSousPartie,_profondeurCouleur);
+  for(unsigned int j=jmin;j<jmin+tailleYSousPartie;j++)
+    for(unsigned int i=imin;i<imin+tailleXSousPartie;i++)
+      retour.setPixel(i-imin,j-jmin,_pixels[j*_tailleX+i][0],_pixels[j*_tailleX+i][1],_pixels[j*_tailleX+i][2]);
+			       
+  return retour;
+}
+
+//retourne un nouveau pixel de même couleur que le pixel demandé
+Lisic::Pixel Lisic::Image::getPixel(const unsigned int& i, const unsigned int& j) const
+{
+  assert(i<_tailleX && j<_tailleY);
+  return Lisic::Pixel((((_pixels[j*_tailleX+i][0])*1.0)/_profondeurCouleur)*255.0,(((_pixels[j*_tailleX+i][1])*1.0)/_profondeurCouleur)*255.0,(((_pixels[j*_tailleX+i][2])*1.0)/_profondeurCouleur)*255.0);
+}
+
+void Lisic::Image::setPixel(const unsigned int& i, const unsigned int& j, const unsigned int& r, const unsigned int& v, const unsigned int& b)
+{
+  assert(i<_tailleX && j<_tailleY);
+  
+  _pixels[j*_tailleX+i][0]=r;
+  _pixels[j*_tailleX+i][1]=v;
+  _pixels[j*_tailleX+i][2]=b;
+  if(_pixels[j*_tailleX+i][0]>_profondeurCouleur)
+    _pixels[j*_tailleX+i][0]=_profondeurCouleur;
+  if(_pixels[j*_tailleX+i][1]>_profondeurCouleur)
+    _pixels[j*_tailleX+i][1]=_profondeurCouleur;
+  if(_pixels[j*_tailleX+i][2]>_profondeurCouleur)
+    _pixels[j*_tailleX+i][2]=_profondeurCouleur;
+}
+
+std::vector<unsigned int> Lisic::Image::extraireCanal(const unsigned int& numeroCanal) const
+{
+  assert(numeroCanal<=2);
+  std::vector<unsigned int> canal;
+  
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    canal.push_back(_pixels[i][numeroCanal]);
+  
+  return canal;
+}
+
+bool Lisic::Image::estNoire() const
+{
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    if(_pixels[i][0]!=0 || _pixels[i][0]!=0 || _pixels[i][0]!=0)
+      return false;
+  return true;
+}
+
+bool Lisic::Image::estBlanche() const
+{
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    if(_pixels[i][0]!=_profondeurCouleur || _pixels[i][0]!=_profondeurCouleur || _pixels[i][0]!=_profondeurCouleur)
+      return false;
+  return true;
+}
+
+bool Lisic::Image::estNiveauGris() const
+{
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    if(_pixels[i][0]!=_pixels[i][1] || _pixels[i][0]!=_pixels[i][2])
+      return false;
+  return true;
+}
+
+unsigned int Lisic::Image::nombreDePixel(const unsigned int& r, const unsigned int& v, const unsigned int& b) const
+{
+  unsigned int retour=0;
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    if(_pixels[i][0]==r && _pixels[i][1]==v && _pixels[i][2]==b)
+      retour++;
+  return retour;
+}
+
+
+void Lisic::Image::affiche() const
+{
+  std::cout << "Taille : " << _tailleX << "x" << _tailleY << " pixels" << std::endl;
+  for(unsigned int j=0;j<_tailleY;j++)
+    {
+      for (unsigned int i=0; i<_tailleX; i++)
+	std::cout << "(" << _pixels[j*_tailleX+i][0] << "," << _pixels[j*_tailleX+i][1] << "," << _pixels[j*_tailleX+i][2] << ") ";
+      std::cout << std::endl;
+    }
+}
+
+std::vector<Lisic::Image> Lisic::Image::morceler(const unsigned int& nvtailleX, const unsigned int& nvtailleY, const bool& force) const
+{
+  std::vector<Lisic::Image> retour;
+  unsigned int i,j;
+
+  if((_tailleX%nvtailleX!=0 || _tailleY%nvtailleY!=0) && !force)
+    return retour;
+  
+  for(j=0;j<_tailleY/nvtailleY;j++)
+    {
+      for(i=0;i<_tailleX/nvtailleX;i++)
+	retour.push_back(getSousPartie(i*nvtailleX,j*nvtailleY,nvtailleX,nvtailleY));
+      
+      //morceaux qui vont un peu moins bien - bande de droite
+      if(_tailleX%nvtailleX)
+	retour.push_back(getSousPartie((_tailleX/nvtailleX)*nvtailleX,j*nvtailleY,_tailleX%nvtailleX,nvtailleY));
+    }
+
+
+  if(_tailleY%nvtailleY)
+    {
+      //morceaux du bas
+      //morceaux en bas à gauche
+      for(i=0;i<_tailleX/nvtailleX;i++)
+	retour.push_back(getSousPartie(i*nvtailleX,(_tailleY/nvtailleY)*nvtailleY,nvtailleX,_tailleY%nvtailleY));
+      
+      //dernier morceau en bas à droite avec ce qu'il reste de l'image
+      if(_tailleX%nvtailleX)
+	retour.push_back(getSousPartie((_tailleX/nvtailleX)*nvtailleX,(_tailleY/nvtailleY)*nvtailleY,_tailleX%nvtailleX,_tailleY%nvtailleY));
+    }
+  
+  return retour;
+}
+
+Lisic::Image Lisic::Image::gradient(const std::vector<int>& mask) const
+{
+  assert(mask.size()==9);
+  
+  Lisic::Image grad(_tailleX-2,_tailleY-2,_profondeurCouleur);
+
+  for(unsigned int j=1;j<_tailleY-1;j++)
+    for(unsigned int i=1;i<_tailleX-1;i++)
+      {
+	unsigned int gradient1, gradient2, gradient3;
+	int res=getPixel(i-1,j-1)[0]*mask[0]+getPixel(i,j-1)[0]*mask[1]+getPixel(i+1,j-1)[0]*mask[2]+getPixel(i-1,j)[0]*mask[3]+getPixel(i,j)[0]*mask[4]+getPixel(i+1,j)[0]*mask[5]+getPixel(i-1,j+1)[0]*mask[6]+getPixel(i,j+1)[0]*mask[7]+getPixel(i+1,j+1)[0]*mask[8];
+	if(res<0)
+	  res*=-1;
+	gradient1=(unsigned int)(res);
+	  
+	res=getPixel(i-1,j-1)[1]*mask[0]+getPixel(i,j-1)[1]*mask[1]+getPixel(i+1,j-1)[1]*mask[2]+getPixel(i-1,j)[1]*mask[3]+getPixel(i,j)[1]*mask[4]+getPixel(i+1,j)[1]*mask[5]+getPixel(i-1,j+1)[1]*mask[6]+getPixel(i,j+1)[1]*mask[7]+getPixel(i+1,j+1)[1]*mask[8];
+	if(res<0)
+	  res*=-1;
+	gradient2=(unsigned int)(res);
+
+	res=getPixel(i-1,j-1)[2]*mask[0]+getPixel(i,j-1)[2]*mask[1]+getPixel(i+1,j-1)[2]*mask[2]+getPixel(i-1,j)[2]*mask[3]+getPixel(i,j)[2]*mask[4]+getPixel(i+1,j)[2]*mask[5]+getPixel(i-1,j+1)[2]*mask[6]+getPixel(i,j+1)[2]*mask[7]+getPixel(i+1,j+1)[2]*mask[8];
+	if(res<0)
+	  res*=-1;
+	gradient3=(unsigned int)(res);
+
+	grad.setPixel(i-1,j-1,gradient1,gradient1,gradient1);
+	if(gradient2>grad.getPixel(i-1,j-1)[0])
+	  grad.setPixel(i-1,j-1,gradient2,gradient2,gradient2);
+	if(gradient3>grad.getPixel(i-1,j-1)[0])
+	  grad.setPixel(i-1,j-1,gradient3,gradient3,gradient3);
+      }
+
+  return grad;
+}
+
+Lisic::Image Lisic::Image::gradientRotation(const std::vector<int>& mask) const
+{
+  assert(mask.size()==9);
+  
+  Lisic::Image grad(_tailleX-2,_tailleY-2,_profondeurCouleur);
+
+  for(unsigned int j=1;j<_tailleY-1;j++)
+    for(unsigned int i=1;i<_tailleX-1;i++)
+      {
+	unsigned int gradient1, gradient2, gradient3, gradient4, gradient5, gradient6, gradient7, gradient8, gradient9;
+	int res=getPixel(i-1,j-1)[0]*mask[0]+getPixel(i,j-1)[0]*mask[1]+getPixel(i+1,j-1)[0]*mask[2]+getPixel(i-1,j)[0]*mask[3]+getPixel(i,j)[0]*mask[4]+getPixel(i+1,j)[0]*mask[5]+getPixel(i-1,j+1)[0]*mask[6]+getPixel(i,j+1)[0]*mask[7]+getPixel(i+1,j+1)[0]*mask[8];
+	if(res<0)
+	  res*=-1;
+	gradient1=(unsigned int)(res);
+
+	res=getPixel(i-1,j-1)[1]*mask[0]+getPixel(i,j-1)[1]*mask[1]+getPixel(i+1,j-1)[1]*mask[2]+getPixel(i-1,j)[1]*mask[3]+getPixel(i,j)[1]*mask[4]+getPixel(i+1,j)[1]*mask[5]+getPixel(i-1,j+1)[1]*mask[6]+getPixel(i,j+1)[1]*mask[7]+getPixel(i+1,j+1)[1]*mask[8];
+	if(res<0)
+	  res*=-1;
+	gradient2=(unsigned int)(res);
+	
+	res=getPixel(i-1,j-1)[2]*mask[0]+getPixel(i,j-1)[2]*mask[1]+getPixel(i+1,j-1)[2]*mask[2]+getPixel(i-1,j)[2]*mask[3]+getPixel(i,j)[2]*mask[4]+getPixel(i+1,j)[2]*mask[5]+getPixel(i-1,j+1)[2]*mask[6]+getPixel(i,j+1)[2]*mask[7]+getPixel(i+1,j+1)[2]*mask[8];
+	if(res<0)
+	  res*=-1;
+	gradient3=(unsigned int)(res);
+
+	res=getPixel(i-1,j-1)[0]*mask[3]+getPixel(i,j-1)[0]*mask[0]+getPixel(i+1,j-1)[0]*mask[1]+getPixel(i-1,j)[0]*mask[6]+getPixel(i,j)[0]*mask[4]+getPixel(i+1,j)[0]*mask[2]+getPixel(i-1,j+1)[0]*mask[7]+getPixel(i,j+1)[0]*mask[8]+getPixel(i+1,j+1)[0]*mask[5];
+	if(res<0)
+	  res*=-1;
+	gradient4=(unsigned int)(res);
+
+	res=getPixel(i-1,j-1)[1]*mask[3]+getPixel(i,j-1)[1]*mask[0]+getPixel(i+1,j-1)[1]*mask[1]+getPixel(i-1,j)[1]*mask[6]+getPixel(i,j)[1]*mask[4]+getPixel(i+1,j)[1]*mask[2]+getPixel(i-1,j+1)[1]*mask[7]+getPixel(i,j+1)[1]*mask[8]+getPixel(i+1,j+1)[1]*mask[5];
+	if(res<0)
+	  res*=-1;
+	gradient5=(unsigned int)(res);
+
+	res=getPixel(i-1,j-1)[2]*mask[3]+getPixel(i,j-1)[2]*mask[0]+getPixel(i+1,j-1)[2]*mask[1]+getPixel(i-1,j)[2]*mask[6]+getPixel(i,j)[2]*mask[4]+getPixel(i+1,j)[2]*mask[2]+getPixel(i-1,j+1)[2]*mask[7]+getPixel(i,j+1)[2]*mask[8]+getPixel(i+1,j+1)[2]*mask[5];
+	if(res<0)
+	  res*=-1;
+	gradient6=(unsigned int)(res);
+
+	res=getPixel(i-1,j-1)[0]*mask[6]+getPixel(i,j-1)[0]*mask[3]+getPixel(i+1,j-1)[0]*mask[0]+getPixel(i-1,j)[0]*mask[7]+getPixel(i,j)[0]*mask[4]+getPixel(i+1,j)[0]*mask[1]+getPixel(i-1,j+1)[0]*mask[8]+getPixel(i,j+1)[0]*mask[5]+getPixel(i+1,j+1)[0]*mask[2];
+	if(res<0)
+	  res*=-1;
+	gradient7=(unsigned int)(res);
+
+	res=getPixel(i-1,j-1)[1]*mask[6]+getPixel(i,j-1)[1]*mask[3]+getPixel(i+1,j-1)[1]*mask[0]+getPixel(i-1,j)[1]*mask[7]+getPixel(i,j)[1]*mask[4]+getPixel(i+1,j)[1]*mask[1]+getPixel(i-1,j+1)[1]*mask[8]+getPixel(i,j+1)[1]*mask[5]+getPixel(i+1,j+1)[1]*mask[2];
+	if(res<0)
+	  res*=-1;
+	gradient8=(unsigned int)(res);
+
+	res=getPixel(i-1,j-1)[2]*mask[6]+getPixel(i,j-1)[2]*mask[3]+getPixel(i+1,j-1)[2]*mask[0]+getPixel(i-1,j)[2]*mask[7]+getPixel(i,j)[2]*mask[4]+getPixel(i+1,j)[2]*mask[1]+getPixel(i-1,j+1)[2]*mask[8]+getPixel(i,j+1)[2]*mask[5]+getPixel(i+1,j+1)[2]*mask[2];
+	if(res<0)
+	  res*=-1;
+	gradient9=(unsigned int)(res);
+
+	grad.setPixel(i-1,j-1,gradient1,gradient1,gradient1);
+	if(gradient2>grad.getPixel(i-1,j-1)[0])
+	  grad.setPixel(i-1,j-1,gradient2,gradient2,gradient2);
+	if(gradient3>grad.getPixel(i-1,j-1)[0])
+	  grad.setPixel(i-1,j-1,gradient3,gradient3,gradient3);
+	if(gradient4>grad.getPixel(i-1,j-1)[0])
+	  grad.setPixel(i-1,j-1,gradient4,gradient4,gradient4);
+	if(gradient5>grad.getPixel(i-1,j-1)[0])
+	  grad.setPixel(i-1,j-1,gradient5,gradient5,gradient5);
+	if(gradient6>grad.getPixel(i-1,j-1)[0])
+	  grad.setPixel(i-1,j-1,gradient6,gradient6,gradient6);
+	if(gradient7>grad.getPixel(i-1,j-1)[0])
+	  grad.setPixel(i-1,j-1,gradient7,gradient7,gradient7);
+	if(gradient8>grad.getPixel(i-1,j-1)[0])
+	  grad.setPixel(i-1,j-1,gradient8,gradient8,gradient8);
+	if(gradient9>grad.getPixel(i-1,j-1)[0])
+	  grad.setPixel(i-1,j-1,gradient9,gradient9,gradient9);
+
+      }
+
+  return grad;
+}
+
+void Lisic::Image::seuil(const unsigned int& numCanal, const unsigned int& s)
+{
+  assert(numCanal<3);
+  for(unsigned int i=0;i<_pixels.size();i++)
+    if(_pixels[i][numCanal]<s)
+      _pixels[i][numCanal]=0;
+    else
+      _pixels[i][numCanal]=_profondeurCouleur;
+}
+
+double Lisic::Image::PSNR(const Image& im, const unsigned int& numCanal) const
+{
+  assert(numCanal<3);
+  assert(im._tailleX==_tailleY && im._tailleY==_tailleY && im._profondeurCouleur==_profondeurCouleur);
+  double eqm=0;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    eqm+=(_pixels[i][numCanal]-im._pixels[i][numCanal])*(_pixels[i][numCanal]-im._pixels[i][numCanal]);
+  eqm/=_pixels.size();
+  return (10.0*log10(_profondeurCouleur*_profondeurCouleur/eqm));
+}
+
+std::tuple<double, double, double> Lisic::Image::PSNR(const Image& im) const
+{
+  assert(im._tailleX==_tailleY && im._tailleY==_tailleY && im._profondeurCouleur==_profondeurCouleur);
+  return std::make_tuple(PSNR(im,0),PSNR(im,1),PSNR(im,2));
+}
+
+std::tuple<fftw_complex*, Lisic::Image, Lisic::Image> Lisic::Image::fourier() const
+{
+  /* assert(_tailleX%2==0 && _tailleY%2==0);
+  Lisic::Image img1(_tailleX,_tailleY,_profondeurCouleur);
+  Lisic::Image img2(_tailleX,_tailleY,_profondeurCouleur);
+
+  double *listModule = new double[_tailleX*_tailleY];
+  double *listPhase = new double[_tailleX*_tailleY];
+
+  double module, phase, moduleMax=0.0;
+  
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	double partieReel=0, partieImaginaire=0;
+	for(unsigned int jImg=0;jImg<_tailleY;jImg++)
+	  for(unsigned int iImg=0;iImg<_tailleX;iImg++)
+	    {
+	      partieReel+=getPixel(iImg,jImg)[0]*cos(-2*M_PI*((i*iImg*1.0)/_tailleX+(j*jImg*1.0)/_tailleY));
+	      partieImaginaire+=getPixel(iImg,jImg)[0]*sin(-2*M_PI*((i*iImg*1.0)/_tailleX+(j*jImg*1.0)/_tailleY));
+	    }
+	
+	module = sqrt(partieReel*partieReel+partieImaginaire*partieImaginaire);
+	if(module > moduleMax && (i>10 && i<_tailleX-10 && j>10 && j<_tailleY-10))
+	  moduleMax=module;
+	phase = (atan2(partieImaginaire,partieReel)+M_PI)/7.0*_profondeurCouleur;
+ 
+	listModule[j*_tailleX+i]=module;
+	listPhase[j*_tailleX+i]=phase;
+      }
+  
+
+
+  if(moduleMax==0)
+    moduleMax=1;
+
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	img1.setPixel(i,j,(unsigned int)(listModule[j*_tailleX+i]/moduleMax*_profondeurCouleur),(unsigned int)(listModule[j*_tailleX+i]/moduleMax*_profondeurCouleur),(unsigned int)(listModule[j*_tailleX+i]/moduleMax*_profondeurCouleur));
+	img2.setPixel(i,j,(unsigned int)(listPhase[j*_tailleX+i]),(unsigned int)(listPhase[j*_tailleX+i]),(unsigned int)(listPhase[j*_tailleX+i]));
+      }
+
+  delete[] listModule;
+  delete[] listPhase;
+
+  for(unsigned int j=0;j<_tailleY/2;j++)
+    for(unsigned int i=0;i<_tailleX/2;i++)
+      {
+	unsigned int echang=img1.getPixel(i,j)[0];
+	img1.setPixel(i,j,img1.getPixel(i+_tailleX/2,j+_tailleY/2)[0],img1.getPixel(i+_tailleX/2,j+_tailleY/2)[0],img1.getPixel(i+_tailleX/2,j+_tailleY/2)[0]);
+	img1.setPixel(i+_tailleX/2,j+_tailleY/2,echang,echang,echang);
+      }
+
+  for(unsigned int j=0;j<_tailleY/2;j++)
+    for(unsigned int i=_tailleX/2;i<_tailleX;i++)
+      {
+	unsigned int echang=img1.getPixel(i,j)[0];
+	img1.setPixel(i,j,img1.getPixel(i-_tailleX/2,j+_tailleY/2)[0],img1.getPixel(i-_tailleX/2,j+_tailleY/2)[0],img1.getPixel(i-_tailleX/2,j+_tailleY/2)[0]);
+	img1.setPixel(i-_tailleX/2,j+_tailleY/2,echang,echang,echang);
+      }
+
+      return std::make_pair(img1,img2);*/
+
+  fftw_complex* spatial_repr;
+  fftw_complex* frequency_repr;
+  fftw_plan plan;
+  unsigned int x,y;
+  std::vector<float> imOut;
+  imOut.resize(_tailleX*_tailleY);
+  std::vector<float> reOut;
+  reOut.resize(_tailleX*_tailleY);
+  std::vector<float> listeModule;
+  listeModule.resize(_tailleX*_tailleY);
+  std::vector<float> listePhase;
+  listePhase.resize(_tailleX*_tailleY);
+  float moduleMax=0;
+  
+  spatial_repr= (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*_tailleX*_tailleY);
+  frequency_repr= (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*_tailleX*_tailleY);
+  
+  /*On remplit la structure qui sera utilisée par fftw*/
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	spatial_repr[j*_tailleX+i][0] = getPixel(i,j)[0];
+	spatial_repr[j*_tailleX+i][1] =  0.0f;
+    }
+  
+  /*on calcule le plan d'exécution*/
+  plan=fftw_plan_dft_2d(_tailleY, _tailleX, spatial_repr, frequency_repr, FFTW_FORWARD, FFTW_ESTIMATE);
+  
+  /*on effectue la transformée de Fourier*/
+  fftw_execute(plan);
+
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	/*on recentre l'image*/
+	x=i;
+	y=j;
+	if (i<_tailleX/2 && j<_tailleY/2){ x=i+_tailleX/2; y=j+_tailleY/2; }
+	if (i>=_tailleX/2 && j<_tailleY/2){ x=i-_tailleX/2; y=j+_tailleY/2; }
+	if (i<_tailleX/2 && j>=_tailleY/2){ x=i+_tailleX/2; y=j-_tailleY/2; }
+	if (i>=_tailleX/2 && j>=_tailleY/2){ x=i-_tailleX/2; y=j-_tailleY/2; }
+	reOut[y*_tailleX+x]=frequency_repr[j*_tailleX+i][0];
+	imOut[y*_tailleX+x]=frequency_repr[j*_tailleX+i][1];
+	listeModule[y*_tailleX+x]=sqrt(reOut[y*_tailleX+x]*reOut[y*_tailleX+x]+imOut[y*_tailleX+x]*imOut[y*_tailleX+x]);
+	listePhase[y*_tailleX+x]=((atan2(imOut[y*_tailleX+x],reOut[y*_tailleX+x]))+M_PI)/(2*M_PI)*_profondeurCouleur;
+	//std::cout << "(" << i << "," << j << ") : " << listePhase[y*_tailleX+x] << std::endl;
+	if(listeModule[y*_tailleX+x]>moduleMax && i>_tailleX/20 && i<_tailleX*0.8 && j>_tailleY/20 && j<_tailleY*0.8)
+	  moduleMax=listeModule[y*_tailleX+x];
+      }
+
+  
+  Lisic::Image img1(_tailleX,_tailleY,_profondeurCouleur);
+  Lisic::Image img2(_tailleX,_tailleY,_profondeurCouleur);
+
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+    {
+      listeModule[j*_tailleX+i]=listeModule[j*_tailleX+i]/moduleMax*_profondeurCouleur;
+      img1.setPixel(i,j,listeModule[j*_tailleX+i],listeModule[j*_tailleX+i],listeModule[j*_tailleX+i]);
+      img2.setPixel(i,j,listePhase[j*_tailleX+i],listePhase[j*_tailleX+i],listePhase[j*_tailleX+i]);
+    }
+  
+  /*on détruit les objets*/
+  fftw_destroy_plan(plan);
+  fftw_free(spatial_repr);
+
+  return std::make_tuple(frequency_repr,img1,img2);
+  
+}
+
+double Lisic::Image::genereAleatoireUniforme(int precision){
+  int puiss=1;
+  for(int i=0;i<precision;i++)
+    puiss*=10;
+  
+  return ((rand()%puiss)*1.0)/puiss;
+}
+
+void Lisic::Image::bruitUniforme(const double& force, const int& type, const bool& verbeux)
+{
+  assert(type==Lisic::Image::GLOBAL || type==Lisic::Image::PARCANAL);
+  struct timespec ts_start;
+  clock_gettime(CLOCK_MONOTONIC, &ts_start);
+  long temps=ts_start.tv_nsec;
+  srand(temps);
+
+  int nvr,nvv,nvb;
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	if(type==Lisic::Image::GLOBAL){
+	  double alea=(genereAleatoireUniforme()-0.5)*0.2*force;
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+alea*_profondeurCouleur/255.0;
+	  nvv=v+alea*_profondeurCouleur/255.0;
+	  nvb=b+alea*_profondeurCouleur/255.0;
+	  if(verbeux)
+	    std::cout << i << " " << j << " " << alea << " " << alea << " " << alea << std::endl;
+	}
+	else{
+	  double alea1=(genereAleatoireUniforme()-0.5)*0.2*force;
+	  double alea2=(genereAleatoireUniforme()-0.5)*0.2*force;
+	  double alea3=(genereAleatoireUniforme()-0.5)*0.2*force;
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+alea1*_profondeurCouleur/255.0;
+	  nvv=v+alea2*_profondeurCouleur/255.0;
+	  nvb=b+alea3*_profondeurCouleur/255.0;
+	  if(verbeux)
+	    std::cout << i << " " << j << " " << alea1 << " " << alea2 << " " << alea3 << std::endl;
+	}
+	if(nvr<0)
+	  nvr=0;
+	if(nvv<0)
+	  nvv=0;
+	if(nvb<0)
+	  nvb=0; 
+	if((unsigned int)nvr>_profondeurCouleur)
+	  nvr=_profondeurCouleur;
+	if((unsigned int)nvv>_profondeurCouleur)
+	  nvv=_profondeurCouleur;
+	if((unsigned int)nvb>_profondeurCouleur)
+	  nvb=_profondeurCouleur;
+	setPixel(i,j,nvr,nvv,nvb);
+      }
+}
+
+std::pair<double,double> Lisic::Image::genereAleatoireGaussien(){
+  //d'après https://www.unilim.fr/pages_perso/jean.debord/math/random/random.htm#III
+  /*double x1=(((rand()%1000)*1.0+1.0)/1001.0); //x1 doit etre different de 0 car on fait un log dessus juste apres
+    double x2=(((rand()%1000)*1.0)/1000.0);
+    double v1=sqrt(-2*log(x1))*cos(2*M_PI*x2);
+    double v2=sqrt(-2*log(x1))*sin(2*M_PI*x2);
+    return std::make_pair(v1,v2);
+  */
+
+  /*D'après the art of computer programming section 3.4.1 sousection C - algorithm P*/
+  double s;
+  double u1,u2,v1=0,v2=0;
+  while(v2<1e-6 && v2>-1e-6){
+    s=1.1;
+    v2=0;
+    while(s>=1.0 || (s<1e-6 && s>-1e-6)){
+      u1=genereAleatoireUniforme();
+      u2=genereAleatoireUniforme();
+      u1=u1*2-1;      
+      u2=u2*2-1;
+      s=u1*u1+u2*u2;
+    }
+      v1=u1*sqrt(-2*log(s)/s);
+      v2=u2*sqrt(-2*log(s)/s);
+  }
+  return std::make_pair(v1,v2);
+}
+
+void Lisic::Image::bruitGaussien(const double& force, const int& type, const bool& verbeux)
+{
+  assert(type==Lisic::Image::GLOBAL || type==Lisic::Image::PARCANAL);
+  
+  struct timespec ts_start;
+  clock_gettime(CLOCK_MONOTONIC, &ts_start);
+  long temps=ts_start.tv_nsec;
+  srand(temps);
+
+  int nvr,nvv,nvb;
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	if(type==Lisic::Image::GLOBAL){
+	  double aleaGaussien=genereAleatoireGaussien().first*force;
+
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+aleaGaussien*_profondeurCouleur/255.0;
+	  nvv=v+aleaGaussien*_profondeurCouleur/255.0;
+	  nvb=b+aleaGaussien*_profondeurCouleur/255.0;
+	  if(verbeux)
+	    std::cout << i << " " << j << " " << aleaGaussien << " " << aleaGaussien << " " << aleaGaussien << std::endl;
+	}
+	else{
+	  double aleaGaussien1=genereAleatoireGaussien().first*0.1*force;
+	  double aleaGaussien2=genereAleatoireGaussien().first*0.1*force;
+	  double aleaGaussien3=genereAleatoireGaussien().first*0.1*force;
+	  
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+aleaGaussien1*_profondeurCouleur/255.0;
+	  nvv=v+aleaGaussien2*_profondeurCouleur/255.0;
+	  nvb=b+aleaGaussien3*_profondeurCouleur/255.0;
+	  if(verbeux)
+	    std::cout << i << " " << j << " " << aleaGaussien1 << " " << aleaGaussien2 << " " << aleaGaussien3 << std::endl;
+	}
+	if(nvr<0)
+	  nvr=0;
+	if(nvv<0)
+	  nvv=0;
+	if(nvb<0)
+	  nvb=0;
+	if((unsigned int)nvr>_profondeurCouleur)
+	  nvr=_profondeurCouleur;
+	if((unsigned int)nvv>_profondeurCouleur)
+	  nvv=_profondeurCouleur;
+	if((unsigned int)nvb>_profondeurCouleur)
+	  nvb=_profondeurCouleur;
+	setPixel(i,j,nvr,nvv,nvb);
+      }
+}
+
+void Lisic::Image::bruitPoivreSel(const double& force, const double& proportion, const int& type, const bool& verbeux)
+{
+  assert(type==Lisic::Image::GLOBAL || type==Lisic::Image::PARCANAL);
+  std::vector<unsigned int> aModif;
+
+
+  struct timespec ts_start;
+  clock_gettime(CLOCK_MONOTONIC, &ts_start);
+  long temps=ts_start.tv_nsec;
+  srand(temps);
+  
+  //Calcul des pixels à modifier
+  if(proportion>0.5){
+    for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+      aModif.push_back(i);
+    for(unsigned int i=0;i<(unsigned int)(_tailleX*_tailleY*(1-proportion));i++)
+      aModif.erase(aModif.begin()+(rand()%(_tailleX*_tailleY-i)));
+  }
+  else{
+    for(unsigned int i=0;i<(unsigned int)(_tailleX*_tailleY*proportion);i++){
+      unsigned int alea=rand()%(_tailleX*_tailleY);
+      bool trouve=false;
+      for(unsigned int j=0;j<aModif.size();j++){
+	if(aModif[j]==alea)
+	  trouve=true;
+      }
+      if(!trouve)
+	aModif.push_back(alea);
+      else
+	i--;
+      
+    }
+  }
+
+  int nvr,nvv,nvb;
+
+    for(unsigned int i=0;i<aModif.size();i++){
+      int coeff=1.0;
+      if(rand()%2)
+	coeff=-1.0;
+      unsigned int x=aModif[i]%_tailleX,y=aModif[i]/_tailleX;
+      double bruit=coeff*0.5*force;
+      if(type==Lisic::Image::GLOBAL){
+	int r=getPixel(x,y).r();
+	int v=getPixel(x,y).v();
+	int b=getPixel(x,y).b();
+	nvr=(int)(r+bruit*_profondeurCouleur/255.0);
+	nvv=(int)(v+bruit*_profondeurCouleur/255.0);
+	nvb=(int)(b+bruit*_profondeurCouleur/255.0);
+	if(verbeux)
+	    std::cout << x << " " << y << " " << bruit << " " << bruit << " " << bruit << std::endl;
+      }
+      else{
+	int r=getPixel(x,y).r();
+	int v=getPixel(x,y).v();
+	int b=getPixel(x,y).b();
+	nvr=r;nvv=v;nvb=b;
+	
+	int alea=(rand()%7);
+	switch(alea){
+	case 0 :
+	  nvb=(int)(b+bruit*_profondeurCouleur/255.0);
+	  if(verbeux)
+	    std::cout << x << " " << y << " 0 0 " << bruit << std::endl;
+	  break;
+	case 1:
+	  nvv=(int)(v+bruit*_profondeurCouleur/255.0);
+	  if(verbeux)
+	    std::cout << x << " " << y << " 0 " << bruit << " 0" << std::endl;
+	  break;
+	case 2:
+	  nvv=(int)(v+bruit*_profondeurCouleur/255.0);
+	  nvb=(int)(b+bruit*_profondeurCouleur/255.0);
+	  if(verbeux)
+	    std::cout << x << " " << y << " 0 " << bruit << " " << bruit << std::endl;
+	  break;
+	case 3:
+	  nvr=(int)(r+bruit*_profondeurCouleur/255.0);
+	  if(verbeux)
+	    std::cout << x << " " << y << " " << bruit << " 0 0" << std::endl;
+	  break;
+	case 4:
+	  nvr=(int)(r+bruit*_profondeurCouleur/255.0);
+	  nvb=(int)(b+bruit*_profondeurCouleur/255.0);
+	  if(verbeux)
+	    std::cout << x << " " << y << " " << bruit << " 0 " << bruit << std::endl;
+	  break;
+	case 5:
+	  nvr=(int)(r+bruit*_profondeurCouleur/255.0);
+	  nvv=(int)(v+bruit*_profondeurCouleur/255.0);
+	  if(verbeux)
+	    std::cout << x << " " << y << " " << bruit << " " << bruit << " 0" << std::endl;
+	  break;
+	default :
+	  nvr=(int)(r+bruit*_profondeurCouleur/255.0);
+	  nvv=(int)(v+bruit*_profondeurCouleur/255.0);
+	  nvb=(int)(b+bruit*_profondeurCouleur/255.0);
+	  if(verbeux)
+	    std::cout << x << " " << y << " " << bruit << " " << bruit << " " << bruit << std::endl;
+	}
+      }
+      if(nvr<0)
+	nvr=0;
+      if(nvv<0)
+	nvv=0;
+      if(nvb<0)
+	nvb=0;
+      if((unsigned int)nvr>_profondeurCouleur)
+	nvr=_profondeurCouleur;
+      if((unsigned int)nvv>_profondeurCouleur)
+	nvv=_profondeurCouleur;
+      if((unsigned int)nvb>_profondeurCouleur)
+	nvb=_profondeurCouleur;
+      setPixel(x,y,nvr,nvv,nvb);
+    }
+}
+
+double Lisic::Image::genereAleatoireCauchy(){
+  std::pair<double,double> p=genereAleatoireGaussien();
+  return (p.first/p.second);
+}
+
+void Lisic::Image::bruitCauchyLorentz(const double& force, const int& type, const bool& verbeux)
+{
+  /*assert(type==Lisic::Image::GLOBAL || type==Lisic::Image::PARCANAL);
+  struct timespec ts_start;
+  clock_gettime(CLOCK_MONOTONIC, &ts_start);
+  long temps=ts_start.tv_nsec;
+  srand(temps);
+
+  double min=0;
+  double max=0;
+  int nb=0;
+  
+  for(int i=0;i<10000000;i++){
+
+    double s;
+    double u1,u2,v1=0,v2=0;
+    while(v2<1e-6 && v2>-1e-6){
+      s=1.1;
+      v2=0;
+      while(s>=1.0 || (s<1e-6 && s>-1e-6)){
+	u1=((rand()%1000)*1.0)/1000.0;
+	u1=u1*2-1;
+	u2=((rand()%1000)*1.0)/1000.0;
+	u2=u2*2-1;
+	s=u1*u1+u2*u2;
+      }
+      v1=u1*sqrt(-2*log(s)/s);
+      v2=u2*sqrt(-2*log(s)/s);
+    }
+      
+    double aleaCauchy=v1/v2;
+    
+    if(aleaCauchy>max)
+      max=aleaCauchy;
+    if(aleaCauchy<min)
+      min=aleaCauchy;
+    //std::cout << aleaCauchy << " ";
+    if(aleaCauchy<4)
+      nb++;
+  }
+  std::cout << std::endl << "min,max : " << min << ";" << max << std::endl;
+  std::cout << (nb*1.0)/10000000.0 << " - " << atan(4)/M_PI+0.5 << std::endl;*/
+
+
+
+  assert(type==Lisic::Image::GLOBAL || type==Lisic::Image::PARCANAL);
+  
+  struct timespec ts_start;
+  clock_gettime(CLOCK_MONOTONIC, &ts_start);
+  long temps=ts_start.tv_nsec;
+  srand(temps);
+
+  int nvr,nvv,nvb;
+
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	if(type==Lisic::Image::GLOBAL){ 
+	  double aleaCauchy=genereAleatoireCauchy()*0.0002*force;
+	  
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+aleaCauchy*_profondeurCouleur/255.0;
+	  nvv=v+aleaCauchy*_profondeurCouleur/255.0;
+	  nvb=b+aleaCauchy*_profondeurCouleur/255.0;
+	  if(verbeux)
+	    std::cout << i << " " << j << " " << aleaCauchy << " " << aleaCauchy << " " << aleaCauchy << std::endl;
+	  
+	}
+	else{
+	  double aleaCauchy1=genereAleatoireCauchy()*0.0002*force;
+	  double aleaCauchy2=genereAleatoireCauchy()*0.0002*force;
+	  double aleaCauchy3=genereAleatoireCauchy()*0.0002*force;
+	  
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+aleaCauchy1*_profondeurCouleur/255.0;
+	  nvv=v+aleaCauchy2*_profondeurCouleur/255.0;
+	  nvb=b+aleaCauchy3*_profondeurCouleur/255.0;
+	  if(verbeux)
+	    std::cout << i << " " << j << " " << aleaCauchy1 << " " << aleaCauchy2 << " " << aleaCauchy3 << std::endl;	   
+	}
+	if(nvr<0)
+	  nvr=0;
+	if(nvv<0)
+	  nvv=0;
+	if(nvb<0)
+	  nvb=0;
+	if((unsigned int)nvr>_profondeurCouleur)
+	  nvr=_profondeurCouleur;
+	if((unsigned int)nvv>_profondeurCouleur)
+	  nvv=_profondeurCouleur;
+	if((unsigned int)nvb>_profondeurCouleur)
+	  nvb=_profondeurCouleur;
+	setPixel(i,j,nvr,nvv,nvb);
+      }
+}
+
+double Lisic::Image::genereAleatoireLaplace(double mu, double b){
+  //D'après wikipédia http://en.wikipedia.org/wiki/Laplace_distribution
+  double alea=genereAleatoireUniforme()+0.00005-0.5;//un nombre entre -0.49995 et 0.49995 pour éviter le -infini
+  double signe=alea<0?-1.0:1.0;
+  double absAlea=alea*signe;
+  return mu-b*signe*log(1-2*absAlea);
+}
+
+void Lisic::Image::bruitLaplacien(const double& force, const int& type, const bool& verbeux)
+{
+  assert(type==Lisic::Image::GLOBAL || type==Lisic::Image::PARCANAL);
+  
+  struct timespec ts_start;
+  clock_gettime(CLOCK_MONOTONIC, &ts_start);
+  long temps=ts_start.tv_nsec;
+  srand(temps);
+  
+  int nvr,nvv,nvb;
+  
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	if(type==Lisic::Image::GLOBAL){ 
+	  double aleaLaplace=genereAleatoireLaplace()*0.1*force;
+	  
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+aleaLaplace*_profondeurCouleur/255.0;
+	  nvv=v+aleaLaplace*_profondeurCouleur/255.0;
+	  nvb=b+aleaLaplace*_profondeurCouleur/255.0; 
+	  if(verbeux)
+	    std::cout << i << " " << j << " " << aleaLaplace << " " << aleaLaplace << " " << aleaLaplace << std::endl;
+	  
+	}
+	else{
+	  double aleaLaplace1=genereAleatoireLaplace()*0.1*force;	  
+	  double aleaLaplace2=genereAleatoireLaplace()*0.1*force;	  
+	  double aleaLaplace3=genereAleatoireLaplace()*0.1*force;
+	  
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+aleaLaplace1*_profondeurCouleur/255.0;
+	  nvv=v+aleaLaplace2*_profondeurCouleur/255.0;
+	  nvb=b+aleaLaplace3*_profondeurCouleur/255.0;
+	  if(verbeux)
+	    std::cout << i << " " << j << " " << aleaLaplace1 << " " << aleaLaplace2 << " " << aleaLaplace3 << std::endl;	   
+	}
+	if(nvr<0)
+	  nvr=0;
+	if(nvv<0)
+	  nvv=0;
+	if(nvb<0)
+	  nvb=0;
+	if((unsigned int)nvr>_profondeurCouleur)
+	  nvr=_profondeurCouleur;
+	if((unsigned int)nvv>_profondeurCouleur)
+	  nvv=_profondeurCouleur;
+	if((unsigned int)nvb>_profondeurCouleur)
+	  nvb=_profondeurCouleur;
+	setPixel(i,j,nvr,nvv,nvb);
+      }
+}
+
+double Lisic::Image::genereAleatoireLogNormale(){
+  //D'après wikipédia http://fr.wikipedia.org/wiki/Loi_normale#Lois_usuelles
+  double alea=genereAleatoireGaussien().first;
+  return exp(alea);
+}
+
+void Lisic::Image::bruitLogNormale(const double& force, const int& type, const bool& verbeux)
+{
+  assert(type==Lisic::Image::GLOBAL || type==Lisic::Image::PARCANAL);
+
+  struct timespec ts_start;
+  clock_gettime(CLOCK_MONOTONIC, &ts_start);
+  long temps=ts_start.tv_nsec;
+  srand(temps);
+  
+  int nvr,nvv,nvb;
+  
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	if(type==Lisic::Image::GLOBAL){ 
+	  double aleaLogNormale=genereAleatoireLogNormale()*0.05*force;
+	  
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+aleaLogNormale*_profondeurCouleur/255.0;
+	  nvv=v+aleaLogNormale*_profondeurCouleur/255.0;
+	  nvb=b+aleaLogNormale*_profondeurCouleur/255.0;
+	  if(verbeux)
+	    std::cout << i << " " << j << " " << aleaLogNormale << " " << aleaLogNormale << " " << aleaLogNormale << std::endl;
+	  
+	}
+	else{
+	  double aleaLogNormale1=genereAleatoireLogNormale()*0.05*force;
+	  double aleaLogNormale2=genereAleatoireLogNormale()*0.05*force;  
+	  double aleaLogNormale3=genereAleatoireLogNormale()*0.05*force;
+	  
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+aleaLogNormale1*_profondeurCouleur/255.0;
+	  nvv=v+aleaLogNormale2*_profondeurCouleur/255.0;
+	  nvb=b+aleaLogNormale3*_profondeurCouleur/255.0;
+	  if(verbeux)
+	    std::cout << i << " " << j << " " << aleaLogNormale1 << " " << aleaLogNormale2 << " " << aleaLogNormale3 << std::endl;	   
+	}
+	if(nvr<0)
+	  nvr=0;
+	if(nvv<0)
+	  nvv=0;
+	if(nvb<0)
+	  nvb=0;
+	if((unsigned int)nvr>_profondeurCouleur)
+	  nvr=_profondeurCouleur;
+	if((unsigned int)nvv>_profondeurCouleur)
+	  nvv=_profondeurCouleur;
+	if((unsigned int)nvb>_profondeurCouleur)
+	  nvb=_profondeurCouleur;
+	setPixel(i,j,nvr,nvv,nvb);
+      }
+}
+
+void Lisic::Image::bruitMultiplicatifUniforme(const double& force, const int& type, const bool& verbeux)
+{
+  assert(type==Lisic::Image::GLOBAL || type==Lisic::Image::PARCANAL);
+  struct timespec ts_start;
+  clock_gettime(CLOCK_MONOTONIC, &ts_start);
+  long temps=ts_start.tv_nsec;
+  srand(temps);
+
+  int nvr,nvv,nvb;
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	if(type==Lisic::Image::GLOBAL){
+	  double alea=(genereAleatoireUniforme()-0.5)*0.002*force;
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+r*alea;
+	  nvv=v+v*alea;
+	  nvb=b+b*alea;
+	  if(verbeux)
+	    std::cout << i << " " << j << " * * *" << std::endl;
+	}
+	else{
+	  double alea1=(genereAleatoireUniforme()-0.5)*0.002*force;
+	  double alea2=(genereAleatoireUniforme()-0.5)*0.002*force;
+	  double alea3=(genereAleatoireUniforme()-0.5)*0.002*force;
+	  int r=getPixel(i,j).r();
+	  int v=getPixel(i,j).v();
+	  int b=getPixel(i,j).b();
+	  nvr=r+r*alea1;
+	  nvv=v+v*alea2;
+	  nvb=b+b*alea3;
+	  if(verbeux)
+	    std::cout << i << " " << j << " * * *" << std::endl;
+	}
+	if(nvr<0)
+	  nvr=0;
+	if(nvv<0)
+	  nvv=0;
+	if(nvb<0)
+	  nvb=0; 
+	if((unsigned int)nvr>_profondeurCouleur)
+	  nvr=_profondeurCouleur;
+	if((unsigned int)nvv>_profondeurCouleur)
+	  nvv=_profondeurCouleur;
+	if((unsigned int)nvb>_profondeurCouleur)
+	  nvb=_profondeurCouleur;
+	setPixel(i,j,nvr,nvv,nvb);
+      }
+  std::cout << std::endl;
+}
+
+void Lisic::Image::bruitMasque(std::string chemin){
+  std::ifstream fic(chemin);
+  assert(fic.good() && fic.is_open());
+  while(!fic.eof()){
+    int x,y;
+    double br,bv,bb,nvr,nvv,nvb;
+    fic >> x >> y >> br >> bv >> bb;
+    int r=getPixel(x,y).r();
+    int v=getPixel(x,y).v();
+    int b=getPixel(x,y).b();
+    nvr=r+br*_profondeurCouleur/255.0;
+    nvv=v+bv*_profondeurCouleur/255.0;
+    nvb=b+bb*_profondeurCouleur/255.0;
+    if(nvr<0)
+      nvr=0;
+    if(nvv<0)
+      nvv=0;
+    if(nvb<0)
+      nvb=0; 
+    if((unsigned int)nvr>_profondeurCouleur)
+      nvr=_profondeurCouleur;
+    if((unsigned int)nvv>_profondeurCouleur)
+      nvv=_profondeurCouleur;
+    if((unsigned int)nvb>_profondeurCouleur)
+      nvb=_profondeurCouleur;
+    setPixel(x,y,nvr,nvv,nvb);
+  }
+}
+
+
+std::vector<double> Lisic::Image::SVD() const
+{
+  /*for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++){
+      if(getPixel(i,j).r()-getPixel(i,j).v()!=0 || 
+	 getPixel(i,j).r()-getPixel(i,j).b()!=0 || 
+	 getPixel(i,j).b()-getPixel(i,j).v()!=0)
+	std::cout << "Pixel en (" << i << "," << j << ") - (" << getPixel(i,j).r() << "," << getPixel(i,j).v() << "," << getPixel(i,j).b() << ")" << std::endl;
+      assert(!(getPixel(i,j).r()-getPixel(i,j).v()!=0 || 
+	     getPixel(i,j).r()-getPixel(i,j).b()!=0 || 
+	       getPixel(i,j).b()-getPixel(i,j).v()!=0));
+    }*/
+  
+  Eigen::MatrixXf m(_tailleY,_tailleX);
+
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      m(j,i)=getPixel(i,j).r();
+
+  Eigen::JacobiSVD<Eigen::MatrixXf> svd(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
+  Eigen::VectorXf valeursSingulieres(svd.singularValues());
+
+  std::vector<double> v;
+  for(int i=0;i<valeursSingulieres.size();i++)
+    v.push_back(valeursSingulieres(i));
+
+  return v;
+
+}
+
+double Lisic::Image::SVD(const unsigned int& num) const
+{
+  std::vector<double> tab=SVD();
+  assert(num<tab.size());
+  return tab[num];
+}
+
+double Lisic::Image::SVD_entropy() const
+{
+  /*Voir Feature selection with SVD entropy : somes modification and extension*/
+  std::vector<double> svd=SVD();
+
+  std::vector<double> eigenValues;
+  double sommeEigenValues = 0;
+  
+  for(unsigned int i=0;i<svd.size();i++){
+    eigenValues.push_back(svd[i]*svd[i]);
+    sommeEigenValues+=svd[i]*svd[i];
+  }
+
+  std::vector<double> v;
+
+  for(unsigned int i=0;i<eigenValues.size();i++)
+    v.push_back(eigenValues[i]/sommeEigenValues);
+
+  double SVD_entropy = 0;
+
+  for(unsigned int i=0;i<eigenValues.size();i++)
+    SVD_entropy+=(v[i]*log(v[i]));
+
+  SVD_entropy*=-1;
+  //Ici, on a des matrices carrées donc on divise par eigenValues.size()
+  //De toute façon, l'étape de calcul du min entre largeur et hauteur de la matrice est faite lors du calcul du SVD
+  SVD_entropy/=log(eigenValues.size());
+
+  return SVD_entropy;
+}
+
+double Lisic::Image::SVD_entropy(std::vector<unsigned int> colonne) const
+{for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++){
+      if(getPixel(i,j).r()-getPixel(i,j).v()!=0 || 
+	 getPixel(i,j).r()-getPixel(i,j).b()!=0 || 
+	 getPixel(i,j).b()-getPixel(i,j).v()!=0)
+	std::cout << "Pixel en (" << i << "," << j << ") - (" << getPixel(i,j).r() << "," << getPixel(i,j).v() << "," << getPixel(i,j).b() << ")" << std::endl;
+      assert(!(getPixel(i,j).r()-getPixel(i,j).v()!=0 || 
+	     getPixel(i,j).r()-getPixel(i,j).b()!=0 || 
+	       getPixel(i,j).b()-getPixel(i,j).v()!=0));
+    }
+  
+  Eigen::MatrixXf m(_tailleY,_tailleX-colonne.size());
+
+  int nbDejaTrouve=0;
+  for(unsigned int i=0;i<_tailleX;i++){
+    bool aAjouter=true;
+    for(unsigned int k=0;k<colonne.size();k++)
+      if(colonne[k]==i)
+	aAjouter=false;
+    if(aAjouter){	
+      for(unsigned int j=0;j<_tailleY;j++)
+	m(j,i-nbDejaTrouve)=getPixel(i,j).r();
+    }else{
+      nbDejaTrouve++;
+    }
+  }
+
+  Eigen::JacobiSVD<Eigen::MatrixXf> temp(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
+  Eigen::VectorXf valeursSingulieres(temp.singularValues());
+
+  std::vector<double> svd;
+  for(int i=0;i<valeursSingulieres.size();i++)
+    svd.push_back(valeursSingulieres(i));
+
+  std::vector<double> eigenValues;
+  double sommeEigenValues = 0;
+  
+  for(unsigned int i=0;i<svd.size();i++){
+    eigenValues.push_back(svd[i]*svd[i]);
+    sommeEigenValues+=svd[i]*svd[i];
+  }
+
+  std::vector<double> v;
+
+  for(unsigned int i=0;i<eigenValues.size();i++)
+    v.push_back(eigenValues[i]/sommeEigenValues);
+
+  double SVD_entropy = 0;
+
+  for(unsigned int i=0;i<eigenValues.size();i++)
+    SVD_entropy+=(v[i]*log(v[i]));
+
+  SVD_entropy*=-1;
+  //Ici, on a des matrices carrées donc on divise par eigenValues.size()
+  //De toute façon, l'étape de calcul du min entre largeur et hauteur de la matrice est faite lors du calcul du SVD
+  SVD_entropy/=log(eigenValues.size());
+
+  return SVD_entropy;
+ 
+}
+
+double Lisic::Image::MSE(const Image& im, const unsigned int& numCanal) const
+{
+  assert(numCanal<=2);
+  assert(_profondeurCouleur==im._profondeurCouleur);
+  assert(_tailleX==im._tailleX && _tailleY==im._tailleY);
+
+  double somme=0;
+  
+  for(unsigned int i=0;i<_tailleX;i+=1)
+    for(unsigned int j=0;j<_tailleY;j+=1)
+      {
+	double inter=((getPixel(i,j)[numCanal])*1.0)-((im.getPixel(i,j)[numCanal])*1.0);
+	somme+=inter*inter;
+      }
+	
+  return somme/(_tailleX*_tailleY);
+  
+}
+
+std::tuple<double, double, double> Lisic::Image::MSE(const Image& im) const
+{
+  assert(im._tailleX==_tailleY && im._tailleY==_tailleY && im._profondeurCouleur==_profondeurCouleur);
+  return std::make_tuple(MSE(im,0),MSE(im,1),MSE(im,2));
+}
+
+double Lisic::Image::SSIM(const Image& im, const unsigned int& numCanal) const
+{
+  assert(numCanal<=2);
+  assert(_tailleX%8==0);
+  assert(_tailleY%8==0);
+  assert(_profondeurCouleur==im._profondeurCouleur);
+  assert(_tailleX==im._tailleX && _tailleY==im._tailleY);
+
+  std::vector<double> listX;
+  listX.resize(64);
+  std::vector<double> listY;
+  listY.resize(64);
+  double somme=0;
+  
+  for(unsigned int depX=0;depX<_tailleX;depX+=8)
+    for(unsigned int depY=0;depY<_tailleY;depY+=8)
+      {
+	
+	for(unsigned int i=0;i<8;i++)
+	  for(unsigned int j=0;j<8;j++){
+	    listX[j*8+i]=((getPixel(depX+i,depY+j)[numCanal])*1.0);
+	    listY[j*8+i]=((im.getPixel(depX+i,depY+j)[numCanal])*1.0);
+	  }
+	
+	double moyX=moyenne(listX);
+	double moyY=moyenne(listY);
+	double varX=variance(listX);
+	double varY=variance(listY);
+	double covXY=covariance(listX,listY);
+	double c1=(0.01*255)*(0.01*255);
+	double c2=(0.03*255)*(0.03*255);
+	somme+=((2*moyX*moyY+c1)*(2*covXY+c2))/((moyX*moyX+moyY*moyY+c1)*(varX+varY+c2));
+      }
+  return somme/(_tailleX*_tailleY/64);
+  
+}
+
+std::tuple<double, double, double> Lisic::Image::SSIM(const Image& im) const
+{
+  assert(im._tailleX==_tailleY && im._tailleY==_tailleY && im._profondeurCouleur==_profondeurCouleur);
+  return std::make_tuple(SSIM(im,0),SSIM(im,1),SSIM(im,2));
+}
+
+double Lisic::Image::DSSIM(const Image& im, const unsigned int& numCanal) const
+{
+  assert(numCanal<=2);
+  assert(_tailleX%8==0);
+  assert(_tailleY%8==0);
+  assert(_profondeurCouleur==im._profondeurCouleur);
+  assert(_tailleX==im._tailleX && _tailleY==im._tailleY);
+
+  double ssim=SSIM(im,numCanal);
+  return (1.0-ssim)/2.0;
+}
+
+std::tuple<double, double, double> Lisic::Image::DSSIM(const Image& im) const
+{
+  assert(im._tailleX==_tailleY && im._tailleY==_tailleY && im._profondeurCouleur==_profondeurCouleur);
+  return std::make_tuple(DSSIM(im,0),DSSIM(im,1),DSSIM(im,2));
+}
+
+Lisic::Image Lisic::Image::filtre_moyenneur(const unsigned int& taille_filtre) const
+{
+  assert((taille_filtre%2)==1);
+  
+  Lisic::Image img_retour(_tailleX,_tailleY);
+  for(unsigned int i=0;i<_tailleX;i++)
+    for(unsigned int j=0;j<_tailleY;j++){
+      unsigned int aAjouter_r=0;
+      unsigned int aAjouter_v=0;
+      unsigned int aAjouter_b=0;
+      int nbValeur=0;
+      for(int i_f=(((int)(taille_filtre))/2)*-1;i_f<=((int)(taille_filtre))/2;i_f++)
+	for(int j_f=(((int)(taille_filtre))/2)*-1;j_f<=((int)(taille_filtre))/2;j_f++){
+	  if(i+i_f>=0 && i+i_f<_tailleX && j+j_f>=0 && j+j_f<_tailleY){
+	    nbValeur++;
+	    aAjouter_r+=getPixel(i+i_f,j+j_f)[0];
+	    aAjouter_v+=getPixel(i+i_f,j+j_f)[1];
+	    aAjouter_b+=getPixel(i+i_f,j+j_f)[2];
+	  }
+	}
+      
+      aAjouter_r/=nbValeur;
+      aAjouter_v/=nbValeur;
+      aAjouter_b/=nbValeur;
+
+      img_retour.setPixel(i,j,aAjouter_r,aAjouter_v,aAjouter_b);
+    }
+
+  return img_retour;
+}
+
+Lisic::Image Lisic::Image::filtre_Gaussien(const unsigned int& taille_filtre, const double& sigma) const
+{
+  assert((taille_filtre%2)==1);
+  
+  Lisic::Image img_retour(_tailleX,_tailleY);
+  for(unsigned int i=0;i<_tailleX;i++)
+    for(unsigned int j=0;j<_tailleY;j++){
+      unsigned int aAjouter_r=0;
+      unsigned int aAjouter_v=0;
+      unsigned int aAjouter_b=0;
+      int nbValeur=0;
+      double coeff,sommeCoeff=0;
+      for(int i_f=(((int)(taille_filtre))/2)*-1;i_f<=((int)(taille_filtre))/2;i_f++)
+	for(int j_f=(((int)(taille_filtre))/2)*-1;j_f<=((int)(taille_filtre))/2;j_f++){
+	  coeff=(1.0/(2*M_PI*sigma*sigma))*exp(-((i_f*i_f+j_f*j_f)/(2*sigma*sigma)));
+	  if(i+i_f>=0 && i+i_f<_tailleX && j+j_f>=0 && j+j_f<_tailleY){
+	    nbValeur++;
+	    aAjouter_r+=coeff*getPixel(i+i_f,j+j_f)[0];
+	    aAjouter_v+=coeff*getPixel(i+i_f,j+j_f)[1];
+	    aAjouter_b+=coeff*getPixel(i+i_f,j+j_f)[2];
+	    sommeCoeff+=coeff;
+	  }
+	}
+      aAjouter_r/=sommeCoeff;
+      aAjouter_v/=sommeCoeff;
+      aAjouter_b/=sommeCoeff;
+
+      img_retour.setPixel(i,j,aAjouter_r,aAjouter_v,aAjouter_b);
+    }
+
+  return img_retour;
+}
+
+Lisic::Image Lisic::Image::filtre_median(const unsigned int& taille_filtre) const
+{
+  assert((taille_filtre%2)==1);
+  
+  Lisic::Image img_retour(_tailleX,_tailleY);
+  for(unsigned int i=0;i<_tailleX;i++)
+    for(unsigned int j=0;j<_tailleY;j++){
+      std::vector<unsigned int> liste_r;
+      std::vector<unsigned int> liste_v;
+      std::vector<unsigned int> liste_b;
+      liste_r.clear();
+      liste_v.clear();
+      liste_b.clear();
+      for(int i_f=(((int)(taille_filtre))/2)*-1;i_f<=((int)(taille_filtre))/2;i_f++)
+	for(int j_f=(((int)(taille_filtre))/2)*-1;j_f<=((int)(taille_filtre))/2;j_f++){
+	  if(i+i_f>=0 && i+i_f<_tailleX && j+j_f>=0 && j+j_f<_tailleY){
+	    liste_r.push_back(getPixel(i+i_f,j+j_f)[0]);
+	    liste_v.push_back(getPixel(i+i_f,j+j_f)[1]);
+	    liste_b.push_back(getPixel(i+i_f,j+j_f)[2]);
+	  }
+	}
+
+      std::sort(liste_r.begin(),liste_r.end());
+      std::sort(liste_v.begin(),liste_v.end());
+      std::sort(liste_b.begin(),liste_b.end());
+      
+      img_retour.setPixel(i,j,liste_r[(liste_r.size()/2)+1],liste_v[(liste_v.size()/2)+1],liste_b[(liste_b.size()/2)+1]);
+    }
+
+  return img_retour;
+}
+
+Lisic::Image Lisic::Image::filtre_Wiener(const unsigned int& taille_filtre) const
+{
+  assert((taille_filtre%2)==1);
+
+  Lisic::Image img_retour(_tailleX,_tailleY);
+  std::vector<double> moyenne_locale_r;
+  std::vector<double> moyenne_locale_v;
+  std::vector<double> moyenne_locale_b;
+  std::vector<double> variance_locale_r;
+  std::vector<double> variance_locale_v;
+  std::vector<double> variance_locale_b;
+  
+  for(unsigned int i=0;i<_tailleX;i++)
+    for(unsigned int j=0;j<_tailleY;j++){
+      std::vector<double> voisinage_r;
+      std::vector<double> voisinage_v;
+      std::vector<double> voisinage_b;
+      for(int i_f=(((int)(taille_filtre))/2)*-1;i_f<=((int)(taille_filtre))/2;i_f++)
+	for(int j_f=(((int)(taille_filtre))/2)*-1;j_f<=((int)(taille_filtre))/2;j_f++){
+	  if(i+i_f>=0 && i+i_f<_tailleX && j+j_f>=0 && j+j_f<_tailleY){
+	    voisinage_r.push_back(getPixel(i+i_f,j+j_f)[0]);
+	    voisinage_v.push_back(getPixel(i+i_f,j+j_f)[1]);
+	    voisinage_b.push_back(getPixel(i+i_f,j+j_f)[2]);
+	  }
+	}
+      moyenne_locale_r.push_back(moyenne(voisinage_r));
+      moyenne_locale_v.push_back(moyenne(voisinage_v));
+      moyenne_locale_b.push_back(moyenne(voisinage_b));
+      variance_locale_r.push_back(variance(voisinage_r));
+      variance_locale_v.push_back(variance(voisinage_v));
+      variance_locale_b.push_back(variance(voisinage_b));
+    }
+
+  double moyenne_variance_r=moyenne(variance_locale_r);
+  double moyenne_variance_v=moyenne(variance_locale_v);
+  double moyenne_variance_b=moyenne(variance_locale_b);
+  
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++){
+      
+      double nv_r=0,nv_b=0,nv_v=0;
+      double sommeCoeff_r=0,sommeCoeff_v=0,sommeCoeff_b=0;
+      for(int i_f=(((int)(taille_filtre))/2)*-1;i_f<=((int)(taille_filtre))/2;i_f++)
+	for(int j_f=(((int)(taille_filtre))/2)*-1;j_f<=((int)(taille_filtre))/2;j_f++){
+	  if(i+i_f>=0 && i+i_f<_tailleX && j+j_f>=0 && j+j_f<_tailleY){
+	    double moyenne_r=moyenne_locale_r[(i+i_f)*_tailleY+(j+j_f)];
+	    double variance_r=variance_locale_r[(i+i_f)*_tailleY+(j+j_f)];
+	    double moyenne_v=moyenne_locale_v[(i+i_f)*_tailleY+(j+j_f)];
+	    double variance_v=variance_locale_v[(i+i_f)*_tailleY+(j+j_f)];
+	    double moyenne_b=moyenne_locale_b[(i+i_f)*_tailleY+(j+j_f)];
+	    double variance_b=variance_locale_b[(i+i_f)*_tailleY+(j+j_f)];
+	    if(variance_r==0) variance_r=0.00001;
+	    if(variance_v==0) variance_v=0.00001;
+	    if(variance_b==0) variance_b=0.00001;
+	    double coul_r=moyenne_r+((variance_r-moyenne_variance_r)/(variance_r))*(getPixel(i+i_f,j+j_f)[0]-moyenne_r);
+	    double coul_v=moyenne_v+((variance_v-moyenne_variance_v)/(variance_v))*(getPixel(i+i_f,j+j_f)[1]-moyenne_v);
+	    double coul_b=moyenne_b+((variance_b-moyenne_variance_b)/(variance_b))*(getPixel(i+i_f,j+j_f)[2]-moyenne_b);
+	    sommeCoeff_r+=coul_r;
+	    sommeCoeff_v+=coul_v;
+	    sommeCoeff_b+=coul_b;
+	    nv_r+=coul_r*getPixel(i+i_f,j+j_f)[0];
+	    nv_v+=coul_v*getPixel(i+i_f,j+j_f)[1];
+	    nv_b+=coul_b*getPixel(i+i_f,j+j_f)[2];
+	  }
+	}
+      nv_r/=sommeCoeff_r;
+      nv_v/=sommeCoeff_v;
+      nv_b/=sommeCoeff_b;
+      if(nv_r<0) nv_r=0;
+      if(nv_v<0) nv_v=0;
+      if(nv_b<0) nv_b=0;
+      if(nv_r>_profondeurCouleur) nv_r=_profondeurCouleur;
+      if(nv_v>_profondeurCouleur) nv_v=_profondeurCouleur;
+      if(nv_b>_profondeurCouleur) nv_b=_profondeurCouleur;
+      
+      img_retour.setPixel(i,j,(unsigned int)(nv_r),(unsigned int)(nv_v),(unsigned int)(nv_b));
+    }
+  
+  return img_retour;
+}
+
+Lisic::Image Lisic::Image::filtre_ondelette(const unsigned int& nbIteration) const
+{
+  cv::Mat Src=cv::Mat(_tailleY, _tailleX, CV_32FC1);
+  cv::Mat Dst=cv::Mat(_tailleY, _tailleX, CV_32FC1);
+  cv::Mat Temp=cv::Mat(_tailleY, _tailleX, CV_32FC1);
+  cv::Mat Filtered=cv::Mat(_tailleY, _tailleX, CV_32FC1);
+
+  
+  cv::Mat GrayFrame=image2Mat(*this);
+  
+  GrayFrame.convertTo(Src,CV_32FC1);
+  cvHaarWavelet(Src,Dst,nbIteration);
+  
+  Dst.copyTo(Temp);
+  
+  cvInvHaarWavelet(Temp,Filtered,nbIteration,HARD,30);
+  
+  Lisic::Image img2(*this);
+  for(unsigned int i=0;i<_tailleX;i++)
+    for(unsigned int j=0;j<_tailleY;j++){
+      float valeur=Temp.at<float>(j,i);
+      img2.setPixel(i,j,(unsigned int)valeur,(unsigned int)valeur,(unsigned int)valeur);
+    }
+  
+  return img2;
+}
+
+double Lisic::Image::param_Andre_filtre_moyenneur_3_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_moyenneur(3);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_moyenneur_3_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_moyenneur(3);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_moyenneur_5_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_moyenneur(5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_moyenneur_5_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_moyenneur(5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_3_05_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(3,0.5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_3_05_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(3,0.5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_3_10_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(3,1);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_3_10_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(3,1);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_3_15_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(3,1.5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_3_15_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(3,1.5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_5_05_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(5,0.5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_5_05_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(5,0.5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_5_10_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(5,1);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_5_10_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(5,1);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_5_15_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(5,1.5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Gaussien_5_15_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Gaussien(5,1.5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_median_3_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_median(3);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_median_3_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_median(3);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_median_5_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_median(5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_median_5_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_median(5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Wiener_3_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Wiener(3);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Wiener_3_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Wiener(3);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Wiener_5_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Wiener(5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_Wiener_5_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_Wiener(5);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_ondelette_2_moyenne() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_ondelette(2);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  return moyenne(tab);
+}
+
+double Lisic::Image::param_Andre_filtre_ondelette_2_ecart_type() const
+{
+  assert(estNiveauGris());
+  Image imgTemp(*this); imgTemp.normaliserA255();
+  std::vector<double> tab;
+  Lisic::Image img_f=imgTemp.filtre_ondelette(2);
+  imgTemp.normaliserA255(); Lisic::Image img2=imgTemp-img_f;
+  for(unsigned int i=0;i<_pixels.size();i++)
+    tab.push_back(img2._pixels[i][0]);
+  
+  return ecartType(tab);
+}
+
+Lisic::Image Lisic::Image::operator-(const Image& im) const
+{
+  assert(im._tailleX==_tailleY && im._tailleY==_tailleY && im._profondeurCouleur==_profondeurCouleur);
+  
+  Lisic::Image img(_tailleX,_tailleY,_profondeurCouleur);
+
+  for(unsigned int j=0;j<_tailleY;j++)
+    for(unsigned int i=0;i<_tailleX;i++)
+      {
+	if((int)(_pixels[j*_tailleX+i][0]-im._pixels[j*_tailleX+i][0])<0)
+	  img._pixels[j*_tailleX+i][0]=im._pixels[j*_tailleX+i][0]-_pixels[j*_tailleX+i][0];
+	else
+	  img._pixels[j*_tailleX+i][0]=_pixels[j*_tailleX+i][0]-im._pixels[j*_tailleX+i][0];
+
+	if((int)(_pixels[j*_tailleX+i][1]-im._pixels[j*_tailleX+i][1])<0)
+	  img._pixels[j*_tailleX+i][1]=im._pixels[j*_tailleX+i][1]-_pixels[j*_tailleX+i][1];
+	else
+	  img._pixels[j*_tailleX+i][1]=_pixels[j*_tailleX+i][1]-im._pixels[j*_tailleX+i][1];
+
+	if((int)(_pixels[j*_tailleX+i][2]-im._pixels[j*_tailleX+i][2])<0)
+	  img._pixels[j*_tailleX+i][2]=im._pixels[j*_tailleX+i][2]-_pixels[j*_tailleX+i][2];
+	else
+	  img._pixels[j*_tailleX+i][2]=_pixels[j*_tailleX+i][2]-im._pixels[j*_tailleX+i][2];
+	//if(img._pixels[j*_tailleX+i][0]!=0 || img._pixels[j*_tailleX+i][1]!=0 || img._pixels[j*_tailleX+i][2]!=0)
+	//std::cout << "(" << i << "," << j << ") : " << (img._pixels[j*_tailleX+i][0]+img._pixels[j*_tailleX+i][1]+img._pixels[j*_tailleX+i][2]) << std::endl;
+      }
+  
+  return img;
+}
+
+bool Lisic::Image::operator==(const Lisic::Image& im) const
+{
+  if(_tailleX!=im._tailleX || _tailleY!=im._tailleY)
+    return false;
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    if(_pixels[i]!=im._pixels[i])
+      return false;
+  return true;
+}
+
+bool Lisic::Image::operator!=(const Lisic::Image& im) const
+{
+  if(_tailleX!=im._tailleX || _tailleY!=im._tailleY)
+    return true;
+  for(unsigned int i=0;i<_tailleX*_tailleY;i++)
+    if(_pixels[i]!=im._pixels[i])
+      return true;
+  return false;
+}
+
+double Lisic::Image::moyenne(std::vector<double> x)
+{
+  double somme=0;
+  for(unsigned int i=0;i<x.size();i++)
+    somme+=x[i];
+  return (somme/x.size());
+}
+
+double Lisic::Image::variance(std::vector<double> x)
+{
+  double moy=moyenne(x),somme=0;
+  for(unsigned int i=0;i<x.size();i++)
+    somme+=(x[i]-moy)*(x[i]-moy);
+  return (somme/x.size());
+}
+
+double Lisic::Image::ecartType(std::vector<double> x)
+{
+  return sqrt(variance(x));
+}
+
+double Lisic::Image::covariance(std::vector<double> x, std::vector<double> y)
+{
+  assert(x.size()==y.size());
+  double centerX=0,centerY=0,somme=0;
+  for(unsigned int i=0;i<x.size();i++)
+    {
+      centerX+=x[i];
+      centerY+=y[i];
+    }
+  centerX/=x.size();centerY/=x.size();
+
+  for(unsigned int i=0;i<x.size();i++)
+    {
+      double tempx=x[i]-centerX;
+      double tempy=y[i]-centerY;
+      double mul=tempx*tempy;
+      somme+=mul;
+    }
+
+  somme/=x.size();
+
+  return somme;
+}
+
+//------------------------------
+//Pour la partie ondelette
+//------------------------------
+//--------------------------------
+// signum
+//--------------------------------
+float Lisic::Image::sgn(float x)
+{
+    float res=0;
+    if(x==0)
+    {
+        res=0;
+    }
+    if(x>0)
+    {
+        res=1;
+    }
+    if(x<0)
+    {
+        res=-1;
+    }
+    return res;
+}
+//--------------------------------
+// Soft shrinkage
+//--------------------------------
+float Lisic::Image::soft_shrink(float d,float T)
+{
+    float res;
+    if(fabs(d)>T)
+    {
+        res=sgn(d)*(fabs(d)-T);
+    }
+    else
+    {
+        res=0;
+    }
+
+    return res;
+}
+//--------------------------------
+// Hard shrinkage
+//--------------------------------
+float Lisic::Image::hard_shrink(float d,float T)
+{
+    float res;
+    if(fabs(d)>T)
+    {
+        res=d;
+    }
+    else
+    {
+        res=0;
+    }
+
+    return res;
+}
+//--------------------------------
+// Garrot shrinkage
+//--------------------------------
+float Lisic::Image::Garrot_shrink(float d,float T)
+{
+    float res;
+    if(fabs(d)>T)
+    {
+        res=d-((T*T)/d);
+    }
+    else
+    {
+        res=0;
+    }
+
+    return res;
+}
+//--------------------------------
+// Wavelet transform
+//--------------------------------
+void Lisic::Image::cvHaarWavelet(cv::Mat &src,cv::Mat &dst,int NIter)
+{
+    float c,dh,dv,dd;
+    assert( src.type() == CV_32FC1 );
+    assert( dst.type() == CV_32FC1 );
+    int width = src.cols;
+    int height = src.rows;
+    for (int k=0;k<NIter;k++) 
+    {
+        for (int y=0;y<(height>>(k+1));y++)
+        {
+            for (int x=0; x<(width>>(k+1));x++)
+            {
+                c=(src.at<float>(2*y,2*x)+src.at<float>(2*y,2*x+1)+src.at<float>(2*y+1,2*x)+src.at<float>(2*y+1,2*x+1))*0.5;
+                dst.at<float>(y,x)=c;
+
+                dh=(src.at<float>(2*y,2*x)+src.at<float>(2*y+1,2*x)-src.at<float>(2*y,2*x+1)-src.at<float>(2*y+1,2*x+1))*0.5;
+                dst.at<float>(y,x+(width>>(k+1)))=dh;
+
+                dv=(src.at<float>(2*y,2*x)+src.at<float>(2*y,2*x+1)-src.at<float>(2*y+1,2*x)-src.at<float>(2*y+1,2*x+1))*0.5;
+                dst.at<float>(y+(height>>(k+1)),x)=dv;
+
+                dd=(src.at<float>(2*y,2*x)-src.at<float>(2*y,2*x+1)-src.at<float>(2*y+1,2*x)+src.at<float>(2*y+1,2*x+1))*0.5;
+                dst.at<float>(y+(height>>(k+1)),x+(width>>(k+1)))=dd;
+            }
+        }
+        dst.copyTo(src);
+    }   
+}
+//--------------------------------
+//Inverse wavelet transform
+//--------------------------------
+void Lisic::Image::cvInvHaarWavelet(cv::Mat &src,cv::Mat &dst,int NIter, int SHRINKAGE_TYPE, float SHRINKAGE_T)
+{
+    float c,dh,dv,dd;
+    assert( src.type() == CV_32FC1 );
+    assert( dst.type() == CV_32FC1 );
+    int width = src.cols;
+    int height = src.rows;
+    //--------------------------------
+    // NIter - number of iterations 
+    //--------------------------------
+    for (int k=NIter;k>0;k--) 
+    {
+        for (int y=0;y<(height>>k);y++)
+        {
+            for (int x=0; x<(width>>k);x++)
+            {
+                c=src.at<float>(y,x);
+                dh=src.at<float>(y,x+(width>>k));
+                dv=src.at<float>(y+(height>>k),x);
+                dd=src.at<float>(y+(height>>k),x+(width>>k));
+
+               // (shrinkage)
+                switch(SHRINKAGE_TYPE)
+                {
+                case HARD:
+                    dh=hard_shrink(dh,SHRINKAGE_T);
+                    dv=hard_shrink(dv,SHRINKAGE_T);
+                    dd=hard_shrink(dd,SHRINKAGE_T);
+                    break;
+                case SOFT:
+                    dh=soft_shrink(dh,SHRINKAGE_T);
+                    dv=soft_shrink(dv,SHRINKAGE_T);
+                    dd=soft_shrink(dd,SHRINKAGE_T);
+                    break;
+                case GARROT:
+                    dh=Garrot_shrink(dh,SHRINKAGE_T);
+                    dv=Garrot_shrink(dv,SHRINKAGE_T);
+                    dd=Garrot_shrink(dd,SHRINKAGE_T);
+                    break;
+                }
+
+                //-------------------
+                dst.at<float>(y*2,x*2)=0.5*(c+dh+dv+dd);
+                dst.at<float>(y*2,x*2+1)=0.5*(c-dh+dv-dd);
+                dst.at<float>(y*2+1,x*2)=0.5*(c+dh-dv-dd);
+                dst.at<float>(y*2+1,x*2+1)=0.5*(c-dh-dv+dd);            
+            }
+        }
+        cv::Mat C=src(cv::Rect(0,0,width>>(k-1),height>>(k-1)));
+        cv::Mat D=dst(cv::Rect(0,0,width>>(k-1),height>>(k-1)));
+        D.copyTo(C);
+    }   
+}
+//--------------------------------
+//Image to cv::Mat
+//--------------------------------
+cv::Mat Lisic::Image::image2Mat(Lisic::Image img)
+{
+  assert(img.estNiveauGris());
+
+  cv::Mat m=cv::Mat(img._tailleY,img._tailleX,CV_8UC1);
+  for(unsigned int i=0;i<img._tailleX;i++)
+    for(unsigned int j=0;j<img._tailleY;j++)
+      m.at<unsigned char>(j,i)=img.getPixel(i,j).r();
+
+  return m;
+}

+ 158 - 0
classeImage/Image.1.hpp

@@ -0,0 +1,158 @@
+#ifndef IMAGE_H
+#define IMAGE_H
+
+#include <cassert>
+#include <time.h>
+#include <iostream>
+#include <fstream>
+#include <cstring>
+#include <cmath>
+#include <cstdlib>
+#include <vector>
+#include <tuple>
+
+#ifdef IM6
+#include <ImageMagick-6/Magick++.h>
+#include <ImageMagick-6/magick/MagickCore.h>
+#endif
+
+#ifdef IM7
+#include <ImageMagick-7/Magick++.h>
+#include <ImageMagick-7/MagickCore/MagickCore.h>
+#endif
+
+#include <opencv2/opencv.hpp>
+#include <fftw3.h>
+#include <Eigen/Core>
+#include <Eigen/SVD>
+#include <chrono>
+#include <thread>
+#include "Pixel.hpp"
+
+//---------------------------------
+//pour la partie ondelette
+//---------------------------------
+// Filter type
+#define NONE 0  // no filter
+#define HARD 1  // hard shrinkage
+#define SOFT 2  // soft shrinkage
+#define GARROT 3  // garrot filter
+
+namespace Lisic{
+  
+  class Image{
+    
+  public :
+    unsigned int _tailleX,_tailleY,_profondeurCouleur;
+    std::vector<Lisic::Pixel> _pixels;
+    static const int GLOBAL = 0x00000000;
+    static const int PARCANAL = 0x00000001;
+    
+  public :
+    Image(const unsigned int& tailleX=1, const unsigned int& tailleY=1, const unsigned int& profondeurCouleur=255);
+    Image(const unsigned int& tailleX, const unsigned int& tailleY, const unsigned int& profondeurCouleur, std::vector<unsigned int> canal1, std::vector<unsigned int> canal2, std::vector<unsigned int> canal3);
+    Image(const char *chemin);
+    Image(const Image& im1, const unsigned int& numeroCanal1, const Image& im2, const unsigned int& numeroCanal2, const Image& im3, const unsigned int& numeroCanal3);
+    Image(const std::vector<Lisic::Image>& vec, const unsigned int& x, const unsigned int& y);
+    Image(const Image &im);
+
+    void normaliserA255();
+    void sauver(const char *chemin) const;
+    void sauver(const std::string chemin) const;
+    void sauverSVG(const char *chemin) const;
+    void sauverSVG(const std::string chemin) const;
+    Image getSousPartie(const unsigned int& imin, const unsigned int& jmin, const unsigned int& tailleXSousPartie, const unsigned int& tailleYSousPartie) const;
+    //retourne un nouveau pixel de même couleur que le pixel demandé
+    Lisic::Pixel getPixel(const unsigned int& i, const unsigned int& j) const;
+    void setPixel(const unsigned int& i, const unsigned int& j, const unsigned int& r, const unsigned int& v, const unsigned int& b);
+    std::vector<unsigned int> extraireCanal(const unsigned int& numCanal) const;
+    bool estNoire() const;
+    bool estBlanche() const;
+    bool estNiveauGris() const;
+    unsigned int nombreDePixel(const unsigned int& r, const unsigned int& v, const unsigned int& b) const;
+    void affiche() const;
+    std::vector<Image> morceler(const unsigned int& nvtailleX, const unsigned int& nvtailleY, const bool& force=false) const;
+    Image gradient(const std::vector<int>& mask) const;
+    Image gradientRotation(const std::vector<int>& mask) const;
+    void seuil(const unsigned int& numCanal, const unsigned int& s);
+    double PSNR(const Image& im, const unsigned int& numCanal) const;
+    std::tuple<double, double, double> PSNR(const Image& im) const;
+    std::tuple<fftw_complex*, Lisic::Image, Lisic::Image> fourier() const;
+    void bruitUniforme(const double& force, const int& type=Lisic::Image::GLOBAL, const bool& verbeux=false);
+    void bruitGaussien(const double& force, const int& type=Lisic::Image::GLOBAL, const bool& verbeux=false);
+    void bruitPoivreSel(const double& force, const double& proportion, const int& type=Lisic::Image::GLOBAL, const bool& verbeux=false);
+    void bruitCauchyLorentz(const double& force, const int& type=Lisic::Image::GLOBAL, const bool& verbeux=false);
+    void bruitLaplacien(const double& force, const int& type=Lisic::Image::GLOBAL, const bool& verbeux=false);
+    void bruitLogNormale(const double& force, const int& type=Lisic::Image::GLOBAL, const bool& verbeux=false);
+    void bruitMultiplicatifUniforme(const double& force, const int& type=Lisic::Image::GLOBAL, const bool& verbeux=false);
+    void bruitMasque(std::string chemin);
+    std::vector<double> SVD() const;
+    double SVD(const unsigned int& num) const;
+    double SVD_entropy() const;
+    double SVD_entropy(std::vector<unsigned int>) const;
+    double MSE(const Image& im, const unsigned int& numCanal) const;
+    std::tuple<double, double, double> MSE(const Image& im) const;
+    double SSIM(const Image& im, const unsigned int& numCanal) const;
+    std::tuple<double, double, double> SSIM(const Image& im) const;
+    double DSSIM(const Image& im, const unsigned int& numCanal) const;
+    std::tuple<double, double, double> DSSIM(const Image& im) const;
+    Image filtre_moyenneur(const unsigned int& taille_filtre) const;
+    Image filtre_Gaussien(const unsigned int& taille_filtre, const double& sigma) const;
+    Image filtre_median(const unsigned int& taille_filtre) const;
+    Image filtre_Wiener(const unsigned int& taille_filtre) const;
+    Image filtre_ondelette(const unsigned int& nbIteration) const;
+    double param_Andre_filtre_moyenneur_3_moyenne() const;
+    double param_Andre_filtre_moyenneur_3_ecart_type() const;
+    double param_Andre_filtre_moyenneur_5_moyenne() const;
+    double param_Andre_filtre_moyenneur_5_ecart_type() const;
+    double param_Andre_filtre_Gaussien_3_05_moyenne() const;
+    double param_Andre_filtre_Gaussien_3_05_ecart_type() const;
+    double param_Andre_filtre_Gaussien_3_10_moyenne() const;
+    double param_Andre_filtre_Gaussien_3_10_ecart_type() const;
+    double param_Andre_filtre_Gaussien_3_15_moyenne() const;
+    double param_Andre_filtre_Gaussien_3_15_ecart_type() const;
+    double param_Andre_filtre_Gaussien_5_05_moyenne() const;
+    double param_Andre_filtre_Gaussien_5_05_ecart_type() const;
+    double param_Andre_filtre_Gaussien_5_10_moyenne() const;
+    double param_Andre_filtre_Gaussien_5_10_ecart_type() const;
+    double param_Andre_filtre_Gaussien_5_15_moyenne() const;
+    double param_Andre_filtre_Gaussien_5_15_ecart_type() const;
+    double param_Andre_filtre_median_3_moyenne() const;
+    double param_Andre_filtre_median_3_ecart_type() const;
+    double param_Andre_filtre_median_5_moyenne() const;
+    double param_Andre_filtre_median_5_ecart_type() const;
+    double param_Andre_filtre_Wiener_3_moyenne() const;
+    double param_Andre_filtre_Wiener_3_ecart_type() const;
+    double param_Andre_filtre_Wiener_5_moyenne() const;
+    double param_Andre_filtre_Wiener_5_ecart_type() const;
+    double param_Andre_filtre_ondelette_2_moyenne() const;
+    double param_Andre_filtre_ondelette_2_ecart_type() const;
+    
+    Image operator-(const Image&) const;
+    bool operator==(const Image&) const;
+    bool operator!=(const Image&) const;
+
+  private :
+    static double genereAleatoireUniforme(int precision=6); // retourne un nombre aléatoire \in [0;1[;
+    static std::pair<double,double> genereAleatoireGaussien(); // retourne un nombre aléatoire suivant la loi normale centrée réduite.
+    static double genereAleatoireCauchy(); // retourne un nombre aléatoire suivant la loi de Cauchy.
+    static double genereAleatoireLaplace(double mu=0, double b=1); //retourne un nombre aléatoire suivant la loi de Laplace ayant mu pour paramètre de position et b de paramètre d'échelle
+    static double genereAleatoireLogNormale(); // retourne un nombre aléatoire suivant la loi Log-normale.
+    static double moyenne(std::vector<double> x);
+    static double variance(std::vector<double> x);
+    static double ecartType(std::vector<double> x);
+    static double covariance(std::vector<double> x, std::vector<double> y);
+    //------------------------
+    //Pour la partie ondelette
+    //------------------------
+    static float sgn(float x);
+    static float soft_shrink(float d,float T);
+    static float hard_shrink(float d,float T);
+    static float Garrot_shrink(float d,float T);
+    static void cvHaarWavelet(cv::Mat &src,cv::Mat &dst,int NIter);
+    static void cvInvHaarWavelet(cv::Mat &src,cv::Mat &dst,int NIter, int SHRINKAGE_TYPE=0, float SHRINKAGE_T=50);
+    static cv::Mat image2Mat(Image img);
+  };
+}
+  
+#endif

+ 5 - 5
classeImage/Image.cpp

@@ -270,19 +270,19 @@ Lisic::Pixel Lisic::Image::getPixel(const unsigned int& i, const unsigned int& j
   return Lisic::Pixel((((_pixels[j*_tailleX+i][0])*1.0)/_profondeurCouleur)*255.0,(((_pixels[j*_tailleX+i][1])*1.0)/_profondeurCouleur)*255.0,(((_pixels[j*_tailleX+i][2])*1.0)/_profondeurCouleur)*255.0);
 }
 
-void Lisic::Image::setPixel(const unsigned int& i, const unsigned int& j, const unsigned int& r, const unsigned int& v, const unsigned int& b)
+void Lisic::Image::setPixel(const double& i, const double& j, const double& r, const double& v, const double& b)
 {
   assert(i<_tailleX && j<_tailleY);
   
   _pixels[j*_tailleX+i][0]=r;
   _pixels[j*_tailleX+i][1]=v;
   _pixels[j*_tailleX+i][2]=b;
-  if(_pixels[j*_tailleX+i][0]>_profondeurCouleur)
+  /*if(_pixels[j*_tailleX+i][0]>_profondeurCouleur)
     _pixels[j*_tailleX+i][0]=_profondeurCouleur;
   if(_pixels[j*_tailleX+i][1]>_profondeurCouleur)
     _pixels[j*_tailleX+i][1]=_profondeurCouleur;
   if(_pixels[j*_tailleX+i][2]>_profondeurCouleur)
-    _pixels[j*_tailleX+i][2]=_profondeurCouleur;
+    _pixels[j*_tailleX+i][2]=_profondeurCouleur;*/
 }
 
 std::vector<unsigned int> Lisic::Image::extraireCanal(const unsigned int& numeroCanal) const
@@ -1227,7 +1227,7 @@ void Lisic::Image::bruitMasque(std::string chemin){
 
 std::vector<double> Lisic::Image::SVD() const
 {
-  for(unsigned int j=0;j<_tailleY;j++)
+  /*for(unsigned int j=0;j<_tailleY;j++)
     for(unsigned int i=0;i<_tailleX;i++){
       if(getPixel(i,j).r()-getPixel(i,j).v()!=0 || 
 	 getPixel(i,j).r()-getPixel(i,j).b()!=0 || 
@@ -1236,7 +1236,7 @@ std::vector<double> Lisic::Image::SVD() const
       assert(!(getPixel(i,j).r()-getPixel(i,j).v()!=0 || 
 	     getPixel(i,j).r()-getPixel(i,j).b()!=0 || 
 	       getPixel(i,j).b()-getPixel(i,j).v()!=0));
-    }
+    }*/
   
   Eigen::MatrixXf m(_tailleY,_tailleX);
 

+ 1 - 1
classeImage/Image.hpp

@@ -64,7 +64,7 @@ namespace Lisic{
     Image getSousPartie(const unsigned int& imin, const unsigned int& jmin, const unsigned int& tailleXSousPartie, const unsigned int& tailleYSousPartie) const;
     //retourne un nouveau pixel de même couleur que le pixel demandé
     Lisic::Pixel getPixel(const unsigned int& i, const unsigned int& j) const;
-    void setPixel(const unsigned int& i, const unsigned int& j, const unsigned int& r, const unsigned int& v, const unsigned int& b);
+    void setPixel(const double& i, const double& j, const double& r, const double& v, const double& b);
     std::vector<unsigned int> extraireCanal(const unsigned int& numCanal) const;
     bool estNoire() const;
     bool estBlanche() const;

File diff suppressed because it is too large
+ 9 - 4
classeImage/Makefile


+ 118 - 0
classeImage/Pixel.1.cpp

@@ -0,0 +1,118 @@
+#include "Pixel.hpp"
+
+Lisic::Pixel::Pixel(const unsigned int& r, const unsigned int& v, const unsigned int& b)
+{
+  _r=r;_v=v;_b=b;
+}
+
+std::tuple<double,double,double> Lisic::Pixel::RGB2XYZ(double r, double g, double b)
+{
+  if(r>0.04045)
+    r=pow((r+0.055)/1.055,2.4);
+  else
+    r=r/12.92;
+  if(g>0.04045)
+    g=pow((g+0.055)/1.055,2.4);
+  else
+    g=g/12.92;
+  if(b>0.04045)
+    b=pow((b+0.055)/1.055,2.4);
+  else
+    b=b/12.92;
+
+  double x = (r * Lisic::Pixel::matRGB2XYZ[0][0] + g * Lisic::Pixel::matRGB2XYZ[1][0] + b * Lisic::Pixel::matRGB2XYZ[2][0]);
+  double y = (r * Lisic::Pixel::matRGB2XYZ[0][1] + g * Lisic::Pixel::matRGB2XYZ[1][1] + b * Lisic::Pixel::matRGB2XYZ[2][1]);
+  double z = (r * Lisic::Pixel::matRGB2XYZ[0][2] + g * Lisic::Pixel::matRGB2XYZ[1][2] + b * Lisic::Pixel::matRGB2XYZ[2][2]);
+
+  return std::make_tuple(x,y,z);
+}
+
+std::tuple<double,double,double> Lisic::Pixel::RGB2LAB(double r, double g, double b)
+{
+  double rNormalize = r / 255.;
+  double gNormalize = g / 255.;
+  double bNormalize = b / 255.;
+
+  std::tuple<double, double, double> xyz = Lisic::Pixel::RGB2XYZ(rNormalize, gNormalize, bNormalize);
+
+  std::tuple<double, double, double> xyzNorm=Lisic::Pixel::RGB2XYZ(1.0,1.0,1.0);
+  
+  double xNorm=std::get<0>(xyz)/std::get<0>(xyzNorm);
+  double yNorm=std::get<1>(xyz)/std::get<1>(xyzNorm);
+  double zNorm=std::get<2>(xyz)/std::get<2>(xyzNorm);
+
+  double fx = 7.787*xNorm+(16.0/116.0);
+  double fy = 7.787*yNorm+(16.0/116.0);
+  double fz = 7.787*zNorm+(16.0/116.0);
+
+  /*double fx = (903.3*xNorm+16.0)/116.0;
+  double fy = (903.3*yNorm+16.0)/116.0;
+  double fz = (903.3*zNorm+16.0)/116.0;*/
+
+  if(xNorm>0.008856)
+    fx=pow(xNorm,1.0/3.0);
+  if(yNorm>0.008856)
+    fy=pow(yNorm,1.0/3.0);
+  if(zNorm>0.008856)
+    fz=pow(zNorm,1.0/3.0);
+
+  return std::make_tuple(116*fy-16,500*(fx-fy),200*(fy-fz));
+}
+
+unsigned int& Lisic::Pixel::operator[](const unsigned int& index)
+{
+  assert(index<=2);
+  switch(index)
+    {
+    case 0 :
+      return r();
+      break;
+	
+    case 1 :
+      return v();
+      break;
+
+    default :
+      return b();
+    }
+}
+
+unsigned int Lisic::Pixel::operator[](const unsigned int& index) const
+{
+  assert(index<=2);
+  switch(index)
+    {
+    case 0 :
+      return r();
+      break;
+	
+    case 1 :
+      return v();
+      break;
+
+    default :
+      return b();
+    }
+}
+
+bool Lisic::Pixel::operator==(const Lisic::Pixel& p) const
+{
+  if(_r!=p._r)
+    return false;
+  if(_v!=p._v)
+    return false;
+  if(_b!=p._b)
+    return false;
+  return true;
+}
+
+bool Lisic::Pixel::operator!=(const Lisic::Pixel& p) const
+{
+  if(_r!=p._r)
+    return true;
+  if(_v!=p._v)
+    return true;
+  if(_b!=p._b)
+    return true;
+  return false;
+}

+ 43 - 0
classeImage/Pixel.1.hpp

@@ -0,0 +1,43 @@
+#ifndef PIXEL_H
+#define PIXEL_H
+
+#include <cassert>
+#include <cmath>
+#include <tuple>
+
+typedef float Pixel[3];
+
+namespace Lisic{
+  class Pixel{
+  private :
+    unsigned int _r,_v,_b;
+
+  public:
+    static constexpr double matRGB2XYZ[3][3] = {{ 0.412424, 0.212656, 0.0193324},  
+						{ 0.357579, 0.715158, 0.119193},   
+						{ 0.180464, 0.0721856, 0.950444}};
+
+    Pixel(const unsigned int& r=0, const unsigned int& v=0, const unsigned int& b=0);
+    
+    inline unsigned int& r(){return _r;}
+    inline unsigned int r() const{return _r;}
+    inline unsigned int& v(){return _v;}
+    inline unsigned int v() const{return _v;}
+    inline unsigned int& b(){return _b;}
+    inline unsigned int b() const{return _b;}
+
+    static std::tuple<double, double, double> RGB2XYZ(double r, double g, double b);
+    static std::tuple<double, double, double> RGB2LAB(double r, double g, double b);
+
+    static std::tuple<double, double, double> RGB2XYZ(Lisic::Pixel p, unsigned int prof){return Lisic::Pixel::RGB2XYZ(p._r/(prof*1.0),p._v/(prof*1.0),p._b/(prof*1.0));}
+    static std::tuple<double, double, double> RGB2LAB(Lisic::Pixel p, unsigned int prof){return Lisic::Pixel::RGB2LAB(p._r/(prof*1.0),p._v/(prof*1.0),p._b/(prof*1.0));}
+
+    unsigned int& operator[](const unsigned int& index);
+    unsigned int operator[](const unsigned int& index) const;
+    bool operator==(const Pixel& p) const;
+    bool operator!=(const Pixel& p) const;
+  };
+}
+
+#endif
+

+ 12 - 4
classeImage/Pixel.cpp

@@ -1,6 +1,6 @@
 #include "Pixel.hpp"
 
-Lisic::Pixel::Pixel(const unsigned int& r, const unsigned int& v, const unsigned int& b)
+Lisic::Pixel::Pixel(const double& r, const double& v, const double& b)
 {
   _r=r;_v=v;_b=b;
 }
@@ -29,7 +29,11 @@ std::tuple<double,double,double> Lisic::Pixel::RGB2XYZ(double r, double g, doubl
 
 std::tuple<double,double,double> Lisic::Pixel::RGB2LAB(double r, double g, double b)
 {
-  std::tuple<double, double, double> xyz = Lisic::Pixel::RGB2XYZ(r,g,b);
+  double rNormalize = r / 255.;
+  double gNormalize = g / 255.;
+  double bNormalize = b / 255.;
+
+  std::tuple<double, double, double> xyz = Lisic::Pixel::RGB2XYZ(rNormalize, gNormalize, bNormalize);
 
   std::tuple<double, double, double> xyzNorm=Lisic::Pixel::RGB2XYZ(1.0,1.0,1.0);
   
@@ -41,6 +45,10 @@ std::tuple<double,double,double> Lisic::Pixel::RGB2LAB(double r, double g, doubl
   double fy = 7.787*yNorm+(16.0/116.0);
   double fz = 7.787*zNorm+(16.0/116.0);
 
+  /*double fx = (903.3*xNorm+16.0)/116.0;
+  double fy = (903.3*yNorm+16.0)/116.0;
+  double fz = (903.3*zNorm+16.0)/116.0;*/
+
   if(xNorm>0.008856)
     fx=pow(xNorm,1.0/3.0);
   if(yNorm>0.008856)
@@ -51,7 +59,7 @@ std::tuple<double,double,double> Lisic::Pixel::RGB2LAB(double r, double g, doubl
   return std::make_tuple(116*fy-16,500*(fx-fy),200*(fy-fz));
 }
 
-unsigned int& Lisic::Pixel::operator[](const unsigned int& index)
+double& Lisic::Pixel::operator[](const unsigned int& index)
 {
   assert(index<=2);
   switch(index)
@@ -69,7 +77,7 @@ unsigned int& Lisic::Pixel::operator[](const unsigned int& index)
     }
 }
 
-unsigned int Lisic::Pixel::operator[](const unsigned int& index) const
+double Lisic::Pixel::operator[](const unsigned int& index) const
 {
   assert(index<=2);
   switch(index)

+ 12 - 10
classeImage/Pixel.hpp

@@ -10,21 +10,23 @@ typedef float Pixel[3];
 namespace Lisic{
   class Pixel{
   private :
-    unsigned int _r,_v,_b;
+
+    // TODO : Issue => pass all color channels in double to allow correct LAB conversion...
+    double _r,_v,_b;
 
   public:
     static constexpr double matRGB2XYZ[3][3] = {{ 0.412424, 0.212656, 0.0193324},  
 						{ 0.357579, 0.715158, 0.119193},   
 						{ 0.180464, 0.0721856, 0.950444}};
 
-    Pixel(const unsigned int& r=0, const unsigned int& v=0, const unsigned int& b=0);
+    Pixel(const double& r=0, const double& v=0, const double& b=0);
     
-    inline unsigned int& r(){return _r;}
-    inline unsigned int r() const{return _r;}
-    inline unsigned int& v(){return _v;}
-    inline unsigned int v() const{return _v;}
-    inline unsigned int& b(){return _b;}
-    inline unsigned int b() const{return _b;}
+    inline double& r(){return _r;}
+    inline double r() const{return _r;}
+    inline double& v(){return _v;}
+    inline double v() const{return _v;}
+    inline double& b(){return _b;}
+    inline double b() const{return _b;}
 
     static std::tuple<double, double, double> RGB2XYZ(double r, double g, double b);
     static std::tuple<double, double, double> RGB2LAB(double r, double g, double b);
@@ -32,8 +34,8 @@ namespace Lisic{
     static std::tuple<double, double, double> RGB2XYZ(Lisic::Pixel p, unsigned int prof){return Lisic::Pixel::RGB2XYZ(p._r/(prof*1.0),p._v/(prof*1.0),p._b/(prof*1.0));}
     static std::tuple<double, double, double> RGB2LAB(Lisic::Pixel p, unsigned int prof){return Lisic::Pixel::RGB2LAB(p._r/(prof*1.0),p._v/(prof*1.0),p._b/(prof*1.0));}
 
-    unsigned int& operator[](const unsigned int& index);
-    unsigned int operator[](const unsigned int& index) const;
+    double& operator[](const unsigned int& index);
+    double operator[](const unsigned int& index) const;
     bool operator==(const Pixel& p) const;
     bool operator!=(const Pixel& p) const;
   };

+ 272 - 0
classeImage/main.cpp

@@ -0,0 +1,272 @@
+#include <iostream>
+#include <stdio.h>
+
+#include <string>
+#include <boost/filesystem.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <math.h>
+#include <omp.h>
+
+#include "Image.hpp"
+#include "Pixel.hpp"
+
+using namespace boost::filesystem;
+
+const std::string folder_path = "../libSVM-3.20/experimentationsTheseTram/fichiersSVD";
+const std::string zone_folder = "zone";
+const std::string config_filename = "config";
+const std::string min_max_filename = "min_max_values";
+const std::string output_file_svd = "SVD_LAB_test_im6.csv"; // for the moment test version in order to retrieve correct file
+const std::string output_file_svdn = "SVDN_LAB_test_im6.csv"; // for the moment test version in order to retrieve correct file
+const std::string output_file_svdne = "SVDNE_LAB_test_im6.csv"; // for the moment test version in order to retrieve correct file
+
+const unsigned nb_blocks = 16;
+
+std::vector<Lisic::Image> getSubImages(Lisic::Image &img){
+    std::vector<Lisic::Image> sub_images;
+    
+    unsigned length_block_elem = sqrt(nb_blocks);
+    unsigned height_block_elem = sqrt(nb_blocks);
+
+    // cut picture in block 
+    unsigned length_block = img._tailleX / length_block_elem;
+    unsigned height_block = img._tailleY / height_block_elem;
+
+    for (unsigned i = 0; i < length_block_elem; i++){
+        for (unsigned j = 0; j < height_block_elem; j++){
+            Lisic::Image sub_block = img.getSousPartie(i*length_block, j*height_block, length_block, height_block);
+            sub_images.push_back(sub_block);
+        }
+    }
+
+    return sub_images;
+}
+
+void imgRGBtoLAB(Lisic::Image &img){
+
+    // convert RGB to LAB all pixels of current image
+    for (unsigned i = 0; i < img._tailleX; i++){
+        for (unsigned j = 0; j < img._tailleY; j++){
+
+            // get current pixel
+            auto current_pixel = img.getPixel(i, j);
+
+            // pixel conversion to lab values
+            auto lab = Lisic::Pixel::RGB2LAB(current_pixel.r(), current_pixel.v(), current_pixel.b());
+
+            //std::cout << "L: " << std::get<0>(lab) << ", A: " <<  std::get<1>(lab) << ", B: " << std::get<2>(lab) << std::endl;
+            // set new values
+            img.setPixel(i, j, std::get<0>(lab), std::get<1>(lab), std::get<2>(lab));
+            //auto pixel = img.getPixel(i, j);
+
+            //std::cout << "L: " << pixel.r() << ", A: " <<  pixel.v() << ", B: " << pixel.b() << std::endl;
+        }
+    }
+}
+
+void generateSVD_LAB_files(path &_p, double &_minValue, double &_maxValue, bool _ne){
+
+    if(is_directory(_p)) {
+        std::cout << _p << " is a directory containing:\n";
+        
+        // search each scenes folder
+        std::vector<std::string> scenes;
+
+        for(auto& scene : boost::make_iterator_range(directory_iterator(_p), {}))
+        {
+            scenes.push_back(scene.path().string());
+        }
+
+        // TODO : really usefull ? Concurrent access from writing ?
+        #pragma omp parallel
+        {
+            #pragma omp for
+            for(unsigned i = 0; i < scenes.size(); i++)
+            {
+                bool first_image = true;
+                std::string path_scene = scenes.at(i);
+                
+                std::cout << path_scene << "\n";
+
+                // read config file
+                std::string end_image_name;
+                std::string prefix_image_name;
+                std::string str_start_counter;
+                std::string str_end_counter;
+                unsigned step_counter;
+
+                std::ifstream in(path_scene + "/" + config_filename);
+
+                in >> end_image_name;
+                in >> prefix_image_name;
+                in >> str_start_counter;
+                in >> str_end_counter;
+                in >> step_counter;
+                in.close();
+
+                // convert and initialisation of variables
+                unsigned start_image_index = std::stoi(str_start_counter);
+                unsigned current_image_index = start_image_index;
+                unsigned end_image_index = std::stoi(str_end_counter);
+
+                // getting all information about images
+                while(current_image_index <= end_image_index){
+
+                    std::string str_current_image_index = std::to_string(current_image_index);
+                    std::string postfix_image_name = str_current_image_index;
+                    
+                    while(postfix_image_name.size() < str_start_counter.size()){
+                        postfix_image_name = "0" + postfix_image_name;
+                    }
+
+                    std::string path_element = path_scene + "/" + prefix_image_name + postfix_image_name + ".png";
+
+                    std::cout << path_element << std::endl;
+
+                    Lisic::Image img(path_element.c_str());
+                    imgRGBtoLAB(img);
+
+                    // find each picture
+                    std::vector<Lisic::Image> sub_images = getSubImages(img);
+
+                    std::string path_zone_folder = path_scene + "/" + zone_folder;
+
+                    // print block information into zones folder
+                    for(unsigned i = 0; i < sub_images.size(); i++){
+
+                        // get correct index
+                        std::string index = std::to_string(i);
+                        if(index.size() < 2){
+                            index = "0" + index;
+                        }
+
+                        // get SVD information of L information
+                        Lisic::Image current_sub_image = sub_images.at(i);
+
+                        std::vector<double> singular_values = current_sub_image.SVD();
+
+                        // check global normalization or not
+                        if(!_ne){
+
+                            // output file path and writer
+                            std::string full_path_csv_svd = path_zone_folder + index + "/" + output_file_svd;
+                            std::string full_path_csv_svdn = path_zone_folder + index + "/" + output_file_svdn;
+                            std::ofstream ofs_svd;
+                            std::ofstream ofs_svdn;
+                            
+                            std::string info_line_svd = postfix_image_name;
+                            std::string info_line_svdn = postfix_image_name;
+
+                            double max_value = *std::max_element(singular_values.begin(), singular_values.end());
+                            double min_value = *std::min_element(singular_values.begin(), singular_values.end());
+
+                            // update min and max values for global normalisation