affichage de graph, de courbes, d'histogrammes en c++ - C++ - Programmation
Marsh Posté le 18-07-2006 à 12:55:13
pour "repérer" tes sinusoïdes, c'est bêtement une question de trouver les valeurs minimales et maximales comprises entre les bornes de tes cases, n'est-ce pas ? Ca ne semble pas si compliqué que ca, à première vue.
Marsh Posté le 18-07-2006 à 13:02:25
En fait, je dois repérer si 2 sinusoïdes se croisent. Comme c'est une expérience, on doit introduire une marge d'erreur, d'ou les cases. Donc si 2 sinusoïdes se trouvent dans une même case, on peut dire qu'elles se croisent.
Evidemment, le but du jeu est de voir si 3 ou 4 sinusoïde se croisent (enfin sont dans une même case).
J'ai un petit problème là... Ca ne marche pas ça La valeur theta reste bloquée à -PI...
Code :
|
Marsh Posté le 18-07-2006 à 13:14:17
theta + 0.1; est une instruction qui n'a pas d'effet. Je suppose que tu voulais mettre un '+=' à la place du '+'
sinon, on fait souvent des remarques sur la gestion des fins de fichiers dans le forum, donc tu vas te faire taper sur les doigts avec cette façon de faire le test (tu fais une lecture de trop, tu ne vérifies pas que ton fscanf a bien réussi à lire les données)
ensuite, si tu es en C++, pourquoi utiliser les archaïsme du C pour la gestion des fichiers ? les fstream ne te plaisent pas ?
Marsh Posté le 18-07-2006 à 13:16:05
On m'a appris comme ça, j'exécute
Tu parles de quels archaïsmes?
Merci pour ton aide
Marsh Posté le 18-07-2006 à 17:22:05
toutsec a écrit : On m'a appris comme ça, j'exécute |
fscanf est une méthode utilisée en C pour lire un fichier.
Certes elle existe toujours en C++ pour des raisons de compatibilité, mais C++ est livré avec tout ce qu'il faut pour gérer les fichiers de façon conviviale pour le programmeur.
C'est un peu comme les char* en C et les string en C++, on peut faire la même chose avec mais l'un est largement plus pratique que l'autre. Le drame c'est que de nombreuses personnes enseignent le C++ à grand coup de char* / fgets / fscanf / sprintf / malloc Je respecte infiniment un programmeur C compétent qui maitrîse ne serait-ce qu'une manipulation correcte sur un fichier ou un char* (beaucoup plus rare qu'on ne croit), mais faire du C++ ce n'est pas balancer toutes les fonctions C en se disant "de toute manière ca passe"
Voici par exemple un programme trés simple qui va ouvrir un fichier test.txt, et lire trois nombres entiers à l'intérieur du fichier en question :
Code :
|
Marsh Posté le 19-07-2006 à 03:15:22
merci
Marsh Posté le 19-07-2006 à 13:12:07
Code :
|
Comment je peux optimiser le truc?
Le programme dure assez longtemps pour finir de tout faire.
Le fichier ou se trouve les données est composé de 2600 entrée, donc à la fin, je me retrouve avec un fichier de txt de 165Mo
Marsh Posté le 19-07-2006 à 13:33:24
Si tu traites un gros fichier il vaut mieux utiliser un buffer assez gros, là tu fais beaucoup de petites lectures/écritures, ce qui ce ressent fortement.
Si tu pouvais :
- lire et stocker en mémoire les 2600 entrées
- calculer
- écrire tous les résultats
Tu irais beaucoup plus vite, mais ca consommerait pas mal de mémoire (notamment pour stocker autant de résultats).
Tu devrais essayer de te faire une petite fonction qui peut lire ton fichier par paquet de n lignes (dans la doc sur les fstream tu verras qu'on peut faire des lecture.read(tableau,taille); pour remplir d'un coup un tableau).
Une fois que tu as ca c'est gagné, tu lis n lignes, tu traites ces valeurs, tu écris m résultats (entre lire n lignes d'un coup et écrire m résultats d'un coup ca ne doit pas être très différent)
Par contre ca ne changera rien au résultat de 165Mo
edit :
ton theta part de 0 et est toujours incrémenté de 0.00174532925... bref tu en as un nombre calculable à l'avance, et tu peux tous les connaître. Tu pourrais avant de commencer ton traitement faire un tableau de toutes les valeurs de theta, du genre :
theta cos(theta) sin(theta)
-PI -1 0
... ... ...
PI -1 0
Après au Xème passage dans ton do/while, au lieu d'aller calculer le cos qui va bien tu irais juste lire tableauCos[X]
Tu calculerais ainsi une seule fois ces valeurs (et pas autant de fois qu'il y a de lignes comme c'est le cas là)
PS : et tu peux même ne calculer que les cos et pas les sin, après tout c'est pareil à une translation près ( cos(PI/2-x) = sin(x) )
Marsh Posté le 19-07-2006 à 13:43:28
Xavier_OM a écrit : Si tu traites un gros fichier il vaut mieux utiliser un buffer assez gros, là tu fais beaucoup de petites lectures/écritures, ce qui ce ressent fortement. Tu devrais essayer de te faire une petite fonction qui peut lire ton fichier par paquet de n lignes (dans la doc sur les fstream tu verras qu'on peut faire des lecture.read(tableau,taille); pour remplir d'un coup un tableau). Par contre ca ne changera rien au résultat de 165Mo
theta cos(theta) sin(theta) Après au Xème passage dans ton do/while, au lieu d'aller calculer le cos qui va bien tu irais juste lire tableauCos[X] PS : et tu peux même ne calculer que les cos et pas les sin, après tout c'est pareil à une translation près |
merci
je vais commencer par faire le tableau des valeurs de theta, cos et sin, c'est ce qui semble le plus à ma porter
je ferai ce que tu me suggères dans un second temps.
Puis normalement, je bosse sur des xeon 3.2Ghz et 2Go de ram, donc je pense que pour la mémoire, ça ira
merci pour ton aide
Marsh Posté le 19-07-2006 à 19:01:24
Code :
|
Bon, j'ai fait ça, mais ça me fait une erreur windows. Surement sur le fait de la création du tableau des cosinus
Mais je ne sais pas trop comment faire pour éviter cette erreur...
edit : c'est une erreur de ma part...
edit ² : je pensais avoir trouver, mais non ²
Marsh Posté le 19-07-2006 à 19:31:21
Pourquoi cela ne marche-t-il pas?
Code :
|
Marsh Posté le 20-07-2006 à 04:10:13
Bon bah, j'ai arrangé tout ça et je peux dire (fièrement ) que la 1ère partie est finie . (merci à xavier_om).
Bref, reste maintenant le plus dur, car là, c'était juste de la lecture et de l'écriture dans un fichier.
(Je chercherai dans un second temps à optimiser, parce 5'35" pour la 1ere partie du prog', c'est trop )
Je ne sais pas si quelqu'un suit ce topic ( ), mais toute(s) idée(s) sera la bienvenue.
Je cherche à repérer à quelles coordonnées (rho et théta) se croisent des sinusoïdes au dela de 2, donc à partir de 3.
Comme c'est des points expérimentaux, on peut avoir une marge d'erreur sur rho et théta, donc on obtient des carrés d'erreur, et je cherche à déterminer le nombre de sinusoïdes passant dans un même carré.
Je ne sais absolument pas par ou commencer .
Vous pouvez aller voir mon 1er post pour des précisions sur ce que je souhaite faire.
Merci
Marsh Posté le 20-07-2006 à 09:10:12
C'est pour une transformée de Hough ton truc ?
Marsh Posté le 20-07-2006 à 12:53:52
exact
Marsh Posté le 20-07-2006 à 13:50:29
Bah tu fais un tableau de vote. D'habitude je code Hough comme ca (en gros) :
Code :
|
Et après faut juste chercher ou se trouve les plus grands nombres de votes.
Marsh Posté le 20-07-2006 à 14:30:14
Tu es entrain de me dire que ce que j'ai fait jusqu'a présent ne sert à rien?
Marsh Posté le 20-07-2006 à 14:31:52
Ben si ca sert, faut bien lire le fichier, récupérer les valeurs, préparer les tableaux de cos/sin
Marsh Posté le 20-07-2006 à 15:02:45
Bah j'ai déja sorti dans un fichier toutes les valeurs des sinusoïdes (avec mon fichier d'essai, j'en ai ~2600).
Il faut juste que j'arrive à trouver un test pour voir à quel couple de rho et theta elles se croisent.
Donc, je dois lire mon fichier ou il y a les sinusoïdes (que j'ai nommé HT.txt) puis faire ton "vote"?
Je n'ai pas trop compris ce truc d'ailleur
Merci pour ton aide
Marsh Posté le 20-07-2006 à 15:42:04
toutsec a écrit : Bah j'ai déja sorti dans un fichier toutes les valeurs des sinusoïdes (avec mon fichier d'essai, j'en ai ~2600). |
Bon je vais faire un petit résumé sur la transformée de Hough
Introduction :
La transformée de Hough est un algorithme pour (entre autre) réparer les contours abimés. Classiquement c'est fondé sur la représentation normale des droites.
Mathématiques :
Soit D(theta, rho) la droite de vecteur normal (cos(theta), sin(theta)) et de distance à l'origine |rho|. C'est sa représentation normale (après tout ya pas que les représentations cartésiennes dans la vie)
Si on prend un point P(x,y) quelconque, on peut dire que ce point est le point d'intersection de toutes les droites passant par lui. Jusque là on ne prend pas des masses de risques, si ya pas de droites passant par P ya rien à dire, si y a une droite, ben yen a une (:D), si yen a 2 qui passe par P, alors P est à l'intersection des 2. Ca, c'est de la démarche intellectuelle !
Prenons un point P0 au pif.
En cartésien : P0 = (x0 ; y0)
En polaire : P0 = (rho0*cos(theta0) ; rho0*sin(theta0))
Si P0 passe par des droites du genre D(theta, rho), alors il doit vérifier :
|
Récapitulons : on est passé d'un point à une droite.
A tout point P0 = (x0,y0) (de RxR, l'espace 2D) on peut associer une sinusoïde (dans 2^RxR mais on s'en fout un peu)
En fait cette sinusoïde, ce n'est pas qu'une représentation d'un point : comme on a supposé que des droites D(theta, rho) passaient par ce point, cette sinusoïde représente l'ensemble des droites D(theta, rho) passant par P(x0, y0)
NB : Réciproquement on pourrait associer à l'ensemble des sinusoïdes qui passeraient par un point Q une jolie droite D
NB : Bon theta on va le limiter à un intervalle de largeur Pi, si les sinusoïdes se croisent en (theta, rho) elles se croiseront aussi en (theta + k*Pi, (-1)^k * rho) donc on s'en fout.
Algorithme :
Prendre un pixel intéressant, trouver sa sinusoïde, voter pour tous les points correspondants à cette sinusoïde (en gros un compteur augmente de 1)
Prendre le pixel intéressant suivant, trouver sa sinusoïde, voter pour tous les points correspondants à celle-ci.
etc
A la fin on regarde où on a le plus de votes et on conclut que des points avec autant de votes sont forcément alignés
Pour mieux comprendre cet algorithme :
Les sinusoïdes vous perturbent ? Un petit mot sur une variante cartésienne, plus simple à visualiser je pense.
La transformée de Hough consiste simplement à passer les pixels intéressants un par un et à tracer pour chacun des droites dans toutes les directions. On marque alors tous les pixels que ces droites associées à ce pixel nous ont fait découvrir (c'est le fameux vote).
On passe au pixel suivant et on recommence.
Si vous imaginez une image blanche avec 4 ou 5 points noirs espacés et alignés, et que vous appliquez cet algorithme, que se passe-t-il ?
A la fin les pixels de la droite que vous voulez recréer ont reçu des votes à cause du premier point noir (car l'une des droites exploratrices est passée par là), du deuxième point noir (idem), du 3eme..., bref les pixels de cette droite ont reçu plus de votes que tous les autres.
Pourquoi ne pas faire en cartésien ? Partir d'un point et tracer des droites dans toutes les directions c'est beaucoup plus simple avec une représentation normale (on fait varier l'angle et roulez jeunesse)
Marsh Posté le 22-07-2006 à 00:48:52
J'ai compris le fonctionnement du HT, mais mon niveau de c++ étant ce qu'il est ...
Bah voila, j'ai fini la phase lecture et de transformée de hough.
Maintenant, le seul problème que j'ai, c'est de diviser "l'espace" (en fait de -90° à 90°) en un tableau avec des cases pour repérer ou passe les sinusoïdes. Un tableau de 1800 cases de longueurs (0.1° de résolution pour l'angle) et d'un nombre de cases de largeur dont je verrai la taille plus tard.
A chaque passage d'une sinusoïde dans une case, son compteur perso doit augmenter de 1 unité (la case). A la fin du passage de toutes les sinusoïdes, je tri le tableau pour me sortir les cases avec un nombre de passage supérieur à 5 (par exemple) et je relève le rho et le théta correspondant et ainsi, j'obtiens mes droites .
Voila, je bloque là, car j'ai de certaines lacunes en c++ .
Merci encore à xavier_om .
Marsh Posté le 18-07-2006 à 12:40:52
Bonjour, j'utilise DevCpp et je dois faire un programme qui transforme un couple de point (x,y) en un autre (p,O) à l'aide de la formule suivante :
p=x.cosO + y.sinO (avec O variant de 0 à 2.Pi)
je vais donc obtenir des sinusoïdes.
Mes couples de points (x,y) sont dans un fichier, j'arrive à les lire, à faire la transformation, ce n'est pas très dur faut dire .
Bref, là ou je bloque, c'est que j'aimerai tracer un histogramme de p en fonction de O pour repérer les sinusoïdes qui se croisent en un même point.
Je ne sais pas si j'explique très bien mais, j'ai fait un dessin pour mieux expliquer.
Le programme doit repérer les cases ou passent les sinusoïdes. Si deux sinusoïdes passent dans une même case, alors, il compte 2.
La dimension des cases étant à définir, selon la résolution que l'on veut obtenir.
Ce que j'ai fait moi, c'est juste la transformation dans le nouveau système, le fait de repérer ou se trouvent les sinusoïdes ne m'inspire pas, étant donné que je ne suis pas un bon programmeur, même pas du tout .
Merci pour votre aide
---------------
Premier Mondial sur Boinc! merci HFR :D