10
votes

Détection de points laser rapide sous-pixels

J'utilise Xna pour construire un projet où je peux dessiner "graffiti" sur mon mur à l'aide d'un projecteur LCD et d'une caméra monochrome filtrée pour ne voir que des pointeurs de points laser à main. Je veux utiliser un nombre quelconque de pointeurs laser - ne vous souciez pas vraiment de les différencier à ce stade.

Le mur est de 10 'x 10', et la caméra n'est que 640x480, donc je tente d'utiliser une mesure de sous-pixels à l'aide d'une courbe SPLINE comme indiqué ici: TPUB.COM

La caméra fonctionne à 120fps (8 bits), donc ma question à vous tous est le moyen le plus rapide de trouver ce centre de points laser à sous-pixel. Actuellement, j'utilise une recherche de force brute 2D pour trouver le pixel le plus brillant de l'image (0 à 254) avant de faire l'interpolation de la spline. Cette méthode n'est pas très rapide et chaque trame prend plus de temps à l'ordinateur qu'il n'y para.

Edit: Pour clarifier, à la fin, mes données de caméra sont représentées par un tableau 2D d'octets indiquant la luminosité du pixel.

Ce que j'aimerais faire, c'est utiliser un Shader Xna pour crier l'image pour moi. Est-ce pratique? D'après ce que je comprends, il n'y a vraiment pas de moyen de garder les variables persistantes dans une shader de pixel, telles que des totaux de course, des moyennes, etc.

Mais pour les arguments, disons que j'ai trouvé les pixels les plus brillants à l'aide de la force brute, puis les stockés et leurs pixels voisins pour la courbe de spline dans x nombre de sommets à l'aide de Texcoords. Est pratique alors d'utiliser HLSL pour calculer une courbe de spline à l'aide de Texcoords?

Je suis également ouvert aux suggestions en dehors de ma boîte Xna, que ce soit DX10 / DX11, peut-être une sorte de FPGA, etc. Je n'ai tout simplement pas vraiment beaucoup d'expérience avec les moyens de crquer des données de cette manière. Je pense que si elles peuvent faire quelque chose comme ça sur une Wii-Mote en utilisant 2 piles AA que je ne vais probablement pas à ce sujet.

Des idées?


10 commentaires

Qu'est-ce qui fait lentement, faire le scan ou faire l'interpolation de la spline par la suite?


L'interpolation de la spline est de loin la composante la plus lente de celui-ci, en fonction de ce que Delta j'évalue la spline. Dans ce cas, je voudrais une précision de 0.1PX.


Je devrais ajouter que si j'ai 20 lasers, le calcul de la spline deviendrait très très cher du processeur.


Frais. Ceci est complètement faisable avec un nombre quelconque de lasers. Montrer une version rugueuse en temps réel. Allez de rugueux à une résolution plus élevée une ligne de rectangle d'écran à la fois, ou lorsque le dessin est terminé.


Si vous avez un projecteur, vous pouvez projeter la même zone que vous tournez, tant que la couleur est différente et que vous filtrez la sortie pour être invisible.


@Nosredna, oui c'est l'idée, de dessiner directement sur ce qui est projeté. J'ai acheté un matériau filtrant de 610 nm pour accéder à mon pointeur laser Radioshacack bon marché de 610 nm. Je mets le filtre sur la caméra afin qu'il ne voit que le laser, peu importe ce que le projecteur s'affiche. Cela fonctionne à 100% à l'exception de la lumière directe du soleil.


Vous devez donc éviter les keystoning, non? Dans votre code, ou votre projecteur a besoin de correction de Keystone ou de votre appareil photo a besoin d'une lentille de quart. :-)


Je le calmège moi-même, car une fois cela terminé, la caméra et le projecteur ne bougent pas. Ce que je fais, c'est dessiner un seul point sur chaque coin de l'écran et avoir une fonction qui lit un point laser pointé sur chacun de ces coins. Donc, peu importe la façon dont le projecteur / caméra est orienté, une fois que j'ai les 4 pixels qui représentent les coins du monde réel, je traduisez facilement entre les deux à l'aide de la géométrie simple.


Droit. Ça a du sens.


Vous savez, je pense que ce serait quelque chose qui pourrait être facilement commercialisé - initialement comme un complément à PowerPoint ou quelque chose (entreprises telles que Flashy Gimmicks!). Vous auriez besoin d'un bouton sur le laser pour le faire comme une souris afin que vous puissiez basculer entre le tirage / non.


7 Réponses :


5
votes

Si, par brute-forçage, vous voulez regarder chaque pixel de manière indépendante, c'est essentiellement la seule façon de le faire. Vous devrez numériser toutes les images de pixels, peu importe ce que vous voulez faire avec l'image. Althouh, vous n'avez peut-être pas besoin de trouver les pixels les plus brillants, vous pouvez filtrer l'image par couleur (ex.: Si vous utilisez un laser rouge). Cela se fait facilement à l'aide d'une image codée par couleur HSV. Si vous recherchez des algorithmes plus rapides, essayez OpenCV. Il a été encore optimisé à nouveau pour un traitement d'image et vous pouvez l'utiliser en C # via une enveloppe:

