Compartir a través de


Detección de objetos mediante Fast R-CNN

Tabla de contenido

Resumen

imagen de imagen

En este tutorial se describe cómo usar Fast R-CNN en la API de Python de CNTK. R-CNN rápido con BrainScript y cnkt.exe se describe aquí.

Los anteriores son ejemplos de imágenes y anotaciones de objetos para el conjunto de datos de comestibles (izquierda) y el conjunto de datos Pascal VOC (derecha) usado en este tutorial.

Fast R-CNN es un algoritmo de detección de objetos propuesto por Ross Girshick en 2015. El documento se acepta en ICCV 2015 y archivado en https://arxiv.org/abs/1504.08083. R-CNN rápido se basa en el trabajo anterior para clasificar eficazmente las propuestas de objetos mediante redes convolucionales profundas. En comparación con el trabajo anterior, Fast R-CNN emplea un esquema de agrupación de regiones de interés que permite reutilizar los cálculos de las capas convolucionales.

Configurar

Para ejecutar el código en este ejemplo, necesita un entorno de Python de CNTK (consulte aquí para obtener ayuda para la instalación). Instale los siguientes paquetes adicionales en el entorno de Python de cntk.

pip install opencv-python easydict pyyaml dlib

Archivos binarios compilados previamente para la regresión del rectángulo de selección y la supresión no máxima

La carpeta Examples\Image\Detection\utils\cython_modules contiene archivos binarios compilados previamente que son necesarios para ejecutar Fast R-CNN. Las versiones que se encuentran actualmente en el repositorio son Python 3.5 para Windows y Python 3.5, 3.6 para Linux, todos 64 bits. Si necesita una versión diferente, puede compilarla siguiendo los pasos descritos en

Copie los archivos binarios generados cython_bbox y (y/o gpu_nms) de $FRCN_ROOT/lib/utils a $CNTK_ROOT/Examples/Image/Detection/utils/cython_modulescpu_nms .

Ejemplo de datos y modelo de línea base

Usamos un modelo AlexNet previamente entrenado como base para el entrenamiento fast-R-CNN (para VGG u otros modelos base, consulte Uso de un modelo base diferente). Tanto el conjunto de datos de ejemplo como el modelo AlexNet previamente entrenado se pueden descargar ejecutando el siguiente comando de Python desde la carpeta FastRCNN:

python install_data_and_model.py

Ejecutar el ejemplo de toy

Para entrenar y evaluar la ejecución de Fast R-CNN

python run_fast_rcnn.py

Los resultados para el entrenamiento con 2000 ROIs en Grocery con AlexNet como modelo base deben ser similares a estos:

AP for          gerkin = 1.0000
AP for          butter = 1.0000
AP for         joghurt = 1.0000
AP for          eggBox = 1.0000
AP for         mustard = 1.0000
AP for       champagne = 1.0000
AP for          orange = 1.0000
AP for           water = 0.5000
AP for         avocado = 1.0000
AP for          tomato = 1.0000
AP for          pepper = 1.0000
AP for         tabasco = 1.0000
AP for           onion = 1.0000
AP for            milk = 1.0000
AP for         ketchup = 0.6667
AP for     orangeJuice = 1.0000
Mean AP = 0.9479

Para visualizar los cuadros de límite previstos y las etiquetas en las imágenes abiertas FastRCNN_config.py desde la FastRCNN carpeta y establecer

__C.VISUALIZE_RESULTS = True

Las imágenes se guardarán en la FastRCNN/Output/Grocery/ carpeta si ejecuta python run_fast_rcnn.py.

Entrenamiento en Pascal VOC

Para descargar los datos pascales y crear los archivos de anotación para Pascal en formato CNTK, ejecute los siguientes scripts:

python Examples/Image/DataSets/Pascal/install_pascalvoc.py
python Examples/Image/DataSets/Pascal/mappings/create_mappings.py

Cambie en dataset_cfg el get_configuration() método de run_fast_rcnn.py a .

from utils.configs.Pascal_config import cfg as dataset_cfg

Ahora está configurado para entrenar en los datos Pascal VOC 2007 mediante python run_fast_rcnn.py. Tenga en cuenta que el entrenamiento puede tardar un tiempo.

Entrenamiento por sus propios datos

