Traitement d'image: amélioration de l'algorithme pour la reconnaissance de 'Coca-Cola Can'


1659

L'un des projets les plus intéressants sur lesquels j'ai travaillé ces dernières années était un projet sur le traitement d'image . L'objectif était de développer un système permettant de reconnaître les «canettes» de Coca-Cola (notez que j'insiste sur le mot «canettes», vous verrez pourquoi dans une minute). Vous pouvez voir un exemple ci-dessous, avec la boîte reconnue dans le rectangle vert avec échelle et rotation.

Correspondance de modèle

Quelques contraintes sur le projet:

  • Le fond peut être très bruyant.
  • La boîte peut avoir n'importe quelle échelle ou rotation ou même orientation (dans des limites raisonnables).
  • L'image peut présenter un certain flou (les contours peuvent ne pas être entièrement droits).
  • Il pourrait y avoir des bouteilles de Coca-Cola dans l'image, et l'algorithme ne devrait détecter que la boîte !
  • La luminosité de l'image peut varier considérablement (vous ne pouvez donc pas vous fier "trop" à la détection des couleurs).
  • La boîte peut être partiellement cachée sur les côtés ou au milieu et peut-être partiellement cachée derrière une bouteille.
  • Il ne pouvait y avoir aucune boîte du tout dans l'image, auquel cas vous deviez ne rien trouver et écrire un message le disant.

Vous pourriez donc vous retrouver avec des choses délicates comme celle-ci (qui dans ce cas, mon algorithme a totalement échoué):

Échec total

J'ai fait ce projet il y a quelque temps, et je me suis beaucoup amusé à le faire, et j'ai eu une mise en œuvre décente. Voici quelques détails sur ma mise en œuvre:

Langage : fait en C ++ à l'aide de la bibliothèque OpenCV .

Prétraitement : Pour le prétraitement de l'image, c'est-à-dire transformer l'image en une forme plus brute à donner à l'algorithme, j'ai utilisé 2 méthodes:

  1. Changement du domaine de couleur de RVB à HSV et filtrage basé sur la teinte "rouge", saturation au-dessus d'un certain seuil pour éviter les couleurs orange, et filtrage de faible valeur pour éviter les tons sombres. Le résultat final était une image binaire en noir et blanc, où tous les pixels blancs représenteraient les pixels correspondant à ce seuil. Évidemment, il y a encore beaucoup de merde dans l'image, mais cela réduit le nombre de dimensions avec lesquelles vous devez travailler. Image binarisée
  2. Filtrage du bruit utilisant le filtrage médian (en prenant la valeur médiane des pixels de tous les voisins et en remplaçant le pixel par cette valeur) pour réduire le bruit.
  3. Utilisation du filtre de détection Canny Edge pour obtenir les contours de tous les éléments après 2 étapes précédentes. Détection de contour

Algorithme : L'algorithme lui-même que j'ai choisi pour cette tâche est tiré de ce livre génial sur l'extraction de fonctionnalités et appelé Generalized Hough Transform (assez différent de la Hough Transform régulière). Cela dit essentiellement quelques choses:

  • Vous pouvez décrire un objet dans l'espace sans connaître son équation analytique (ce qui est le cas ici).
  • Il résiste aux déformations de l'image telles que la mise à l'échelle et la rotation, car il testera essentiellement votre image pour chaque combinaison de facteur d'échelle et de facteur de rotation.
  • Il utilise un modèle de base (un modèle) que l'algorithme "apprendra".
  • Chaque pixel restant dans l'image de contour votera pour un autre pixel qui sera censé être le centre (en termes de gravité) de votre objet, en fonction de ce qu'il a appris du modèle.

En fin de compte, vous vous retrouvez avec une carte thermique des votes, par exemple ici, tous les pixels du contour de la boîte voteront pour son centre de gravité, vous aurez donc beaucoup de votes dans le même pixel correspondant à la centre, et verra un pic dans la carte de chaleur comme ci-dessous:

GHT

Une fois que vous avez cela, une simple heuristique basée sur un seuil peut vous donner l'emplacement du pixel central, à partir duquel vous pouvez dériver l'échelle et la rotation, puis tracer votre petit rectangle autour d'elle (l'échelle finale et le facteur de rotation seront évidemment relatifs à votre modèle original). En théorie au moins ...

Résultats : Maintenant, bien que cette approche ait fonctionné dans les cas de base, elle faisait gravement défaut dans certains domaines:

  • C'est extrêmement lent ! Je n'insiste pas assez sur cela. Il a fallu presque une journée entière pour traiter les 30 images de test, évidemment parce que j'avais un facteur d'échelle très élevé pour la rotation et la translation, car certaines des boîtes étaient très petites.
  • Il était complètement perdu lorsque les bouteilles étaient dans l'image, et pour une raison quelconque, il a presque toujours trouvé la bouteille au lieu de la boîte (peut-être parce que les bouteilles étaient plus grandes, avaient donc plus de pixels, donc plus de votes)
  • Les images floues n'étaient également pas bonnes, car les votes se sont retrouvés en pixels à des emplacements aléatoires autour du centre, se terminant ainsi par une carte thermique très bruyante.
  • Un écart dans la translation et la rotation a été obtenu, mais pas dans l'orientation, ce qui signifie qu'une boîte qui n'était pas directement face à l'objectif de la caméra n'a pas été reconnue.

Pouvez-vous m'aider à améliorer mon algorithme spécifique , en utilisant exclusivement des fonctionnalités OpenCV , pour résoudre les quatre problèmes spécifiques mentionnés?

J'espère que certaines personnes en tireront également des leçons, après tout, je pense que non seulement les personnes qui posent des questions devraient apprendre. :)


45
On pourrait dire que cette question est plus appropriée sur dsp.stackexchange.com ou stats.stackexchange.com, et vous devriez certainement envisager de poser de nouveau la question sur ces sites.
ely

49
La première chose à faire ici est d'analyser pourquoi les différents cas de défaillance se produisent. Par exemple, isolez des exemples d'endroits où les bouteilles gagnent, où les images sont floues, etc., et effectuez une analyse statistique pour apprendre la différence entre leurs représentations Hough et celles que vous souhaitez détecter. Quelques bons endroits pour en apprendre davantage sur les approches alternatives sont ici et ici
le

7
@stacker fait un bon point. Pour la vitesse, vous souhaitez obtenir des fonctionnalités bon marché à calculer, comme des histogrammes de dégradés orientés. Une première approche vraiment naïve serait d'étiqueter manuellement un tas de rectangles de boîtes dans certaines images d'apprentissage, et d'utiliser ces exemples négatifs et aléatoires pour former un SVM ou un classificateur d'arbre de décision. La formation prendra plus de temps, mais l'exécution sur de nouvelles images sera beaucoup plus rapide. Je prévois d'écrire cette méthode lorsque j'aurai plus de temps libre pour inclure les bonnes références.
le

9
Que diriez-vous d'une approche similaire à reCAPTCHA ? ;)
George Duckett

39
Pourquoi cela a-t-il été déplacé de dsp.stackexchange.com ? Il semble que ce site serait encore mieux adapté à stackoverflow o_O
BlueRaja - Danny Pflughoeft

Réponses:


672

Une autre approche consisterait à extraire des entités (points-clés) à l'aide de la transformation d' entité invariante à l' échelle (SIFT) ou des entités robustes accélérées (SURF).

Il est implémenté dans OpenCV 2.3.1.

Vous pouvez trouver un bel exemple de code en utilisant les fonctionnalités de Features2D + Homography pour trouver un objet connu

Les deux algorithmes sont invariants à l'échelle et à la rotation. Comme ils fonctionnent avec des fonctionnalités, vous pouvez également gérer l' occlusion (tant que suffisamment de points clés sont visibles).

Entrez la description de l'image ici

Source d'image: exemple de tutoriel

