Introducción
Faster R-CNN es un algoritmo de detección de objetivos de dos etapas propuesto por Ross B. Girshick en 2016. Faster R-CNN integra la extracción de características, la red de propuesta de región para la extracción de la región de interés y la regresión y clasificación final del cuadro delimitador en una sola red, lo que mejora en gran medida el rendimiento general de la red.
Este artículo analiza Faster R-CNN desde los siguientes cuatro aspectos:
- Capas de conv. Faster R-CNN primero usa un conjunto de capas simples de conv+relu+pooling para extraer mapas de características de la imagen de entrada. Estos mapas de características se compartirán para la capa RPN subsiguiente y la capa completamente conectada;
- Región Propuesta Redes. La red RPN se usa para generar propuestas de regiones efectivas.Esta capa juzga si el ancla pertenece a positivo (fondo) o negativo (primer plano) a través de softmax, y luego usa la regresión de cuadro delimitador para corregir las anclas para obtener propuestas precisas;
- Puesta en común del retorno de la inversión. Esta capa recopila los mapas de características de entrada y las propuestas y, después de sintetizar esta información, extrae los mapas de características de la propuesta y los envía a la siguiente capa totalmente conectada;
- Clasificación y regresión Utilice los mapas de características de la propuesta para calcular la categoría de las propuestas y vuelva a realizar la regresión del cuadro delimitador para obtener la posición final precisa;
columna vertebral
Tomando VGG16 como ejemplo, presente la composición principal de Faster R-CNN. La columna vertebral contiene tres capas de conv, relu y pooling.Como se muestra en la siguiente figura, hay 13 capas de conv, 13 capas de relu y 4 capas de pooling.
La configuración de parámetros de todas las capas convolucionales es la misma, kernel_size=3, pad=1, stride=1, es decir, los tamaños del mapa de características de entrada y salida son los mismos, y los parámetros de la capa de agrupación se establecen en: kernel_size= 2, pad=0, stride =2, es decir, el tamaño de salida es solo la mitad del tamaño de entrada.
Dado que toda la red troncal contiene 4 capas de agrupación, se supone que el tamaño de la imagen de entrada es M ∗ NM *NMETRO∗N , luego, después de la inferencia de la columna vertebral, el tamaño del mapa de características de salida esM 16 ∗ N 16 \frac{M}{16}*\frac{N}{16}dieciséism∗dieciséisnorte.
Redes de Propuestas Regionales(RPN)
Una vez que la red troncal proporciona las características de la imagen, la imagen de entrada ingresa a la red RPN. Los resultados específicos se muestran en la siguiente figura: La red RPN se divide
en dos ramas: clasificación y regresión. La rama de clasificación usa sotfmax para clasificar la red predeterminada. el anclaje del marco candidato es positivo o negativo; la rama de regresión es responsable de predecir el desplazamiento del cuadro objetivo real en relación con el cuadro candidato predeterminado. Finalmente, la capa Propuesta combina el ancla positiva y el desplazamiento de regresión correspondiente para obtener la propuesta.
El siguiente tamaño de imagen de entrada es C = 3, H = 576, W = 1024 C = 3, H = 576, W = 1024C=3 ,H=576 ,W=1024 casos, después de que la red troncal extrae la característica, el tamaño del mapa de características es1x512x36x64
(disposición NCHW).
anclas
En Faster R-CNN, se proporcionan 9 anclas de diferentes tamaños y diferentes relaciones de aspecto, que contienen cuatro valores ( x 1 , y 1 , x 2 , y 2 ) (x_1,y_1,x_2,y_2)( X1,y1,X2,y2) representa las coordenadas de las esquinas superior izquierda e inferior derecha del rectángulo, y el ancla se muestra en la siguiente figura:
Una cosa a tener en cuenta es queel tamaño del ancla en Faster R-CNN es relativo al tamaño de entrada de la red. Tome el tamaño de la imagen de entrada comoC = 3, H = 576, W = 1024 C = 3, H = 576, W = 1024C=3 ,H=576 ,W=1024 casos, Faster R-CNN contiene un total de:
ceil ( 1024 / 16 ) ∗ ceil ( 576 / 16 ) ∗ 9 = 64 ∗ 36 ∗ 9 = 20736 ceil(1024/16)*ceil(576/16)*9 =64 *36*9=20736ce i l ( 1024/16 )∗ce i l ( 576/16 )∗9=64∗36∗9=20,736
anclas, estas anclas se reflejan en la entrada de la red, como se muestra en la figura a continuación, para cada ancla se requiere una rama de clasificación para determinar si contiene objetos, y la inclusión de objetos es positiva, de lo contrario es negativa. Al mismo tiempo, dado que existe un desplazamiento entre la posición real del objetivo y el ancla, se necesita la rama de regresión para predecir el desplazamiento.
rama softmax
Después del backbone, el tamaño del mapa de características es 1x512x36x64
, primero a través de la convolución 1×1, el tamaño del mapa de características obtenido es 1x18x36x64
, entre ellos 18=2*9
, hay 9 anclas, y cada ancla puede ser positiva o negativa.
Luego hay una operación de remodelación, la dimensión del mapa de características obtenido 1x2x36*9x64
es principalmente para la conveniencia de la clasificación softmax, y luego se remodela para restaurar el estado original. El fragmento de código de implementación de la rama de clasificación es el siguiente:
# define bg/fg classifcation score layer
self.nc_score_out = len(self.anchor_scales) * len(self.anchor_ratios) * 2 # 2(bg/fg) * 9 (anchors)
self.RPN_cls_score = nn.Conv2d(512, self.nc_score_out, 1, 1, 0) # 1×1卷积
def forward(): # 前向推理
# get rpn classification score
rpn_cls_score = self.RPN_cls_score(rpn_conv1)
# reshape + softmax + reshape
rpn_cls_score_reshape = self.reshape(rpn_cls_score, 2)
rpn_cls_prob_reshape = F.softmax(rpn_cls_score_reshape, 1)
rpn_cls_prob = self.reshape(rpn_cls_prob_reshape, self.nc_score_out)
La clasificación sotfmax obtiene anclas positivas, lo que equivale a extraer inicialmente el área candidata al objetivo de detección.
rama de regresión
La regresión de rama de regresión obtiene el desplazamiento entre el ancla y la verdad del suelo, por lo que en la fase de entrenamiento, la señal de supervisión es la brecha entre el ancla y el marco real ( tx , ty , tw , th ) (t_x,t_y,t_w , t_h)( tx,ttu,tw,th),其中tx , ty t_x,t_ytx,ttues el valor de traslación del punto central, tw , th t_w,t_htw,thes el valor de escala de ancho y alto. ( tx , ty , tw , th ) (t_x,t_y,t_w,t_h)( tx,ttu,tw,th) se calcula de la siguiente manera:
tx = ( x − xa ) / wa ; ty = ( y − ya ) / ha t_x = (x - x_a)/w_a; t_y=(y-y_a)/h_atx=( X−Xun) / wun;ttu=( y−yun) / horaun
tw = registro ( w / wa ) ; th = log ( h / ha ) t_w=log(w/w_a);t_h=log(h/h_a)tw=logaritmo ( w / w _ _un) ;th=log ( h / h _ _un)
de los cualesxa , ya , wa , ha x_a, y_a, w_a, h_aXun,yun,wun,hunEs el valor de la coordenada del ancla. El fragmento de código de la rama de regresión es el siguiente:
# define anchor box offset prediction layer
self.nc_bbox_out = len(self.anchor_scales) * len(self.anchor_ratios) * 4 # 4(coords) * 9 (anchors)
self.RPN_bbox_pred = nn.Conv2d(512, self.nc_bbox_out, 1, 1, 0)
def forward():
# get rpn offsets to the anchor boxes
rpn_bbox_pred = self.RPN_bbox_pred(rpn_conv1)
Capa de propuesta
La capa de propuesta calcula una propuesta precisa a través de los anclajes positivos y su compensación de regresión correspondiente, y la envía a la capa de agrupación de RoI posterior. La definición de la capa Propuesta es la siguiente:
# define proposal layer
self.RPN_proposal = _ProposalLayer(self.feat_stride, self.anchor_scales, self.anchor_ratios)
def forward():
rois = self.RPN_proposal((rpn_cls_prob.data, rpn_bbox_pred.data, im_info,
cfg_key))
La capa de propuesta tiene tres entradas: la salida de la rama softmax y la rama de regresión, más im_info. Donde im_info=[M,N,scale_factor], M y N son las dimensiones de entrada de la red, scale_factor es la información de escala de la imagen original PxQ, redimensionada a MxN.
El proceso de ejecución de la capa de propuesta es el siguiente:
- Obtenga el marco objetivo preliminar y retroceda todos los anclajes de acuerdo con el desplazamiento previsto para obtener el marco objetivo preliminar;
anchors = self._anchors.view(1, A, 4) + shifts.view(K, 1, 4)
anchors = anchors.view(1, K * A, 4).expand(batch_size, K * A, 4)
# Transpose and reshape predicted bbox transformations to get them
# into the same order as the anchors:
bbox_deltas = bbox_deltas.permute(0, 2, 3, 1).contiguous()
bbox_deltas = bbox_deltas.view(batch_size, -1, 4)
# Convert anchors into proposals via bbox transformations
proposals = bbox_transform_inv(anchors, bbox_deltas, batch_size)
- Elimine las anclas positivas que excedan los límites de la imagen;
# 2. clip predicted boxes to image
proposals = clip_boxes(proposals, im_info, batch_size)
- Ordene las puntuaciones softmax positivas de entrada y seleccione los primeros anclajes RPN_PRE_NMS_TOP_N;
# # 4. sort all (proposal, score) pairs by score from highest to lowest
_, order = torch.sort(scores_keep, 1, True)
if pre_nms_topN > 0 and pre_nms_topN < scores_keep.numel():
order_single = order_single[:pre_nms_topN]
proposals_single = proposals_single[order_single, :]
scores_single = scores_single[order_single].view(-1,1)
- Eliminar anclas positivas con tamaño muy pequeño;
- Realice NMS en los anclajes positivos restantes;
# 6. apply nms (e.g. threshold = 0.7)
# 7. take after_nms_topN (e.g. 300)
# 8. return the top proposals (-> RoIs top)
keep_idx_i = nms(torch.cat((proposals_single, scores_single), 1), nms_thresh, force_cpu=not cfg.USE_GPU_NMS)
keep_idx_i = keep_idx_i.long().view(-1)
if post_nms_topN > 0:
keep_idx_i = keep_idx_i[:post_nms_topN]
proposals_single = proposals_single[keep_idx_i, :]
scores_single = scores_single[keep_idx_i, :]
La información de destino de la salida de propuesta por la capa de propuesta es relativa a la imagen de entrada M×N.
Agrupación de retorno de la inversión
La capa de RoI Pooling es responsable de recopilar propuestas y calcular los mapas de características correspondientes a las propuestas, y luego ingresarlos en la red posterior. Tiene dos entradas:
- mapas de características compartidas;
- Salida de buzones de propuestas por RPN (relativa a entrada de red M×N)
# define anchor target layer
self.RPN_anchor_target = _AnchorTargetLayer(self.feat_stride, self.anchor_scales, self.anchor_ratios)
def forward():
rpn_data = self.RPN_anchor_target((rpn_cls_score.data, gt_boxes, im_info, num_boxes))
La razón para usar RoI Pooling:
dado que el tamaño y la forma de los cuadros de propuesta generados por RPN son diferentes, para un modelo entrenado, la entrada y la salida deben tener un tamaño fijo. Para cajas de diferentes formas, Faster R-CNN propone utilizar RoI Pooling para resolver este problema.
El flujo de trabajo de RoI Pooling:
Suponga que el mapa de características de entrada es como se muestra en la figura a continuación:
La posición de los cuadros de propuesta proyectados en el mapa de características es como se muestra en la figura:
Suponiendo que la salida es un mapa de características de 2 × 2, luego, el área de proyección se divide en secciones de 2 × 2, obtenga:
Luego haga una agrupación máxima para cada sección, obtenga:
Por lo tanto, la agrupación de RoI consiste en agrupar mapas de características de diferentes tamaños en mapas de características del mismo tamaño, lo que es beneficioso para la salida a la siguiente capa de red.
Dado que la posición de la propuesta generalmente se obtiene mediante la regresión del modelo, generalmente es un número de coma flotante, y el mapa de características después de la agrupación requiere un tamaño fijo. Hay dos cuantificaciones en este proceso:
- Cuantifique los límites de la propuesta en coordenadas con valores enteros;
- Dividir el área límite cuantificada en kxk secciones en promedio y cuantificar el límite de cada sección;
Después de las dos cuantificaciones anteriores, el marco candidato tiene una cierta desviación de la posición de regresión inicial en este momento, y esta desviación afectará la precisión de detección .
Clasificación y regresión
La salida del mapa de características 7×7 por RoI Pooling se envía luego a un módulo Clasificador, y luego se calcula la categoría específica de cada propuesta a través de la capa Lineal y softmax, y se genera la confianza del objetivo, y el desplazamiento de posición de la propuesta es obtenido además mediante el uso de la cantidad de regresión para retroceder cuadros objetivo más precisos. Como se muestra en la siguiente figura:
A continuación se muestra el código del módulo Clasificador, que forma parte del modelo VGG;
self.classifier = nn.Sequential(
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(True),
nn.Dropout(p=dropout),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Dropout(p=dropout),
)
La capa totalmente conectada y la capa softmax determinan la categoría de la propuesta y generan la confianza correspondiente;
self.RCNN_cls_score = nn.Linear(4096, self.n_classes)
cls_prob = F.softmax(cls_score, 1)
El desplazamiento se obtiene utilizando la capa completamente conectada para refinar aún más la posición del objetivo.
self.RCNN_bbox_pred = nn.Linear(4096, 4 * self.n_classes)