Rechercher des objets dans les images? Ayant un échantillon de formation et un ensemble minimum de connaissances sur les réseaux de neurones, tout étudiant peut aujourd'hui obtenir une solution d'une certaine précision. Cependant, la plupart des réseaux de neurones utilisés pour résoudre ce problème sont assez profonds et nécessitent donc beaucoup de données pour la formation, ils fonctionnent relativement lentement dans la phase d'inférence (surtout si l'appareil n'a pas de GPU), ils pèsent beaucoup et sont assez énergivores. Tout ce qui précède peut être très critique dans certains cas, principalement pour les applications mobiles.
Les codes-barres sont des objets avec une structure assez simple. Au cours des recherches, nous avons pu, en utilisant une approche relativement originale, rechercher des objets aussi simples de manière très précise (nous battons à la pointe de la technologie) et assez rapidement (en temps réel sur un CPU moyen). De plus, notre détecteur est très léger, avec seulement 30k poids. Nous parlerons des résultats de nos recherches dans cet article.
Mais avant de parler de la solution, cela vaut la peine de plonger un peu dans le sujet, et peut-être que cela vaut la peine de commencer par ce que sont les codes-barres.
Qu'est-ce qu'un code-barres et pourquoi le rechercher?
Les codes-barres sont un nom générique pour un groupe de formats de données lisibles par machine. Vous avez probablement entendu parler des codes à barres et des codes QR - ce ne sont que des cas spéciaux de codes à barres. Dans le monde moderne, ils peuvent être trouvés sur les billets, sur les marchandises dans les magasins, dans les documents officiels et dans de nombreux autres endroits.

Les codes à barres sont généralement divisés en unidimensionnel, représenté par un ensemble de rayures noires et blanches, et bidimensionnel, composé de petits blocs carrés ou rectangulaires. Comme vous pouvez le voir sur la figure, en général, les différents types sont très similaires les uns aux autres.
La complexité peut être représentée par certains types de codes-barres dont la longueur n'est pas spécifiée. Ces codes à barres peuvent être arbitrairement longs et en même temps très minces.

L'exemple ci-dessus est artificiel, mais des codes à barres aux proportions similaires se trouvent dans des documents réels, en particulier dans les factures.
Et comme ce sont des formats lisibles par machine, ils devraient être relativement facilement reconnus par le matériel. Cependant, la première étape sur le chemin de la reconnaissance est la recherche, et elle sera discutée dans cet article.
Il convient de noter que les scanners laser et de nombreuses applications impliquent la participation active d'une personne - vous devez pointer clairement l'appareil photo / scanner vers le code à barres afin qu'il soit reconnu, auquel cas le besoin de recherche, bien sûr, disparaît. Cependant, dans ce scénario, les utilisateurs sont obligés de faire des efforts supplémentaires de leur part, ce qui n'est pas bon. Cette approche ne permet pas non plus la reconnaissance de plusieurs objets dans l'image, limitée à un seul.
Énoncé du problème et mesures de qualité
Que souhaiterions-nous du détecteur de code-barres créé?
- Trouver tous les codes-barres dans l'image est suffisamment précis *
- Trouvez des codes-barres longs et très étroits
- CPU en temps réel
* Il est proposé d'utiliser la mesure f pour les objets avec un seuil de IoU = 0,5 comme métrique principale de précision. Nous examinerons également la précision, le taux de rappel et de détection.
Définition formelle des métriquesTout d'abord, nous introduisons le concept IoU - Intersection over Union (également connu sous le nom de Jaccard Index). Avoir vrai ( ) et prévu ( ) le masque de l'objet, IoU est calculé comme la zone d'intersection divisée par la zone de l'union.
Il est facile de voir que l'IoU prend des valeurs de 0 à 1. Maintenant, sur la base de cette mesure, nous introduisons les concepts de précision, de rappel, de f-mesure et de taux de détection.
Soit N objets dans l'échantillon. Nous fixons le seuil IoU égal à un certain nombre fixe (par exemple 0,5). Pour un objet et détection crois que si , l'objet a été trouvé (1), sinon nous pensons que l'objet n'a pas été trouvé (0). Alors défini comme la proportion d'échantillons d'objets trouvés, - la proportion de détections correspondant à au moins un objet échantillon. La mesure f est définie comme la moyenne harmonique .
Reste à comprendre ce qu'est un taux de détection. Soit M images avec des objets dans l'échantillon. Nous calculons l'IoU entre les masques vrai et prédit dans l'image , de même coupons le seuil de l'image. Le taux de détection est la fraction d'images par laquelle l'IoU total de tous les objets réels avec l'IoU total de tous les objets prédits est supérieur à un seuil donné t.
Dans les études précédentes (sur la détection des codes-barres), il est d'usage d'utiliser le taux de détection pour évaluer la qualité. Cependant, considérons cette situation - qu'il y ait un très grand et un très petit objet dans l'image, mais le détecteur a trouvé grand et n'a pas trouvé petit. Dans ce cas, le taux de détection ne signalera une erreur que si le seuil est très grand. près de 1. tout ne sera pas supérieur à 0,5 pour les valeurs de seuil arbitraires , ce qui rendra également la mesure f inférieure à 1. Autrement dit, pour un tel exemple, la mesure f peut signaler une erreur plus tôt (dans le sens d'un seuil inférieur ) que le taux de détection.
Par conséquent, dans nos expériences, nous nous sommes appuyés sur la mesure f et avons utilisé le taux de détection pour comparer avec le travail des années précédentes.
Inspiré par les détecteurs de texte
Peut-être que le détecteur d'objets le plus célèbre et le plus populaire lorsque la vitesse est importante est YOLO (You Only Look Once). Il existe également des versions ultérieures de YOLOv2 et YOLOv3, mais en général, cette approche est bonne pour les objets plus ou moins carrés, mais pour trouver des objets étroits mais très allongés, cette approche n'est pas si forte.
Nous avons donc décidé d'aller dans l'autre sens. Comme vous pouvez facilement le voir, les lignes avec du texte dans l'image sont également très allongées et étroites, et la tâche de trouver du texte dans des images dans la communauté scientifique est assez populaire (certainement plus populaire que la recherche de codes à barres) et diverses architectures intéressantes basées sur la structure du graphique ont été inventées pour cela. Notre décision est motivée par un seul des travaux de recherche de texte dans lesquels l'architecture PixelLink est proposée.
PixelLink pour la recherche de texte
L'essence de l'approche est la suivante - résolvons le problème de la segmentation d'instance comme ceci:
- Pour chaque pixel, nous allons résoudre le problème de classification binaire (texte / pas texte).
- Pour chaque pixel, nous prédirons 8 liens (liens) avec ses voisins. La communication signifie que cette paire de pixels appartient à un objet (instance).
- Après avoir reçu une carte de segmentation texte / non-texte et des cartes avec des liens de l'image, nous assemblons un graphique dans lequel les sommets seront des pixels dont la classe de texte est prédite et les bords sont des liens.
- Nous trouvons les composants connectés dans ce graphique.
- Autour de chaque composant connecté, sélectionnez le rectangle englobant minimum (par exemple, en utilisant OpenCV), qui sera la détection finale.
Ce processus est illustré graphiquement, la figure est tirée de l' article d'origine .