Le traitement prend quelques centaines de ms pour SIFT, SURF est un peu plus rapide, mais il ne convient pas aux applications en temps réel. ORB utilise FAST qui est plus faible en ce qui concerne l'invariance de rotation.

Les papiers originaux


6
Je suis d'accord avec @stacker - SIFT est un excellent choix. Il est très robuste contre les opérations d'échelle et de rotation. Il est quelque peu robuste contre la déformation en perspective (cela peut être amélioré comme suggéré par l'empileur: une base de données de modèles avec différentes vues en perspective de l'objet souhaité). D'après mon expérience, son talon d'Achille serait de fortes variations d'éclairage et un calcul très coûteux. Je ne connais aucune implémentation Java. Je connais une implémentation OpenCV et j'ai utilisé une implémentation GPU c ++ / Windows ( SiftGPU ) adaptée aux performances en temps réel.

31
Une note d'avertissement: autant j'aime SIFT / SURF et ce qu'ils m'ont fait, ils sont encombrés de brevets. Cela pourrait être un problème, selon un certain nombre de conditions, y compris la situation géographique AFAIK.
Agos

12
Essayez donc ORB ou FREAK d'OpenCV qui n'ont aucun problème de brevet. ORB est beaucoup plus rapide que SIFT. ORB c'est un peu pauvre avec des variations d'échelle et de lumière dans mon expérience mais testez vous-même.
Rui Marques

66
Comment pouvez-vous accepter cela comme une réponse ... Aucun des descripteurs de fonctionnalités ne peut différencier les bouteilles des canettes. Je suis d'accord que SIFT, SURF, ORB, FREAK etc. peuvent vous aider dans la mise en correspondance des fonctionnalités mais .. Qu'en est-il de vos autres parties de la question comme les occlusions, la bouteille vs le bidon, etc. J'espère que ce n'est pas une solution complète en fait si vous le souhaitez avoir GOOGLED votre problème probablement le premier résultat serait cette réponse uniquement.
G453

11
@ G453 vous avez absolument raison! Il était probablement fasciné par les performances de SHIFT et a oublié que l'extraction et la mise en correspondance des fonctionnalités n'étaient PAS LE PROBLÈME ...
sepdek

383

Pour accélérer les choses, je profiterais du fait que l'on ne vous demande pas de trouver une image / un objet arbitraire, mais spécifiquement une avec le logo Coca-Cola. Ceci est important car ce logo est très distinctif, et il devrait avoir une signature caractéristique, invariante dans l'échelle dans le domaine fréquentiel, en particulier dans le canal rouge du RVB. C'est-à-dire que le motif alterné de rouge à blanc à rouge rencontré par une ligne de balayage horizontal (formé sur un logo aligné horizontalement) aura un "rythme" distinctif lorsqu'il passera par l'axe central du logo. Ce rythme "s'accélérera" ou "ralentira" à différentes échelles et orientations, mais restera proportionnellement équivalent. Vous pouvez identifier / définir quelques dizaines de telles lignes de balayage, à la fois horizontalement et verticalement à travers le logo et plusieurs autres en diagonale, dans un motif d'étoile. Appelez-les les «lignes de balayage de signature».

Ligne de numérisation de signature

La recherche de cette signature dans l'image cible est une simple question de numérisation de l'image en bandes horizontales. Recherchez une haute fréquence dans le canal rouge (indiquant le passage d'une région rouge à une blanche), et une fois trouvée, voyez si elle est suivie par l'un des rythmes de fréquence identifiés lors de la session de formation. Une fois qu'une correspondance est trouvée, vous saurez instantanément l'orientation et l'emplacement de la ligne de balayage dans le logo (si vous gardez une trace de ces choses pendant l'entraînement), il est donc trivial d'identifier les limites du logo à partir de là.

Je serais surpris si ce n'était pas un algorithme à efficacité linéaire, ou presque. Cela ne résout évidemment pas la discrimination de votre bidon, mais au moins vous aurez vos logos.

(Mise à jour: pour la reconnaissance de la bouteille, je chercherais du coke (le liquide brun) adjacent au logo - c'est-à-dire à l' intérieur de la bouteille. Ou, dans le cas d'une bouteille vide, je chercherais un bouchon qui aura toujours le même forme, taille et distance de base du logo et seront généralement toutes blanches ou rouges. Recherchez une forme elliptique de couleur unie où un capuchon devrait être, par rapport au logo. Pas infaillible bien sûr, mais votre objectif ici devrait être de trouver les faciles les rapide .)

(Cela fait quelques années depuis mes jours de traitement d'images, j'ai donc gardé cette suggestion de haut niveau et conceptuelle. Je pense qu'elle pourrait légèrement se rapprocher du fonctionnement d'un œil humain - ou du moins de la façon dont fonctionne mon cerveau!)


24
C'est une excellente suggestion, j'aime particulièrement le fait que cet algorithme devrait être assez rapide, même s'il aura probablement de nombreux faux négatifs. L'un de mes objectifs cachés est d'utiliser cette détection en temps réel pour la robotique, ce qui pourrait être un bon compromis!
Charles Menguy

42
Oui, on oublie souvent (dans un domaine caractérisé par la précision) que les algorithmes d' approximation sont essentiels pour la plupart des tâches de modélisation en temps réel et dans le monde réel. (J'ai basé ma thèse sur ce concept.) Enregistrez vos algorithmes exigeants en temps pour des régions limitées (pour tailler les faux positifs). Et rappelez-vous: en robotique, vous n'êtes généralement pas limité à une seule image. En supposant un robot mobile, un alg rapide peut rechercher des dizaines d'images sous différents angles en moins de temps que les algs sophistiqués n'en dépensent un, réduisant considérablement les faux négatifs.
kmote

29
J'aime l'idée d'utiliser ce qui équivaut à un lecteur de codes-barres pour une détection extrêmement rapide des logos Coca-Cola. +1!
Li-aung Yip

8
Le problème de la recherche de signatures dans ce cas est que si nous tournons la boîte de l'autre côté, c'est-à-dire en masquant la signature, l'algorithme ne parviendra pas à détecter la boîte.
karlphillip

34
@karlphillip: Si vous cachez la signature, c'est-à-dire le logo, alors toute méthode basée sur la recherche du logo va échouer.
Li-aung Yip

162

Problème amusant: quand j'ai regardé l'image de votre bouteille, j'ai pensé que c'était aussi une canette. Mais, en tant qu'humain, ce que j'ai fait pour faire la différence, c'est que j'ai alors remarqué que c'était aussi une bouteille ...

Alors, pour distinguer les canettes et les bouteilles, pourquoi ne pas simplement rechercher les bouteilles en premier? Si vous en trouvez un, masquez l'étiquette avant de chercher des canettes.

Pas trop difficile à mettre en œuvre si vous faites déjà des canettes. Le véritable inconvénient est qu'il double votre temps de traitement. (Mais en pensant aux applications du monde réel, vous allez finir par vouloir faire des bouteilles de toute façon ;-)


5
Oui, j'y ai pensé aussi, mais je n'ai pas eu beaucoup de temps pour le faire. Comment reconnaîtriez-vous une bouteille, car sa partie principale ressemblera à une boîte à l'échelle? Je pensais aussi à la recherche du bouchon rouge et voir s'il était aligné avec le centre en bouteille, mais cela ne semble pas très robuste.
Charles Menguy

42
S'il y a un capuchon (ou anneau) rouge parallèle au "Coca cola", c'est très probablement une bouteille.
Lukasz Madon

@linker Comment avez-vous formé votre algorithme pour les canettes? Avez-vous eu des exemples de canettes? Que diriez-vous de la formation avec des exemples de bouteilles?
siamii

