langage C transformée de Hough

langage C transformée de Hough - C++ - Programmation

Marsh Posté le 25-02-2010 à 05:21:49    

Bonjour a tous  ,
 
Je suis en stage a l etranger et mon professeur m a demandé de programmer la transformée de Hough en C bien qu il sache que je suis debutante. Ce programme a pour but de detecter les lignes blanches de la route dans une image.( c est un programme que j utilise apres avoir filtré l image par le filtre de Sobel)
Je ne sais pas ce qui ne va pas dans mon programme, il compile mais il ne detecte pas bien les lignes, je ne sais plus quoi faire...! cela doit etre dans l'algorithme, mais je ne trouve plus rien a changer...
 
Voila mon programme:
Je vous en supplie aidez moi s'il vous plait!!!!
 

Code :
  1. extern "C"
  2. {
  3. #include <pgm.h>
  4. }
  5. #include <stdio.h>
  6.  
  7. #include <math.h>
  8.  
  9. #include <pam.h>
  10.  
  11.  
  12.  
  13. main(int argc, char *argv[])
  14. {
  15.  
  16.  
  17.  
  18.  int x, y;
  19.  int dx,dy;
  20.  int G;
  21.  FILE *infile, *outfile;
  22.  int cols, lignes, format,thetadeg,rr;
  23.  gray maxval;
  24.  gray **table1, **table2, ;//two * to have a 2 dimension table **accumulateur
  25.  int k,e,d,max,p,q,retient,bidul,s,lala,a,b,acc,rint,tint,yint,A,B,rint2,lala2;
  26.  int m=0;
  27.  int j=0;
  28.  int i=0;
  29.  double rmax,r,theta,c;
  30.  double co,pi,thetaRad;
  31.  const int m_FacteurEtalement = 20000;
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  int **accumulateur2= new int*[m_FacteurEtalement];
  40.  for(lala=0;lala<m_FacteurEtalement;lala++) {
  41.    accumulateur2[lala] = new int[m_FacteurEtalement];
  42.  
  43.  }
  44.  
  45.  
  46.  if (argc!=3) {
  47.    printf("Mauvais Nombres Arguments\n" );
  48.    return 0 ;
  49.  }
  50.  
  51.  
  52.  // Reading of the file
  53.  pgm_init(&argc, argv);
  54.  infile = pm_openr(argv[1]);
  55.  pgm_readpgminit( infile, &cols, &lignes, &maxval, &format );//reading of the file called infile
  56.  table1 = new gray*[lignes];// reservation of an espace of the memory. the espace size is "rows"/
  57.  table2 = new gray*[lignes];
  58.  
  59.  
  60.  for (y = 0; y <lignes; y++) {//for each ligne y
  61.    table1[y] = pgm_allocrow (cols);// reservation of a memory space with the size of one column
  62.    table2[y] = pgm_allocrow (cols);
  63.  
  64.    pgm_readpgmrow( infile, table1[y], cols, maxval, format);//read but also filed the new created space (grayrow) with the original image(whiwh is in the file infile)
  65.  }
  66.  
  67.  
  68.  rmax=floor( sqrt(lignes^2+cols^2)+1);
  69.  
  70.  
  71.  
  72.  //INITIALISATION IMAGE2
  73.  
  74.  for(y = 0; y < lignes; y++)
  75.    {
  76.      for(x = 0; x < cols; x++){
  77.  
  78.        table2[y][x]=0;
  79.      }
  80.    }
  81.  
  82.  
  83.  //INITIALISATION ACCUMULATEUR
  84.  
  85.  for(y = 0; y < m_FacteurEtalement; y++)
  86.    {
  87.      for(x = 0; x < m_FacteurEtalement; x++)
  88.        {
  89.          accumulateur2[y][x]=0;
  90.        }
  91.    }
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  //INCREMENTATION ACCUMULATEUR
  102.  
  103.  for(x = 0; x < lignes; x++)
  104.    {
  105.  
  106.      for(y = 0; y < cols; y++)//parcours de l'image1
  107.  
  108.        {
  109.  
  110.          if (table1[x][y]>60 )//si le pixel est blanc
  111.  
  112.            {
  113.  
  114.              for (thetadeg = 0; thetadeg <360; thetadeg++)
  115.  
  116.                {
  117.                  thetaRad=6.28*thetadeg/360;//conversion en radian
  118.                  r=x*cos(thetaRad)+y*sin(thetaRad) ; // tracage des "lignes" dans l accumulateur
  119.                  rint = static_cast<int>(r); // j en fait un entier car je devrais l'utiliser comme indice de tableau
  120.                  rint2=-rint;
  121.  
  122.                  if (-rint<m_FacteurEtalement && rint<0 )
  123.                    {
  124.  
  125.                      accumulateur2[rint2][thetadeg]++;
  126.  
  127.                    }
  128.                }
  129.            }
  130.        }
  131.    }
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  //TRACAGE DE LIGNES DANS LA NOUVELLE IMAGE
  139.  
  140.  
  141.  for(rr = 0; rr < m_FacteurEtalement; rr++) //parcours de l accumulateur -------------> nombre pê a changer
  142.    {
  143.      for(thetadeg = 0; thetadeg < 360; thetadeg++)
  144.        {
  145.  
  146.          if (accumulateur2[rr][thetadeg]>59) // --------------pê a changer
  147.  
  148.            {
  149.              for(x = 0; x< lignes; x++) //parcours de l image2
  150.                {
  151.                  thetaRad=6.28*thetadeg/360;
  152.                  A=static_cast<int>((cos(thetaRad))/sin(thetaRad));
  153.                  B=static_cast<int>(-rr/sin(thetaRad));
  154.  
  155.                  if (-A*x+B<cols && -A*x+B>0 && A!=0){
  156.                    table2[x][-A*x+B]=255;
  157.                  }
  158.  
  159.                }
  160.  
  161.            }
  162.        }
  163.  
  164.    }
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  // Saving
  172.  outfile = pm_openw(argv[2]);
  173.  pgm_writepgminit( outfile, cols, lignes, maxval, 0 );
  174.  for (y = 0; y<lignes; y++){
  175.    pgm_writepgmrow(outfile, table2[y],cols, maxval, 0);
  176.  }
  177.  
  178.  
  179.  
  180.  
  181.  //release of space
  182.  
  183.  for (y=0; y<lignes;y++){
  184.    pgm_freerow( table1[y] );
  185.    pgm_freerow( table2[y] );
  186.  
  187.  }
  188.  free(table1);
  189.  free(table2);
  190.  
  191.  pm_close( outfile );
  192.  pm_close( infile );
  193.  
  194.  
  195.  
  196.  
  197.  for(lala=0;lala<rmax;lala++){
  198.    delete accumulateur2[lala];
  199.  }
  200.  delete [] accumulateur2;
  201.  
  202.  
  203.  
  204.  
  205. }


 
 