Cette approche de recherche de texte donne des résultats assez décents comparables à l'état de l'art.
Pixel Lien rechercher des codes-barres
Revenons maintenant aux codes-barres. Nous nous sommes demandé - avons-nous vraiment besoin de ces liens? Après tout, les codes-barres, contrairement au texte, dans la grande majorité des cas, sont éloignés les uns des autres. Et en effet, selon la spécification, de nombreux types de codes-barres doivent avoir un certain écart avec les objets voisins les plus proches.
En général, nous avons décidé que nous n'avions pas particulièrement besoin de liens et avons modifié l'approche comme suit:
- Nous résolvons le problème de la segmentation sémantique - pour chaque pixel, nous déterminons la classe de code-barres / non-code-barres.
- Nous construisons un graphique avec des sommets en pixels pour lesquels le type de code-barres est déterminé. En tant que bords, au lieu de rechercher des liens, nous considérons qu'il existe un lien entre n'importe quelle paire de pixels adjacents du type code à barres.
- Nous trouvons les composants connectés dans ce graphique.
- Autour de chaque composant connecté, sélectionnez le rectangle englobant minimum, qui sera la détection finale.
Nous avons donc décidé du schéma de solution général. Les paragraphes 2 à 4 peuvent être considérés comme triviaux, mais voyons comment traiter exactement la segmentation sémantique.
Architecture de réseau pour la segmentation sémantique
Un peu d'histoire couramment utilisée
En général, la segmentation sémantique utilisant des réseaux de neurones se poursuit depuis environ 2013 depuis l'avènement de U-Net. Dans U-Net, la résolution spatiale a d'abord été progressivement réduite dans Encoder, puis progressivement augmentée dans Decoder, il y a également eu des sauts de connexion entre les attributs Encoder intermédiaires et les attributs Decoder intermédiaires. Un peu plus tard, des convolutions dilatées sont apparues (voir la figure ci-dessous), ce qui a donné une meilleure qualité, mais a nécessité plus de mémoire et de calculs pour le traitement. Eh bien, à la fin, il y avait une approche connue sous le nom de Deeplabv3 +, combinant ces deux approches et étant à la pointe de la technologie parmi les architectures conçues par l'homme au moment de la rédaction de ce document (en fait, grâce à Neural Architecture Search, des solutions plus efficaces, par exemple ).
Arrêtons-nous un peu plus sur la convolution dilatée, car dans la décision finale, nous nous appuierons sur ses propriétés.
La convolution normale fonctionne comme ceci

