Detecção de Objetos Multiescala
===============================
Em :numref:`sec_anchor`, geramos várias caixas de âncora centralizadas
em cada pixel da imagem de entrada. Essas caixas de âncora são usadas
para amostrar diferentes regiões da imagem de entrada. No entanto, se as
caixas de âncora forem geradas centralizadas em cada pixel da imagem,
logo haverá muitas caixas de âncora para calcularmos. Por exemplo,
assumimos que a imagem de entrada tem uma altura e uma largura de 561 e
728 pixels, respectivamente. Se cinco formas diferentes de caixas de
âncora são geradas centralizadas em cada pixel, mais de dois milhões de
caixas de âncora (:math:`561 \times 728 \times 5`) precisam ser
previstas e rotuladas na imagem.
Não é difícil reduzir o número de caixas de âncora. Uma maneira fácil é
aplicar amostragem uniforme em uma pequena parte dos pixels da imagem de
entrada e gerar caixas de âncora centralizadas nos pixels amostrados.
Além disso, podemos gerar caixas de âncora de números e tamanhos
variados em várias escalas. Observe que é mais provável que objetos
menores sejam posicionados na imagem do que objetos maiores. Aqui,
usaremos um exemplo simples: Objetos com formas de :math:`1 \times 1`,
:math:`1 \times 2`, e :math:`2 \times 2` podem ter 4, 2 e 1 posição(ões)
possível(is) em uma imagem com a forma :math:`2 \times 2`.. Portanto, ao
usar caixas de âncora menores para detectar objetos menores, podemos
amostrar mais regiões; ao usar caixas de âncora maiores para detectar
objetos maiores, podemos amostrar menos regiões.
Para demonstrar como gerar caixas de âncora em várias escalas, vamos ler
uma imagem primeiro. Tem uma altura e largura de :math:`561 \times 728`
pixels.
.. raw:: html
.. raw:: html
.. code:: python
%matplotlib inline
from mxnet import image, np, npx
from d2l import mxnet as d2l
npx.set_np()
img = image.imread('../img/catdog.jpg')
h, w = img.shape[0:2]
h, w
.. parsed-literal::
:class: output
(561, 728)
.. raw:: html
.. raw:: html
.. code:: python
%matplotlib inline
import torch
from d2l import torch as d2l
img = d2l.plt.imread('../img/catdog.jpg')
h, w = img.shape[0:2]
h, w
.. parsed-literal::
:class: output
(561, 728)
.. raw:: html
.. raw:: html
Em :numref:`sec_conv_layer`, a saída da matriz 2D da rede neural
convolucional (CNN) é chamada um mapa de recursos. Podemos determinar os
pontos médios de caixas de âncora uniformemente amostradas em qualquer
imagem, definindo a forma do mapa de feições.
A função ``display_anchors`` é definida abaixo. Vamos gerar caixas de
âncora ``anchors`` centradas em cada unidade (pixel) no mapa de feições
``fmap``. Uma vez que as coordenadas dos eixos :math:`x` e :math:`y` nas
caixas de âncora ``anchors`` foram divididas pela largura e altura do
mapa de feições ``fmap``, valores entre 0 e 1 podem ser usados para
representar as posições relativas das caixas de âncora em o mapa de
recursos. Uma vez que os pontos médios das “âncoras” das caixas de
âncora se sobrepõem a todas as unidades no mapa de características
“fmap”, as posições espaciais relativas dos pontos médios das “âncoras”
em qualquer imagem devem ter uma distribuição uniforme. Especificamente,
quando a largura e a altura do mapa de feições são definidas para
``fmap_w`` e\ ``fmap_h`` respectivamente, a função irá conduzir uma
amostragem uniforme para linhas ``fmap_h`` e colunas de
pixels\ ``fmap_w`` e usá-los como pontos médios para gerar caixas de
âncora com tamanho ``s`` (assumimos que o comprimento da lista ``s`` é
1) e diferentes proporções (``ratios``).
.. raw:: html
.. raw:: html
.. code:: python
def display_anchors(fmap_w, fmap_h, s):
d2l.set_figsize()
# The values from the first two dimensions will not affect the output
fmap = np.zeros((1, 10, fmap_h, fmap_w))
anchors = npx.multibox_prior(fmap, sizes=s, ratios=[1, 2, 0.5])
bbox_scale = np.array((w, h, w, h))
d2l.show_bboxes(d2l.plt.imshow(img.asnumpy()).axes,
anchors[0] * bbox_scale)
.. raw:: html
.. raw:: html
.. code:: python
def display_anchors(fmap_w, fmap_h, s):
d2l.set_figsize()
# The values from the first two dimensions will not affect the output
fmap = torch.zeros((1, 10, fmap_h, fmap_w))
anchors = d2l.multibox_prior(fmap, sizes=s, ratios=[1, 2, 0.5])
bbox_scale = torch.tensor((w, h, w, h))
d2l.show_bboxes(d2l.plt.imshow(img).axes,
anchors[0] * bbox_scale)
.. raw:: html
.. raw:: html
Primeiro, vamos nos concentrar na detecção de pequenos objetos. A fim de
tornar mais fácil distinguir na exibição, as caixas de âncora com
diferentes pontos médios aqui não se sobrepõem. Assumimos que o tamanho
das caixas de âncora é 0,15 e a altura e largura do mapa de feições são
4. Podemos ver que os pontos médios das caixas de âncora das 4 linhas e
4 colunas da imagem estão uniformemente distribuídos.
.. raw:: html
.. raw:: html
.. code:: python
display_anchors(fmap_w=4, fmap_h=4, s=[0.15])
.. figure:: output_multiscale-object-detection_ad7147_21_0.svg
.. raw:: html
.. raw:: html
.. code:: python
display_anchors(fmap_w=4, fmap_h=4, s=[0.15])
.. figure:: output_multiscale-object-detection_ad7147_24_0.svg
.. raw:: html
.. raw:: html
Vamos reduzir a altura e a largura do mapa de feições pela metade e usar
uma caixa de âncora maior para detectar objetos maiores. Quando o
tamanho é definido como 0,4, ocorrerão sobreposições entre as regiões de
algumas caixas de âncora.
.. raw:: html
.. raw:: html
.. code:: python
display_anchors(fmap_w=2, fmap_h=2, s=[0.4])
.. figure:: output_multiscale-object-detection_ad7147_30_0.svg
.. raw:: html
.. raw:: html
.. code:: python
display_anchors(fmap_w=2, fmap_h=2, s=[0.4])
.. figure:: output_multiscale-object-detection_ad7147_33_0.svg
.. raw:: html
.. raw:: html
Finalmente, vamos reduzir a altura e a largura do mapa de feições pela
metade e aumentar o tamanho da caixa de âncora para 0,8. Agora, o ponto
médio da caixa de âncora é o centro da imagem.
.. raw:: html
.. raw:: html
.. code:: python
display_anchors(fmap_w=1, fmap_h=1, s=[0.8])
.. figure:: output_multiscale-object-detection_ad7147_39_0.svg
.. raw:: html
.. raw:: html
.. code:: python
display_anchors(fmap_w=1, fmap_h=1, s=[0.8])
.. figure:: output_multiscale-object-detection_ad7147_42_0.svg
.. raw:: html
.. raw:: html
Como geramos caixas de âncora de tamanhos diferentes em escalas
múltiplas, vamos usá-las para detectar objetos de vários tamanhos em
escalas diferentes. Agora vamos apresentar um método baseado em redes
neurais convolucionais (CNNs).
Em uma determinada escala, suponha que geramos :math:`h \times w`
conjuntos de caixas de âncora com diferentes pontos médios baseados em
:math:`c_i` mapas de feições com a forma :math:`h \times w` e o número
de caixas de âncora em cada conjunto é :math:`a` . Por exemplo, para a
primeira escala do experimento, geramos 16 conjuntos de caixas de âncora
com diferentes pontos médios com base em 10 (número de canais) mapas de
recursos com uma forma de :math:`4 \times 4`, e cada conjunto contém 3
caixas de âncora. A seguir, cada caixa de âncora é rotulada com uma
categoria e deslocamento com base na classificação e posição da caixa
delimitadora de verdade. Na escala atual, o modelo de detecção de objeto
precisa prever a categoria e o offset de :math:`h \times w` conjuntos de
caixas de âncora com diferentes pontos médios com base na imagem de
entrada.
Assumimos que os mapas de características :math:`c_i` são a saída
intermediária da CNN com base na imagem de entrada. Uma vez que cada
mapa de características tem :math:`h \times w` posições espaciais
diferentes, a mesma posição terá :math:`c_i` unidades. De acordo com a
definição de campo receptivo em :numref:`sec_conv_layer`, as unidades
:math:`c_i` do mapa de feições na mesma posição espacial têm o mesmo
campo receptivo na imagem de entrada. Assim, elas representam a
informação da imagem de entrada neste mesmo campo receptivo. Portanto,
podemos transformar as unidades :math:`c_i` do mapa de feições na mesma
posição espacial nas categorias e deslocamentos das :math:`a` caixas de
âncora geradas usando essa posição como um ponto médio. Não é difícil
perceber que, em essência, usamos as informações da imagem de entrada em
um determinado campo receptivo para prever a categoria e deslocamento
das caixas de âncora perto do campo na imagem de entrada.
Quando os mapas de recursos de camadas diferentes têm campos receptivos
de tamanhos diferentes na imagem de entrada, eles são usados para
detectar objetos de tamanhos diferentes. Por exemplo, podemos projetar
uma rede para ter um campo receptivo mais amplo para cada unidade no
mapa de recursos que está mais perto da camada de saída, para detectar
objetos com tamanhos maiores na imagem de entrada.
Implementaremos um modelo de detecção de objetos multiescala na seção
seguinte.
Resumo
------
- Podemos gerar caixas de âncora com diferentes números e tamanhos em
várias escalas para detectar objetos de diferentes tamanhos em várias
escalas.
- A forma do mapa de feições pode ser usada para determinar o ponto
médio das caixas de âncora que amostram uniformemente qualquer
imagem.
- Usamos as informações da imagem de entrada de um determinado campo
receptivo para prever a categoria e o deslocamento das caixas de
âncora próximas a esse campo na imagem.
Exercícios
----------
1. Dada uma imagem de entrada, suponha que
:math:`1 \times c_i \times h \times w` seja a forma do mapa de
características, enquanto :math:`c_i, h, w` são o número, altura e
largura do mapa de características. Em quais métodos você pode pensar
para converter essa variável na categoria e deslocamento da caixa de
âncora? Qual é o formato da saída?
.. raw:: html
.. raw:: html
`Discussões `__
.. raw:: html
.. raw:: html
`Discussões `__
.. raw:: html
.. raw:: html
.. raw:: html