Preparación de un conjunto de datos personalizado

Opción 1: Herramienta de etiquetado de objetos visuales (recomendado)

Visual Object Tagging Tool (VOTT) es una herramienta de anotación multiplataforma para etiquetar recursos de vídeo e imagen.

Captura de pantalla vott

VOTT proporciona las siguientes características:

  • Etiquetado asistido por ordenador y seguimiento de objetos en vídeos mediante el algoritmo de seguimiento camshift.
  • Exportar etiquetas y recursos al formato Fast-RCNN de CNTK para entrenar un modelo de detección de objetos.
  • Ejecutar y validar un modelo de detección de objetos CNTK entrenado en vídeos nuevos para generar modelos más seguros.

Anotación con VOTT:

  1. Descargar la versión más reciente
  2. Siga el archivo Léame para ejecutar un trabajo de etiquetado.
  3. Después de etiquetar etiquetas de exportación en el directorio del conjunto de datos

Opción 2: Usar scripts de anotación

Para entrenar un modelo CNTK Fast R-CNN en su propio conjunto de datos, proporcionamos dos scripts para anotar regiones rectangulares en imágenes y asignar etiquetas a estas regiones. Los scripts almacenarán las anotaciones en el formato correcto según sea necesario en el primer paso de la ejecución de Fast R-CNN (A1_GenerateInputROIs.py). En primer lugar, almacene las imágenes en la siguiente estructura de carpetas.

  • <your_image_folder>/negative : imágenes usadas para el entrenamiento que no contienen ningún objeto
  • <your_image_folder>/positive : imágenes usadas para el entrenamiento que contienen objetos
  • <your_image_folder>/testImages : imágenes usadas para pruebas que contienen objetos

Para las imágenes negativas, no es necesario crear ninguna anotación. Para las otras dos carpetas, use los scripts proporcionados:

  • Ejecute C1_DrawBboxesOnImages.py para dibujar cuadros de límite en las imágenes.
    • En el script establecido imgDir = <your_image_folder> (/positive o /testImages) antes de ejecutarse.
    • Agregue anotaciones mediante el cursor del mouse. Una vez anotados todos los objetos de una imagen, al presionar la tecla "n", se escribe el archivo .bboxes.txt y, a continuación, se continúa con la siguiente imagen, "u" deshace (es decir, quita) el último rectángulo y "q" sale de la herramienta de anotación.
  • Ejecute C2_AssignLabelsToBboxes.py para asignar etiquetas a los cuadros de límite.
    • En el script establecido imgDir = <your_image_folder> (/positive o /testImages) antes de ejecutar...
    • ... y adapte las clases del script para reflejar las categorías de objetos, por ejemplo classes = ("dog", "cat", "octopus").
    • El script carga estos rectángulos anotados manualmente para cada imagen, los muestra uno a uno y pide al usuario que proporcione la clase de objeto haciendo clic en el botón correspondiente a la izquierda de la ventana. Las anotaciones de verdad básica marcadas como "sin decidir" o "excluir" se excluyen completamente del procesamiento adicional.

Entrenamiento en un conjunto de datos personalizado

Después de almacenar las imágenes en la estructura de carpetas descrita y anotarlas, ejecute

python Examples/Image/Detection/utils/annotations/annotations_helper.py

después de cambiar la carpeta de ese script a la carpeta de datos. Por último, cree un MyDataSet_config.py elemento en la utils\configs carpeta siguiendo los ejemplos existentes:

__C.CNTK.DATASET == "YourDataSet":
__C.CNTK.MAP_FILE_PATH = "../../DataSets/YourDataSet"
__C.CNTK.CLASS_MAP_FILE = "class_map.txt"
__C.CNTK.TRAIN_MAP_FILE = "train_img_file.txt"
__C.CNTK.TEST_MAP_FILE = "test_img_file.txt"
__C.CNTK.TRAIN_ROI_FILE = "train_roi_file.txt"
__C.CNTK.TEST_ROI_FILE = "test_roi_file.txt"
__C.CNTK.NUM_TRAIN_IMAGES = 500
__C.CNTK.NUM_TEST_IMAGES = 200
__C.CNTK.PROPOSAL_LAYER_SCALES = [8, 16, 32]

