Calcule o gradiente para um histograma em C ++
Pergunta
Calculei o histograma (uma matriz 1D simples) para uma imagem em escala de cinza 3D. Agora eu gostaria de calcular o gradiente para este histograma em cada ponto. Portanto, isso significaria que eu tenho que calcular o gradiente para uma função 1D em determinados pontos. No entanto, eu não tenho uma função. Então, como posso calculá -lo com valores de concreto x e y?
Por uma questão de simplicidade, você provavelmente poderia me explicar isso em um exemplo de histograma - por exemplo, com os seguintes valores (x é a intensidade e a frequência dessa intensidade):
x1 = 1; y1 = 3
x2 = 2; y2 = 6
x3 = 3; y3 = 8
x4 = 4; y4 = 5
x5 = 5; y5 = 9
x6 = 6; y6 = 12
x7 = 7; y7 = 5
x8 = 8; y8 = 3
x9 = 9; y9 = 5
x10 = 10; y10 = 2
Sei que isso também é um problema de matemática, mas como preciso resolvê -lo em C ++ I, você pode me ajudar aqui.
Obrigado pelo seu conselho Marc
Solução
Eu acho que você pode calcular seu gradiente usando a mesma abordagem usada na detecção de borda de imagem (que é um cálculo de gradiente). Se o seu histograma estiver em um vetor, você poderá calcular uma aproximação do gradiente como*:
for each point in the histogram compute
gradient[x] = (hist[x+1] - hist[x])
Essa é uma maneira muito simples de fazê -lo, mas não tenho certeza se é a mais precisa.
- aproximação porque você está trabalhando com dados discretos em vez de contínuo
Editado:
Outros operadores podem enfatizar pequenas diferenças (pequenos gradientes se tornarão mais enfatizados). O algoritmo Roberts deriva do cálculo derivado:
lim delta -> 0 = f(x + delta) - f(x) / delta
O Delta tende infinitamente a 0 (para evitar a divisão 0), mas nunca é zero. Como na memória do computador, isso é impossível, o menor que podemos obter do delta é 1 (porque 1 é a menor distância de pontos em uma imagem (ou histograma)).
Substituindo
lim delta -> 0 to lim delta -> 1
Nós temos
f(x + 1) - f(x) / 1 = f(x + 1) - f(x) => vet[x+1] - vet[x]
Outras dicas
Dois geralmente se aproximam aqui:
- uma aproximação discreta à derivada
- Pegue a verdadeira derivada de uma função ajustada
No Primeiro caso tentar:
g = (y_(i+1) - y_(i-1))/2*dx
em todos os pontos, exceto os fins, ou um dos
g_left-end = (y_(i+1) - y_i)/dx
g_right-end = (y_i - y_(i-1))/dx
Onde dx
é o espaçamento entre x pontos. (Ao contrário da definição igualmente correta Andres sugeriu, este é simétrico. Se isso importa ou não, depende de você usar o caso.)
No Segundo caso, ajuste a spline para seus dados [*] e pergunte à biblioteca spline a derivada no ponto que você deseja.
*] Use uma biblioteca! Não implemente isso você mesmo, a menos que este seja um projeto de aprendizado. Eu usaria RAIZ Porque eu já tenho na minha máquina, mas é um pacote bastante pesado apenas para obter uma spline ...
Finalmente, se você estiver barulhento, você deseja suavizá -los antes de fazer a detecção de inclinação. Isso foi evitar perseguir o barulho e só olha para encostas em larga escala.
Pegue um pouco de papel quadrado e desenhe seu histograma. Desenhe também eixos verticais e horizontais através do ponto 0,0 do seu histograma.
Pegue uma borda reta e, a cada ponto em que você está interessado, gire a borda reta até que ela concorra à sua idéia do que é o gradiente nesse ponto. É mais importante que você faça isso, sua definição de gradiente é a que você deseja.
Uma vez que a borda reta estiver no ângulo que você deseja desenhar uma linha nesse ângulo.
Drop perpendiculares de 2 pontos na linha que você acabou de desenhar. Será mais fácil dar a seguinte etapa se a distância horizontal entre os 2 pontos escolhidos for de cerca de 25% ou mais da largura do seu histograma. A partir dos mesmos 2 pontos, desenham linhas horizontais para cruzar o eixo vertical do seu histograma.
Suas linhas agora definem uma distância x e uma distância y, ou seja, o comprimento dos eixos horizontais/ verticais (respectivamente) marcados por suas interseções com as linhas perpendiculares/ horizontais. O gradiente que você deseja é a distância Y dividida pela distância x.
Agora, para traduzir isso em código é muito direto, além da etapa 2. Você deve definir quais são os critérios para determinar o que é o gradiente em qualquer ponto do histograma. As opções simples incluem:
a) Em cada ponto, defina sua borda reta para passar pelo ponto e a próxima à sua direita;
b) Em cada ponto, defina sua borda reta para passar pelo ponto e a próxima à esquerda;
c) Em cada ponto, defina sua borda reta para passar pelo ponto à esquerda e o ponto para a direita.
Você pode investigar opções mais complexas, como ajustar uma curva (como um polinômio quadrático ou de ordem superior) através de vários pontos no seu histograma e usando o derivado disso para representar o gradiente.
Até você entender a pergunta no papel, evite codificar em C ++ ou qualquer outra coisa. Depois de entender, a codificação deve ser trivial.