Merci de m'avoir lue
PS: je compile comme ca:  
g++ main.cpp -o prob -L"C:\Program Files\GnuWin32\lib" -I"C:\Program Files\GnuWin32\include" -lnetpbm
 
[Note de la modération: reformaté et mis dans la bonne catégorie C++, vu les delete [] finaux]


Message édité par gilou le 05-03-2010 à 11:39:24
Reply

Marsh Posté le 25-02-2010 à 05:21:49   

Reply

Marsh Posté le 25-02-2010 à 08:51:44    

Je ne suis pas familier de l'implémentation de ces algorithmes de transformation mathématique, mais sans commentaires ton code est à peu près imbitable pour moi et je doute qu'un autre (à moins d'être un champion de ce genre d'algo) ne soit plus à l'aise et plus enclin à y consacrer du temps pour comprendre ton implémentation.

 

Si l'implémentation est ok, le problème vient peut être de ton image d'entrée ou de tes constantes dans le code ?
Je pense que Hough doit être un algo assez sensible, à manier avec du recul, pas comme un gros Sobel des familles pour les contours.

 

On doit pouvoir trouver des dizaines d'exemples d'implémentations sur google, avec des images tests.
Je peux te montrer une implémentation qui fonctionne, en espérant que ça puisse t'apporter une aide quelconque.
Tu en as une abondamment commentée et qui fonctionne plutôt bien dans le projet AForge. C'est du .Net mais les types utilisés sont essentiellement des types primitifs et les fonctions sont les opérations mathématiques de base, il y a juste un petit peu d'orienté objet mais rien d'impossible à faire autrement en C. Le seul truc particulier c'est l'utilisation des types Bitmap en fin de calcul pour produire la sortie.
Le code source :
http://code.google.com/p/aforge/so [...] rmation.cs
Une petite doc : http://www.aforgenet.com/framework [...] c75d9c.htm
Ceci dit comme tu as déjà tenté une première approche et que la leur en est loin je ne sais pas si ça t'aidera. A voir ton code et tes commentaires en franglais je me doute que c'est déjà une repompe de quelque chose...


