Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1378 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Détecter un point du centre d'une cible...

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Détecter un point du centre d'une cible...

n°733505
gustifotz
Posté le 21-05-2004 à 13:19:26  profilanswer
 

Bijour les gens,
 
Voilà, j'ai un petit problème pour détecter un point particulier de mon écran.  :(  
Imaginez une image qui resemblerait à une série de cercles concentriques, un peu comme une cible de tir à l'arc ou de fléchettes. Les cercles sont noirs et l'espace entre les cercles est laissé en blanc. Mon problème est simple : Comment est-ce que je peux récupérer les coordonnées d'un des points contenus dans le cercle le plus petit (le cercle du milieu de la cible), n'importe lequel fait l'affaire, pourvu qu'il soit contenu dans le centre de la cible... Vous voyez le truc hein?!  :)  
 
J'ai tenté de coder ca en effectuant une boucle sur chaque ligne et en incrémentant un compteur dès qu'un pixel noir est lu. Je garde alors le numéro d'une des lignes qui contiennent le plus de pixels noirs (en excluant les lignes pour lesquelles deux pixels noirs sont adjacents (partie supérieure d'un cercle par ex.)) Ce numéro de ligne est une de mes coordonnées recherchées. Je n'ai plus qu'à effectuer la même opération sur les colonnes et j'aurai ma deuxième coordonnée.
Voici le bout de code que j'ai écrit :

Code :
  1. int FindCenter (int picwidth, int picheight, CDC* pDC)
  2. {
  3. int ord;
  4. int *countpix;
  5. countpix = new int[picheight];
  6. for (int k = 1; k <= picheight; k++)
  7.  countpix[k] = 0;
  8. for (int i = 1; i <= picheight; i++)
  9. {
  10.  for (int j = 1; j <= picwidth; j++)
  11.  {
  12.   if (pDC->GetPixel (j,i) == RGB (0, 0, 0) &&
  13.       pDC->GetPixel (j+1, i) == RGB (255, 255, 255)
  14.   {
  15.    countpix[i] ++;
  16.   }
  17.  }
  18.  if (countpix[i] < countpix[i-1])
  19.  {
  20.   ord = i-1;
  21.   break;
  22.  }
  23. }
  24. return ord;
  25. }


Bon, mais apparemment il y a qqchose qui ne fonctionne pas dans ce code et je prévois que pour une image de la taille de mon écran, l'opération sera longue...  :cry:  
Est-ce que vous avez des idées d'algorithmes, un peu plus rapides? Comment est-ce que je pourrais coder ca plus efficacement?
Toutes vos suggestions sont les bienvenues. Par avance merci.

mood
Publicité
Posté le 21-05-2004 à 13:19:26  profilanswer
 

n°733510
Moktar1er
No one replies...
Posté le 21-05-2004 à 13:29:29  profilanswer
 

le centre de la cible correspond au centre de l'image?

n°733513
gustifotz
Posté le 21-05-2004 à 13:34:43  profilanswer
 

Ben non justement... C'est une cible qui peut avoir une taille variable (nombre variable de ronds concentriques) et qui peut être affichée n'importe où à l'écran.
C'eût été trop simple sinon... :)

n°733515
Moktar1er
No one replies...
Posté le 21-05-2004 à 13:35:51  profilanswer
 

il n'y a que ta cible à l'écran? ou il y a d'autres objets?

n°733521
Joel F
Real men use unique_ptr
Posté le 21-05-2004 à 13:41:11  profilanswer
 

Effectue une correlation du motif de la cible sur l'image.
Si tu n'as qu'une cible dans l'image, le max de corrélation te donne la position de la cible.
 
 
 

n°733527
gustifotz
Posté le 21-05-2004 à 13:46:16  profilanswer
 

moktar1er -> Il n'y a que ma cible à l'écran, pas d'autres objets.  
Joel F -> Je ne connais pas le motif de la cible à l'avance :(...
Y aurait pas un truc plus simple?... :) Qu'est-ce que vous pensez de mon idée au départ? A votre avis, ca peut fonctionner?

n°733551
Moktar1er
No one replies...
Posté le 21-05-2004 à 14:06:42  profilanswer
 

bah s'il n'y a que la cible: détection d'objet->boîte englobante->centre de la cible