Tenga en cuenta que __C.CNTK.PROPOSAL_LAYER_SCALES no se usa para Fast R-CNN, solo para Fast R-CNN.

Para entrenar y evaluar Fast R-CNN en los datos, cambie en dataset_cfg el get_configuration() método de run_fast_rcnn.py a

from utils.configs.MyDataSet_config import cfg as dataset_cfg

y ejecutan python run_fast_rcnn.py.

Detalles técnicos

El algoritmo Fast R-CNN se explica en la sección Detalles del algoritmo junto con una visión general de alto nivel de cómo se implementa en la API de Python de CNTK. Esta sección se centra en la configuración de Fast R-CNN y cómo usar diferentes modelos base.

Parámetros

Los parámetros se agrupan en tres partes:

  • Parámetros del detector (consulte FastRCNN/FastRCNN_config.py)
  • Parámetros del conjunto de datos (consulte, por ejemplo utils/configs/Grocery_config.py, )
  • Parámetros del modelo base (consulte, por ejemplo utils/configs/AlexNet_config.py, )

Las tres partes se cargan y combinan en el get_configuration() método de run_fast_rcnn.py. En esta sección se tratarán los parámetros del detector. Los parámetros del conjunto de datos se describen aquí, los parámetros del modelo base aquí. A continuación se describen los parámetros más importantes de FastRCNN_config.py. Todos los parámetros también se comentan en el archivo. La configuración usa el EasyDict paquete que permite un acceso sencillo a diccionarios anidados.

# Number of regions of interest [ROIs] proposals
__C.NUM_ROI_PROPOSALS = 200 # use 2000 or more for good results
# the minimum IoU (overlap) of a proposal to qualify for training regression targets
__C.BBOX_THRESH = 0.5

# Maximum number of ground truth annotations per image
__C.INPUT_ROIS_PER_IMAGE = 50
__C.IMAGE_WIDTH = 850
__C.IMAGE_HEIGHT = 850

# Use horizontally-flipped images during training?
__C.TRAIN.USE_FLIPPED = True
# If set to 'True' conv layers weights from the base model will be trained, too
__C.TRAIN_CONV_LAYERS = True

Las propuestas de ROI se calculan sobre la marcha en la primera época mediante la implementación de búsqueda selectiva del dlib paquete. El número de propuestas generadas se controla mediante el __C.NUM_ROI_PROPOSALS parámetro . Se recomienda usar alrededor de 2000 propuestas. El encabezado de regresión solo se entrena en esas ROIs que tienen una superposición (IoU) con un cuadro de verdad de tierra de al menos __C.BBOX_THRESH.

__C.INPUT_ROIS_PER_IMAGE especifica el número máximo de anotaciones de verdad del suelo por imagen. Actualmente, CNTK requiere establecer un número máximo. Si hay menos anotaciones, se rellenarán internamente. __C.IMAGE_WIDTH y __C.IMAGE_HEIGHT son las dimensiones que se usan para cambiar el tamaño y rellenar las imágenes de entrada.

__C.TRAIN.USE_FLIPPED = True aumentará los datos de entrenamiento al voltear todas las imágenes de todas las demás épocas, es decir, la primera época tiene todas las imágenes normales, la segunda tiene todas las imágenes volteadas, etc. __C.TRAIN_CONV_LAYERS determina si las capas convolucionales, de entrada a la asignación de características convolucionales, se entrenarán o corregirán. Corregir los pesos de la capa de conv significa que los pesos del modelo base se toman y no se modifican durante el entrenamiento. (También puede especificar cuántas capas de conv desea entrenar, consulte la sección Uso de un modelo base diferente).

# NMS threshold used to discard overlapping predicted bounding boxes
__C.RESULTS_NMS_THRESHOLD = 0.5

# If set to True the following two parameters need to point to the corresponding files that contain the proposals:
# __C.DATA.TRAIN_PRECOMPUTED_PROPOSALS_FILE
# __C.DATA.TEST_PRECOMPUTED_PROPOSALS_FILE
__C.USE_PRECOMPUTED_PROPOSALS = False

__C.RESULTS_NMS_THRESHOLD es el umbral de NMS que se usa para descartar cuadros de límite previstos superpuestos en la evaluación. Un umbral inferior produce menos eliminaciones y, por tanto, más cuadros de límite previstos en la salida final. Si establece __C.USE_PRECOMPUTED_PROPOSALS = True el lector leerá las ROIs precalutadas de los archivos de texto. Esto se usa por ejemplo para el entrenamiento en datos pascales VOC. Los nombres __C.DATA.TRAIN_PRECOMPUTED_PROPOSALS_FILE de archivo y __C.DATA.TEST_PRECOMPUTED_PROPOSALS_FILE se especifican en Examples/Image/Detection/utils/configs/Pascal_config.py.

# The basic segmentation is performed kvals.size() times. The k parameter is set (from, to, step_size)
__C.roi_ss_kvals = (10, 500, 5)
# When doing the basic segmentations prior to any box merging, all
# rectangles that have an area < min_size are discarded. Therefore, all outputs and
# subsequent merged rectangles are built out of rectangles that contain at
# least min_size pixels. Note that setting min_size to a smaller value than
# you might otherwise be interested in using can be useful since it allows a
# larger number of possible merged boxes to be created
__C.roi_ss_min_size = 9
# There are max_merging_iterations rounds of neighboring blob merging.
# Therefore, this parameter has some effect on the number of output rectangles
# you get, with larger values of the parameter giving more output rectangles.
# Hint: set __C.CNTK.DEBUG_OUTPUT=True to see the number of ROIs from selective search
__C.roi_ss_mm_iterations = 30
# image size used for ROI generation
__C.roi_ss_img_size = 200

Los parámetros anteriores configuran la búsqueda selectiva de dlib. Para obtener más información, consulte la página principal de dlib. Los siguientes parámetros adicionales se usan para filtrar las ROIs generadas w.r.t. longitud mínima y máxima del lado, área y relación de aspecto.

# minimum relative width/height of an ROI
__C.roi_min_side_rel = 0.01
# maximum relative width/height of an ROI
__C.roi_max_side_rel = 1.0
# minimum relative area of an ROI
__C.roi_min_area_rel = 0.0001
# maximum relative area of an ROI
__C.roi_max_area_rel = 0.9
# maximum aspect ratio of an ROI vertically and horizontally
__C.roi_max_aspect_ratio = 4.0
# aspect ratios of ROIs for uniform grid ROIs
__C.roi_grid_aspect_ratios = [1.0, 2.0, 0.5]

Si la búsqueda selectiva devuelve más ROIs de las solicitadas, se muestrean aleatoriamente. Si se devuelven menos ROIs adicionales se generan en una cuadrícula normal mediante el especificado __C.roi_grid_aspect_ratios.

Uso de un modelo base diferente

Para usar un modelo base diferente, debe elegir una configuración de modelo diferente en el get_configuration() método de run_fast_rcnn.py. Se admiten dos modelos inmediatamente:

    # for VGG16 base model use:         from utils.configs.VGG16_config import cfg as network_cfg
    # for AlexNet base model use:       from utils.configs.AlexNet_config import cfg as network_cfg

Para descargar el modelo VGG16, use el script de descarga en <cntkroot>/PretrainedModels:

    python download_model.py VGG16_ImageNet_Caffe

Si desea usar otro modelo base diferente, debe copiar, por ejemplo, el archivo utils/configs/VGG16_config.py de configuración y modificarlo según el modelo base:

# model config
__C.MODEL.BASE_MODEL = "VGG16"
__C.MODEL.BASE_MODEL_FILE = "VGG16_ImageNet_Caffe.model"
__C.MODEL.IMG_PAD_COLOR = [103, 116, 123]
__C.MODEL.FEATURE_NODE_NAME = "data"
__C.MODEL.LAST_CONV_NODE_NAME = "relu5_3"
__C.MODEL.START_TRAIN_CONV_NODE_NAME = "pool2" # __C.MODEL.FEATURE_NODE_NAME
__C.MODEL.POOL_NODE_NAME = "pool5"
__C.MODEL.LAST_HIDDEN_NODE_NAME = "drop7"
__C.MODEL.FEATURE_STRIDE = 16
__C.MODEL.RPN_NUM_CHANNELS = 512
__C.MODEL.ROI_DIM = 7

Para investigar los nombres de nodo del modelo base, puede usar el plot() método de cntk.logging.graph. Tenga en cuenta que los modelos resNet no se admiten actualmente, ya que la agrupación de roi en CNTK aún no admite la agrupación media de roi.