Message édité par TotalRecall le 25-02-2010 à 08:55:49

---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 03-03-2010 à 18:46:49    

pas mieux

 

par contre quand on travaille sur des images, on utilise généralement des tableau à une dimension, ce qui est beaucoup, beaucoup plus facile à utiliser et à manipuler (ça t'évite les doubles pointeurs,etc). Je te conseillerais de faire cela et de recréer ton algo from scratch.

 

la correspondance est :

 

image[y][x] = tab[x + SX*y], où SX est la taille en X de ton image. Tu peux créer une macro par exemple pour acceder à tes images :

 
Code :
  1. int SX, SY; //tailles x(largeur) et y(longeur) des tes images
  2. IMG(tab,i,j) tab[j + (i)*(SX)]
 

quand tu alloues un tableau pour une image, c'est:

 
Code :
  1. tab[SX*SY];
 

2/ il faut aussi que tu vérifies comment fonctionne ton algo sur les bords de ton image .... c'est une source d'erreur fréquente, car une image est un ouvert de R2. Après, je sais pas si c'est ça le problème mais les "problèmes de bords" peuvent se propager sur l'image et donner n'importe nawak.

 

3/ vérifie les problèmes de cast. A mon avis l'erreur est là. Exemple : tu déclare un

 
Code :
  1. int max;
 

et tu affectes la valeur de retour de floor(); qui renvoie un flottant ou un double.

 

good luck

Message cité 1 fois
Message édité par in_your_phion le 03-03-2010 à 18:52:08
Reply

Marsh Posté le 03-03-2010 à 19:18:05    

in_your_phion a écrit :

pas mieux
par contre quand on travaille sur des images, on utilise généralement des tableau à une dimension, ce qui est beaucoup, beaucoup plus facile à utiliser et à manipuler (ça t'évite les doubles pointeurs,etc). Je te conseillerais de faire cela et de recréer ton algo from scratch.

 

sauf que non. Les allocations façon NRC sont bien plus simples que ces calculs d'index, cf les MOULTS topics que j'ai fait sur le sujet.
le coup du tab[i+h*j] est vraiment bof et est source d'erreurs.

Message cité 1 fois
Message édité par Joel F le 03-03-2010 à 19:18:34
Reply

Marsh Posté le 04-03-2010 à 11:39:43    

Joel F a écrit :

 

sauf que non. Les allocations façon NRC sont bien plus simples que ces calculs d'index, cf les MOULTS topics que j'ai fait sur le sujet.
le coup du tab[i+h*j] est vraiment bof et est source d'erreurs.

 

yo,

 

c'est quoi les allocations façons NRC ? En tous cas tous le monde autour de moi utilisait des tableaux 1D, j'ai jamais vu personne utiliser des tableaux 2D en fait, mais bon c dans la recherche donc bon.


Message édité par in_your_phion le 04-03-2010 à 11:42:05
Reply

Marsh Posté le 04-03-2010 à 11:57:04    

Au risque de dire une connerie je suis quasi sûr qu'il parle de ceci : http://www.nrbook.com/a/bookcpdf.php (par exemple, y a plein d'autres liens, cf Numerical Recipes in C)
C'est un ensemble d'astuce et de best practices pour tout ce qui touche aux maths. Très instructif d'ailleurs pour quiconque travaille avec ça par contre faut un solide bagage mathématique et beaucoup de café pour suivre parfois...

 

Et en l'occurrence pour les tableaux 2D je pense qu'il parle du principe de tiling qui consiste à ne pas parcourir tout le tableau mais à découper celui-ci en zones carrées parcourues séquentiellement, ce qui va plus vite qu'un parcours intégral. Mais là je ne suis pas sûr du tout qu'il parle de ça :D.
Fais une recherche sur son pseudo tu devrais trouver de quoi il s'agit (à moins que tu ne préfères lire le bouquin :whistle:)


Message édité par TotalRecall le 04-03-2010 à 11:59:57

---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 04-03-2010 à 11:58:32    

Reply

Marsh Posté le 04-03-2010 à 12:10:53    


 
je doute pas de l'interêt de l'allocation NRC pour de l'optim de brutor pour des tableaux de dimensions N>2
 
pour un stage, pour coder la transformée de ouf je pense pas que ce soit nécessaire  :o  
 
perso, je trouve que les tableaux 1D c'est vachement plus facile à utiliser (un seul free, pas de doubles pointeurs, etc). Mais bon après c'est comme gVim vs Emacs, il y aura toujours débat!
 

Reply

Marsh Posté le 04-03-2010 à 12:28:39    

Je pense qu'il parle du fait d'allouer ton tableau 1D à l'ancienne et d'ajouter en plus un tableau de pointeurs vers les débuts de chaque ligne, un peu comme ça :  
 

Code :
  1. template <class T>
  2. class tablo2D:
  3. private:
  4. vector<T> data1D;
  5. vector<T*> lignes;
  6. public
  7. /*...*/
  8. Link(){
  9. for(int i = 0 ; i < hauteur ; ++i)
  10. {
  11. lignes[i] = data1D + i*largeur;
  12. }
  13. };
  14. T* operator[](cont int & a){return lignes[a];};


 
Tu gardes un tableau 1D pour les masoc... gens qui aiment bien. Et tu peux accéder simplement à la case (i,j) en faisant
 

Code :
  1. tablo[j][i] = ...


 
Tout ce que tu perds, c'est l'allocation de (hauteur)*size_t, c'est pas très grave avec des grosses images.

Reply

Marsh Posté le 04-03-2010 à 13:03:34    

in_your_phion a écrit :


 
je doute pas de l'interêt de l'allocation NRC pour de l'optim de brutor pour des tableaux de dimensions N>2
 
pour un stage, pour coder la transformée de ouf je pense pas que ce soit nécessaire  :o  
 
perso, je trouve que les tableaux 1D c'est vachement plus facile à utiliser (un seul free, pas de doubles pointeurs, etc). Mais bon après c'est comme gVim vs Emacs, il y aura toujours débat!


 
je dis pas le contraire, juste que filer des bonnes habitudes au gens, c'est pas plus mal ;)
Je peut te dire que quadn tu devras faire des trucs genre deroulage de tableau 3D + blocking + strip-mining tu seras bien content 'avoir un acces en i,j,k qu'un polynome infmae :)