n°733559
Joel F
Real men use unique_ptr
Posté le 21-05-2004 à 14:12:07  profilanswer
 

ta cible tu en as un modéle : série de cercle concntrique.
Apres par corréllation successive avec un algo scale-independant, tu va retrouver la meilleur estimation de la position/rayon de ta cible.


Message édité par Joel F le 21-05-2004 à 14:12:20
n°733629
gustifotz
Posté le 21-05-2004 à 14:41:29  profilanswer
 

Bon, j'ai oublié de vous dire que je suis débutant... :)
J'aime bien l'idée de la boîte englobante, mais comment tu peux coder ca, en gros.

n°733673
Moktar1er
No one replies...
Posté le 21-05-2004 à 15:04:43  profilanswer
 

bah si le fond de ton image est uniforme, tu va chercher le premier pixel de couleur différente du fond dans les 4 directions:
- tu prends 1 boîte qui fait la taille de ton image
- te déplace le coté gauche vers la droite jusqu'à ce que tu rencontre 1 point de couleur différente du fond
- la même chose pour les 3 autres cotés
- et normalement, le centre de ta boite, c'est le centre de ton cercle

mood
Publicité
Posté le 21-05-2004 à 15:04:43  profilanswer
 

n°733942
torpe23
Posté le 21-05-2004 à 16:32:11  profilanswer
 
n°735552
Moktar1er
No one replies...
Posté le 24-05-2004 à 09:19:57  profilanswer
 


 
alors là, proposer un hough pour un problème comme le sien c'est super intelligent sisi...
il peut faire un super algo de detection d'objet par composantes connexes qui va lui trouver sa cible en quelques millisecondes, mais toi tu lui proposes de se lancer sur une usine à gaz
en plus, que la cible soit circulaire ou autre on n'en a rien à battre à priori. ce n'est pas une detection de cercle qu'il cherche, c'est une detection de centre d'objet.
donc là dessus, hough, non! :o

n°735623
gustifotz
Posté le 24-05-2004 à 10:09:05  profilanswer
 

Salut tout le monde,
Mon problème a légèrement évolué...  :) Il se trouve que je peux utiliser la souris pour cliquer un des points du centre de ma cible et ainsi récupérer les coordonnées du point cliqué. Cela facilite énormément les choses. Merci pour toutes vos suggestions.  :hello:

n°735625
Moktar1er
No one replies...
Posté le 24-05-2004 à 10:10:43  profilanswer
 

dis... t'aurais pas un exemple d'image à nous poster ici, qu'on fasse mumuse avec [:cupra]

n°735628
lorill
Posté le 24-05-2004 à 10:14:11  profilanswer
 

j'y connais rien, donc [:cupra]

n°735660
gustifotz
Posté le 24-05-2004 à 10:29:49  profilanswer
 

Il s'avère que ma cible composée de cercles concentriques peut également être de forme patatoidale. Donc au lieu d'être une cible toute propre faite avec de jolis cercles, il faut s'imaginer une succession de formes concentriques plus ou moins quelconques (Dessinées sous Paint par ex., la cible peut-être de taille variable, composée d'un nombre aléatoire de patates et située n'importe où sur l'image).
Je veux bien poster un exemple de figure avec laquelle je travaille mais je comprends pas bien comment on fait, il faut d'abord l'uploader qqpart sur un http et utiliser les balises [img], c'est ca?
Sinon, est-ce que qqn sait quelle fonction utiliser pour récupérer les coordonnées d'un pixel cliqué avec la souris??

n°735670
Moktar1er
No one replies...
Posté le 24-05-2004 à 10:36:33  profilanswer
 

- pour ton image oui c'est ça, il faut l'uploader sur un serveur  quelconque
- pour les coordonées, ça dépend un peu de ce avec quoi du développe (MFC, Win32 etc.)
 
edit: pour heberger ton image, tu peux aller sur www.imageshack.us
et tu postes ensuite l'url de ton image entre [img] et [/img]


Message édité par Moktar1er le 24-05-2004 à 10:38:41
n°735680
gustifotz
Posté le 24-05-2004 à 10:41:35  profilanswer
 

