Correspondência de modelos NCC
Tutorial em vídeo 8 - Correspondência de modelos NCC: https://singtown.com/learn/49598/
Algoritmo NCC:
# Template Matching Example - Normalized Cross Correlation (NCC)
#
# Este exemplo mostra como usar a funcionalidade NCC da câmara OpenMV para
# corresponder pequenos trechos de imagem a partes de uma imagem... exceto em
# ambientes extremamente controlados, o NCC não é muito útil.
#
# AVISO: o suporte a NCC precisa de ser reformulado! Atualmente, esta
# funcionalidade ainda precisa de muito trabalho para se tornar útil. Este
# script permanece para mostrar que a funcionalidade existe, mas, no seu
# estado atual, é inadequada.
import csi
import time, csi, image
csi0 = csi.CSI()
from image import SEARCH_EX, SEARCH_DS
#Importa SEARCH_EX e SEARCH_DS do módulo image. Usando from import, importamos
#apenas as partes necessárias, SEARCH_EX e SEARCH_DS, sem importar o módulo image inteiro.
# Reinicia o sensor
csi0.reset()
# Define as definições do sensor
csi0.contrast(1)
csi0.gainceiling(16)
# A resolução máxima para correspondência de modelos com SEARCH_EX é QQVGA
csi0.framesize(csi.QQVGA)
# Pode definir uma janela para reduzir a imagem de pesquisa.
#csi0.window(((640-80)//2, (480-60)//2, 80, 60))
csi0.pixformat(csi.GRAYSCALE)
# Carrega o modelo.
# O modelo deve ser uma imagem pequena (ex. 32x32 pixels) em escala de cinza.
template = image.Image("template.pgm")
#carrega a imagem do modelo
clock = time.clock()
# Executa a correspondência de modelos
while (True):
clock.tick()
img = csi0.snapshot()
# find_template(template, threshold, [roi, step, search])
# ROI: o tuplo da região de interesse (x, y, w, h).
# Step: o passo do ciclo usado (y+=step, x+=step); use um passo maior para acelerar.
# Search é image.SEARCH_EX para pesquisa exaustiva ou image.SEARCH_DS para pesquisa em diamante
#
# Nota 1: o ROI tem de ser menor que a imagem e maior que o modelo.
# Nota 2: na pesquisa em diamante, step e ROI são ambos ignorados.
r = img.find_template(template, 0.70, step=4, search=SEARCH_EX) #, roi=(10, 0, 60, 60))
#find_template(template, threshold, [roi, step, search]); no threshold,
#o 0.7 é o limiar de semelhança, roi é a área de correspondência (vértice superior esquerdo em (10, 0), retângulo com 80 de comprimento e 60 de largura),
#note que o tamanho do roi deve ser maior que a imagem do modelo e menor que o framebuffer.
#marca a imagem correspondida
if r:
img.draw_rectangle(r)
print(clock.fps())
Note que, como o tamanho da imagem do nosso modelo excede a memória flash integrada do openmv, precisamos de inserir o cartão SD antes de executar os passos seguintes. (Note que deve inserir o cartão SD antes de ligar) E esta correspondência de modelos só pode ser usada a partir da versão de firmware 1.6 ou superior, caso contrário será apresentado "can not find SEARCH_EX" durante a execução
Primeiro, precisamos de criar ou importar um modelo. Note que este modelo tem de estar em formato pgm e tem um limite de tamanho que não pode exceder o tamanho em pixéis do openmv. Podemos capturar diretamente uma imagem de modelo a partir do openmv. Pode primeiro executar a rotina helloworld.py para que o framebuffer mostre a imagem e depois capturá-la.

Selecione a opção guardar imagem no pc. Note que a imagem capturada e guardada diretamente do openmv está em formato bmp. Precisamos de a converter para o formato pgm. Pode fazer a conversão online neste site https://convertio.co/zh/bmp-pgm/
Depois, guardamos o modelo pgm convertido no cartão SD (existem 8 modelos neste cartão SD, e o modelo da imagem acima é guardado como ball0.pgm)

Depois abrimos a rotina de correspondência de modelos

Altere o nome do ficheiro de modelo template.pgm na linha 28 para ball0.pgm

E execute diretamente!

Esta é a utilização da função de correspondência de modelos find_template:

r = img.find_template(template, 0,7, roi=(10,0,80,60), step=4, search=SEARCH_EX) O 0.7 em threshold é o limiar de semelhança, e roi é a área de correspondência (o vértice superior esquerdo é (10, 0), o comprimento é 80 e a largura é 60). Note que o tamanho de roi deve ser maior que a imagem do modelo e menor que o framebuffer.
Note que esta correspondência de modelos usa o algoritmo NCC, que só consegue corresponder áreas semelhantes ao tamanho do modelo. Se quiser corresponder imagens de tamanhos diferentes, precisa de guardar vários modelos de tamanhos diferentes.
Se ocorrerem os seguintes problemas após a execução do programa:
- A imagem do modelo é demasiado grande, recomenda-se que a imagem do modelo seja menor que 80*60

- O OpenMV2 não tem memória suficiente, mude QQVGA para QQCIF

Comparação entre correspondência de modelos e deteção de pontos característicos:
Correspondência de modelos (find_temolate) utiliza o algoritmo NCC, que só consegue corresponder padrões que tenham basicamente o mesmo tamanho e ângulo da imagem do modelo. As limitações são relativamente grandes. Se o padrão alvo no campo de visão for ligeiramente maior ou menor do que a imagem do modelo, a correspondência pode não ser bem-sucedida.
A correspondência de modelos é adequada para situações em que a distância entre a câmara e o objeto alvo é fixa e não é necessário movimento dinâmico. Por exemplo, é adequada para a deteção de objetos específicos numa linha de montagem, mas não para um carro seguir uma bola de voleibol em movimento (porque a distância entre a bola em movimento e a câmara é dinâmica, o tamanho da bola visto pela câmara vai mudar e não será exatamente igual à imagem do modelo).
Para correspondência em vários ângulos e tamanhos, pode tentar guardar vários modelos e utilizar a Correspondência de vários modelos.
Deteção de pontos característicos (find_keypoint): Se acabou de iniciar a execução do programa, a rotina extrai a primeira imagem como a característica do objeto alvo, e kpts1 guarda essa característica. Por predefinição, corresponderá a várias escalas e ângulos da característica alvo, e não apenas ao tamanho e ângulo guardados inicialmente. É mais flexível do que a correspondência de modelos e não precisa de guardar várias imagens de modelo como na correspondência de vários modelos.
A deteção de pontos característicos também pode guardar as características alvo com antecedência. Isto não era recomendado anteriormente porque a interferência da luz ambiente e outros fatores podiam causar características diferentes sob luzes diferentes de cada vez que o programa era executado, reduzindo o grau de correspondência. No entanto, na versão mais recente do firmware foram adicionados ajustes de exposição, balanço de brancos e valor de ganho automático. O valor de exposição e o valor de balanço de brancos podem ser definidos manualmente, o que reduz relativamente a interferência da luz. Pode também tentar guardar as características alvo com antecedência.