Correspondência de modelos usando OpenCV em Python
A correspondência de modelo é uma técnica para localizar áreas de uma imagem que são semelhantes a um patch (modelo).
Um patch é uma pequena imagem com certos recursos. O objetivo da correspondência de modelos é encontrar o patch / modelo em uma imagem.
Para encontrá-lo, o usuário deve fornecer duas imagens de entrada: Imagem de origem (S) - A imagem na qual encontrar o modelo e Imagem de modelo (T) - A imagem que deve ser encontrada na imagem de origem.
- É basicamente um método para pesquisar e encontrar a localização de uma imagem de modelo em uma imagem maior.
- A ideia aqui é encontrar regiões idênticas de uma imagem que correspondam a um modelo que fornecemos, fornecendo um limite
- O limite depende da precisão com a qual queremos detectar o modelo na imagem de origem.
- Por exemplo, se estamos aplicando o reconhecimento de rosto e queremos detectar os olhos de uma pessoa, podemos fornecer uma imagem aleatória de um olho como modelo e pesquisar a fonte (o rosto de uma pessoa).
- Nesse caso, como os “olhos” mostram uma grande quantidade de variações de pessoa para pessoa, mesmo se definirmos o limite como 50% (0,5), o olho será detectado.
- Nos casos em que modelos quase idênticos devem ser pesquisados, o limite deve ser definido como alto. (T> = 0,8)
Como funciona a correspondência de modelos?
- A imagem do modelo simplesmente desliza sobre a imagem de entrada (como na convolução 2D)
- O modelo e o patch da imagem de entrada sob a imagem do modelo são comparados.
- O resultado obtido é comparado com o limite.
- Se o resultado for maior que o limite, a parte será marcada como detectada.
- Na função cv2.matchTemplate (img_gray, template, cv2.TM_CCOEFF_NORMED) o primeiro parâmetro é a imagem principal, o segundo parâmetro é o modelo a ser correspondido e o terceiro parâmetro é o método usado para correspondência.
import
cv2
import
numpy as np
img_rgb
=
cv2.imread(
'mainimage.jpg'
).
img_gray
=
cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template
=
cv2.imread(
'template'
,
0
)
w, h
=
template.shape[::
-
1
]
res
=
cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold
=
0.8
loc
=
np.where( res >
=
threshold)
for
pt
in
zip
(
*
loc[::
-
1
]):
cv2.rectangle(img_rgb, pt, (pt[
0
]
+
w, pt[
1
]
+
h), (
0
,
255
,
255
),
2
)
cv2.imshow(
'Detected'
,img_rgb)
Limitações da correspondência de modelo:
- As ocorrências de padrão devem preservar a orientação da imagem do padrão de referência (modelo)
- Como resultado, ele não funciona para versões giradas ou dimensionadas do modelo, pois uma mudança na forma / tamanho / cisalhamento etc. do modelo de objeto Wrt resultará em uma correspondência falsa.
- O método é ineficiente ao calcular a imagem de correlação de padrões para imagens médias a grandes, pois o processo é demorado.
Para evitar o problema causado pelos diferentes tamanhos do modelo e da imagem original, podemos usar a multiescala . No caso de onde, só porque as dimensões do seu modelo não correspondem às dimensões da região na imagem que você deseja corresponder, não significa que você não pode aplicar a correspondência de modelo.
Mecanismo de multiescala na correspondência de modelo
O processo de Multi scaling é o seguinte:
- Faça um loop sobre a imagem de entrada em várias escalas (ou seja, torne a imagem de entrada progressivamente menor e menor).
- Aplique a correspondência de modelo usando cv2.matchTemplate e acompanhe a correspondência com o maior coeficiente de correlação (junto com as coordenadas x, y da região com o maior coeficiente de correlação).
- Depois de percorrer todas as escalas, pegue a região com o maior coeficiente de correlação e use-a como sua região "correspondente".
import
cv2
import
numpy as np
img_rgb
=
cv2.imread(
'mainimage.jpg'
)
img_gray
=
cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template
=
cv2.imread(
'template'
,
0
)
w, h
=
template.shape[::
-
1
]
found
=
None
for
scale
in
np.linspace(
0.2
,
1.0
,
20
)[::
-
1
]:
resized
=
imutils.resize(img_gray, width
=
int
(img_gray.shape[
1
]
*
scale))
r
=
img_gray.shape[
1
]
/
float
(resized.shape[
1
])
if
resized.shape[
0
] < h
or
resized.shape[
1
] < w:
break
found
=
(maxVal, maxLoc, r)
(_, maxLoc, r)
=
found
(startX, startY)
=
(
int
(maxLoc[
0
]
*
r),
int
(maxLoc[
1
]
*
r))
(endX, endY)
=
(
int
((maxLoc[
0
]
+
tW)
*
r),
int
((maxLoc[
1
]
+
tH)
*
r))
cv2.rectangle(image, (startX, startY), (endX, endY), (
0
,
0
,
255
),
2
)
cv2.imshow(
"Image"
, image)
cv2.waitKey(
0
)
Explicação passo a passo do código acima:
- Depois de armazenar a largura e a altura do modelo em w e r, inicializamos uma variável encontrada para manter o controle da região e escala da imagem com a melhor correspondência. A partir daí, começamos o loop pelas múltiplas escalas da imagem usando a função np.linspace. Esta função aceita três argumentos, o valor inicial, o valor final e o número de fatias iguais entre eles. Neste exemplo, começaremos com 100% do tamanho original da imagem e trabalharemos para baixo até 20% do tamanho original em pedaços de 20 por cento de tamanhos iguais.
- Em seguida, redimensionamos a imagem de acordo com a escala atual e calculamos a proporção da largura antiga em relação à nova largura - como você verá mais tarde, é importante manter o controle dessa proporção. Fazemos uma verificação para garantir que a imagem de entrada seja maior do que a correspondência do nosso modelo. Se o modelo for maior, nossa chamada cv2.matchTemplate gerará um erro, portanto, apenas interrompemos o loop se for esse o caso.
- Neste ponto, podemos aplicar a correspondência de modelo à nossa imagem redimensionada:
- A função cv2.minMaxLoc pega nosso resultado de correlação e retorna uma 4-tupla que inclui o valor de correlação mínimo, o valor de correlação máximo, a (x, y) -coordenada do valor mínimo e a (x, y) -coordenada de o valor máximo, respectivamente. Estamos interessados apenas no valor máximo e coordenar (x, y), portanto, mantemos os máximos e descartamos os mínimos.
- Depois disso, inspecionamos as regiões da imagem que estão sendo correspondidas a cada iteração da escala. A partir daí, atualizamos nossa variável encontrada para acompanhar o valor máximo de correlação encontrado até agora, a (x, y) -coordenada do valor máximo, junto com a proporção da largura da imagem original para a largura da imagem redimensionada atual .
- Depois de percorrer todas as escalas da imagem, desempacotamos nossa variável encontrada e, em seguida, calculamos nossas coordenadas inicial e final (x, y) de nossa caixa delimitadora. Cuidado especial é tomado para multiplicar as coordenadas da caixa delimitadora pela proporção para garantir que as coordenadas correspondam às dimensões originais da imagem de entrada.
- Por fim, desenhamos nossa caixa delimitadora e a exibimos em nossa tela.
Este artigo foi contribuído por Pratima Upadhyay . Se você gosta de GeeksforGeeks e gostaria de contribuir, você também pode escrever um artigo usando contribute.geeksforgeeks.org ou enviar o seu artigo para contribute@geeksforgeeks.org. Veja o seu artigo que aparece na página principal do GeeksforGeeks e ajude outros Geeks.
Escreva comentários se encontrar algo incorreto ou se quiser compartilhar mais informações sobre o tópico discutido acima.
As postagens do blog Acervo Lima te ajudaram? Nos ajude a manter o blog no ar!
Faça uma doação para manter o blog funcionando.
70% das doações são no valor de R$ 5,00...
Diógenes Lima da Silva