Je développe avec les MFC sous Visual C++ 6.0. Je pensais pouvoir utiliser GetDeviceCaps mais c'est pas bon, la fonction ne permet pas de récupérer les coordonnées du pixel.
 Pour l'exemple d'image, je crois qu'il serait plus simple que tu en traces une sous paint par toi-même, tu vois à peu près à quoi ca ressemble?? Y a intérêt parce que j'ai fait de super descriptions... :)

n°735692
Moktar1er
No one replies...
Posté le 24-05-2004 à 10:46:19  profilanswer
 

genre ça?
http://img19.imageshack.us/img19/1055/cible.PNG
 
pour les MFC, désolé, j'ai utilisé ça ya trop longtemps maintenant :D tu peux sûrement trouver ton bonheur dans la MSDN

n°735709
gustifotz
Posté le 24-05-2004 à 10:52:56  profilanswer
 

Bon, apparemment mes explications étaient pas si claires  :D ...
Ca serait plutôt genre ca :
http://img12.imageshack.us/img12/6593/patates.jpg
Comment est-ce que je peux alors récupérer les coordonnées d'une des points de la patate la plus petite, celle qui se trouve au milieu de ma pseudo cible.
En fait, pour tout vous dire, mon application doit ensuite colorier chaque anneau de la cible d'une couleur différente. J'utilise alors les coordonnées d'une ligne horizontale passant par toutes les patates, je parcours la ligne, et chaque fois que je passe d'un anneau à un autre, je colore avec une autre couleur, si c'est pas déjà fait.
Existe-t-il un algorithme classique, connu, qui peut exécuter ce genre d'opération??

n°735728
Moktar1er
No one replies...
Posté le 24-05-2004 à 11:04:55  profilanswer
 

pour le remplissage c'est simple comme bonjour, tu fais appel à ton ami "flood fill", vu la taille de tes anneaux, ça devrait passer sans problèmes (et rapide en plus)
pour la detection de centre, tu pars d'un coin de l'image et tu recherche 1 point noir; le premier que tu trouves c'est forcément un point du contour le plus exterieur -> suivi de contour + etiquetage
tu reprends ta recherche de point noir non etiquetté et dès que tu en trouves 1, re-suivi de contour et re-etiquettage
et ainsi de suite, jusqu'à ce que tu ne retombe sur 1 point noir de la même etiquette que la dernière que tu as créé; dans ce cas tu as trouvé ton dernier cercle
et voilà :D

n°735733
gustifotz
Posté le 24-05-2004 à 11:08:34  profilanswer
 

Ok ca m'a pas l'air trop compliqué, mais qu'est-ce que tu entends par étiquetage?? Il ne faudrait pas plutôt partir d'un coin de la boîte englobante?

n°735738
Moktar1er
No one replies...
Posté le 24-05-2004 à 11:14:24  profilanswer
 