Reply

Marsh Posté le 04-03-2010 à 13:03:34   

Reply

Marsh Posté le 04-03-2010 à 15:40:07    

Question : j'ai vu dans wikipedia que la transfo de Hough était brevetée. Ca veut pas dire que quand on veut l'utiliser dans un programme il faut verser des sous au détenteur du brevet?


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 04-03-2010 à 16:19:33    

C'est possible (j'en sais absolument rien en fait :d) mais ça m'etonne un peu... En imagerie c'est assez fréquemment utilisé, il y en a des implémentations libres un peu partout et des variantes (comme celle qui étend l'algo d'origine aux autres formes géométriques)... Je pense que c'est plus une histoire de protection intellectuelle de la paternité du truc qu'une histoire de sous.


Message édité par TotalRecall le 04-03-2010 à 16:21:12

---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 05-03-2010 à 09:07:08    

le brevet date de 1962 et un brevet, même le plus velu possible ne peut pas durer plus de 20 ans, pour que la propriété intellectuelle ne joue pas un rôle de ralentisseur de l'utilisation des avancées technologiques (en informatique, ça peut faire rire 20 ans, mais le concept de brevet est plus ancien et cette limite peut trouver son sens).  

Reply

Marsh Posté le 05-03-2010 à 12:01:11    

Une petite remarque en passant: plutôt que thetaRad=6.28*thetadeg/360 écris thetaRad=(6.28*thetadeg)/360 c'est plus lisible, et tu est sure qu'il va pas y avoir d'abord une division entière thetadeg/360 (ce n'est peut être pas le cas ici, mais je n'ai jamais eu envie de m'encombrer l'esprit avec les tables d'ordre de précédence quand un parenthèsage bien fait permet de ne pas se poser la question).

 

Au lieu de faire plusieurs fois

 

for (thetadeg = 0; thetadeg <360; thetadeg++)
    {
        thetaRad=6.28*thetadeg/360;//conversion en radian
        .....
    }
peut être qu'utiliser un tableau a 360 entrées avec la valeur en radian calculé une fois pour toutes serait plus simple.
D'autre part, la pratique habituelle est de faire: thetaRad = (thetadeg * M_PI) / 180 ou on utilise la constante M_PI définie dans <math.h>

 

Autre point:
A=static_cast<int>((cos(thetaRad))/sin(thetaRad));
B=static_cast<int>(-rr/sin(thetaRad));
A et B sont calculés au niveau de la 3e boucle interne, mais ils sont invariants et calculables au niveau de la 2eme.

 

A+,


Message édité par gilou le 05-03-2010 à 17:09:24

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed