5.20. Regressão e similaridade¶
Duas medições adicionais na classe Image resumem a imagem como algo diferente de uma distribuição de valores de pixel. A regressão linear de pixels com limiar fornece a uma aplicação uma linha sobre a qual pode agir – a entrada clássica para um robô seguidor de linha. A medição de similaridade fornece a uma aplicação um único número que descreve o grau de semelhança entre duas imagens – a entrada natural para um teste de regressão de imagem de referência ou para um detetor de alterações grosseiras.
5.20.1. Regressão linear¶
Quando os pixels de primeiro plano de uma imagem formam uma linha através do fotograma – a fita numa pista que um robô está a seguir, a linha de um horizonte, a orla de uma estrada ou de um corredor – a aplicação normalmente não quer cada pixel de primeiro plano individualmente. Quer a linha de melhor ajuste através de todos eles, parametrizada de modo a poder decidir como a linha está orientada e onde cruza o fotograma.
get_regression() realiza esse ajuste. Recebe o mesmo formato de tuplo de limiar que binary() e find_blobs() usam, identifica cada pixel que corresponde ao limiar e devolve um único resultado line que descreve a linha de melhor ajuste através desses pixels:
line = img.get_regression([(0, 60)])
if line:
img.draw_line((line.x1(), line.y1(),
line.x2(), line.y2()),
color=(255, 0, 0))
O ajuste usa a regressão linear Theil-Sen – um método robusto que tolera valores atípicos melhor do que o ajuste por mínimos quadrados mais familiar. Um pequeno conjunto de pixels afastados da linha verdadeira não distorce o resultado da forma como o fariam com os mínimos quadrados, o que corresponde à realidade ruidosa de um primeiro plano com limiar real.
O resultado line contém os pontos extremos recortados ao retângulo da imagem (x1, y1, x2, y2), o comprimento e a magnitude da linha (length, magnitude), e a descrição geométrica da linha em forma polar (theta, rho) – o ângulo da linha relativamente à horizontal e a sua distância perpendicular à origem. A forma polar é o que um ciclo de controlo normalmente precisa: theta diz ao robô para que lado a linha está inclinada, rho diz-lhe onde a linha cruza a imagem, e um ciclo de retroação sobre os dois mantém o robô centrado na linha.
Alguns argumentos de palavra-chave ajustam a robustez e o custo. x_stride e y_stride saltam pixels durante o ajuste – strides maiores tornam a regressão mais económica ao custo de ajustar menos pixels. area_threshold e pixels_threshold rejeitam linhas que não têm pixels correspondentes suficientes. target_size redimensiona a entrada para um tamanho menor antes do ajuste – a regressão corre mais rapidamente num substituto de 80 por 60 da imagem sem grande perda de precisão na direção da linha.
Se não for possível ajustar nenhuma linha aceitável – se o limiar não correspondeu a nenhum pixel, ou correspondeu a um padrão que não se parece com uma linha – o método devolve None. O código real de seguimento de linha protege cada chamada a get_regression() com uma verificação de None antes de aceder aos atributos da linha.
5.20.2. Similaridade de imagens¶
Um tipo diferente de medição: em vez de perguntar «o que contém a imagem?», pergunta-se «qual é o grau de semelhança entre estas duas imagens?». A operação a utilizar é get_similarity(), que calcula o Índice de Similaridade Estrutural (SSIM) entre a imagem de origem e uma imagem de referência.
s = img.get_similarity(reference)
print(s.mean, s.stdev)
O SSIM é a métrica padrão de similaridade de imagens utilizada em todo o processamento de imagem porque se comporta da forma como a intuição humana sobre similaridade funciona – um pequeno deslocamento ou uma pequena variação de brilho reduz ligeiramente a pontuação, enquanto uma grande alteração estrutural (objeto em falta, cena diferente) a reduz drasticamente. A pontuação varia entre -1 e +1: +1 significa que as duas imagens são idênticas, 0 significa que não têm relação, e -1 significa que são estruturalmente opostas. O objeto similarity devolvido expõe o SSIM médio ao longo da imagem, mais o desvio padrão, o mínimo e o máximo das pontuações por tile.
Para o tipo de comparação em que um número pequeno é melhor do que um grande – um teste de regressão que deve reportar zero para «nada mudou» e aumentar à medida que as alterações se acumulam – a opção dssim=True devolve a dissimilaridade estrutural: o SSIM médio subtraído de 1, pelo que o valor de retorno é 0.0 para imagens idênticas e aumenta à medida que diferem.
5.20.3. Casos de uso para SSIM¶
As duas aplicações mais comuns:
Testes de regressão com imagem de referência. Uma estrutura de testes captura um fotograma de referência em condições conhecidamente boas e guarda-o como imagem de referência. As execuções de teste subsequentes capturam nas mesmas condições e comparam com a imagem de referência usando SSIM. Uma pontuação acima de um determinado limiar (0.95 ou 0.98 consoante a tolerância) é aprovação; abaixo é reprovação. A estrutura de testes não precisa de saber o que mudou – a pontuação SSIM é o sinal.
Deteção de alterações grosseiras. Uma aplicação que pretende uma versão mais grosseira da diferença entre fotogramas – uma que ignora pequenas variações de brilho mas reage a grandes alterações estruturais – pode usar o SSIM contra um fotograma de referência em vez do difference() por pixel seguido de um limiar. O SSIM é menos sensível à deriva de iluminação do que a diferença por pixel, o que o torna a melhor escolha quando o objetivo é detetar «a cena parece materialmente diferente» em vez de «algum pixel individual mudou.»
Ambas as aplicações usam a mesma chamada – img.get_similarity(reference) – e disparam sobre um limiar da pontuação devolvida. A diferença é apenas se o limiar é alto (teste de regressão, à procura de uma correspondência quase idêntica) ou baixo (deteção de alterações, à procura de qualquer grande alteração estrutural).
5.20.4. A forma de transformar e comparar¶
Uma subtileza útil: get_similarity() aceita os mesmos parâmetros x, y, x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette, hint e transform que draw_image(). A imagem de referência é posicionada, dimensionada e transformada por esses parâmetros antes de a comparação SSIM ser executada.
Isto significa que uma aplicação pode perguntar «quão semelhante é esta cena a um fotograma de referência após um deslocamento / rotação / escala conhecidos» sem preparar uma imagem de referência pré-transformada. É a forma económica de construir um rastreador que pesquisa um espaço de parâmetros e reporta qual transformação da referência melhor corresponde ao fotograma atual.