Detalles del algoritmo

Fast R-CNN

Los R-CNN para la detección de objetos fueron presentados por primera vez en 2014 por Ross Girshick et al., y se mostraron para superar los enfoques anteriores de última generación en uno de los principales desafíos de reconocimiento de objetos en el campo: Pascal VOC. Desde entonces, se publicaron dos artículos de seguimiento que contienen mejoras de velocidad significativas: Fast R-CNN y Faster R-CNN.

La idea básica de R-CNN es tomar una red neuronal profunda que se entrenó originalmente para la clasificación de imágenes mediante millones de imágenes anotadas y modificarla con el fin de la detección de objetos. La idea básica del primer documento de R-CNN se ilustra en la figura siguiente (tomada del documento): (1) Dada una imagen de entrada, (2) en un primer paso, se generan propuestas de gran número de regiones. (3) Estas propuestas de región, o regiones de interés (ROIs), se envían cada una de ellas de forma independiente a través de la red que genera un vector de, por ejemplo, 4096 valores de punto flotante para cada ROI. Por último, (4) se aprende un clasificador que toma la representación de ROI flotante 4096 como entrada y genera una etiqueta y confianza para cada ROI.

Imagen

Aunque este enfoque funciona bien en términos de precisión, es muy costoso calcular, ya que la red neuronal debe evaluarse para cada ROI. Fast R-CNN aborda este inconveniente mediante la evaluación de la mayoría de la red (para ser específicas: las capas de convolución) una sola vez por imagen. Según los autores, esto conduce a una velocidad de 213 veces durante las pruebas y una velocidad de 9 veces mayor durante el entrenamiento sin pérdida de precisión. Esto se logra mediante el uso de una capa de agrupación de ROI que proyecta el ROI en el mapa de características convolucionales y realiza la agrupación máxima para generar el tamaño de salida deseado que espera la capa siguiente. En el ejemplo de AlexNet que se usa en este tutorial, la capa de agrupación de ROI se coloca entre la última capa convolucional y la primera capa totalmente conectada. En el código de la API de Python de CNTK que se muestra a continuación, esto se realiza mediante la clonación de dos partes de la red, y conv_layers .fc_layers A continuación, la imagen de entrada se normaliza primero, se inserta a través de conv_layers, la roipooling capa y fc_layers , por último, se agregan los encabezados de predicción y regresión que predicen la etiqueta de clase y los coeficientes de regresión por ROI candidato, respectivamente.

def create_fast_rcnn_model(features, roi_proposals, label_targets, bbox_targets, bbox_inside_weights, cfg):
    # Load the pre-trained classification net and clone layers
    base_model = load_model(cfg['BASE_MODEL_PATH'])
    conv_layers = clone_conv_layers(base_model, cfg)
    fc_layers = clone_model(base_model, [cfg["MODEL"].POOL_NODE_NAME], [cfg["MODEL"].LAST_HIDDEN_NODE_NAME], clone_method=CloneMethod.clone)

    # Normalization and conv layers
    feat_norm = features - Constant([[[v]] for v in cfg["MODEL"].IMG_PAD_COLOR])
    conv_out = conv_layers(feat_norm)

    # Fast RCNN and losses
    cls_score, bbox_pred = create_fast_rcnn_predictor(conv_out, roi_proposals, fc_layers, cfg)
    detection_losses = create_detection_losses(...)
    pred_error = classification_error(cls_score, label_targets, axis=1)

    return detection_losses, pred_error

def create_fast_rcnn_predictor(conv_out, rois, fc_layers, cfg):
    # RCNN
    roi_out = roipooling(conv_out, rois, cntk.MAX_POOLING, (6, 6), spatial_scale=1/16.0)
    fc_out = fc_layers(roi_out)

    # prediction head
    cls_score = plus(times(fc_out, W_pred), b_pred, name='cls_score')

    # regression head
    bbox_pred = plus(times(fc_out, W_regr), b_regr, name='bbox_regr')

    return cls_score, bbox_pred

La implementación original de Caffe que se usa en los documentos de R-CNN se puede encontrar en GitHub: RCNN, Fast R-CNN y Faster R-CNN.