[ http://www.codeproject.com/kb/ cs / intel_opencv.aspx] [1]

OpenCV peut également vous aider à trouver facilement les centres de points et à suivre chaque point.

Y a-t-il une raison pour laquelle vous utilisez une caméra 120FPS? Vous savez que l'œil humain ne peut voir qu'environ 30fps? Je suppose que c'est de suivre des mouvements laser très rapides ... Vous voudrez peut-être envisager de le mettre en panne, car le traitement en temps réel de 120fps sera très difficile à atteindre.


0 commentaires

4
votes

Courir à travers 640 * 480 octets pour trouver l'octet le plus élevé doit fonctionner dans une MS. Même sur des processeurs lents. Pas besoin de prendre la route des shaders.

Je conseillerais d'optimiser votre boucle. Par exemple: Ceci est vraiment lent (car il fait une multiplication avec chaque liste de réseau): p> xxx pré>

ceci est beaucoup plus rapide: p>

byte [] myBytes = new byte[640*480];
//fill it with your image

byte highest=0;
int found=-1, foundX=-1, foundY=-1;
int len = 640*480;
for(i=0; i<len; i++)
{
    if(myBytes[i] > highest)
    {
        highest = myBytes[i];
        found = i;
    }
}
if(found!=-1)
{
    foundX = i%640;
    foundY = i/640;
}


0 commentaires

3
votes

La force brute est la seule voie réelle, mais votre idée d'utiliser un shader est bonne - vous déchargiez la chèque de force brute de la CPU, qui ne peut que regarder un petit nombre de pixels simultanément (environ 1 par noyau), au GPU, qui dispose probablement de plus de 100 cœurs (pipelines) pouvant comparer simultanément des pixels (votre algorithme devra peut-être être modifié un peu pour bien fonctionner avec la 1 instruction - de nombreux cœurs d'un GPU). < / p>

Le plus gros problème que je vois est de savoir si vous pouvez ou non que vous puissiez déplacer ces données au GPU assez rapidement.


3 commentaires

Comment puis-je suivre le pixel le plus élevé unique sur un cadre dans le GPU? Suis-je comprendre cela correct en ce que les noyaux muettes ne peuvent pas partager la mémoire d'une manière qui leur permettrait de comparer un pixel au pixel le plus brillant précédent?


Un GPU pourrait être considéré comme une vaste collection de processeurs vraiment simples optimisées pour les opérations mathématiques. La plus grande différence Bien que le décodeur d'instructions ait été dépouillé - un seul contrôleur envoie la même instruction à chaque noyau idiot, où elle est exécutée sur ce morceau de données de noyau. Si des déclarations sont effectuées en exécutant le même code deux fois - au lieu de ramification, les noyaux qui ne correspondent pas à la condition juste arrêter. Les mêmes données sont ensuite envoyées à nouveau, mais avec l'instruction de comparaison inversée.


Dans votre cas, vous ne pouvez pas comparer au immédiat précédent pixel le plus brillant, car l'une des (disons) 128 noyaux aurait pu trouver un pixel plus lumineux. Au lieu de cela, essayez d'avoir chaque concentré de noyau sur une ligne propre - trouvez le pixel le plus brillant dans la ligne (traitement simultanément de 128 lignes). Une fois que les lignes de l'image ont été résumées efficacement comme le pixel le plus brillant de cette ligne, vous pouvez trouver le plus brillant de manière globale de manière sérieuse.



1
votes

Mettez légèrement la caméra à l'écart de la mise au point et du bitblt contre un échantillon neutre. Vous pouvez rapidement numériser des lignes pour les valeurs non 0. De plus, si vous êtes à 8 bits et ramasser 4 octets à la fois, vous pouvez traiter l'image plus rapidement. Comme un autre indiqué, vous risquez de réduire le taux de trame. Si vous avez moins de fidélité que l'image résultante, il n'y a pas beaucoup de point au taux de balayage élevé.

(la légère caméra à base de focus aidera à obtenir des points les plus brillants et à réduire les faux positifs si vous avez une surface chargée ... bien sûr en supposant que vous ne tirez pas une surface lisse / plate)


0 commentaires

2
votes

Une autre optimisation à considérer: Si vous dessinez, l'emplacement actuel du pointeur est probablement fermé le dernier emplacement du pointeur. N'oubliez pas la dernière position enregistrée du pointeur entre les cadres et seulement scanner une région proche de cette position ... Dites une zone de 1'x1 '. Seulement si le pointeur n'est pas trouvé dans cette zone, vous devez numériser toute la surface.

Évidemment, il y aura un compromis entre la rapidité avec laquelle votre programme peut numériser et la rapidité avec laquelle vous pourrez déplacer votre souris avant que la caméra "perd" le pointeur et doit aller à la balayage lente et d'image complète . Une petite expérimentation révélera probablement la valeur optimale.

Projet cool, au fait.


2 commentaires

