Reconocimiento de carreteras mediante segmentación semántica.

En la serie anterior, realicé un experimento con el movimiento autónomo de mi tanque de origen . El camino se reconoció utilizando un filtro de color, y la máscara resultante fue a la entrada de una red neuronal clasificador especialmente entrenada, que eligió ir a la derecha, izquierda o recta.

El punto débil fue el reconocimiento de la carretera en sí debido a la variabilidad de los tonos de color, por lo que la red neuronal de toma de decisiones produjo resultados extraños. Los comentarios sobre ese artículo recomendaron prestar atención a la segmentación semántica. El tema resultó prometedor y el uso de redes neuronales segmentadas trajo sus ventajas, pero también sus desventajas, ¿dónde estaría sin ellas?

Pero primero lo primero y un poco de equipamiento.

Segmentación


La segmentación es el proceso de resaltar algunas partes de una imagen. El tipo de segmentación más simple y obvio es el color. Sin embargo, utilizando este método, es imposible entender qué y dónde se representa en la imagen.

Aquí hay un buen artículo que describe enfoques primitivos.

Segmentación semántica


Segmentación semántica: dividir una imagen en objetos con la determinación de los tipos de estos objetos.

Se parece a esto:



Los resultados son muy impresionantes, veamos qué vale la pena traducir a la vida real.

U-net


La red neuronal más famosa, desarrollada originalmente para la medicina.
Fuente primaria

La gente rápidamente se dio cuenta de que el enfoque se puede utilizar para todas las ocasiones.

Hay muchos artículos en Internet sobre cómo preparar datos y entrenar redes U-net:


Sin embargo, no encontré una red U-net lista para usar y experimentar rápidamente.

E-net


Una red más joven y menos conocida. Diseñado solo para reconocer las calles de la ciudad.


Datos


Los conjuntos de datos más populares para la segmentación de calles (inicialmente enseñaron E-net):


En los mismos conjuntos de datos, U-net ahora está siendo entrenado.

Elección de implementación


La avalancha de nueva información sobre segmentación fue bastante abrumadora. Instintivamente, quería entender algo más simple. No sentía el zen interno para comprender la arquitectura de las redes y pasar tiempo aprendiendo. Pero en el artículo de PyImageSearch había una red neuronal preparada y entrenada, además, en un formato compatible con OpenCV-DNN.

Entonces, la elección se hizo hacia la menor resistencia.

El uso es muy simple:
(Lo que es más preocupante es que la red está entrenada en imágenes de 1024x512; en primer lugar, esto es más de lo que la cámara da en Raspberry y, en segundo lugar, el rendimiento requerido para procesar esta cantidad de datos es algo confuso. Como resultado, el problema principal será exactamente eso).

Leemos la red neuronal de los archivos (en uno, el modelo en sí, en los otros nombres de clase, en los terceros colores).

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 

Segmentamos la imagen, marcando simultáneamente segmentos en la parte superior de la imagen original
(En mi caso, todas las clases excepto el camino son 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 

Cheque


Tomamos imágenes ya hechas del tanque y establecemos una red neuronal segmentada en ellas.

1



Solo el lado izquierdo de la acera se reconoce como costoso.

Comprimimos la imagen y tomamos un tamaño central de 64x64:
(Este tamaño es esperado por la red neuronal, que decide cambiar de dirección)



La red neuronal de la dirección (de hecho, el clasificador) ordena a la izquierda. No muy correcto, pero soportable.

2



Una situación similar, nuevamente, se pierde la esquina inferior derecha (también hay asfalto mojado).
Sin embargo, la mayor parte del camino aún se reconoce.



El clasificador ofrece ir directamente.

3

La situación cuando el robot estaba en medio de la acera.



El camino se reconoce casi a la perfección.



El clasificador ordena tomar a la derecha (para encontrar el borde del camino la próxima vez).

Solicitud


Habiendo conjurado un poco sobre el firmware del tanque, reemplacé el detector de carretera de color con una red neuronal segmentada.

Al lanzar todo esto en la Raspberry Pi, lo primero que salió fue un rendimiento deprimente.
Se tarda 6 segundos en segmentar una imagen: durante este tiempo, el tanque logra deslizarse a través de todos los giros con un trote vigoroso.

En pruebas reales, esto sucedió, a pesar del reconocimiento casi perfecto de la acera y los comandos correctos de la red neuronal de control, durante el tiempo en que se procesó la imagen, el tanque logró hacerse a un lado.



En general, las imágenes de este tamaño no se pueden digerir en Raspberry.
Parece que todavía tienes que entrenar una red neuronal especializada.

Referencias


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


All Articles