1
La force de cet algorithme est que vous n'avez besoin que d' un seul modèle pour vous entraîner, puis il applique toutes les transformations pour le faire correspondre à d'autres boîtes potentielles. J'utilisais une version binarisée et basée sur les contours de ce modèle pour m'entraîner, donc la seule différence entre la canette et la bouteille serait le bouchon, mais je crains que cela n'apporte plus de faux positifs car le centre de gravité serait quelque part sur le bord ou à l'extérieur de la bouteille. Cela vaut la peine d'essayer, je suppose. Mais cela doublera mon temps de traitement et je vais pleurer;)
Charles Menguy

7
Il s'agit essentiellement d'une direction raisonnable. Je dirais que c'est un peu différent: trouvez d'abord tous les candidats, puis pour chaque candidat, déterminez s'il s'agit d'une bouteille, d'une canette ou autre chose.
MSalters

131

N'est-il pas difficile, même pour les humains, de faire la distinction entre une bouteille et une canette dans la deuxième image (à condition que la zone transparente de la bouteille soit cachée)?

Ils sont presque les mêmes, sauf pour une très petite région (c'est-à-dire que la largeur en haut de la boîte est un peu petite tandis que l'emballage de la bouteille est de la même largeur partout, mais un changement mineur n'est-ce pas?)

La première chose qui m'est venue à l'esprit était de vérifier le haut rouge de la bouteille. Mais c'est toujours un problème, s'il n'y a pas de couvercle pour la bouteille, ou si elle est partiellement cachée (comme mentionné ci-dessus).

La deuxième chose que je pensais concernait la transparence de la bouteille. OpenCV a quelques travaux sur la recherche d'objets transparents dans une image. Consultez les liens ci-dessous.

Regardez particulièrement ceci pour voir avec quelle précision ils détectent le verre:

Voir leur résultat de mise en œuvre:

Entrez la description de l'image ici

Ils disent que c'est la mise en œuvre du document "Un cadre de contour actif géodésique pour trouver du verre" par K. McHenry et J. Ponce, CVPR 2006 .

Cela pourrait être utile dans votre cas un peu, mais le problème se pose à nouveau si la bouteille est remplie.

Je pense donc ici, vous pouvez rechercher le corps transparent des bouteilles en premier ou une zone rouge connectée latéralement à deux objets transparents qui est évidemment la bouteille. (Lorsque vous travaillez idéalement, une image comme suit.)

Entrez la description de l'image ici

Vous pouvez maintenant supprimer la zone jaune, c'est-à-dire l'étiquette de la bouteille et exécuter votre algorithme pour trouver la boîte.

Quoi qu'il en soit, cette solution a également des problèmes différents comme dans les autres solutions.

  1. Cela ne fonctionne que si votre bouteille est vide. Dans ce cas, vous devrez rechercher la zone rouge entre les deux couleurs noires (si le liquide Coca Cola est noir).
  2. Un autre problème si la partie transparente est couverte.

Mais de toute façon, s'il n'y a aucun des problèmes ci-dessus dans les images, cela semble être une meilleure façon.


+1 J'y ai pensé et j'étais en train de mettre en œuvre cette approche. Cependant, @linker devrait partager son ensemble d'images afin que nous puissions essayer de faire des suppositions plus instruites.
karlphillip

ouais .. je pense aussi que c'était bien s'il y avait plus d'images.
Abid Rahman K

Considérant que nous n'avons que les étiquettes des bouteilles / canettes et aucun des autres facteurs distinctifs du bouchon de la bouteille ou de la transparence ou de la boîte supérieure / inférieure - La largeur de la bouteille est différente de la largeur de la boîte.
Ken

Que faire si une boîte est placée devant le logo de la bouteille?
AlgoRythm

51

J'aime vraiment les réponses de Darren Cook et du stacker à ce problème. J'étais en train de jeter mes pensées dans un commentaire à ce sujet, mais je pense que mon approche est trop en forme de réponse pour ne pas partir d'ici.

En bref, vous avez identifié un algorithme pour déterminer qu'un logo Coca-Cola est présent à un emplacement particulier dans l'espace. Vous essayez maintenant de déterminer, pour des orientations arbitraires et des facteurs d'échelle arbitraires, une heuristique appropriée pour distinguer les canettes Coca-Cola des autres objets, y compris: les bouteilles , les panneaux d'affichage , les publicités et l' attirail Coca-Cola tous associés à ce logo emblématique. Vous n'avez pas mentionné un grand nombre de ces cas supplémentaires dans votre énoncé de problème, mais je pense qu'ils sont essentiels au succès de votre algorithme.

Le secret ici est de déterminer quelles caractéristiques visuelles une boîte contient ou, à travers l'espace négatif, quelles caractéristiques sont présentes pour les autres produits Coke qui ne sont pas présents pour les boîtes. À cette fin, la première réponse actuelle esquisse une approche de base pour sélectionner "peut" si et seulement si "bouteille" n'est pas identifié, soit par la présence d'un bouchon de bouteille, d'un liquide ou d'autres heuristiques visuelles similaires.

Le problème est que cela tombe en panne. Une bouteille peut, par exemple, être vide et ne pas avoir de bouchon, ce qui conduit à un faux positif. Ou, il pourrait s'agir d' une bouteille partielle avec des fonctionnalités supplémentaires mutilées, conduisant à nouveau à une fausse détection. Inutile de dire que ce n'est pas élégant, ni efficace pour nos besoins.

À cette fin, les critères de sélection les plus corrects pour les boîtes semblent être les suivants:

  • La forme de la silhouette de l'objet, comme vous l'avez esquissé dans votre question , est-elle correcte? Si oui, +1.
  • Si nous supposons la présence de lumière naturelle ou artificielle, détectons-nous un contour chromé de la bouteille qui signifie s'il s'agit d'aluminium? Si oui, +1.
  • Déterminons-nous que les propriétés spéculaires de l'objet sont correctes, par rapport à nos sources lumineuses ( lien vidéo illustratif sur la détection des sources lumineuses )? Si oui, +1.
  • Pouvons-nous déterminer d'autres propriétés de l'objet qui l'identifient comme une boîte, y compris, mais sans s'y limiter, le biais d'image topologique du logo, l'orientation de l'objet, la juxtaposition de l'objet (par exemple, sur une surface plane comme une table ou dans le cadre d'autres canettes), et la présence d'une tirette? Si oui, pour chacun, +1.

Votre classification pourrait alors ressembler à ceci:

  • Pour chaque match candidat, si la présence d'un logo Coca Cola a été détectée, tracez une bordure grise.
  • Pour chaque match supérieur à +2, tracez une bordure rouge.

Cela met en évidence visuellement à l'utilisateur ce qui a été détecté, en soulignant les points faibles faibles qui peuvent, correctement, être détectés comme des canettes mutilées.

La détection de chaque propriété comporte une complexité temporelle et spatiale très différente, et pour chaque approche, un passage rapide sur http://dsp.stackexchange.com est plus que raisonnable pour déterminer l'algorithme le plus correct et le plus efficace pour vos besoins. Mon intention ici est, purement et simplement, de souligner que détecter si quelque chose est possible en invalidant une petite partie de l'espace de détection candidat n'est pas la solution la plus robuste ou efficace à ce problème, et idéalement, vous devriez prendre les mesures appropriées en conséquence.

Et salut, félicitations pour la publication de Hacker News! Dans l'ensemble, c'est une question assez formidable, digne de la publicité qu'elle a reçue. :)


2
C'est une approche intéressante qui vaut au moins la peine d'être essayée, j'aime beaucoup votre raisonnement sur le problème
Charles Menguy

C'est une sorte de ce que je pensais: n'excluez pas des types particuliers de faux positifs. Règle plus de fonctionnalités de ce qui fait une canette de coke. Mais je me demande: que faites-vous d'une boîte de conserve écrasée? Je veux dire, si vous marchez sur une canette de coke, c'est toujours une canette de coke. Mais il n'aura plus la même forme. Ou est-ce que ce problème est AI-Complete?
Ian

41

En regardant la forme

Jetez un œil à la forme de la partie rouge de la boîte / bouteille. Remarquez comment la boîte se rétrécit légèrement tout en haut tandis que l'étiquette de la bouteille est droite. Vous pouvez distinguer ces deux en comparant la largeur de la partie rouge sur toute sa longueur.

Regarder les faits saillants

Une façon de distinguer les bouteilles et les canettes est le matériau. Une bouteille est en plastique tandis qu'une canette est en aluminium. Dans des situations suffisamment éclairées, l'examen de la spécularité serait une façon de distinguer une étiquette de bouteille d'une étiquette de boîte.

Pour autant que je sache, c'est ainsi qu'un humain ferait la différence entre les deux types d'étiquettes. Si les conditions d'éclairage sont médiocres, il y aura forcément une certaine incertitude dans la distinction des deux. Dans ce cas, vous devez être en mesure de détecter la présence de la bouteille transparente / translucide elle-même.


J'aime l'idée, mais il semble que vous ayez besoin de très bonnes conditions d'éclairage. Dans l'exemple d'image où il y a à la fois une canette et une bouteille par exemple, cela semble un peu difficile à faire la distinction.
Charles Menguy

Dans votre exemple, remarquez comment la spécularité de l'étiquette en plastique est beaucoup plus diffuse que les taches très lumineuses sur la boîte? Voilà comment vous pouvez le dire.
tskuzzy

Je vois, quel type de représentation de l'espace colorimétrique utiliseriez-vous dans ce cas pour capturer la spécularité dans votre algorithme? Cela semble assez difficile à obtenir en RVB ou en HSV
Charles Menguy

3
Et si la source lumineuse était derrière la boîte? Je pense que vous ne verriez pas le point culminant.
Rui Marques

37

Veuillez jeter un œil au traqueur Predator de Zdenek Kalal . Il nécessite une certaine formation, mais il peut apprendre activement comment l'objet suivi regarde différentes orientations et échelles et le fait en temps réel!

Le code source est disponible sur son site. C'est dans MATLAB , mais il y a peut-être une implémentation Java déjà effectuée par un membre de la communauté. J'ai réussi à réimplémenter la partie tracker du TLD en C #. Si je me souviens bien, TLD utilise des fougères comme détecteur de points clés. J'utilise à la place SURF ou SIFT (déjà suggéré par @stacker) pour réacquérir l'objet s'il a été perdu par le tracker. Le retour du tracker permet de construire facilement avec le temps une liste dynamique de modèles de sift / surf qui permettent avec le temps de réacquérir l'objet avec une très grande précision.

Si vous êtes intéressé par mon implémentation C # du tracker, n'hésitez pas à demander.


Merci pour le lien qui semble intéressant. En ce qui concerne la formation, quelle est la taille de l'ensemble de formation qui serait raisonnable pour obtenir des résultats raisonnables? Si vous avez une implémentation même en c # ce serait très utile aussi!
Charles Menguy

En recherchant le TLD, j'ai trouvé un autre utilisateur à la recherche d'une implémentation C # --- y a-t-il une raison pour ne pas mettre votre travail sur Github? stackoverflow.com/questions/29436719/…
spillner

2
NB Années, plus tard, le lien est maintenant mort
J Evans

33

Si vous n'êtes pas limité à un appareil photo qui ne faisait pas partie de vos contraintes, vous pouvez peut-être utiliser un capteur de portée comme la Xbox Kinect . Avec cela, vous pouvez effectuer une segmentation assortie basée sur la profondeur et la couleur de l'image. Cela permet une séparation plus rapide des objets dans l'image. Vous pouvez ensuite utiliser la correspondance ICP ou des techniques similaires pour même faire correspondre la forme de la boîte plutôt que juste son contour ou sa couleur et étant donné qu'elle est cylindrique, cela peut être une option valide pour n'importe quelle orientation si vous avez un scan 3D précédent de la cible. Ces techniques sont souvent assez rapides, en particulier lorsqu'elles sont utilisées dans un but précis, ce qui devrait résoudre votre problème de vitesse.

Je pourrais également suggérer, pas nécessairement pour la précision ou la vitesse, mais pour le plaisir, vous pouvez utiliser un réseau neuronal formé sur votre image segmentée de teinte pour identifier la forme de la boîte. Celles-ci sont très rapides et peuvent souvent être précises à 80/90%. La formation serait un peu longue, car vous devrez identifier manuellement la boîte dans chaque image.


3
En fait, je n'ai pas expliqué cela dans le message, mais pour cette mission, on m'a donné un ensemble d'environ 30 images et j'ai dû faire un algorithme qui les correspondrait toutes dans diverses situations, comme décrit. Bien sûr, certaines images ont finalement été testées pour tester l'algorithme. Mais j'aime l'idée des capteurs Kinect, et j'aimerais en savoir plus sur le sujet!
Charles Menguy

Quelle serait approximativement la taille de l'ensemble d'entraînement avec un réseau neuronal pour avoir des résultats satisfaisants? Ce qui est bien avec cette méthode, c'est aussi que je n'ai besoin que d'un modèle pour correspondre à presque tout.
Charles Menguy

2
Si votre ensemble d'images est prédéfini et limité, juste des résultats parfaits et parfaits dans votre prog;)
sne11ius

Oui, si je m'entraîne sur l'ensemble de données contre lequel je vais exécuter l'algorithme, bien sûr, j'obtiendrai des résultats parfaits :) Mais par exemple pour cette tâche, le programme a été testé par l'enseignant à la fin sur un ensemble d'images tenues . Je voudrais faire quelque chose qui serait robuste et pas trop adapté aux données d'entraînement.
Charles Menguy

Le nombre d'ensembles d'entraînement varie, vous devez cependant faire attention à certaines choses: ne vous entraînez pas trop, vous voulez probablement un ensemble de test pour montrer comment votre précision se passe. Le nombre d'ensembles d'entraînement dépendra également du nombre de couches que vous utiliserez.
Fantastique Mr Fox

24

Je détecterais des rectangles rouges: RVB -> HSV, filtre rouge -> image binaire, fermer (dilater puis éroder, dit imclosematlab)

Regardez ensuite à travers les rectangles du plus grand au plus petit. Les rectangles qui ont des rectangles plus petits dans une position / échelle connue peuvent tous les deux être supprimés (en supposant que les proportions des bouteilles sont constantes, le plus petit rectangle serait un bouchon de bouteille).

Cela vous laisserait des rectangles rouges, alors vous devrez en quelque sorte détecter les logos pour savoir s'il s'agit d'un rectangle rouge ou d'une canette de coca. Comme l'OCR, mais avec un logo connu?


2
Comme cela a été discuté sur DSP dans le court laps de temps où il a été déplacé, certaines bouteilles peuvent ne pas avoir de bouchons;) ou le bouchon pourrait être partiellement caché.
Charles Menguy