Alors que la convolution dilatée est indiquée ci-dessous (dans l'image, le facteur dilaté est 2)

Vous pouvez remarquer que la convolution conventionnelle est en fait un cas spécial de convolution dilatée (avec facteur de dilatation 1).
En général, une discussion sur les solutions pour la segmentation sémantique est un sujet pour un article séparé plutôt volumineux, je voulais juste faire un petit rappel dans lequel la chose la plus importante est de traiter avec le dispositif de convolution dilaté. Si vous êtes nouveau dans la segmentation sémantique, voici la meilleure revue connue de l'auteur, cependant, pour comprendre ce qui va se passer ensuite, il n'est pas nécessaire de s'y familiariser.
Si tout était si simple ...
La principale exigence pour notre réseau de neurones, en plus de la qualité, est la vitesse. Dans nos données, il y a des codes à barres si petits par rapport à la taille de l'image que la résolution minimale à laquelle il est logique d'exécuter un réseau de neurones devrait être d'au moins 512x512, et de préférence 1024x1024. Dans le même temps, il est nécessaire de travailler sur le CPU pendant pas plus de 100 ms sur l'image (et aussi sur un cœur!). En termes de l'ensemble des exigences pour la résolution d'entrée et la durée totale de fonctionnement, la tâche n'est pas très triviale. Avec de telles restrictions sévères, l'utilisation d'architectures fortes et profondes n'est pas possible. Pour être honnête, nous n'avons pas encore satisfait à l'exigence de 100 ms sur un cœur, mais la solution finale fonctionne à 40 ms sur 4 cœurs (Intel Core i5, 3,2 GHz).
Malheureusement, toutes les architectures que nous connaissons pour la segmentation sémantique ne correspondaient pas catégoriquement à ces restrictions. Nous avons donc eu le choix: soit on ne sait pas proposer quelque chose de complètement nouveau, soit on essaie de simplifier autant que possible l'une des architectures populaires. Nous n'avions pas d'idées brillantes, nous avons donc choisi cette dernière.
Inspiré par Context Aggregation Network
Les convolutions dilatées ont la propriété utile suivante - si vous les appliquez séquentiellement avec un facteur dilaté croissant exponentiellement, le champ récepteur augmentera de façon exponentielle (alors que dans le cas des convolutions ordinaires, il croît linéairement).

La figure ( source ) montre l'augmentation exponentielle du champ récepteur du réseau neuronal lors de l'application séquentielle de convolution dilatée. (a) F1 est obtenu à partir de F0 par convolution avec dilatation = 1, champ récepteur = 3x3 pour chaque élément de F1 (b) F2 est obtenu à partir de F1 par convolution avec dilatation = 2, champ récepteur = 7x7 pour chaque élément de F2 (c) F3 obtenu à partir de F2 en utilisant la convolution avec dilatation = 4, champ récepteur = 15x15 pour chaque élément de F3
Dans l'article "Multi-Scale Context Aggregation by Dilated Convolutions" , un bloc spécial (appelé par les auteurs du Context Module) a été inventé sur la base de cette propriété, qui est utilisée pour collecter des informations à partir du contexte du pixel actuel. Dans l'article, ce bloc est utilisé au-dessus d'un réseau qui sait déjà comment résoudre le problème de segmentation pour affiner ces prédictions à l'aide d'informations de contexte.
Nous avons décidé de prendre ce module de contexte, mais de ne pas l' utiliser pour améliorer les prédictions d'un bon modèle existant, mais comme la partie principale du réseau de convolution, ce qui résoudra ce problème. En général, notre architecture est organisée comme suit (voir tableau):
- Module Downscale - convolution initiale pour extraire les fonctionnalités les plus simples et réduire la résolution.
- Le module de contexte est essentiellement un ensemble de convolutions dilatées qui augmentera rapidement le champ récepteur, rassemblant ainsi des attributs d'un contexte plus large.
- La couche finale (convolution 1x1), recevant une carte de probabilité pour la segmentation sémantique du code-barres / non-code-barres. De plus, si nous voulons distinguer le type de codes-barres détectés, N canaux sont également prévus (voir ci-dessous).

C'est-à-dire que dans l'architecture résultante, un petit nombre constant de canaux C = 24 est utilisé dans chaque couche, les 3 premières convolutions réduisent la résolution, les convolutions suivantes (module de contexte) augmentent le champ récepteur de chaque élément de la carte d'entités.
Le tableau des hyperparamètres d'architecture, entre autres, indique si la convolution sur la couche actuelle est séparable. Les convolutions séparables donnent théoriquement une accélération de l'ordre de k ^ 2 fois par rapport à une convolution conventionnelle, où k est la taille du filtre. En pratique, l'accélération peut être bien moindre (tout dépend de la résolution de l'image, du nombre de filtres d'entrée et de sortie).
Au départ, nous avons essayé de rendre toutes les circonvolutions séparables, mais cela a fait beaucoup baisser la qualité. Ensuite, nous avons décidé de ne séparer que les 3 premières convolutions, qui fonctionnent avec des résolutions d'image plus élevées et, par conséquent, nécessitent plus de calculs que les convolutions suivantes. Dans le même temps, la qualité d'un tel remplacement a déjà légèrement baissé. Total en raison de la séparabilité, le réseau neuronal a accéléré de 20% supplémentaires.
Il reste le dernier moment inexpliqué - que signifie le nombre N dans la dernière couche. N est responsable du nombre de types d'objets différents (dans notre cas, les codes-barres) que nous voulons distinguer. Si nous considérons le cas le plus simple - lorsque vous avez seulement besoin de trouver des objets et que vous n'avez pas besoin de déterminer leur type (c'est un code-barres et quoi qu'il arrive) - vous pouvez considérer N = 0. Si nous voulons toujours distinguer les types de codes-barres (il s'agit d'un code-barres de type [tel ou tel]), alors dans la dernière couche, N canaux sont ajoutés dans lesquels les probabilités d'être d'un certain type sont prédites. Maintenant, après avoir reçu la détection sous la forme du rectangle dans lequel se trouve le code-barres, nous pouvons faire la moyenne des probabilités des classes à l'intérieur de ce rectangle trouvé, à partir desquelles nous pouvons trouver le type du code-barres trouvé.
Résultats
Après avoir reçu une solution, vous devez toujours regarder autour de vous et comparer la qualité de la solution avec les études antérieures. En général, la tâche de rechercher des codes-barres n'est pas très populaire, depuis 10 ans, seuls 1 à 2 articles ont été publiés par an (comme vous le savez, la manière la plus simple de battre l'état de l'art est de trouver la tâche impopulaire, ce que nous avons finalement fait.) .). Le tableau ci-dessous se compare à d'autres approches sur deux ensembles de données, sur l'un desquels nous avons obtenu de meilleurs résultats.

L'excellence, bien sûr, n'est pas super impressionnante, mais toujours présente. Cependant, la principale caractéristique de la solution trouvée n'est pas exactement, mais en vitesse - par rapport au même YOLO sur le même GPU (GTX 1080), et à une résolution d'image plus élevée, notre méthode fonctionne ~ 3,5 fois plus vite.

En plus de l'avantage de vitesse, il y a un avantage en poids du modèle final. Le détecteur a environ 30 000 échelles, tandis que la grande majorité des réseaux de convolution modernes (même affûtés pour les appareils mobiles) ont des millions de paramètres. La solution finale pèse encore moins que LeNet, qui avait environ 60 000 paramètres.
Conclusion
En fait, ce travail repose sur deux idées simples:
- Détection par segmentation sémantique.
- Utilisation d'une séquence de convolution dilatée avec un petit nombre de canaux pour la croissance la plus rapide possible du champ récepteur.
Le résultat a été une architecture très légère et rapide, qui a néanmoins montré des résultats assez décents (et a même battu SOTA dans la tâche impopulaire de trouver des codes à barres). De plus, l'application de cette approche ne se limite pas aux codes-barres. Nous avons utilisé la même architecture pour trouver du texte, rechercher des cartes de visite et des passeports et obtenir de bons résultats pour ces tâches.
Cependant, il convient de noter que cette approche sous cette forme présente des limites. Si 2 objets du même type sont situés très proches, ils resteront collés en un seul. Peut-être que dans la prochaine série, nous vous dirons comment faire face à un tel problème.
Sur la base des résultats d'expériences avec des codes-barres, nous avons écrit un article qui sera présenté à l' ICDAR2019 à Sydney.
Littérature
- Un article avec les résultats de nos expériences et un grand nombre de détails. Détecteur universel de codes à barres via la segmentation sémantique
- Un excellent article de synthèse sur le développement d'architectures pour la segmentation sémantique. lien
- PixelLink: détection du texte de scène via la segmentation d'instance
- Cet article concerne l'utilisation de la convolution dilatée pour améliorer les prévisions en collectant des informations à partir du contexte. Agrégation de contexte multi-échelle par convolutions dilatées
Groupe de recherche en vision par ordinateur