2009-12-29 23 views
1

J'ai calculé l'histogramme (un tableau 1d simple) pour une image en niveaux de gris 3D. Maintenant, je voudrais calculer le gradient pour cet histogramme à chaque point. Donc, cela signifierait que je dois calculer le gradient pour une fonction 1D à certains points. Cependant je n'ai pas de fonction. Alors, comment puis-je le calculer avec des valeurs concrètes x et y?Calculer le gradient pour un histogramme en C++

Par souci de simplicité pourriez-vous expliquer sans doute cela pour moi sur un histogramme exemple - par exemple avec les valeurs suivantes (x est l'intensité, et y la fréquence de cette intensité):

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; Je sais que c'est aussi un problème de maths, mais comme j'ai besoin de le résoudre en C++, vous pouvez m'aider ici.

Merci pour vos conseils Marc

+2

Puisque vous n'avez pas de fonction, et que ces points peuvent être ajustés à un nombre arbitraire de fonctions qui passent par ces points, le gradient est inconnaissable. Vous devrez mieux contraindre les paramètres de la fonction cachée afin de découvrir le dégradé. Peut-être préféreriez-vous plutôt connaître le gradient de la droite la mieux ajustée à tous ces points (régression linéaire) ou spécifier que vous voulez connaître le gradient d'une fonction quadratique (par exemple) qui passe le plus près de ces points? –

+0

Salut, comme je l'ai écrit ci-dessous, j'ai besoin du dégradé pour déterminer si la pente de mes histogrammes est en baisse ou en hausse. Et en général, je pense que l'approche d'Andreas d'en bas devrait être ok. Cependant, je ne sais pas s'il y a des problèmes avec les valeurs aberrantes sur la pente. Vos suggestions (régression linéaire ou gradient d'un quadratique) résoudraient-elles ce problème? De plus, j'aimerais utiliser ces calculs sur différents histogrammes. La régression linéaire fonctionne-t-elle partout, puisque l'histogramme peut avoir de nombreux pics et n'augmente ou ne diminue pas toujours dans toute la plage d'intensité. Merci pour votre aide, Cordialement – Marc

+0

@ Marc encore une chose (pas lié à la question). Les gens ne seront pas très désireux de vous aider si vous n'acceptez pas les réponses ou même ne votez pas dans les réponses que vous pensez pouvoir vous être utiles – Andres

Répondre

3

Je pense que vous pouvez calculer votre gradient en utilisant la même approche que celle utilisée pour la détection de bordure d'image (qui est un calcul de gradient). Si votre histogramme est un vecteur, vous pouvez calculer une approximation du gradient comme *:

for each point in the histogram compute 
    gradient[x] = (hist[x+1] - hist[x]) 

Ceci est un moyen très simple de le faire, mais je ne sais pas si c'est le plus précis.

  • approximation parce que vous travaillez avec des données discrètes au lieu de continu

Edité:

D'autres opérateurs se peut mettre l'accent sur les petites différences (petits gradients seront devenus plus accentuées). algorithme Roberts dérive du calcul dérivé:

lim delta -> 0 = f(x + delta) - f(x)/delta 

delta tend infiniment à 0 (afin d'éviter la division 0) mais jamais nul. Comme dans la mémoire de l'ordinateur c'est impossible, le plus petit de delta est 1 (parce que 1 est la plus petite distance entre les points d'une image (ou histogramme)).

Substituer

lim delta -> 0 to lim delta -> 1 

nous obtenons

f(x + 1) - f(x)/1 = f(x + 1) - f(x) => vet[x+1] - vet[x] 
+0

Salut, pour la détection de frontière dans les images 2D qu'ils utilisent souvent des masques comme: [-1 0 1] [-2 0 2] [-1 0 1] (ce qui devrait être un masque 3x3 - chaque partie de [] est une ligne). Un autre type de masque comme celui-ci peut-il être utilisé par 1D? Par exemple comme ceci: -1 0 1, ou -2 0 2 (donc pour mon premier masque: -1 * hist [x-1] + 0 * hist [x] + 1 * hist [x + 1]) cela améliore probablement votre approche (qui est fondamentalement un masque avec 1 -1) ou les résultats seraient-ils plus mauvais? Observe – Marc

+1

En fait, l'algorithme auquel j'ai répondu ici est celui des opérateurs de détection de frontières Roberts (l'algorithme de détection de bord le plus simple). Vous pouvez le faire en utilisant des masques de convolution si vous voulez [1 -1] mais vous obtiendrez le même résultat et je pense que le calcul des différences est plus rapide. Vous pouvez utiliser n'importe quelle variation d'algorithme d'image ici comme Laplace [-1 2 -1] - L'opérateur de Laplace peut être écrit comme [0 -1 0] [- 1 4 -1] [0-1 0] mais ici je l'ai adapté à 1D. – Andres

+1

@Andres: Un masque de convolution [1 -1] * est * la différence! Non seulement le résultat, mais aussi le calcul est identique ... bien que si vous y pensez "de gauche à droite", [-1 1] est le signe correspondant. [-1 2 -1] peut être considéré comme la somme des différences de chaque côté. – musicinmybrain

2
  1. Prenez le papier quadrillé et dessiner dessus votre histogramme. Dessinez aussi des axes verticaux et horizontaux à travers le point 0,0 de votre histogramme. Prenez une ligne droite et, à chaque point qui vous intéresse, faites pivoter le bord droit jusqu'à ce qu'il soit en accord avec votre idée de ce que le dégradé est en ce point. Il est très important que vous fassiez ceci, votre définition de gradient est celle que vous voulez.

  2. Une fois que le bord droit est à l'angle que vous désirez, tracez une ligne à cet angle.

  3. Perdez des perpendiculaires à partir de 2 points sur la ligne que vous venez de tracer. Il sera plus facile de prendre l'étape suivante si la distance horizontale entre les 2 points choisis est d'environ 25% ou plus de la largeur de votre histogramme. À partir des mêmes 2 points, tracez des lignes horizontales pour couper l'axe vertical de votre histogramme. Vos lignes définissent maintenant une distance x et une distance y, c'est-à-dire la longueur des axes horizontaux/verticaux (respectivement) balisés par leurs intersections avec les perpendiculaires/lignes horizontales. Le gradient que vous voulez est la distance y divisée par la distance x.

Maintenant, pour traduire en code est très simple, à l'exception de l'étape 2. Vous devez définir quels sont les critères pour déterminer ce que le gradient en tout point de l'histogramme est.Les choix simples sont les suivants:

a) à chaque point, placez votre droite pour passer le point et le suivant vers la droite; B) à chaque point, placez votre droite pour passer le point et le suivant vers la gauche; C) à chaque point, placez votre droite pour passer par le point à gauche et le point à droite. Vous voudrez peut-être étudier des choix plus complexes tels que l'ajustement d'une courbe (comme un polynôme quadratique ou d'ordre supérieur) à travers un certain nombre de points sur votre histogramme et en utilisant la dérivée de cela pour représenter le gradient. Jusqu'à ce que vous compreniez la question sur papier, évitez de coder en C++ ou quoi que ce soit d'autre. Une fois que vous l'aurez compris, le codage devrait être trivial.

+1

essentiellement vous lui avez dit de compenser tout gradient est agréable à lui, soit esthétiquement ou autrement. Vous ne semblez pas avoir de méthode générique pour calculer de tels angles, même si j'applaudis la façon dont votre approche ramène à la question centrale (quel gradient voulez-vous?). –

+0

Oui, c'est vrai. C'est son travail de définir ce que le dégradé devrait être et ce n'est pas un problème trivial. S'il veut un dégradé esthétique, il a le droit d'en avoir un, bien que je soupçonne que ce n'est pas ce dont il a vraiment besoin dans cette situation. Je prétends aussi que mesurer la pente d'une droite est exactement une façon générique de calculer un gradient. Mais c'est le choix de l'OP. –

+0

Bonjour, merci pour vos réponses. En fait, j'ai besoin du dégradé pour déterminer si la pente de mes histogrammes augmente ou diminue. Pour l'instant je veux commencer à un certain pic de l'histogramme et découvrir dans quelle gamme d'intensité à gauche et à droite du pic la pente est en train de tomber. Et à partir de quand commence une nouvelle pente ascendante vers un autre pic. En général, l'approximation suggérée ci-dessous (par Andreas) serait acceptable, mais je pense qu'il peut y avoir des valeurs aberrantes sur la pente descendante. Ce serait bien si je pouvais éviter de telles interprétations erronées. salutations – Marc

2

Deux approches généralement ici:

  1. une approximation discrète au dérivé
  2. prendre le dérivé réel d'une fonction ajustée

Dans le premier cas essai:

g = (y_(i+1) - y_(i-1))/2*dx 

à tous les points à l'exception des extrémités, ou l'une des

g_left-end = (y_(i+1) - y_i)/dx 
g_right-end = (y_i - y_(i-1))/dx 

dx est l'espacement entre les points x.(Contrairement à la celle-ci est symétrique. Que importe la définition tout aussi correcte Andres suggested, ou non dépend de vous utilisez le cas.)

Dans le second cas, installez un spline à vos données [*], et demander la spline bibliothèque le dérivé au point que vous voulez.

[*] Utilisez une bibliothèque! Ne l'implémentez pas vous-même, sauf s'il s'agit d'un projet d'apprentissage. J'utiliser ROOT parce que je l'ai déjà sur ma machine, mais il est un peu lourd paquet juste pour obtenir une spline ...


Enfin, si vous les données est bruyant, vous voulez Ma lisser avant de faire une détection de pente. C'était vous éviter de chasser le bruit, et seulement regarder les pentes à grande échelle.

+0

Pouvez-vous expliquer ce que vous voulez dire par symétrique? +1 – Andres

+1

@Andres: Bien sûr. Imaginez un pic symétrique dans l'histogramme avec de longues queues plates. Parce que votre fonction (naturelle si vous pensez à la limite différentielle, bien sûr) implique «i» et «i + 1», mais pas «i-1», le centre de la distribution du gradient bimodal ne sera pas sur le centre du pic. Comme je l'ai dit, cela pourrait ou ne pas avoir d'importance. Et le mien a deux cas spéciaux où votre seul n'en a qu'un. Décisions, décisions ... – dmckee

+0

C'est génial. En traitement d'image, il y a un problème similaire (pas avec la fonction bimodale). Le bord détecté ne correspond pas parfaitement aux bordures de l'image originale (les bords peuvent être considérés comme une sorte de fonction sigmoïde). En théorie, le passage à zéro devrait résoudre ce problème (dérivée double), mais en raison de la nature discrète de l'image, ce n'est pas très précis. Cheers – Andres