Reconnaissance routière par segmentation sémantique

Dans la série précédente, j'ai mené une expérience avec le mouvement autonome de mon réservoir d'origine . La route a été reconnue à l'aide d'un filtre de couleur, et le masque résultant est allé à l'entrée d'un réseau neuronal classificateur spécialement formé, qui a choisi d'aller à droite, à gauche ou tout droit.

Le point faible était la reconnaissance de la chaussée elle-même en raison de la variabilité des nuances de couleur, à cause de laquelle le réseau neuronal décisionnel a produit des résultats étranges. Les commentaires sur cet article recommandaient de prêter attention à la segmentation sémantique. Le sujet s'est avéré prometteur et l'utilisation de réseaux de neurones segmentés a apporté ses avantages, mais aussi ses inconvénients, où en serait-il sans eux.

Mais tout d'abord et un peu d'équipement.

Segmentation


La segmentation est le processus de mise en évidence de certaines parties d'une image. La forme de segmentation la plus simple et la plus évidente est la couleur. Cependant, en utilisant cette méthode, il est impossible de comprendre quoi et où est représenté sur l'image.

Voici un bon article décrivant les approches primitives.

Segmentation sémantique


Segmentation sémantique - fractionner une image en objets avec déterminer les types de ces objets.

Cela ressemble à ceci:



Les résultats sont très impressionnants, voyons ce que cela vaut la peine de traduire dans la vraie vie.

U-net


Le réseau neuronal le plus célèbre, développé à l'origine pour la médecine.
Source primaire

Les gens ont rapidement réalisé que l'approche peut être utilisée pour toutes les occasions.

Il existe de nombreux articles sur Internet pour préparer les données et former les réseaux U-net:


Cependant, je n'ai pas trouvé de réseau U-net prêt à l'emploi et à expérimenter rapidement.

E-net


Un réseau plus jeune et moins connu. Conçu uniquement pour reconnaître les rues de la ville.


Les données


Les ensembles de données les plus populaires pour la segmentation des rues (ils ont d'abord enseigné E-net):


Sur les mêmes ensembles de données, U-net est maintenant en cours de formation.

Choix d'implémentation


Le flot de nouvelles informations sur la segmentation a été assez écrasant. Instinctivement, je voulais passer à quelque chose de plus simple. Je n'ai pas ressenti le zen intérieur pour comprendre l'architecture des réseaux et passer du temps à apprendre. Mais dans l'article de PyImageSearch, il y avait d'ailleurs un réseau neuronal prêt à l'emploi et formé, dans un format compatible avec OpenCV-DNN.

Le choix s'est donc porté sur la moindre résistance.

L'utilisation est très simple:
(Ce qui est le plus inquiétant, c'est que le réseau est formé aux images 1024x512 - c'est, premièrement, plus que ce que la caméra donne sur Raspberry, et deuxièmement, les performances requises pour traiter cette quantité de données sont quelque peu déroutantes. En conséquence, le problème principal sera exactement cela).

Nous lisons le réseau neuronal à partir de fichiers (dans l'un, le modèle lui-même, dans les autres noms de classe, dans la troisième - couleurs).

def load_segment_model(): try: classes = None with open(PiConf.SEGMENT_CLASSES) as f: classes = f.read().strip().split("\n") colors = None with open(PiConf.SEGMENT_COLORS) as f: colors= f.read().strip().split("\n") colors = [np.array(c.split(",")).astype("int") for c in colors] colors = np.array(colors, dtype="uint8") print("[INFO] loading model...") net = cv2.dnn.readNet(PiConf.SEGMENT_MODEL) return net, classes, colors except Exception as e: logging.exception("Cannot load segment model") return None, None, None 

Nous segmentons l'image, marquant simultanément des segments au-dessus de l'image d'origine
(Dans mon cas, toutes les classes sauf la route sont invisibles).

 def segment_image(image_path, seg_net, seg_classes, seg_colors): image0 = cv2.imread(image_path) image = cv2.resize(image0, (1024, 512),interpolation=cv2.INTER_NEAREST) blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (1024, 512), 0, swapRB=True, crop=False) seg_net.setInput(blob) start = time.time() output = seg_net.forward() end = time.time() print("[INFO] inference took {:.4f} seconds".format(end - start)) (numClasses, height, width) = output.shape[1:4] classMap = np.argmax(output[0], axis=0) mask = seg_colors[classMap] mask = cv2.resize(mask, (image0.shape[1], image0.shape[0]),interpolation=cv2.INTER_NEAREST) classMap = cv2.resize(classMap, (image0.shape[1], image0.shape[0]), interpolation=cv2.INTER_NEAREST) gmask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY) gmask = cv2.resize(gmask, (128, 64), interpolation=cv2.INTER_NEAREST) gmask = gmask[0:64,32:96] output = ((0.6 * image0) + (0.4 * mask)).astype("uint8") return output, gmask 

Vérifier


Nous prenons des photos toutes faites du réservoir et y installons un réseau neuronal segmenté.

1



Seul le côté gauche du trottoir est reconnu comme cher.

Nous compressons l'image et en prenons une taille centrale de 64x64:
(Cette taille est attendue par le réseau neuronal, qui décide de changer de direction)



Le réseau neuronal de la direction (en fait - le classificateur) commande de prendre à gauche. Pas très correct, mais supportable.

2



Une situation similaire, encore une fois, le coin inférieur droit est perdu (il y a aussi de l'asphalte mouillé).
Cependant, la majeure partie de la route est encore reconnue.



Le classificateur propose d'aller tout droit.

3

La situation lorsque le robot était au milieu du trottoir.



La route est reconnue presque parfaitement.



Le classificateur commande de prendre à droite (pour trouver le bord de la route la prochaine fois).

Candidature


Après avoir évoqué un peu le firmware du réservoir, j'ai remplacé le détecteur de route en couleur par un réseau neuronal à segmentation.

Lors du lancement de tout cela sur le Raspberry Pi, la première chose qui est sortie a été une baisse des performances.
Il faut 6 secondes pour segmenter une image - pendant ce temps, le char parvient à se faufiler dans tous les virages avec un trot vigoureux.

Dans de vrais tests, cela s'est produit - malgré la reconnaissance presque parfaite du trottoir et les commandes correctes du réseau de neurones de contrôle - pendant le traitement de l'image, le char a réussi à s'écarter.



En général, les images de cette taille ne peuvent pas être digérées sur Raspberry.
Il semble que vous ayez encore à faire la formation d'un réseau neuronal spécialisé.

Les références


Source: https://habr.com/ru/post/fr452088/


All Articles