Como o Gaussian Blur é implementado?

42

Eu li que o desfoque é feito em gráficos em tempo real, fazendo-o em um eixo e depois no outro.

Eu fiz um pouco de convolução em 1D no passado, mas não estou super confortável com isso, nem sei exatamente o que convolver nesse caso.

Alguém pode explicar em termos simples como é feito um Desfoque Gaussiano 2D de uma imagem?

Também ouvi dizer que o raio do Blur pode afetar o desempenho. Isso se deve a uma convolução maior?

Alan Wolfe
fonte

Respostas:

48

Na convolução, duas funções matemáticas são combinadas para produzir uma terceira função. No processamento de imagens, as funções são geralmente chamadas de kernels. Um kernel nada mais é do que uma matriz (quadrada) de pixels (uma pequena imagem, por assim dizer). Geralmente, os valores no kernel somam um. Isso é para garantir que nenhuma energia seja adicionada ou removida da imagem após a operação.

Especificamente, um núcleo gaussiano (usado para desfoque gaussiano) é uma matriz quadrada de pixels em que os valores de pixel correspondem aos valores de uma curva gaussiana (em 2D).

Imagem vinculada a http://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm

Cada pixel da imagem é multiplicado pelo kernel gaussiano. Isso é feito colocando o pixel central do kernel no pixel da imagem e multiplicando os valores na imagem original pelos pixels no kernel que se sobrepõem. Os valores resultantes dessas multiplicações são somados e esse resultado é usado para o valor no pixel de destino. Olhando para a imagem, você multiplicaria o valor em (0,0) na matriz de entrada pelo valor em (i) na matriz do kernel, o valor em (1,0) na matriz de entrada pelo valor em (h ) na matriz do kernel e assim por diante. e adicione todos esses valores para obter o valor de (1,1) na imagem de saída.

Imagem vinculada a http://www.songho.ca/dsp/convolution/convolution.html

Para responder sua segunda pergunta primeiro, quanto maior o kernel, mais cara será a operação. Portanto, quanto maior o raio do desfoque, mais longa será a operação.

Para responder à sua primeira pergunta, como explicado acima, a convolução pode ser feita multiplicando cada pixel de entrada com o kernel inteiro. No entanto, se o kernel for simétrico (que é um kernel gaussiano), você também poderá multiplicar cada eixo (x e y) independentemente, o que diminuirá o número total de multiplicações. Em termos matemáticos adequados, se uma matriz é separável, ela pode ser decomposta em matrizes (M × 1) e (1 × N). Para o kernel gaussiano acima, isso significa que você também pode usar os seguintes kernels:

1256[1464141624164624362464162416414641]=1256[14641][14641]

Agora você multiplicaria cada pixel na imagem de entrada com os dois núcleos e adicionaria os valores resultantes para obter o valor do pixel de saída.

Para mais informações sobre como ver se um kernel é separável, siga este link .

Editar: os dois núcleos mostrados acima usam valores ligeiramente diferentes. Isso ocorre porque o parâmetro (sigma) usado para a curva gaussiana para criar esses núcleos foi ligeiramente diferente nos dois casos. Para uma explicação sobre quais parâmetros influenciam a forma da curva gaussiana e, portanto, os valores no kernel seguem este link

Edit: na segunda imagem acima, diz que o kernel usado é invertido. Obviamente, isso só faz diferença se o kernel que você usa não é simétrico. A razão pela qual você precisa inverter o kernel tem a ver com as propriedades matemáticas da operação de convolução (consulte o link para obter uma explicação mais aprofundada sobre convolução). Simplificando: se você não inverter o kernel, o resultado da operação de convolução será invertido. Ao virar o kernel, você obtém o resultado correto.

Bert
fonte
1
Você poderia adicionar uma breve nota para explicar por que os dois núcleos 5 por 5 diferentes têm números ligeiramente diferentes (um com 273 e outro com 256)? Parece uma confusão potencial para alguém novo nisso.
Trichoplax
Da mesma forma, você poderia explicar por que o kernel é invertido no seu segundo diagrama? Não acho relevante para a explicação, mas o fato de ser um passo extra aparente pode dificultar o entendimento de alguém que não sabe que não é necessário.
Trichoplax
não se esqueça de trabalhar no espaço de cores linear para obter resultados corretos.
v.oddou
16

Aqui está o melhor artigo que li sobre o tema: Desfoque Gaussiano eficiente com amostragem linear . Ele aborda todas as suas perguntas e é realmente acessível.

Para o leigo, uma explicação muito curta: Gaussiana é uma função com a bela propriedade de ser separável, o que significa que uma função Gaussiana 2D pode ser calculada combinando duas funções Gaussianas 1D.

n×nO(n2)2×nO(n)

nn

Julien Guertault
fonte
13

Em geral, uma convolução é realizada tomando-se a integral do produto de duas funções em uma janela deslizante, mas se você não é do fundo da matemática, essa não é uma explicação muito útil e certamente não lhe dará uma intuição útil por isso. Mais intuitivamente, uma convolução permite que vários pontos em um sinal de entrada afetem um único ponto em um sinal de saída.

Como você não está muito confortável com as convoluções, vamos primeiro revisar o que significa uma convolução em um contexto discreto como esse e, em seguida, analisar um borrão mais simples.

Em nosso contexto discreto, podemos multiplicar nossos dois sinais simplesmente multiplicando cada amostra correspondente. A integral também é simples de fazer de forma discreta, apenas adicionamos cada amostra no intervalo em que estamos integrando. Uma convolução simples e discreta é calcular uma média móvel. Se você deseja obter a média móvel de 10 amostras, isso pode convencer seu sinal por uma distribuição com 10 amostras e 0,1 de altura, cada amostra na janela primeiro é multiplicada por 0,1 e todas as 10 são adicionadas para produzir a média. Isso também revela uma distinção interessante e importante, quando você está desfocando com uma convolução, a distribuição que você usa deve somar 1,0 em todas as suas amostras; caso contrário, aumentará ou diminuirá o brilho geral da imagem quando você a aplicar.

Agora que analisamos as convoluções, podemos passar para os borrões. Um desfoque gaussiano é implementado mediante a convolução de uma imagem por uma distribuição gaussiana. Outros borrões são geralmente implementados pela convolução da imagem por outras distribuições. O desfoque mais simples é o desfoque de caixa e usa a mesma distribuição que descrevemos acima, uma caixa com área de unidade. Se quisermos desfocar uma área de 10x10, multiplicamos cada amostra na caixa por 0,01 e, em seguida, somamos todas elas para produzir o pixel central. Ainda precisamos garantir que a soma total de todas as amostras em nossa distribuição de desfoque seja 1,0 para garantir que a imagem não fique mais clara ou mais escura.

r

ex2/22π

O(n2)O(n).

porglezomp
fonte
1
Olhando para sua outra resposta, parece que sua formação em matemática é melhor do que eu estava trabalhando, mas espero que ainda entre em detalhes suficientes para ser útil. Queria que fosse útil para pessoas de qualquer formação que entendessem isso.
porglezomp
1
Se você está falando comigo, de jeito nenhum. Sua resposta e a de Bert são surpreendentemente esclarecedoras. Muito obrigado! Tenho que digerir a informação um pouco agora (:
Alan Wolfe
11

O(n2)O(n)

Mas há mais dois truques que você pode considerar em uma implementação real:

O filtro tem um certo raio e, por isso, nas bordas, você precisará calcular com pixels que ficam fora da imagem. Nesse caso, você pode tentar um dos seguintes procedimentos: para os pixels externos, você simplesmente pega o último valor possível (ou seja, o pixel na borda, como em max(x, 0).) Ou pode "refletir" a imagem para fora (como em x < 0 ? -x : x). Ou você pode simplesmente parar na fronteira, mas precisará ajustar o denominador no filtro de convolução para que ele totalize 1. Por exemplo:

sum1256[1464141624164624362464162416414641]=sum1225[0000001624160024361600162416000000]=1.
     1
    1 1
   1 2 1
  1 3 3 1
[1 4 6 4 1]
Ecir Hana
fonte