Nós colamos várias fotos em uma longa usando visão computacional

Artigos anteriores descreveram o método de seis pontos para desembrulhar rótulos e como treinamos a rede neural . Este artigo descreve como colar fragmentos feitos de ângulos diferentes em uma imagem longa.





Os rótulos são pré-segmentados e implantados pela rede neural descrita no artigo anterior.







Como a colagem geralmente funciona? Você precisa tirar duas fotos sobrepostas, calcular o deslocamento mútuo e sobrepor uma sobre a outra. Parece muito simples, mas vamos repassar cada uma das etapas.



Para calcular o deslocamento mútuo, você precisa encontrar alguns objetos que estão presentes em ambas as imagens e, de alguma forma, calcular a transformação dos pontos de uma imagem para outra. Essa mudança pode ser representada por uma matriz de transformação, onde os elementos da matriz codificam várias transformações ao mesmo tempo - escala, translação e rotação.



Existe uma excelente tabela na wikipedia que mostra como e quais elementos afetam a transformação.



Como você pode ver na imagem abaixo, existem objetos comuns suficientes:







Mas há um problema com os objetos selecionados - eles são difíceis de detectar algoritmicamente. Em vez disso, costuma-se procurar objetos mais simples - os chamados "cantos", eles também são descritores ("descritores", "recursos").



Há um ótimo artigo na documentação do OpenCV sobre por que os cantos - em resumo, definir uma linha é fácil, mas fornece apenas uma coordenada. Portanto, também é necessário detectar a segunda linha (não paralela). Se convergirem em um ponto, então este lugar é ideal para encontrar um descritor, é também um canto (embora os descritores reais não sejam cantos no sentido geométrico da palavra).



Um dos algoritmos para encontrar descritores é SIFT (Scale-Invariant Feature Transform). Apesar de ter sido inventado em 1999, é bastante popular devido à sua simplicidade e confiabilidade. Este algoritmo foi patenteado, mas a patente expirou nesta primavera (2020). No entanto, eles não conseguiram transferi-lo para a compilação principal do OpenCV, então você precisa usar uma compilação especial não livre.



Então, vamos encontrar cantos semelhantes em ambas as imagens:



sift = cv2.xfeatures2d.SIFT_create()
features_left = sift.detectAndCompute(left_image, None)






features_right = sift.detectAndCompute(left_image, None)






Vamos usar o matcher Flann - ele tem bom desempenho mesmo se o número de descritores for grande.



KNN = 2
LOWE = 0.7
TREES = 5
CHECKS = 50

matcher = cv2.FlannBasedMatcher({'algorithm': 0, 'trees': TREES}, {'checks': CHECKS})
matches = matcher.knnMatch(left_descriptors, right_descriptors, k=KNN)

logging.debug("filtering matches with lowe test")

positive = []
for left_match, right_match in matches:
    if left_match.distance < LOWE * right_match.distance:
        positive.append(left_match)


As linhas amarelas mostram como o combinador encontrou correspondências.







Como você pode ver claramente, existem apenas cerca de metade das correspondências corretas. No entanto, se as correspondências corretas sempre fornecem a mesma transformação, as incorretas mostram uma direção caoticamente nova. Essa. teoricamente, eles podem ser separados um do outro:







um dos algoritmos para encontrar a transformação correta é RANSAC. Este algoritmo funciona muito bem quando você deseja separar bons valores de ruído - este é exatamente o caso.



Felizmente, o OpenCV já possui funções que encontrarão a matriz de transformação por correspondências usando RANSAC, ou seja, na verdade, você não precisa escrever nada.



Vamos usar a função estimativaAffinePartial2D que procura as seguintes transformações: rotação, escala e translação (4 graus de liberdade).



H, _ = cv2.estimateAffinePartial2D(right_matches, left_matches, False)


Assim que a matriz de transformação for encontrada, podemos transformar a imagem certa para colagem.



Fragmento esquerdo: Fragmento





direito:







Primeiro, vamos usar a maneira mais simples de colar fragmentos, quando cada pixel de sua interseção é calculado como uma média. Infelizmente, o resultado é razoável - a imagem duplica visivelmente, especialmente perto da linha de colagem.







Na animação, a diferença entre os dois quadros é mais claramente visível:







Isso não é surpreendente - as fotos foram tiradas de ângulos diferentes, a rede neural também as expandiu de forma ligeiramente diferente e, como resultado, havia pequenas discrepâncias.



Para colagem perfeita, é necessário compensar a distorção não linear. A distorção pode ser representada como um campo vetorial com a mesma resolução da imagem original, mas em vez da cor, um deslocamento será codificado em cada pixel. Este campo vetorial é denominado “fluxo óptico”.



Em geral, existem diferentes métodos para calcular o fluxo óptico - alguns deles são integrados diretamente no OpenCV, e também existem redes neurais especiais.



No nosso caso, omitirei a técnica específica, mas publicarei o resultado:







Mas a compensação deve ser realizada na proporção de ambos os fragmentos. Para fazer isso, vamos dividi-lo em duas matrizes: O







fragmento esquerdo será compensado da esquerda para a direita de forma crescente, enquanto o da direita - vice-versa.



Agora, os dois fragmentos se sobrepõem quase perfeitamente:







Agora a sobreposição está geometricamente correta, mas observamos um salto muito perceptível no brilho nas costuras:







Este problema pode ser facilmente corrigido se em vez dos valores médios, eles forem sobrepostos com um gradiente:







Com esta abordagem, a costura não é visível de todo:







Em princípio, existem também outras técnicas de colagem, por exemplo , mesclagem multibanda, que são usados ​​para costurar panoramas, mas não funcionam bem com texto - somente a compensação de fluxo ótico pode remover completamente o fantasma do texto.



Agora vamos colar a imagem completa:







Versão final:







Outras melhorias poderiam ser a compensação do efeito de sombra (lado direito da imagem), ou ainda mais pós-processamento de cor e contraste. Você também pode ver que a geometria global sofreu um pouco - as linhas à direita subiram ligeiramente. Teoricamente, este problema também pode ser corrigido adicionando uma correção de escala global, mas esta também não é uma tarefa completamente trivial.



Examinamos como a colagem funciona, uma solução pronta está disponível aqui na forma de uma API REST. Também recomendo olhar os seguintes links:






All Articles