Entrenamiento de SVM frente a NN

Patrick Buehler proporciona instrucciones sobre cómo entrenar una SVM en la salida de R-CNN de CNTK Fast (con las características 4096 de la última capa totalmente conectada), así como una discusión sobre ventajas y desventajas aquí.

La búsqueda selectiva es un método para buscar un conjunto grande de posibles ubicaciones de objetos en una imagen, independientemente de la clase del objeto real. Funciona agrupando píxeles de imagen en segmentos y, a continuación, realizando la agrupación en clústeres jerárquicos para combinar segmentos del mismo objeto en propuestas de objetos.

imagen de imagen

Para complementar las ROIs detectadas de la búsqueda selectiva, agregamos ROIs que cubren uniformemente la imagen a diferentes escalas y relaciones de aspecto. La imagen de la izquierda muestra una salida de ejemplo de búsqueda selectiva, donde cada ubicación de objeto posible se visualiza mediante un rectángulo verde. Las ROIs que son demasiado pequeñas, demasiado grandes, etc. se descartan (medio) y, por último, las ROIs que cubren uniformemente la imagen se agregan (derecha). Estos rectángulos se usan después como regiones de interés (ROIs) en la canalización de R-CNN.

El objetivo de la generación de ROI es encontrar un pequeño conjunto de ROIs que, sin embargo, cubra de forma estricta tantos objetos de la imagen como sea posible. Este cálculo debe ser lo suficientemente rápido, al mismo tiempo que la búsqueda de ubicaciones de objetos en diferentes escalas y relaciones de aspecto. Se mostró que la búsqueda selectiva funciona bien para esta tarea, con una buena precisión para acelerar las ventajas y desventajas.

NMS (supresión no máxima)

Los métodos de detección de objetos suelen generar varias detecciones que cubren completamente o parcialmente el mismo objeto en una imagen. Estas ROIs deben combinarse para poder contar objetos y obtener sus ubicaciones exactas en la imagen. Esto se hace tradicionalmente mediante una técnica denominada Supresión no máxima (NMS). La versión de NMS que usamos (y que también se usó en las publicaciones de R-CNN) no combina ROIs, sino que intenta identificar qué ROIs cubren mejor las ubicaciones reales de un objeto y descarta todas las demás ROIs. Esto se implementa mediante la selección iterativa del ROI con mayor confianza y eliminación de todas las demás ROIs que se superponen significativamente a este ROI y se clasifican como de la misma clase. El umbral de la superposición se puede establecer en PARAMETERS.py (detalles).

Resultados de detección antes (izquierda) y después (derecha) Supresión no máxima:

imagen de imagen

mAP (media precisión media)

Una vez entrenado, la calidad del modelo se puede medir mediante criterios diferentes, como precisión, recuperación, precisión, área bajo curva, etc. Una métrica común que se usa para el desafío de reconocimiento de objetos Pascal VOC es medir la precisión media (AP) para cada clase. La siguiente descripción de Average Precision se toma de Everingham et. al. La precisión media media (mAP) se calcula tomando el promedio sobre los PUNTOS de acceso de todas las clases.

Para una tarea y clase determinada, la curva de precisión y recuperación se calcula a partir de la salida clasificada de un método. La recuperación se define como la proporción de todos los ejemplos positivos clasificados por encima de un rango determinado. La precisión es la proporción de todos los ejemplos anteriores que son de la clase positiva. El AP resume la forma de la curva de precisión y recuperación, y se define como la precisión media en un conjunto de once niveles de recuperación espaciados igualmente [0,0,1, . . . ,1]:

imagen

La precisión en cada nivel de recuperación r se interpola tomando la precisión máxima medida para un método para el que la recuperación correspondiente supere r:

imagen

donde p( Comparador) es la precisión medida en la recuperación Comparador. La intención de interpolar la curva de precisión y recuperación de esta manera es reducir el impacto de las "alternancias" en la curva de precisión y recuperación, causada por pequeñas variaciones en la clasificación de ejemplos. Debe tenerse en cuenta que para obtener una puntuación alta, un método debe tener precisión en todos los niveles de recuperación: penaliza los métodos que recuperan solo un subconjunto de ejemplos con alta precisión (por ejemplo, vistas laterales de automóviles).