22

Cela peut être une idée très naïve (ou peut ne pas fonctionner du tout), mais les dimensions de toutes les canettes de coke sont fixes. Il se peut que si la même image contient à la fois une canette et une bouteille, vous pouvez les distinguer par des considérations de taille (les bouteilles vont être plus grandes). Maintenant, en raison de la profondeur manquante (c'est-à-dire de la cartographie 3D à la cartographie 2D), il est possible qu'une bouteille semble rétrécie et qu'il n'y ait pas de différence de taille. Vous pouvez récupérer des informations détaillées à l'aide de la stéréo-imagerie , puis récupérer la taille d'origine.


3
En fait non: il n'y a pas de contrainte de taille ou d'orientation (ou d'orientation mais je n'ai pas vraiment géré ça), donc vous pouvez avoir une bouteille très loin en arrière-plan, et une boîte au premier plan, et la boîte serait bien plus grande que la bouteille.
Charles Menguy

J'ai également vérifié que le rapport largeur / hauteur est assez similaire pour la bouteille et le bidon, ce n'est donc pas vraiment une option également.
Charles Menguy

Le rapport d'étiquette (étant une marque déposée) est le même. Donc, si la (plus grande) bouteille est légèrement plus éloignée sur l'image, sa taille sera exactement la même que celle de la boîte.
littleadv

3
Pour expliquer un peu plus. Supposons que la canette soit à z = 0 et la bouteille à z = -100. Comme la bouteille est loin derrière, elle paraîtra plus petite. Mais si je sais que la bouteille est à z = -100 et peut à z = 0, alors je peux calculer la taille attendue de la boîte / bouteille si les deux sont traduites en z = 0. Alors maintenant, ils sont à la même profondeur et je peux donc prendre des décisions en fonction de la taille.
Sharad

2
Ce n'est qu'un commentaire, pas une réponse, mais il est beaucoup plus proche d'être une réponse que le commentaire en tant que réponse ci-dessus avec 120 votes.
Fattie

22

Hmm, je pense en fait que je suis sur quelque chose (c'est comme la question la plus intéressante jamais - donc ce serait dommage de ne pas continuer à essayer de trouver la réponse "parfaite", même si une réponse acceptable a été trouvée) .. .

Une fois que vous avez trouvé le logo, vos ennuis sont à moitié terminés. Ensuite, il vous suffit de comprendre les différences entre ce qui est autour du logo. De plus, nous voulons faire le moins possible. Je pense que c'est en fait cette partie facile ...

Qu'y a - t -il autour du logo? Pour une canette, on peut voir du métal qui, malgré les effets de l'éclairage, ne change absolument pas dans sa couleur de base. Tant que nous connaissons l'angle de l'étiquette, nous pouvons dire ce qui est directement au-dessus, nous examinons donc la différence entre ceux-ci:

Ici, ce qui est au-dessus et en dessous du logo est complètement sombre, de couleur uniforme. Relativement facile à cet égard.

Ici, ce qui est au-dessus et en dessous est clair, mais toujours de couleur uniforme. C'est tout argent, et le métal tout argent semble en fait assez rare, ainsi que les couleurs argentées en général. De plus, il se trouve dans une mince glissière et suffisamment proche du rouge qui a déjà été identifié pour que vous puissiez suivre sa forme sur toute sa longueur pour calculer un pourcentage de ce qui peut être considéré comme l'anneau métallique de la boîte. Vraiment, vous n'avez besoin que d'une petite fraction de cela n'importe où le long de la boîte pour dire qu'elle en fait partie, mais vous devez toujours trouver un équilibre qui garantit qu'il ne s'agit pas seulement d'une bouteille vide avec quelque chose de métal derrière.

Et enfin, le plus délicat. Mais ce n'est pas si difficile, une fois que nous allons uniquement par ce que nous pouvons voir directement au-dessus (et en dessous) de l'emballage rouge. Son transparent, ce qui signifie qu'il montrera tout ce qui se trouve derrière. C'est bien, car les choses qui se trouvent derrière ne sont probablement pas aussi homogènes en couleur que le métal circulaire argenté de la boîte. Il pourrait y avoir beaucoup de choses différentes derrière cela, qui nous diraient que c'est une bouteille vide (ou remplie de liquide clair), ou une couleur uniforme, ce qui pourrait signifier qu'elle est remplie de liquide ou que la bouteille est simplement devant un couleur unie. Nous travaillons avec ce qui se rapproche le plus du haut et du bas, et les chances que les bonnes couleurs soient au bon endroit sont relativement minces. Nous savons que c'est une bouteille, car elle n'a pas cet élément visuel clé de la boîte,

(ce dernier était le meilleur que j'ai pu trouver d'une grande bouteille de coca cola vide - il est intéressant de noter que le bouchon ET l'anneau sont jaunes, indiquant que la rougeur du bouchon ne devrait probablement pas être invoquée)

Dans les rares cas où une nuance d'argent similaire se trouve derrière la bouteille, même après l'abstraction du plastique, ou si la bouteille est remplie d'une manière ou d'une autre de la même teinte de liquide argenté, nous pouvons nous rabattre sur ce que nous pouvons approximativement estimer être le la forme de l'argent - qui, comme je l'ai mentionné, est circulaire et épouse la forme de la boîte. Mais même si je n'ai aucune connaissance certaine du traitement d'image, cela semble lent. Mieux encore, pourquoi ne pas en déduire en vérifiant une fois les côtés du logo pour vous assurer qu'il n'y a rien de la même couleur argentée? Ah, mais que se passe-t-il s'il y a la même nuance d'argent derrière une boîte? Ensuite, nous devons en effet prêter plus d'attention aux formes, en regardant à nouveau le haut et le bas de la boîte.

Selon la façon dont tout cela doit être parfait, cela pourrait être très lent, mais je suppose que mon concept de base est de vérifier d'abord les choses les plus faciles et les plus proches. Passez par les différences de couleur autour de la forme déjà assortie (ce qui semble de toute façon la partie la plus triviale) avant de faire l'effort de déterminer la forme des autres éléments. Pour l'énumérer, il va:

  • Trouvez l'attraction principale (fond de logo rouge, et éventuellement le logo lui-même pour l'orientation, bien que dans le cas où la boîte est détournée, vous devez vous concentrer uniquement sur le rouge)
  • Vérifiez la forme et l'orientation, encore une fois via la rougeur très distinctive
  • Vérifiez les couleurs autour de la forme (car elles sont rapides et indolores)
  • Enfin, si nécessaire, vérifiez la forme de ces couleurs autour de l'attraction principale pour la bonne rondeur.

Dans le cas où vous ne pouvez pas faire cela, cela signifie probablement que le haut et le bas de la boîte sont couverts, et la seule chose possible qu'un humain aurait pu utiliser pour faire une distinction fiable entre la boîte et la bouteille est l'occlusion et la réflexion de la boîte, ce qui serait une bataille beaucoup plus difficile à traiter. Cependant, pour aller encore plus loin, vous pouvez suivre l'angle de la boîte / bouteille pour vérifier plus de traits ressemblant à des bouteilles, en utilisant les techniques de numérisation semi-transparentes mentionnées dans les autres réponses.

Des cauchemars supplémentaires intéressants pourraient inclure une boîte commodément assise derrière la bouteille à une distance telle que le métal se trouve juste au-dessus et en dessous de l'étiquette, ce qui échouerait toujours tant que vous balayez sur toute la longueur du rouge étiquette - ce qui est en fait plus problématique parce que vous ne détectez pas une boîte où vous pourriez avoir, au lieu de considérer que vous détectez réellement une bouteille, y compris la boîte par accident. Le verre est à moitié vide, dans ce cas!


En tant que clause de non-responsabilité, je n'ai aucune expérience et n'ai jamais pensé au traitement d'image en dehors de cette question, mais c'est tellement intéressant que cela m'a fait réfléchir assez profondément, et après avoir lu toutes les autres réponses, je considère que cela peut être le moyen le plus simple et le plus efficace de le faire. Personnellement, je suis juste content que je ne fait avoir à penser à la programmation de cela!

ÉDITER

mauvais dessin d'une boîte de peinture MS De plus, regardez ce dessin que j'ai fait dans MS Paint ... Il est absolument horrible et assez incomplet, mais en vous basant uniquement sur la forme et les couleurs, vous pouvez deviner ce que ce sera probablement. En substance, ce sont les seules choses pour lesquelles on a besoin de s'embêter à numériser. Lorsque vous regardez cette forme très distincte et cette combinaison de couleurs si proches, que pourrait-il être d'autre? Le bit que je n'ai pas peint, le fond blanc, doit être considéré comme "quelque chose d'incohérent". S'il avait un fond transparent, il pourrait passer sur presque n'importe quelle autre image et vous pouvez toujours le voir.


10
La nuance particulière du rouge est principalement subjective et fortement influencée par les considérations d'éclairage et la balance des blancs. Vous pourriez être surpris de voir à quel point ceux-ci peuvent changer. Considérez, par exemple, cette illusion en damier .
Octopus du

2
Une mise à jour du lien publié par @Octopus
Hat

Une illusion de perception n'affecte pas ce que voit votre webcam - c'est-à-dire ce que votre code obtient - seulement comment un œil humain trompe utilement (?) Le cerveau.
barny

17

Je ne suis pas au courant d'OpenCV mais en regardant le problème logiquement, je pense que vous pourriez faire la différence entre la bouteille et le pouvez en changeant l'image que vous recherchez, c'est-à-dire Coca Cola. Vous devez incorporer jusqu'à la partie supérieure de la boîte, car dans le cas de la boîte, il y a une doublure argentée au-dessus du coca-cola et dans le cas d'une bouteille, il n'y aura pas une telle doublure argentée.

Mais évidemment, cet algorithme échouera dans les cas où le haut de la boîte est caché, mais dans ce cas, même l'homme ne pourra pas faire la différence entre les deux (si seule la portion coca cola de la bouteille / boîte est visible)


1
J'ai eu la même pensée, mais je pense que la doublure argentée sur le dessus de la boîte change considérablement en fonction de l'angle de la boîte sur la photo. Il peut s'agir d'une ligne droite ou d'un cercle. Peut-être pourrait-il utiliser les deux comme référence?
Alexis Dufrenoy

15

J'aime le défi et je voulais donner une réponse qui résout le problème, je pense.

  1. Extraire les fonctionnalités (points clés, descripteurs tels que SIFT, SURF) du logo
  2. Faites correspondre les points avec une image modèle du logo (en utilisant Matcher tel que Brute Force)
  3. Estimer les coordonnées du corps rigide (problème PnP - SolvePnP)
  4. Estimer la position du capuchon en fonction du corps rigide
  5. Faites une rétroprojection et calculez la position du pixel de l'image (ROI) du bouchon de la bouteille (je suppose que vous avez les paramètres intrinsèques de la caméra)
  6. Vérifiez avec une méthode si le bouchon est là ou non. S'il y a, alors c'est la bouteille

La détection du capuchon est un autre problème. Cela peut être compliqué ou simple. Si j'étais vous, je vérifierais simplement l'histogramme des couleurs dans le ROI pour une décision simple.

S'il vous plaît, donnez votre avis si je me trompe. Merci.


13

J'ai quelques années de retard pour répondre à cette question. Avec l'état de l'art poussé à ses limites par les CNN au cours des 5 dernières années, je n'utiliserais pas OpenCV pour faire cette tâche maintenant! ( Je sais que vous vouliez spécifiquement des fonctionnalités OpenCv dans la question ) Je pense que des algorithmes de détection d'objet tels que Faster-RCNN, YOLO, SSD, etc. pourraient résoudre ce problème avec une marge importante par rapport aux fonctionnalités OpenCV. Si je devais résoudre ce problème maintenant (après 6 ans !!), j'utiliserais certainement Faster-RCNN .


5
OP a déclaré qu'il y avait 30 images haute résolution, ce qui n'est probablement pas le meilleur scénario pour la formation des ConvNets. Non seulement ils sont trop peu nombreux (même augmentés), mais la partie haute résolution détruirait les ConvNets.
Kostas Mouratidis

11

J'aime votre question, qu'elle soit hors sujet ou non: P

Un côté intéressant; Je viens de terminer un sujet dans mon diplôme où nous avons couvert la robotique et la vision par ordinateur. Notre projet pour le semestre était incroyablement similaire à celui que vous décrivez.

Nous avons dû développer un robot qui utilisait une Xbox Kinect pour détecter les bouteilles et les canettes de coke dans n'importe quelle orientation dans diverses conditions d'éclairage et d'environnement. Notre solution consistait à utiliser un filtre passe-bande sur le canal de Hue en combinaison avec la transformation de cercle de Hough. Nous avons pu un peu contraindre l'environnement (nous avons pu choisir où et comment positionner le robot et le capteur Kinect), sinon nous allions utiliser les transformations SIFT ou SURF.

Vous pouvez lire notre approche sur mon blog sur le sujet :)


2
Projet intéressant mais il ne s'applique qu'à votre configuration très spécifique.
Rui Marques

11

L'apprentissage en profondeur

Rassemblez au moins quelques centaines d'images contenant des canettes de cola, annotez la boîte englobante qui les entoure en tant que classes positives, incluez des bouteilles de cola et d'autres produits de cola les étiquetez classes négatives ainsi que des objets aléatoires.

Sauf si vous collectez un très grand ensemble de données, effectuez l'astuce de l'utilisation des fonctionnalités d'apprentissage en profondeur pour un petit ensemble de données. Idéalement, en utilisant une combinaison de machines à vecteurs de support (SVM) avec des réseaux neuronaux profonds.

Une fois que vous avez alimenté les images dans un modèle d'apprentissage approfondi préalablement formé (par exemple, GoogleNet), au lieu d'utiliser la couche de décision (finale) du réseau neuronal pour effectuer des classifications, utilisez les données des couches précédentes comme fonctionnalités pour former votre classificateur.

OpenCV et Google Net: http://docs.opencv.org/trunk/d5/de7/tutorial_dnn_googlenet.html

OpenCV et SVM: http://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html


10

Il existe un tas de descripteurs de couleurs utilisés pour reconnaître les objets, le papier ci-dessous en compare beaucoup. Ils sont particulièrement puissants lorsqu'ils sont combinés avec SIFT ou SURF. SURF ou SIFT seuls ne sont pas très utiles dans une image de coca cola car ils ne reconnaissent pas beaucoup de points d'intérêt, vous avez besoin des informations de couleur pour vous aider. J'utilise BIC (Border / Interior Pixel Classi fi cation) avec SURF dans un projet et cela a très bien fonctionné pour reconnaître des objets.

Descripteurs de couleurs pour la récupération d'images Web: une étude comparative


9

Vous avez besoin d'un programme qui apprend et améliore la précision de la classification de manière organique à partir de l'expérience.

Je vais suggérer un apprentissage en profondeur, avec l'apprentissage en profondeur, cela devient un problème trivial.

Vous pouvez recycler le modèle de création v3 sur Tensorflow:

Comment recycler la couche finale d'Inception pour de nouvelles catégories .

Dans ce cas, vous allez former un réseau neuronal convolutif pour classer un objet comme un coca-cola peut ou non.


2
Hot dog ou pas hot dog?
YellowPillow

6

Comme alternative à toutes ces belles solutions, vous pouvez former votre propre classificateur et rendre votre application robuste aux erreurs. Par exemple, vous pouvez utiliser Haar Training , fournissant un bon nombre d'images positives et négatives de votre cible.

Il peut être utile d'extraire uniquement des boîtes et peut être combiné avec la détection d'objets transparents.


3

Il existe un package de vision par ordinateur appelé HALCON de MVTec dont les démos pourraient vous donner de bonnes idées d'algorithmes. Il existe de nombreux exemples similaires à votre problème que vous pouvez exécuter en mode démo, puis regarder les opérateurs dans le code et voir comment les implémenter à partir des opérateurs OpenCV existants.

J'ai utilisé ce package pour prototyper rapidement des algorithmes complexes pour des problèmes comme celui-ci, puis trouver comment les implémenter en utilisant les fonctionnalités OpenCV existantes. En particulier pour votre cas, vous pouvez essayer d'implémenter dans OpenCV la fonctionnalité intégrée à l'opérateur find_scaled_shape_model . Certains opérateurs pointent le document scientifique concernant l'implémentation d'algorithmes qui peut aider à découvrir comment faire quelque chose de similaire dans OpenCV. J'espère que cela t'aides...


0

Si vous êtes intéressé à ce que ce soit en temps réel, alors ce dont vous avez besoin est d'ajouter un filtre de prétraitement pour déterminer ce qui est numérisé avec les éléments lourds. Un bon filtre de pré-traitement rapide et très en temps réel qui vous permettra de numériser des choses qui sont plus susceptibles d'être une canette de coca-cola qu'avant de passer à des choses plus douteuses est quelque chose comme ceci: recherchez dans l'image les plus gros correctifs de couleur qui sont une certaine tolérance loin de la sqrt(pow(red,2) + pow(blue,2) + pow(green,2))boîte de coca-cola. Commencez avec une tolérance de couleur très stricte et descendez vers des tolérances de couleur plus clémentes. Ensuite, lorsque votre robot manque de temps pour traiter le cadre actuel, il utilise les bouteilles actuellement trouvées pour vos besoins. Veuillez noter que vous devrez modifier les couleurs RVB dans le sqrt(pow(red,2) + pow(blue,2) + pow(green,2))pour les obtenir juste.

En outre, cela semble vraiment stupide, mais vous êtes-vous assuré d'activer les -oFastoptimisations du compilateur lorsque vous avez compilé votre code C?


0

Peut-être trop d'années de retard, mais néanmoins une théorie à essayer.

Le rapport du rectangle de délimitation de la région du logo rouge à la dimension globale de la bouteille / boîte est différent. Dans le cas de Can, devrait être de 1: 1, alors qu'il sera différent dans celui de la bouteille (avec ou sans bouchon). Cela devrait faciliter la distinction entre les deux.

Mise à jour: La courbure horizontale de la région du logo sera différente entre la boîte et la bouteille en raison de leur différence de taille respective. Cela pourrait être particulièrement utile si votre robot doit ramasser une canette / bouteille et que vous décidez de la poignée en conséquence.


-1

Les premières choses que je rechercherais sont les couleurs - comme le ROUGE, lors de la détection des yeux rouges dans une image - il y a une certaine gamme de couleurs à détecter, certaines caractéristiques à ce sujet compte tenu de la zone environnante et telles que la distance par rapport à l'autre œil s'il est en effet visible dans l'image.

1: La première caractéristique est la couleur et le rouge est très dominant. Après avoir détecté le Coca Cola Red, il y a plusieurs éléments d'intérêt 1A: Quelle est la taille de cette zone rouge (est-elle en quantité suffisante pour déterminer une vraie boîte ou non - 10 pixels ne sont probablement pas suffisants), 1B: Contient-elle la couleur de l'étiquette - "Coca-Cola" ou vague. 1B1: Y a-t-il assez pour considérer une forte probabilité qu'il s'agisse d'une étiquette.

L'article 1 est une sorte de raccourci - prétraitez si cette morve de biche existe dans l'image - passez à autre chose.

Donc, si c'est le cas, je peux alors utiliser ce segment de mon image et commencer à regarder un peu plus de zoom sur la zone en question - regardez essentiellement la région / les bords environnants ...

2: Étant donné la zone d'image ci-dessus identifiée en 1 - vérifiez les points environnants [bords] de l'élément en question. R: Y a-t-il ce qui semble être un haut ou un bas de boîte - argent? B: Une bouteille peut sembler transparente, mais il en va de même pour une table en verre - il y a donc une table / étagère en verre ou une zone transparente - si c'est le cas, il en existe plusieurs. Une bouteille PEUT avoir un capuchon rouge, il se peut que ce ne soit pas le cas, mais elle devrait avoir la forme du bouchon de la bouteille / des vis filetées ou un capuchon. C: Même si cela échoue A et B, il peut toujours être un bidon - partiel .. C'est plus complexe quand il est partiel car un flacon / bidon partiel peut avoir la même apparence, donc un traitement supplémentaire de la mesure du bord de la région rouge à bord .. petite bouteille pourrait être de taille similaire ..

3: Après l'analyse ci-dessus, c'est à ce moment-là que je regarderais le lettrage et le logo de la vague - car je peux orienter ma recherche de certaines lettres dans les mots Comme vous pourriez ne pas avoir tout le texte en raison de ne pas avoir tous les peut, l'onde s'alignerait à certains points sur le texte (en termes de distance) afin que je puisse rechercher cette probabilité et savoir quelles lettres devraient exister à ce point de l'onde à la distance x.


-9

C'est un vieux projet sur lequel j'ai travaillé. Les images MAP sont très faciles à utiliser avec javascript. Je vous propose l'objet, vous le lisez et savez l'utiliser. Nous n'avons pas besoin de JQuery et d'autres systèmes pour utiliser des images MAP.

    //Copyright Cherif yahiaoui, by ELEBAN.FR

//variables de flottement.
var myInstOne = null;
var globalize = null;

var eleban_preload_images = function (name, imgs, url){
try{
    var oThis = this;
    this.images = new Array();
    this.imageshover = new Array();
    this.imagesNames = new Array(imgs.split(";"));


        for(var i=0; i < this.imagesNames[0].length; i++){
            this.images[i] = new Image();
            this.imageshover[i] = new Image();
        }

    this.url = url;

    this.GetAbsoluteurl = function () {

    var img = new Image(); img.src = url;
    url = img.src; img = null; 
        this.url = url; 

    };

    this.Preload = function () {

        for(var i=0; i < this.imagesNames[0].length; i++){
            this.images[i].src = this.url+("btn-"+this.imagesNames[0][i]+".png");
            this.imageshover[i].src = this.url+("btn-"+this.imagesNames[0][i]+"-hover.png");
        }

    };
    this.GetAbsoluteurl();
    this.Preload();
}
finally {return;}
}

var g_preloaderhover = new eleban_preload_images("loaderhover","menu;malette;reservation;cabine;facebook;map;amis","./images/");


//variable arret flottement
var g_stopflo = false;

var myObjfloater = function(name, idname, itop, differ ) {
var oThis = this; // création d'une référence vers l'objet courant
this.name = name;
this.id =idname;
this.xstep= 0.3;
this.itime = 30;
this.obj = null;
this.y = itop;
this.yadd = 0;
this.up = true;
this.pause = false;
this.differ = differ;
this.coordsimage = null;
this.objimg = null;
this.initimages = false;
this.compteur = 0;
this.over = false;
this.timeoutstop = null;
try{
this.initimage = function(){
var img = this.obj.getElementsByTagName('img')[0];
this.coordsimage = new Array(img.width, img.height);
this.objimg = img;
this.initimages = true;
};


this.myMethod = function() {
if(!g_stopflo){
    if(this.differ != 0){ 
this.differ=this.differ-0.1; 
}else{

if(this.obj){
if(this.over == false){
    this.yadd=this.yadd+0.1; this.itime = this.itime + 10;
this.obj.style.visibility = "hidden";
this.y = ((this.up)? this.y - this.yadd : this.y + this.yadd);
this.obj.style.marginTop = this.y +"%" ;
this.obj.style.visibility = "visible";

if (this.yadd > this.xstep){ 
    this.up = (this.up)? false : true;
    this.yadd = -0.1; this.itime=180;
}
}
}else{
    if (document){
        if(document.getElementById) {
         this.obj = document.getElementById(this.id); 
        //this.y = this.obj.offsetTop;
        }else{
        if(document.getElementByTagName) { this.obj = document.getElementByTagName(this.id); this.y = this.obj.offsetTop;}
        }

    }
}
}
this.timeoutstop=setTimeout(function() { oThis.myMethod(); }, this.itime);
}    
};

this.callDelayed = function() {
    // utilisation de la référence vers l'objet
if(!g_stopflo){
    this.timeoutstop=setTimeout(function() { oThis.myMethod(); }, this.itime);
}
};
}
finally {return;}
};

// special creation des zones AREA
function eleban_createallarea(){
try{
var measur = new Array("w", "h");
measur["w"] = new Array(330,570,185,300,115,390,225);
measur["h"] = new Array(460,570,295,450,100,190,115);
var ititle = new Array("Voir les menus  et nos suggestions","Repas &agrave; emporter","R&eacute;servation d&rsquo;une table","Nous contacter","Nous rejoindre sur FaceBook","Calculer votre trajet","liste des amis");
var ihref = new Array("menus.html","emporter.html","reservation.html","contact.html","likebox.html","google.html","amis.html");
var b_map = new Array(0,1,2,3,4,5,6);
b_map[0] = "71,32,240,32,249,43,289,352,280,366,102,385,90,371,51,38";
b_map[1] = "66,52,95,14,129,56,115,91,100,93,112,273,128,284,122,366,176,343,193,296,191,194,147,189,145,166,201,111,199,84,545,105,532,354,509,388,412,478,32,401,77,383,87,375,82,286,95,269,94,221,24,195,11,165,9,120,89,123,89,94,78,92,77,92,77,93,75,93,77,93,76,93,79,92";
b_map[2] = "19,25,169,38,173,112,161,113,105,103,90,125,91,262,121,269,124,281,96,293,62,289,49,281,56,268,83,264,84,121,71,98,16,90";
b_map[3] = "60,0,216,1,226,20,225,403,168,421,42,410,45,10";
b_map[4] = "31,7,72,10,82,18,88,45,88,71,76,81,29,80,17,68,16,18";
b_map[5] = "91,40,141,38,178,27,184,4,211,5,223,24,240,23,386,135,229,121,103,180,6,156,49,94";
b_map[6] = "6,32,69,18,79,6,118,7,141,2,149,10,211,17,202,28,209,30,189,62,195,70,178,74,180,90,164,90,154,107,68,101,34,104,34,98,18,97,28,84,15,84,30,65";

if (document.getElementById){
for (var i=0; i<b_map.length;i++){
var obj = document.getElementById("pc_menu"+i);
    if(obj){
    var ct = '<img class=\"pc_menu\" src=\"'+g_preloaderhover.images[i].src+'\" alt=\"\" width=\"'+measur["w"][i]+'\" height=\"'+measur["h"][i]+'\" usemap=\"#MAP_INDEX'+i+'\" \/>';
    ct+='<map name=\"MAP_INDEX'+i+'\">';
    ct+='<area shape=\"poly\" coords=\"'+b_map[i]+'\" title=\"'+ititle[i]+'\" href=\"'+ihref[i]+'\" \/>';
    ct+='<\/map>';
    obj.innerHTML = ct;
    }
}
}
}
finally {return;}
}

//preload, creation et gestion de tous les evenements


var image_resizer = function(g_layer){


    b_org_elm = new Array("w",  "h");
    b_org_elm["w"] = new Array(330,570,185,300,115,390,225);
    b_org_elm["h"] = new Array(460,570,295,450,100,190,115);

    b_map = new Array(0,1,2,3,4,5,6);
    b_map[0] = new Array(71,32,240,32,249,43,289,352,280,366,102,385,90,371,51,38);
    b_map[1] = new Array(66,52,95,14,129,56,115,91,100,93,112,273,128,284,122,366,176,343,193,296,191,194,147,189,145,166,201,111,199,84,545,105,532,354,509,388,412,478,32,401,77,383,87,375,82,286,95,269,94,221,24,195,11,165,9,120,89,123,89,94,78,92,77,92,77,93,75,93,77,93,76,93,79,92);
    b_map[2] = new Array(19,25,169,38,173,112,161,113,105,103,90,125,91,262,121,269,124,281,96,293,62,289,49,281,56,268,83,264,84,121,71,98,16,90);
    b_map[3] = new Array(60,0,216,1,226,20,225,403,168,421,42,410,45,10);
    b_map[4] = new Array(31,6,70,10,78,18,84,23,88,44,88,70,78,80,75,81,33,82,23,76,18,69,16,22,21,13);
    b_map[5] = new Array(91,40,141,38,178,27,184,4,211,5,223,24,240,23,386,135,229,121,103,180,6,156,49,94);
    b_map[6] = new Array(6,32,69,18,79,6,118,7,141,2,149,10,211,17,202,28,209,30,189,62,195,70,178,74,180,90,164,90,154,107,68,101,34,104,34,98,18,97,28,84,15,84,30,65);


    b_layer = g_layer;

//gere mouseover
    this.mouseover = function(e){
        if (!e) var e = window.event;
        var tg = (window.event) ? e.srcElement : e.target
            if (tg.nodeName){
                if(tg.nodeName == "AREA"){
                var divpar = (tg.parentNode)? tg.parentNode.parentNode : tg.parentElement.parentElement;
                    if (divpar){
                        if(divpar.nodeName == "DIV"){
                            var iiobjimg = divpar.getElementsByTagName('img');
                                if (iiobjimg){
                                    ii = parseInt(divpar.id.substring(divpar.id.length-1,divpar.id.length));
                                    iiobjimg[0].src = g_preloaderhover.imageshover[ii].src;
                                }
                        }
                    }
                }
            }
    };

//gere mouseout
    this.mouseout = function(e){
        if (!e) var e = window.event;
        tg = (window.event) ? e.srcElement : e.target
            if (tg.nodeName){
                if(tg.nodeName == "AREA"){
                divpar = (tg.parentNode)? tg.parentNode.parentNode : tg.parentElement.parentElement;
                    if (divpar){
                        if(divpar.nodeName == "DIV"){
                            var iiobjimg = divpar.getElementsByTagName('img');
                                if (iiobjimg){
                                    ii = parseInt(divpar.id.substring(divpar.id.length-1,divpar.id.length));
                                    iiobjimg[0].src = g_preloaderhover.images[ii].src;
                                }
                        }
                    }
                }
            }
    };

//ajout evenements entree sortie à la page web lors du chargement de la page
    this.init = function () {

        for(var i=0; i<b_org_elm["w"].length;i++){
            w = document.getElementById("pc_menu"+i).offsetWidth;
            h = document.getElementById("pc_menu"+i).offsetHeight;

            xa = w/parseFloat(b_org_elm["w"][i]);
            ya = h/parseFloat(b_org_elm["h"][i]);

            area = document.getElementById("pc_menu"+i).getElementsByTagName('area')[0];

            b_map2 = area.coords.split(",");
            yswitch = true;
                for(m=0; m<b_map2.length;m++){
                b_map2[m] = Math.round(parseFloat(b_map[i][m]) * ((yswitch)? xa: ya));
                yswitch = (yswitch)? false :  true;
                }
            area.coords = b_map2.join(',');
        }
    }; 


    this.resize = function () {
    clearTimeout(myInstOne.timeoutstop);
    g_stopflo=true;

    globalize.init();
    g_stopflo=false;
    myInstOne.obj = null;
    myInstOne.callDelayed();
    };


    nar = document.getElementsByTagName('area').length;

        for(var i=0; i<nar;i++){
            var elem = document.getElementsByTagName('area')[i];
            if (elem.addEventListener){
                    elem.addEventListener("onmouseover",this.mouseover,true);
                elem.addEventListener("onmouseout",this.mouseout,true);
            }else if (elem.attachEvent) {
                    elem.attachEvent("onmouseover", this.mouseover);
                    elem.attachEvent("onmouseout", this.mouseout);
            }else{
                    elem["onmouseover"] = this.mouseover;
                    elem["onmouseout"] = this.mouseout;
            }
        }

            window.onresize = this.resize;
        window.onmouseover = this.mouseover;
        window.onmouseout = this.mouseout;
}


//permet de temporiser et éviter les erreurs de chargement des objets
function temporise_Init(Lastdiv){
if(document.getElementById){
    if(document.getElementById(Lastdiv)){

    eleban_createallarea();

    myInstOne = new myObjfloater('b_menumap11', 'pc_menu1', 1, 0);

    globalize = new image_resizer(document.getElementById('pc_redim'));
    globalize.init();
        globalize.resize();



    }else{
    setTimeout(temporise_Init(Lastdiv), 30);
    }
}
}


window.onload = function () {
temporise_Init("pc_bandeau");
}

4
qu'est-ce que cela fait?
user8408080
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.