Pourquoi juste 1x1. Pourquoi ne pas incrémenter la taille 1 ^ 2. Donc, si ce n'est pas trouvé dans un 1x1, il vérifiera alors 2x2, 4x4, etc. Un peu de soin et vous pourriez aller à travers la zone que vous avez déjà vérifiée.


Je pensais à ce sujet aussi. Mais il peut avoir plusieurs lasers afin qu'il va de tout de même regarder chaque pixel. Un laser peut allumer ou rentrer à la zone sans préavis.



1
votes

Démarrer avec un tampon de sortie noir. Oubliez le sous-pixel pour l'instant. Chaque cadre, chaque pixel, faites ceci:

outbuff = max (outbuff, inbuff);

Filtrage de sous-pixel sur une troisième tampon "propre" lorsque vous avez terminé avec l'image. Ou faire un morceau ou une ligne de l'écran à la fois en temps réel. Avantage: vue "rugueuse" en temps réel du dessin, nettoyé comme vous allez.

Lorsque vous convertissez du tampon de sortie brutal au troisième tampon "propre", vous pouvez effacer le rugueux au noir. Cela vous permet de continuer à dessiner pour toujours sans ralentir.

En dessinant le "nettoyage" sur le dessus sur le "rugueux", peut-être d'une couleur légèrement différente, vous aurez le meilleur des deux mondes.

Ceci est similaire à ce que les programmes de peinture font - si vous dessinez vraiment rapidement, vous voyez une version rugueuse, puis le programme de peinture "Nettoie" l'image quand elle a le temps.


Certains commentaires sur l'algorithme:

J'ai vu beaucoup de tricheurs dans cette arène. J'ai joué Sonic sur un émulateur de Sega Genesis qui upsemples. Et il a des algorithmes assez sauvages qui fonctionnent très bien et sont très rapides.

Vous avez en fait des avantages que vous pouvez gagner, car vous pourriez connaître la luminosité et le rayon du point.

Vous pourriez simplement regarder chaque pixel et ses 8 voisins et laisser ces 9 pixels "voter" en fonction de leur luminosité pour l'endroit où se trouve le sous-pixel.


Autres pensées

Votre main n'est pas si précise lorsque vous contrôlez un pointeur laser. Essayez d'obtenir tous les points tous les 10 images, identifiant les faisceaux qui sont lesquels sont lesquels sont ceux (basés sur le mouvement précédent, et la comptabilisation des nouveaux points, des lasers éteints et des points qui ont entré ou laissé le champ visuel), puis en tirant une hauteur. courbe de résolution. Ne vous inquiétez pas pour le sous-pixel dans l'entrée - Dessinez simplement la courbe dans la sortie haute résolution.

Utilisez une spline Catmull-ROM, qui passe tous les points de contrôle.


2 commentaires

J'aime cette idée, fait un sens parfait. Donc, peut-être représenter les pixels "propres" comme des structures contenant des valeurs de 5x5 pixels et les traversent dans une file d'attente sur un thread séparé. Néanmoins, brûler à travers cette file d'attente serait une entreprise de processeur massif. Peut-être que je peux stocker chacune de ces structures dans un sommet et faire la courbe Spline sur la carte vidéo? Je cherche toujours un moyen rapide d'éclairage de calculer 5x5 splines 2D. Merci pour cette suggestion de haut niveau!


Cela n'a pas d'importance à quel point c'est lent. Vous pouvez optimiser plus tard. Vous venez de regarder la minuterie et de voir combien de l'écran vous pouvez faire chaque image.



3
votes

Vous traitez de mathématiques assez complexes si vous voulez une précision du sous-pixel. Je pense que Cet article est quelque chose à considérer. Malheureusement, vous devrez payer pour le voir à l'aide de ce site. Si vous avez accès à une bibliothèque appropriée, ils peuvent être capables de l'en obtenir pour vous.

Le lien dans la publication d'origine suggérée faire des calculs de 1000 splines pour chaque axe - il a traité X et Y indépendamment, ce qui est OK pour les images circulaires mais est un peu éteint si l'image est une ellipse asymétrique. Vous pouvez utiliser ce qui suit pour obtenir une estimation raisonnable:

x C = somme (x n .f (x n )) / somme (f (x n ))

où x c est la moyenne, x n est Le point un point sur l'axe des x et f (x n ) est la valeur au point x n . Donc pour cela: xxx

donne:

somme (x n .f (x n )) = 1 * 2 + 3 * 3 + 4 * 9 + 5 * 10 + 6 * 4 + 7 * 1

somme (f (x n )) = 1 + 3 + 9 + 10 + 4 + 1

x c = 128/28 = 4.57

et répéter pour l'axe de Y.


2 commentaires

Cela fonctionne assez bien. Cela fonctionne beaucoup plus vite pour moi que ma mise en œuvre de la spline aussi. C'est à peu près réel! Merci pour la suggestion.


À propos du lien: Juste chercher le titre. Top Hit: groups.mrl.illinois.edu/granick/publications/pdf%20files/200 9 / ...