Aqui está o que eu gostaria de fazer:
Estou tirando fotos com uma webcam em intervalos regulares. Mais ou menos como um lapso de tempo. No entanto, se nada realmente mudou, ou seja, a imagem parece a mesma, não quero armazenar o instantâneo mais recente.
Imagino que exista alguma maneira de quantificar a diferença, e eu teria que determinar empiricamente um limite.
Estou procurando mais simplicidade do que perfeição. Eu estou usando python.
python
image-processing
background-subtraction
image-comparison
timelapse
transportadora
fonte
fonte
Respostas:
Ideia geral
Opção 1: carregue as duas imagens como matrizes (
scipy.misc.imread
) e calcule uma diferença entre elementos (pixel por pixel). Calcule a norma da diferença.Opção 2: Carregue as duas imagens. Calcule algum vetor de recurso para cada um deles (como um histograma). Calcule a distância entre vetores de recursos em vez de imagens.
No entanto, existem algumas decisões a serem tomadas primeiro.
Questões
Você deve responder a estas perguntas primeiro:
As imagens têm a mesma forma e dimensão?
Caso contrário, pode ser necessário redimensioná-las ou cortá-las. A biblioteca PIL ajudará a fazê-lo em Python.
Se forem tiradas com as mesmas configurações e o mesmo dispositivo, provavelmente são as mesmas.
As imagens estão bem alinhadas?
Caso contrário, convém executar a correlação cruzada primeiro, para encontrar o melhor alinhamento primeiro. O SciPy tem funções para fazer isso.
Se a câmera e a cena estiverem paradas, é provável que as imagens estejam bem alinhadas.
A exposição das imagens é sempre a mesma? (A luminosidade / contraste é o mesmo?)
Caso contrário, você pode normalizar as imagens.
Mas tenha cuidado, em algumas situações isso pode fazer mais mal do que bem. Por exemplo, um único pixel brilhante em um fundo escuro tornará a imagem normalizada muito diferente.
As informações de cores são importantes?
Se você quiser observar alterações de cores, terá um vetor de valores de cores por ponto, em vez de um valor escalar, como na imagem em escala de cinza. Você precisa de mais atenção ao escrever esse código.
Existem arestas distintas na imagem? É provável que eles se mexam?
Se sim, você pode aplicar o algoritmo de detecção de borda primeiro (por exemplo, calcular gradiente com as transformações Sobel ou Prewitt, aplicar algum limite) e comparar as arestas na primeira imagem com as arestas na segunda.
Há ruído na imagem?
Todos os sensores poluem a imagem com uma certa quantidade de ruído. Sensores de baixo custo têm mais ruído. Você pode aplicar alguma redução de ruído antes de comparar imagens. O desfoque é a abordagem mais simples (mas não a melhor) aqui.
Que tipo de mudanças você deseja observar?
Isso pode afetar a escolha da norma a ser usada para a diferença entre imagens.
Considere usar a norma Manhattan (a soma dos valores absolutos) ou a norma zero (o número de elementos que não é igual a zero) para medir quanto a imagem mudou. O primeiro dirá o quanto a imagem está desativada, o segundo dirá apenas quantos pixels diferem.
Exemplo
Presumo que suas imagens estejam bem alinhadas, com o mesmo tamanho e formato, possivelmente com exposição diferente. Para simplificar, eu os converto em escala de cinza, mesmo que sejam imagens coloridas (RGB).
Você precisará destas importações:
Função principal, leia duas imagens, converta em escala de cinza, compare e imprima resultados:
Como comparar
img1
eimg2
são matrizes 2D SciPy aqui:Se o arquivo for uma imagem colorida,
imread
retornará uma matriz 3D, canais RGB médios (o último eixo da matriz) para obter intensidade. Não é necessário fazer isso para imagens em escala de cinza (por exemplo.pgm
):A normalização é trivial, você pode optar por normalizar para [0,1] em vez de [0,255].
arr
é uma matriz SciPy aqui, portanto, todas as operações são baseadas em elementos:Execute a
main
função:Agora você pode colocar tudo isso em um script e executar duas imagens. Se compararmos a imagem consigo mesma, não há diferença:
Se borrarmos a imagem e comparamos com o original, há alguma diferença:
PS Script compare.py inteiro .
Atualização: técnicas relevantes
Como a pergunta é sobre uma sequência de vídeo, em que os quadros provavelmente são quase os mesmos, e você procura algo incomum, gostaria de mencionar algumas abordagens alternativas que podem ser relevantes:
Eu recomendo dar uma olhada no livro “Learning OpenCV”, capítulos 9 (partes e segmentação de imagens) e 10 (rastreamento e movimento). O primeiro ensina a usar o método de subtração Background, o último fornece algumas informações sobre os métodos de fluxo óptico. Todos os métodos são implementados na biblioteca OpenCV. Se você usa Python, sugiro usar o OpenCV ≥ 2.3 e seu
cv2
módulo Python.A versão mais simples da subtração em segundo plano:
Versões mais avançadas levam em consideração séries temporais para cada pixel e lidam com cenas não estáticas (como mover árvores ou grama).
A idéia do fluxo óptico é pegar dois ou mais quadros e atribuir o vetor de velocidade a cada pixel (fluxo óptico denso) ou a alguns deles (fluxo óptico esparso). Para estimar o fluxo óptico esparso, você pode usar o método Lucas-Kanade (também é implementado no OpenCV). Obviamente, se houver muito fluxo (média alta acima dos valores máximos do campo de velocidade), algo estará se movendo no quadro e as imagens subseqüentes serão mais diferentes.
Comparar histogramas pode ajudar a detectar mudanças repentinas entre quadros consecutivos. Essa abordagem foi usada em Courbon et al, 2010 :
fonte
RuntimeWarning: invalid value encountered in double_scalars
na linha 44 (return (arr-amin)*255/rng
) e umValueError: array must not contain infs or NaNs
na linha 30 (z_norm = norm(diff.ravel(), 0)
)rng
igual a zero. Basta adicionar um cheque e setrng = 1
Uma solução simples:
Codifique a imagem como um JPEG e procure uma alteração substancial no tamanho do arquivo .
Eu implementei algo semelhante nas miniaturas de vídeo e tive muito sucesso e escalabilidade.
fonte
Você pode comparar duas imagens usando as funções do PIL .
O objeto diff é uma imagem na qual cada pixel é o resultado da subtração dos valores de cores desse pixel na segunda imagem da primeira imagem. Usando a imagem diff, você pode fazer várias coisas. O mais simples é a
diff.getbbox()
função. Ele mostrará o retângulo mínimo que contém todas as alterações entre as duas imagens.Provavelmente você pode implementar aproximações dos outros itens mencionados aqui usando funções do PIL também.
fonte
Dois métodos populares e relativamente simples são: (a) a distância euclidiana já sugerida, ou (b) correlação cruzada normalizada. A correlação cruzada normalizada tende a ser visivelmente mais robusta às mudanças de iluminação do que a simples correlação cruzada. A Wikipedia fornece uma fórmula para a correlação cruzada normalizada . Existem métodos mais sofisticados também, mas exigem um pouco mais de trabalho.
Usando sintaxe parecida com numpy,
assumindo que
i1
ei2
são matrizes de imagem em escala de cinza 2D.fonte
Uma coisa trivial para tentar:
Realize uma nova amostra de ambas as imagens em miniaturas pequenas (por exemplo, 64 x 64) e compare as miniaturas pixel por pixel com um determinado limite. Se as imagens originais forem quase as mesmas, as miniaturas reamostradas serão muito parecidas ou até exatamente iguais. Este método cuida do ruído que pode ocorrer principalmente em cenas com pouca luz. Pode até ser melhor se você usar a escala de cinza.
fonte
Estou abordando especificamente a questão de como calcular se elas são "suficientemente diferentes". Eu suponho que você possa descobrir como subtrair os pixels um por um.
Primeiro, eu pegava um monte de imagens sem mudar nada e descobria a quantidade máxima que qualquer pixel muda apenas por causa de variações na captura, ruído no sistema de imagem, artefatos de compactação JPEG e alterações momento a momento na iluminação . Talvez você descubra que diferenças de 1 ou 2 bits são esperadas mesmo quando nada se move.
Então, para o teste "real", você deseja um critério como este:
Então, talvez, se E = 0,02, P = 1000, isso significaria (aproximadamente) que seria "diferente" se algum pixel único mudasse em mais de ~ 5 unidades (assumindo imagens de 8 bits) ou se mais de 1000 pixels tiveram algum erro.
Isso se destina principalmente a ser uma boa técnica de "triagem" para identificar rapidamente imagens próximas o suficiente para não precisar de mais exames. As imagens que "falham" podem então se tornar uma técnica mais elaborada / cara que não teria falsos positivos se a câmera tremesse um pouco, por exemplo, ou fosse mais robusta às mudanças de iluminação.
Eu corro um projeto de código aberto, o OpenImageIO , que contém um utilitário chamado "idiff" que compara diferenças com limites como este (ainda mais elaborado, na verdade). Mesmo se você não quiser usar este software, consulte a fonte para ver como fizemos. É usada comercialmente um pouco e essa técnica de limiar foi desenvolvida para que pudéssemos ter um conjunto de testes para renderização e processamento de imagens, com "imagens de referência" que podem ter pequenas diferenças de plataforma para plataforma ou quando fizemos pequenos ajustes para algoritmos, então queríamos uma operação de "correspondência dentro da tolerância".
fonte
Eu tive um problema semelhante no trabalho, estava reescrevendo nosso ponto de extremidade de transformação de imagem e queria verificar se a nova versão estava produzindo a mesma ou quase a mesma saída da versão antiga. Então eu escrevi isso:
https://github.com/nicolashahn/diffimg
Que opera em imagens do mesmo tamanho e, no nível por pixel, mede a diferença de valores em cada canal: R, G, B (, A), pega a diferença média desses canais e calcula a média da diferença entre todos os pixels e retorna uma proporção.
Por exemplo, com uma imagem 10x10 de pixels brancos e a mesma imagem, mas um pixel mudou para vermelho, a diferença nesse pixel é 1/3 ou 0,33 ... (RGB 0,0,0 vs 255,0,0 ) e em todos os outros pixels é 0. Com um total de 100 pixels, 0,33 ... / 100 = uma diferença de ~ 0,33% na imagem.
Acredito que isso funcionaria perfeitamente para o projeto do OP (percebo que este é um post muito antigo agora, mas publicando para futuros StackOverflowers que também desejam comparar imagens em python).
fonte
A maioria das respostas dadas não trata de níveis de iluminação.
Eu normalizaria a imagem para um nível de luz padrão antes de fazer a comparação.
fonte
Outra maneira simples e agradável de medir a semelhança entre duas imagens:
Se outras pessoas estiverem interessadas em uma maneira mais poderosa de comparar a similaridade de imagens, montei um tutorial e um aplicativo da Web para medir e visualizar imagens semelhantes usando o Tensorflow.
fonte
skimage
é muito bom de usar para esta aplicação. Eu usofrom skimage.measure import compare_ssim, compare_mse
muito. skimage.measure docs .Você viu o algoritmo para encontrar imagens semelhantes ? Confira para ver sugestões.
Eu sugeriria uma transformação wavelet de seus quadros (eu escrevi uma extensão C para isso usando a transformação Haar); comparando os índices dos maiores fatores de onda (proporcionalmente) entre as duas figuras, você deve obter uma aproximação de similaridade numérica.
fonte
Peço desculpas se é tarde demais para responder, mas desde que eu venho fazendo algo semelhante, pensei que poderia contribuir de alguma forma.
Talvez com o OpenCV você possa usar a correspondência de modelos. Supondo que você esteja usando uma webcam como você disse:
Dica: max_val (ou min_val, dependendo do método usado) fornecerá números, números grandes. Para obter a diferença em porcentagem, use a correspondência de modelo com a mesma imagem - o resultado será 100%.
Pseudo código para exemplificar:
Espero que ajude.
fonte
A distância dos motores da Terra pode ser exatamente o que você precisa. Pode ser um pouco pesado para implementar em tempo real.
fonte
Que tal calcular a distância de Manhattan das duas imagens. Isso fornece valores n * n. Em seguida, você poderia fazer algo como uma média de linha para reduzir para n valores e uma função sobre isso para obter um único valor.
fonte
Tenho tido muita sorte com imagens jpg tiradas com a mesma câmera em um tripé (1) simplificando bastante (como ir de 3000 pixels de largura a 100 pixels de largura ou menos) (2) achatando cada conjunto de jpg em um único vetor (3) correlacionar imagens sequenciais em pares com um algoritmo de correlação simples para obter o coeficiente de correlação (4) coeficiente de correlação ao quadrado para obter o quadrado r (ie fração da variabilidade em uma imagem explicada pela variação na próxima) (5) geralmente em minha aplicação se r-quadrado <0,9, digo que as duas imagens são diferentes e algo aconteceu no meio.
Isso é robusto e rápido na minha implementação (Mathematica 7)
Vale a pena brincar com a parte da imagem em que você está interessado e focar nisso cortando todas as imagens nessa pequena área, caso contrário, uma mudança distante da câmera, mas importante, será perdida.
Não sei como usar o Python, mas tenho certeza de que também faz correlações, não?
fonte
você pode calcular o histograma de ambas as imagens e calcular o coeficiente de Bhattacharyya , este é um algoritmo muito rápido e eu o usei para detectar alterações de tiro em um vídeo de críquete (em C usando openCV)
fonte
Confira como o Haar Wavelets é implementado pelo isk-daemon . Você pode usar o código imgdb C ++ para calcular a diferença entre as imagens rapidamente:
fonte
Eu tive o mesmo problema e escrevi um módulo python simples que compara duas imagens do mesmo tamanho usando o ImageChops da almofada para criar uma imagem diff em preto / branco e resume os valores do histograma.
Você pode obter essa pontuação diretamente ou um valor percentual comparado a uma comparação completa de preto versus branco.
Ele também contém uma função is_equal simples, com a possibilidade de fornecer um limite difuso abaixo (e incluindo) da imagem que passa como igual.
A abordagem não é muito elaborada, mas talvez seja útil para outros que estão por aí lutando com o mesmo problema.
https://pypi.python.org/pypi/imgcompare/
fonte
Uma abordagem um pouco mais baseada em princípios é usar um descritor global para comparar imagens, como GIST ou CENTRIST. Uma função de hash, conforme descrito aqui , também fornece uma solução semelhante.
fonte
resultado:
Falso
Verdadeiro
image2 \ 5.jpg image1 \ 815.jpg
image2 \
6.jpg image1 \ 819.jpg
image2 \ 7.jpg image1 \ 900.jpg
image2 \ 8.jpg image1 \ 998.jpg image2 \ 9.jpg image1 \ 1012 .jpg
as imagens de exemplo:
815.jpg
5.jpg
fonte
Eu acho que você poderia simplesmente calcular a distância euclidiana (isto é, sqrt (soma dos quadrados das diferenças, pixel por pixel)) entre a luminância das duas imagens e considerá-las iguais se isso cair abaixo de algum limiar empírico. E é melhor fazê-lo envolvendo uma função C.
fonte
Existem muitas métricas disponíveis para avaliar se duas imagens se parecem / com o que elas se parecem.
Não vou entrar em nenhum código aqui, porque acho que deve ser um problema científico, além de técnico.
Geralmente, a questão está relacionada à percepção do ser humano nas imagens, de modo que cada algoritmo tem seu suporte nos traços do sistema visual humano.
As abordagens clássicas são:
Preditor de diferenças visíveis: um algoritmo para a avaliação da fidelidade da imagem ( https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1666/0000/Visible-differences-predictor--an-algorithm-for-the- avaliação-de / 10.1117 / 12.135952.short? SSO = 1 )
Avaliação da qualidade da imagem: da visibilidade do erro à semelhança estrutural ( http://www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf )
FSIM: um índice de similaridade de recursos para avaliação da qualidade da imagem ( https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf )
Entre eles, o SSIM (Avaliação da qualidade da imagem: da visibilidade do erro à semelhança estrutural) é o mais fácil de calcular e sua sobrecarga também é pequena, conforme relatado em outro artigo "Avaliação da qualidade da imagem com base na similaridade de gradiente" ( https: //www.semanticscholar .org / paper / Avaliação da qualidade da imagem com base no gradiente-Liu-Lin / 2b819bef80c02d5d4cb56f27b202535e119df988 ).
Existem muitas outras abordagens. Dê uma olhada no Google Scholar e pesquise algo como "diferença visual", "avaliação da qualidade da imagem" etc., se você estiver interessado / realmente se interessar pela arte.
fonte
Existe uma solução simples e rápida usando numpy calculando o erro quadrático médio:
fonte