Orientation dev pour mon app

StephSteph Membre
14:06 modifié dans Vos applications #1
Bonjour à  tous,

J'ai une petite app en cours de validation sur le store. C'est une app qui utilise le flash de l'iPhone4 pour envoyer des signaux morse.

En gros, soit vous envoyez des points et des traits à  la main, soit vous entrez une phrase dans un champ texte et ça traduit automatiquement.

Maintenant, j'aimerai m'attaquer à  la traduction inverse, à  savoir, détecter les flashs de lumières et en déduire les caractères. Je ne sais pas trop comment commencer aussi aurais-je besoin de quelques conseils.

Je suppose que ce que je veux faire s'apparente à  la réalité augmentée (piou ça va être chaud), avez-vous des pistes ou des tutos qui m'aiderai un peu ?

Merci beaucoup :)

Réponses

  • AliGatorAliGator Membre, Modérateur
    14:06 modifié #2
    Heu cela n'a pas vraiment à  voir avec la Réalité Augmentée.
    La réalité augmentée consiste à  analyser le contexte dans lequel se trouve l'utilisateur, pour lui rajouter des informations en fonction de ce contexte. Cela peut consister à  faire la capture du flux vidéo puis de l'analyse de l'image pour en déterminer des points d'intérêt, mais cela peut aussi se baser sur les coordonnées GPS de l'iPhone et son orientation (boussole) pour déterminer l'environnement (et les points d'intérêt également donc).
    Et surtout une fois ces POI trouvés, le propre de la réalité augmentée est justement d'utiliser ces informations contextuelles pour augmenter la réalité, c'est à  dire rajouter des informations en corrélation avec le contexte déterminé (par exemple rajouter un objet 3D en fonction d'un tag détecté sur l'image, de son orientation, etc).


    Bref ce que tu veux faire n'a rien à  voir, pas la peine de sortir les frameworks de RA pour faire ça ça serait un bazooka pour tuer une mouche et pire ça ne serait à  priori pas adapté. Pour ton cas tu n'as qu'une simple analyse basique d'image à  faire à  la limite (détection d'un seuil de luminosité sur l'image reçue, si les capteurs de la camera sont saturés par le flash d'en face, ou détection d'une variation de luminosité importante locale si tu as vraiment un point lumineux généré par le flash d'en face s'il est trop loin pour saturer les capteurs). Pas de recherche de POI dans l'image, et surtout pas "d'augmentation de la réalité".


    Après il faut faire des tests pour voir ce que ça donne quand tu filmes un iPhone générant un code morse (avec ton appli actuelle), quel est l'effet sur l'image filmée par un autre iPhone ? En effet vu que c'est un flash, il risque de saturer l'image en luminosité au moment où il est allumé, ça risque pas trop d'être juste un cercle blanc bien délimité quoi.

    Le plus simple est de calculer à  mon avis la luminosité globale de ton image (tu pourras ajuster la formule de calcul selon la précision que tu veux, genre soit juste L=(R+G+B)/3 pour faire simple soit les formules de conversion entre espaces colorimétriques RGB>TSL pour être plus fin, voire le mieux, conversion de l'image en niveaux de gris, puis moyenne des valeurs de luminosité des pixels de l'image) et de regarder les oscillation de sa valeur : si ton iPhone filme bien toujours la même zone (pas de modification du cadrage genre déplacement de l'iPhone) pendant l'acquisition du code morse, ça suffira amplement à  priori.
    Log les valeurs de luminosité calculé sur les images, voire mieux, trace un graphe si tu peux de cette valeur de luminosité au cours du temps, tu verras que cette valeur va du coup osciller autour de la luminosité moyenne de ta scène, et te révéler ainsi les "points" et "traits" du flash d'en face quand il émet le morse ;)
  • CéroceCéroce Membre, Modérateur
    14:06 modifié #3
    Comme l'indique Ali ça n'a rien à  voir avec la réalité augmentée. Ce que tu veux faire n'est pas simple, surtout si tu n'as aucune connaissance sur le traitement d'image.

    Pour repérer les tâches blanches, on peut utiliser un algorithme très simple de seuil: on parcourt tous les pixels de l'image, en additionnant les valeur rouge+vert+bleu. Au dessus d'un certain seuil (par exemple 3*253) atteint par un nombre suffisant de pixels (par exemple 40), on a une tâche blanche sur cette image.

    Ensuite, on peut construire (en mémoire) un tracé de la forme:
    <br />Flash<br /><br />	1&nbsp; &nbsp; _____&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; __________<br /><br />	0 ___&nbsp; &nbsp;  ______________&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ____________<br />	<br />	--------------------------------------------------&gt; temps<br />


    Il faut ensuite repérer le début d'une émission: c'est quand le flash est resté à  zéro depuis un certain temps (1 s ?) et qu'il passe à  1, puis compter le temps à  1 pour savoir quel est le caractère.

    J'ai dit que ce n'était pas simple ?
  • StephSteph Membre
    14:06 modifié #4
    Merci à  vous deux.

    Je sais bien que ce que je voudrai faire n'est pas facile, mais je prendrai mon temps pour le faire ya pas de souci. Je risque de m'arracher les cheveux plus d'une fois car comme tu le penses à  juste titre Céroce, je n'ai pas de notion de traitement de l'image en dev.

    Merci pour vos pistes, je vais faire quelques recherches également de mon côté. Le truc c'est que parcourir chaque pixel de l'image si on est à  30 images par seconde, ça va bouffer de la ressource. De plus, je dois détecté la durée de la tâche blanche afin de savoir s'il s'agit d'un point ou d'un trait, bref c'est d'autant plus complexe. Et pour finir, ça doit fonctionner de jour comme de nuit si possible ...
  • AliGatorAliGator Membre, Modérateur
    septembre 2010 modifié #5
    Je vois que Céroce et moi on a le même algo au final : calculer la luminosité moyenne de l'image, tracer la courbe d'évolution de cette luminosité au cours du temps, et l'utiliser pour détecter les changements brusques de lumière.
    Tu peux commencer par un algo assez simple comme l'a décrit Céroce, et mettre en place la structure du module de détection avec. Au fur et à  mesure que tu le testeras tu pourras toujours améliorer l'algo.

    Pour le calcul des pixels, je me demande si ce n'est pas plus simple de convertir l'image en noir & blanc (enfin niveaux de gris plutôt) d'abord avant de parcourir les pixels : ainsi tu n'auras qu'à  ajouter les valeurs L de chaque pixels (qui seront déjà  un unique octet représentant la luminosité du pixel puisque tu seras dans l'espace colorimétrique "niveaux de gris") plutôt que parcourir R+G+B pour chaque pixel.

    En plus c'est plus adapté car il faut savoir que la luminosité d'une couleur ne se résume pas à  L=(R+G+B)/3 vu que chaque couleur n'impacte pas de la même manière les capteurs de luminosité de nos yeux (après, la moyenne des valeurs de Rouge,Vert et Bleu ainsi calculée reste une approximation suffisante si on veut faire un calcul rapide et à  la louche, genre pour ton cas ça devrait pas gêner, mais bon)

    L'idée serait même peut-être, quitte à  créer une version en niveaux de gris de ton image avant de parcourir ses pixels, d'en profiter pour la réduire aussi (50% ? 25 ?) histoire d'avoir moins de pixels à  analyser ensuite.

    Si tu utilises les méthodes disponibles dans le SDK pour réduire une image et la transformer en niveaux de gris (UIGraphicsBeginImageContext ou CGBitmapContextCreate(...) par exemple) la création de cette miniature N&B ne sera pas méchante et en plus optimisée, t'évitant de trop complexifier ton algo.

    Je te conseille vivement la lecture du Quartz 2D Programming Guide qui contient toutes les informations nécessaires pour manipuler des images et des pixels en Cocoa.
  • StephSteph Membre
    14:06 modifié #6
    Je vais lire ça ali, mais l'idée du noir et blanc est très bonne ainsi que celle de réduire la taille de l'image :)

    Je vous tiens au jus, j'ai un autre petit projet à  finir et après j'attaque celui-là . Il reste en tâche de fond dans mon crâne pour mûrir un peu :)

  • CéroceCéroce Membre, Modérateur
    14:06 modifié #7
    dans 1283416550:

    Je vais lire ça ali, mais l'idée du noir et blanc est très bonne ainsi que celle de réduire la taille de l'image :)


    Désolé Ali, mais ce ne sont pas forcément de bonnes idées, ça dépend de comment travaille Core Graphics (en utilisant le copro graphique ou pas), et encore.

    Passer l'image en niveaux de gris peut être fait par deux appels de fonction avec Core Graphics, mais c'est bien l'iPhone qui va faire le travail alors si on peut éviter, on évite. C'est pour ça que je disais de travailler directement avec les valeurs RVB. Par ailleurs, dans ce cas, on se fiche de la façon dont l'oe“il humain perçoit les couleurs, on recherche juste une tâche très lumineuse.

    On n'est pas obligé de traiter toutes les images envoyées par la caméra (on peut travailler à  1/5 s, soit ~une image sur 6).

    On n'est pas non plus obligé d'analyser toute l'image, par exemple, on peut tester une ligne sur 2 et une colonne sur 2, ça revient au même que traiter une image réduite. Donc pareil que plus haut: on ne réduit pas l'image, c'est du travail pour l'iPhone (le copro graphique est capable de faire ce genre de réductions, mais ça implique des transferts entre mémoire vidéo et mémoire centrale).

  • StephSteph Membre
    14:06 modifié #8
    Clairement, je dois optimiser le plus possible car j'aimerai décoder en temps réel (t'en qu'a être fou, autant aller au bout lol), je ferai peut-être une première version avec capture de la vidéo puis traitement et affichage du résultat, mais le temps réel c'est ce que voudrons les users je pense.

    Merci Céroce pour tes conseils également.
  • AliGatorAliGator Membre, Modérateur
    14:06 modifié #9
    Oui tout à  fait Céroce.
    Si je proposais cette solution c'est plutôt par facilité pour Céroce pour commencer.
    Si tu veux optimiser, faut voir les résultats pour voir dans quel sens et vers quel axe optimiser.

    Par exemple je suis d'accord que convertir en niveaux de gris prends du temps donc on peut lire directement R V et B pourquoi pas. Faudra savoir que la valeur obtenue ne sera pas la même, mais à  priori vu l'algo simpliste dont on a besoin c'est pas gênant.
    De même, prendre qu'une ligne sur 2 ou une colonne sur 2 n'a pas le même effet que de réduire l'image à  50% en terme de résultat final (la réduction faisant un calcul prenant en compte les pixels voisins lors du downscaling), mais là  encore c'est sans doute acceptable également, on n'est pas dans du traitement d'image haute volée, et ce que l'on a à  détecter est très simple, juste une varition lumineuse qui reste conséquente (le gradient entre une image où le flash est éteint et une où elle est allumé est suffisament flagrant)

    Après il est toujours temps d'améliorer l'algo selon les performances qu'on obtiendra ainsi que les résultats (images très bruitée ? seuil trop variable ? etc) si l'archi logicielle est bien faite après tout l'algo est une boite noire, une fonction à  qui on passe une image en entrée et qui nous répond YES ou NO pour dire s'il y a un flash sur l'image, sa façon pour le déterminer pourra être adaptée plus tard pour de meilleures perfs.


    Sinon il y a également d'autres pistes d'algo possibles, par exemple faire le calcul de corrélation entre l'image courante et la précédente (limite avec juste une composition de type "négatif") qui permettrait de très rapidement détecter quand on change d'état de flash allumé à  flash éteint et vice-versa. Pour ce genre de solution il faut stabiliser l'image et voir également en pratique quel qualité d'image on a (SNR, etc) et quel est le contexte (filmer pile poil un iPhone en face qui fait du morse, ou bien est-ce qu'on veut que les iPhones puissent être à  500m l'un de l'autre, quelle tolérance aux éléments extérieurs, genre s'il y a autre chose qui bouge sur l'image, une personne qui passe dans le champ par exemple et donc apparaà®t sur l'image même si elle n'occulte pas le flash de l'autre iPhone ça gênera la détection...)

    Bref tout cela dépend du contexte, des types d'images que tu auras (flash qui sature les capteurs de l'autre iPhone car assez près, tolérance aux perturbations, ...) et des performances attendues.
    Le plus simple donc pour moi est que tu mettes l'algo dans une boite noire, que pour l'instant tu développes un algo simple à  implémenter rapidement pour tester, il sera temps après de l'améliorer en terme de perfs (vitesse), empreinte mémoire ou résultats une fois l'ensemble de la chaà®ne mis en place, non ?
  • StephSteph Membre
    14:06 modifié #10
    Oui tu as raison.

    En fait je vais démarrer la capture vidéo, envoyer les infos à  une fonction qui effectivement retournera un booléen ou un truc simple et ensuite, je n'aurais qu'a améliorer la fonction si besoin :)
  • AliGatorAliGator Membre, Modérateur
    14:06 modifié #11
    En plus à  mon avis il serait intéressant de voir (quitte à  les poster ici ?) des captures de ce que tu veux analyser. Histoire de se faire une idée du contexte et donc des contraintes auxquelles le traitement d'image seront exposées :
    - effet de la présence du flash sur la photo ? (à  priori une tâche plus lumineuse à  un endroit, mais peut-être des effets de bords, en particulier ensemble de la photo plus exposé, voire saturé)
    - distances auxquelles tu veux détecter le flash (impactera sur ce que tu dois détecter sur la photo et les seuils de tolérance)
    - environnement intérieur/extérieur/jour/nuit
    ...
Connectez-vous ou Inscrivez-vous pour répondre.