etiquettage: tu donnes une "couleur" à chaque point du premier contour (genre 0,0,1)
pareil (0,0,2) aux points du 2ème contour etc.
tu trouveras facilement des infos sur le net à propos de "suivi de contour" et "etiquettage"
ça fait partie des bases de l'analyse d'image ;)
sinon plus bête:
tu pars de l'exterieur et tu cherches 1 point noir: si tu en trouves 1, tu avances tant que c'est noir (pour pallier au problème d'épaisseur de trait), et dès que tu sors du contour, tu remplis (flood-fill) avec 1 couleur
et après tu déroules:
- tant que non noir j'avance
- tant que noir j'avance
- je remplis avec une nouvelle couleur

n°735752
gustifotz
Posté le 24-05-2004 à 11:19:41  profilanswer
 

Ok merci. Actuellement j'utilise la deuxième solution. Je pense que je vais la garder, elle a l'air de fonctionner correctement, il ne me reste plus qu'à choper la bonne ligne pour effectuer l'opération...

n°735899
torpe23
Posté le 24-05-2004 à 12:37:01  profilanswer
 

moktar1er a écrit :

alors là, proposer un hough pour un problème comme le sien c'est super intelligent sisi...


J't'emmerde bonhomme! Il veut un algo de recherche de centre; comme par hasard, je tombe sur le lien 5 min après; je reviens donc gentillement pour lui proposer. Après, il en fait ce qu'il veut! Au pire, ce sera bon pour sa culture et celle de tout ceux qui viendront lire le post. Bref, j'vois pas l'intéret de ta critique!

n°735999
Moktar1er
No one replies...
Posté le 24-05-2004 à 13:41:28  profilanswer
 

torpe23 a écrit :

J't'emmerde bonhomme! Il veut un algo de recherche de centre; comme par hasard, je tombe sur le lien 5 min après; je reviens donc gentillement pour lui proposer. Après, il en fait ce qu'il veut! Au pire, ce sera bon pour sa culture et celle de tout ceux qui viendront lire le post. Bref, j'vois pas l'intéret de ta critique!


 
euh... déjà tu peux commencer par faire attention à tes mots
ensuite ma critique je te l'ai déjà exposée plus haut:
hough = terriblement lent = Hors Sujet par rapport à sa demande à lui (patatoïdes)
donc voilà pour pourquoi Hough ne sert à rien dans ce cas

n°737559
gustifotz
Posté le 25-05-2004 à 12:59:32  profilanswer
 

Bon, alors j'ai écrit une petite fonction censée me renvoyer le numéro de la dernière ligne passant par toutes les patates de ma cible :

Code :
  1. int FindLine (int picwidth, int picheight, CDC *pDC)
  2. {
  3. int counter, ycoord;
  4. int *tab, *tot;
  5. tab = new int[picwidth];
  6. tot = new int[picheight];
  7. for (int i = 1; i <= picheight; i++)
  8. {
  9.  tot = 0;
  10.  counter = 0;
  11.  for (int j = 1; j <= picwidth; j++)
  12.  {
  13.   if (pDC->GetPixel (j,i) == RGB (0, 0, 0))
  14.    tab [j] = 1;
  15.   else
  16.    tab [j] = 0;
  17.  }
  18.  for (int l = 1; l <= picwidth; l++)
  19.   if (tab[j] >= tab[j-1] && tab[j] > tab[j+1])
  20.    counter ++;
  21.  tot[i] = counter;
  22. }
  23. for (int k = 1; k <= picheight; k++)
  24. {
  25.  if (tot[k] > tot[k+1])
  26.  {
  27.   ycoord = k;
  28.   break;
  29.  }
  30. }
  31. return ycoord;
  32. }


Seulement bien évidemment ca ne tourne pas. Explications : L'image a une largeur [i]picwidth et une hauteur picheight. Je déclare un tableau tab, de taille picwidth. Pour chaque ligne, je remplis ce tableau tab avec des 1 ou des 0, selon que le pixel lu soit noir ou blanc. Une fois que ma ligne est lue et que mon tableau tab est rempli, je le parcourt à nouveau et je détecte le nombre de passages de 1 à 0 (front descendant). Je stock ce nombre dans le tableau tot. Ainsi tot[i] contient le nombre de fronts descendants de i ème ligne.
Une fois que mon tableau tot est rempli, je cherche l'indice i tel que tot[i] soit supérieur à tous les autres tot[k] (k != i). Bien entendu il y a plusieurs lignes pourlesquelles tot[i] est max : ce sont toutes lignes passant par ma patate du milieu. Je sélectionne la dernière par un test tout simple :

Code :
  1. if (tot[k] > tot[k+1])


En effet les valeurs contenues dans tot[i] sont croissantes en fonction de i, jusqu'a cette fameuse ligne dont je veux récupérer la position.
Bon, j'espère que tout est clair et que vous allez me dire ce bug, parce qu'apparemment ca môrch pô...  :??:  
Je retourne bien le numéro de la ligne avec

Code :
  1. return k;

?

n°737588
gustifotz
Posté le 25-05-2004 à 13:15:01  profilanswer
 

En fait je me complique un peu la vie, j'ai pas besoin de deux tableaux et de ces 1 et ces 0, je peux faire ca directement et m'épargner une étape superflue :
int FindLine (int picwidth, int picheight, CDC *pDC)

Code :
  1. {
  2. int counter, ycoord;
  3. int *tot;
  4. tot = new int[picheight];
  5. for (int i = 1; i <= picheight; i++)
  6. {
  7.  counter = 0;
  8.  for (int j = 1; j <= picwidth; j++)
  9.   if (pDC->GetPixel (j,i) == RGB (0, 0, 0) &&
  10.    pDC->GetPixel (j+1, i) == RGB (255, 255, 255))
  11.    counter ++;
  12.  tot[i] = counter;
  13. }
  14. for (int k = 1; k <= picheight; k++)
  15. {
  16.  if (tot[k] > tot[k+1])
  17.  {
  18.   ycoord = k;
  19.   break;
  20.  }
  21. }
  22. return ycoord;
  23. }


Donc en fait, ce qui merde, à mon avis, c'est la recherche de la position du plus grand élément dans tot... Des suggestions?

n°737594
gustifotz
Posté le 25-05-2004 à 13:20:05  profilanswer
 

Mais évidemment que ca merde, suis allé trop vite là. Ma condition

Code :
  1. if (tot[k] > tot[k+1])

est valable pour plus d'une ligne... Ferais mieux de réfléchir un peu...  

n°737595
Moktar1er
No one replies...
Posté le 25-05-2004 à 13:20:43  profilanswer
 

déjà, fais tes boucles:
i=0; i<picheight; i++
j=0; j<picwidth; j++
k=0; k<picheight; k++
 
parceque là tu fais des débordements

n°737598
gustifotz
Posté le 25-05-2004 à 13:24:53  profilanswer
 

?? Pourquoi? Ca colle pas si je vais de 1 à picwidth? C'pareil non?

n°737683
Moktar1er
No one replies...
Posté le 25-05-2004 à 14:11:15  profilanswer
 

bah nan
ton tableau a picheight cases
vu qu'en C les indices commencent à 0, l'indice max c'est picheight-1

n°737848
gustifotz
Posté le 25-05-2004 à 15:07:09  profilanswer
 

Oui exact, j'ai corrigé ca, et je crois que c'est ca qui buggé en fait... Donc voici ma fonction finale, qui fonctionne, tests à l'appui :

Code :
  1. int FindLine (int picwidth, int picheight, CDC *pDC)
  2. {
  3. int counter, ycoord;
  4. int *tot;
  5. tot = new int[picheight];
  6. for (int i = 0; i < picheight; i++)
  7. {
  8.  counter = 0;
  9.  for (int j = 0; j < picwidth; j++)
  10.   if (pDC->GetPixel (j,i) == RGB (0, 0, 0) &&
  11.    pDC->GetPixel (j+1, i) == RGB (255, 255, 255))
  12.    counter ++;
  13.  tot[i] = counter;
  14. }
  15. for (int m = 0; m < picheight; m++)
  16.  if (tot[m] > tot[m+1])
  17.  {
  18.   ycoord = m;
  19.   break;
  20.  }
  21. return ycoord;
  22. }


Merci pour le coup de pouce.
Si tu utilises également cette fonction :

Code :
  1. void ChangeColor (int picwidth, int picheight, CDC* pDC)
  2. {
  3. int k = 0;
  4. int ymid = FindLine (picwidth, picheight, pDC);
  5. for (int l = 0; l < picwidth; l++)
  6.  if (pDC->GetPixel (l, ymid) == RGB (0, 0, 0) &&
  7.   pDC->GetPixel (l-1, ymid) == RGB (255, 255, 255))
  8.  {
  9.   CBrush* new_brush = new CBrush (RGB(255-20*k, 255-20*k, 255-20*k));
  10.   pDC->SelectObject (new_brush);
  11.   pDC->ExtFloodFill (l-1, ymid, RGB (255,255,255), FLOODFILLSURFACE);
  12.   k++;
  13.  }
  14. }


tu peux tester avec l'image que j'ai postée un peu plus haut, ca tourne. Encore une fois merci pour ton aide moktar1er et merci également aux autres pour leurs suggestions.

n°737849
Moktar1er
No one replies...
Posté le 25-05-2004 à 15:08:24  profilanswer
 

j'avoue que je n'ai pas regardé le code dans le détail, mais le principal est que ça marche comme tu veux
content d'avoir pu rendre service

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Détecter un point du centre d'une cible...

 

Sujets relatifs
Comment detecter si une carte son est installé avec acces???[PHP]Détecter les modules installés
Comment detecter un depassement de capacite dans une additionComment détecter une valeure vide ?
Définir le point d'entrée dans une appli-web (dans le web.xml)tableau dans power point
Quelle est la meilleure manière de détecter Opera ?Détecter si l'OS est Win ou linux...
Algorithme de collision entre un point et un rectangle.Detecter une fleche "onkeypressed"
Plus de sujets relatifs à : Détecter un point du centre d'une cible...


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR