[c++] Traitement d'image: Amélioration de l'algorithme pour la reconnaissance de 'Coca-Cola Can'


Answers

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

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

Je serais surpris si ce n'était pas un algorithme linéairement efficace, ou presque. Évidemment, cela n'aborde pas la question de la discrimination de votre bouteille, 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 bonnet qui La même forme de base, la même taille et la même distance que le logo seront généralement blanches ou rouges.Recherchez une forme elliptique de couleur unie où un chapeau devrait être, par rapport au logo.Non infaillible bien sûr, mais votre but ici devrait être de trouver les faciles facilement .)

(Cela fait quelques années que j'ai passé mes jours de traitement d'image, j'ai donc gardé cette suggestion de haut niveau et conceptuelle, je pense qu'elle pourrait légèrement approximer la façon dont un œil humain pourrait fonctionner - ou du moins comment mon cerveau fonctionne!)

Question

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 «cannettes» 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.

Quelques contraintes sur le projet:

  • L'arrière-plan pourrait être très bruyant.
  • La boîte pourrait avoir n'importe quelle échelle ou rotation ou même orientation (dans des limites raisonnables).
  • L'image peut avoir un certain degré de 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 devrait seulement détecter la canette !
  • La luminosité de l'image peut varier énormément (vous ne pouvez donc pas compter "trop" sur la détection des couleurs).
  • La boîte pourrait ê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 dans l'image, auquel cas vous ne deviez rien trouver et écrire un message le disant.

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

J'ai fait ce projet il y a un certain 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:

Langue : Fait en C ++ en utilisant la bibliothèque OpenCV .

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

  1. Changement de domaine de couleur de RGB en HSV et filtrage basé sur la teinte "rouge", saturation au-dessus d'un certain seuil pour éviter les couleurs de type 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 qui correspondent à 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.
  2. Filtrage du bruit en utilisant un filtrage médian (en prenant la valeur de pixel médiane de tous les voisins et en remplaçant le pixel par cette valeur) pour réduire le bruit.
  3. Utilisation de Canny Edge Detection Filter pour obtenir les contours de tous les éléments après 2 étapes précédentes.

Algorithme : L'algorithme que j'ai choisi pour cette tâche a été tiré de this livre génial sur l'extraction de caractéristiques et appelé Transformée de Hough Généralisée (assez différent de la Transformée Hough ordinaire). Il 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 d'image telles que la mise à l'échelle et la rotation, car il testera fondamentalement 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 va "apprendre".
  • Chaque pixel restant dans l'image de contour va voter pour un autre pixel qui sera soi-disant le centre (en termes de gravité) de votre objet, basé sur ce qu'il a appris du modèle.

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

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 de lui (échelle finale et facteur de rotation modèle original). En théorie au moins ...

Résultats : Maintenant, même si cette approche fonctionnait dans les cas de base, elle manquait cruellement dans certains domaines:

  • C'est extrêmement lent ! Je ne le souligne pas assez. Il a fallu près d'une journée complète pour traiter les 30 images de test, évidemment parce que j'avais un facteur d'échelle très élevé pour la rotation et la traduction, car certaines des boîtes étaient très petites.
  • Il était complètement perdu quand les bouteilles étaient dans l'image, et pour une raison quelconque, presque toujours trouvé la bouteille au lieu de la boîte (peut-être parce que les bouteilles étaient plus grandes, donc plus de pixels, donc plus de votes)
  • Les images floues n'étaient également pas bonnes, car les votes se sont retrouvés en pixel dans des endroits aléatoires autour du centre, se terminant ainsi par une carte de chaleur très bruyante.
  • Une variance de la translation et de la rotation a été obtenue, mais pas dans l'orientation, ce qui signifie qu'une boîte qui ne faisait 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 apprendront aussi quelque chose, après tout, je pense que non seulement les personnes qui posent des questions devraient apprendre. :)




If you are interested in it being realtime, then what you need is to add in a pre-processing filter to determine what gets scanned with the heavy-duty stuff. A good fast, very real time, pre-processing filter that will allow you to scan things that are more likely to be a coca-cola can than not before moving onto more iffy things is something like this: search the image for the biggest patches of color that are a certain tolerance away from the sqrt(pow(red,2) + pow(blue,2) + pow(green,2)) of your coca-cola can. Start with a very strict color tolerance, and work your way down to more lenient color tolerances. Then, when your robot runs out of an allotted time to process the current frame, it uses the currently found bottles for your purposes. Please note that you will have to tweak the RGB colors in the sqrt(pow(red,2) + pow(blue,2) + pow(green,2)) to get them just right.

Also, this is gona seem really dumb, but did you make sure to turn on -oFast compiler optimizations when you compiled your C code?




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 les algorithmes de détection d'objets tels que Faster-RCNN, YOLO, SSD, etc., auraient un problème avec une marge significative par rapport aux fonctionnalités OpenCV. Si je devais résoudre ce problème maintenant (après 6 ans !!) j'utiliserais certainement Faster-RCNN .




The first things I would look for are color - like RED , when doing Red eye detection in an image - there is a certain color range to detect , some characteristics about it considering the surrounding area and such as distance apart from the other eye if it is indeed visible in the image.

1: First characteristic is color and Red is very dominant. After detecting the Coca Cola Red there are several items of interest 1A: How big is this red area (is it of sufficient quantity to make a determination of a true can or not - 10 pixels is probably not enough), 1B: Does it contain the color of the Label - "Coca-Cola" or wave. 1B1: Is there enough to consider a high probability that it is a label.

Item 1 is kind of a short cut - pre-process if that doe snot exist in the image - move on.

So if that is the case I can then utilize that segment of my image and start looking more zoom out of the area in question a little bit - basically look at the surrounding region / edges...

2: Given the above image area ID'd in 1 - verify the surrounding points [edges] of the item in question. A: Is there what appears to be a can top or bottom - silver? B: A bottle might appear transparent , but so might a glass table - so is there a glass table/shelf or a transparent area - if so there are multiple possible out comes. A Bottle MIGHT have a red cap, it might not, but it should have either the shape of the bottle top / thread screws, or a cap. C: Even if this fails A and B it still can be a can - partial.. This is more complex when it is partial because a partial bottle / partial can might look the same , so some more processing of measurement of the Red region edge to edge.. small bottle might be similar in size ..

3: Après l'analyse ci-dessus c'est quand je regarderais le lettrage et le logo d'onde - parce que je peux orienter ma recherche pour certaines des lettres dans les mots Comme vous pourriez ne pas avoir tout le texte dû à 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.




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. Donc peut-être si la même image contient à la fois une canette et une bouteille, alors vous pouvez les différencier par des considérations de taille (les bouteilles vont être plus grandes). Maintenant, en raison de la profondeur manquante (c.-à-d. De la cartographie 3D à la cartographie 2D), il est possible qu'une bouteille apparaisse rétrécie et qu'il n'y ait pas de différence de taille. Vous pouvez récupérer des informations de profondeur en utilisant l' stereo-imaging , puis récupérer la taille d'origine.




Si vous n'êtes pas limité à une caméra qui n'était pas dans l'une de vos contraintes, vous pouvez peut-être passer à l'aide d'un capteur de portée comme la Xbox Kinect . Avec cela, vous pouvez effectuer une segmentation en profondeur et en couleur de l'image. Cela permet une séparation plus rapide des objets dans l'image. Vous pouvez ensuite utiliser ICP matching ou des techniques similaires pour faire correspondre la forme de la boîte plutôt que son contour ou sa couleur et étant donné qu'il est cylindrique, cela peut être une option valable pour toute orientation si vous avez déjà un scan 3D de la cible. Ces techniques sont souvent assez rapides surtout lorsqu'elles sont utilisées dans un but précis qui devrait résoudre votre problème de vitesse.

Aussi, je pourrais suggérer, pas nécessairement pour la précision ou la vitesse, mais pour le plaisir, vous pouvez utiliser un réseau de neurones formés sur votre image segmentée de teinte pour identifier la forme de la boîte. Ceux-ci sont très rapides et peuvent souvent être jusqu'à 80/90% précis. La formation serait un processus un peu long, bien que vous deviez identifier manuellement la boîte dans chaque image.




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

Ils sont presque identiques à l'exception d'une très petite région (c'est-à-dire, la largeur au sommet de la canette est un peu petite alors que l'enveloppe de la bouteille est de la même largeur, mais un changement mineur?).

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

La deuxième chose que je pensais était à propos de la transparence de la bouteille. OpenCV a quelques travaux sur la recherche d'objets transparents dans une image. Vérifiez les liens ci-dessous.

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

Voir leur résultat d'implantation:

Ils disent que c'est la mise en œuvre de l'article "A Geodesic Active Contour Framework for Finding Glass" by K. McHenry and J. Ponce, CVPR 2006. .. (Télécharger le papier) .

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

Je pense donc ici, vous pouvez d'abord chercher le corps transparent des bouteilles ou pour une région rouge reliée à deux objets transparents latéralement qui est évidemment la bouteille. (Lorsque vous travaillez idéalement, une image comme suit.)

Maintenant, vous pouvez 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 aussi 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 région 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.




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

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

Vous pouvez recycler le modèle initial v3 sur Tensorflow:

Comment recycler le calque final d'Inception pour de nouvelles catégories .

Dans ce cas, vous allez former un réseau de neurones convolutionnels pour classer un objet comme un coca-cola ou non.




Je ne suis pas au courant de OpenCV mais en regardant le problème logiquement, je pense que vous pourriez différencier entre la bouteille et la canette en changeant l'image que vous recherchez, par exemple Coca Cola. Vous devez incorporer jusqu'à la partie supérieure de la boîte comme dans le cas de la cannette il y a une doublure d'argent au sommet de la coca cola et dans le cas de la bouteille, il n'y aura pas une telle doublure d'argent.

Mais évidemment, cet algorithme échouera dans les cas où le sommet de la canette est caché, mais dans ce cas même l'humain ne sera pas en mesure de faire la différence entre les deux (si seulement la portion de coca-cola est visible)




Regarder la forme

Jetez un coup d'oeil à la forme de la partie rouge de la canette / 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 entre ces deux en comparant la largeur de la partie rouge à travers la longueur de celui-ci.

Regarder les faits saillants

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

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 devriez être capable de détecter la présence de la bouteille transparente / translucide elle-même.




Il y a un tas de descripteurs de couleur utilisés pour reconnaître les objets, le papier ci-dessous compare beaucoup d'entre eux. Ils sont particulièrement puissants lorsqu'ils sont combinés avec SIFT ou SURF. SURF ou SIFT seul ne sont pas très utiles dans une image de coca-cola parce qu'ils ne reconnaissent pas beaucoup de points d'intérêt, vous avez besoin de l'information de couleur pour vous aider. J'utilise BIC (Classi fi cation de pixels de bord / intérieur) avec SURF dans un projet et cela fonctionne très bien pour reconnaître des objets.

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




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.






Related