Question

Ma boucle interne contient un calcul de profilage révèle être problématique.

L'idée est de prendre un pixel en niveaux de gris x (0 <= x <= 1), et "augmenter le contraste". Mes exigences sont assez lâche, tout ce qui suit:

  • pour x <0,5, 0 <= f (x)
  • pour x> 0,5, x
  • f (0) = 0
  • f (x) = 1 - f (1 - x), à savoir il doit être "symétrique"
  • De préférence, la fonction doit être lisse.

Ainsi, le graphique doit ressembler à ceci:

Graph.

J'ai deux implémentations (leurs résultats diffèrent, mais les deux sont conforme):

float cosContrastize(float i) {
    return .5 - cos(x * pi) / 2;
}

float mulContrastize(float i) {
    if (i < .5) return i * i * 2;
    i = 1 - i;
    return 1 - i * i * 2;
}

Je demande soit un microoptimization pour l'une de ces mises en œuvre, ou un original, plus rapide de votre formule.

Peut-être que l'un d'entre vous peut même les bits tripoter;)

Était-ce utile?

La solution

trivialement vous pouvez simplement seuil, mais j'imagine que cela est trop stupide:

return i < 0.5 ? 0.0 : 1.0;

Puisque vous parlez de « contraste de plus en plus: » Je suppose que les valeurs d'entrée sont des valeurs de luminance. Si oui, et ils sont discrets (peut-être est une valeur de 8 bits), vous pouvez utiliser une table de consultation pour le faire assez rapidement.

Votre 'mulContrastize' semble raisonnablement rapide. Une optimisation serait d'utiliser les mathématiques entier. Disons que, encore une fois, vos valeurs d'entrée pourraient effectivement être passés comme une valeur non signée 8 bits dans [0..255]. (Encore une fois, peut-être une hypothèse bien?) Vous pourriez faire quelque chose à peu près comme ...

int mulContrastize(int i) {
  if (i < 128) return (i * i) >> 7; 
  // The shift is really: * 2 / 256
  i = 255 - i;
  return 255 - ((i * i) >> 7);

Autres conseils

Considérez ce qui suit sigmoïde Fonctions (correctement traduites en forme à la plage souhaitée):

capture d'écran


je la figure ci-dessus généré Matlab. Si vous êtes intéressé ici le code:

x = -3:.01:3;
plot(   x, 2*(x>=0)-1, ...
        x, erf(x), ...
        x, tanh(x), ...
        x, 2*normcdf(x)-1, ...
        x, 2*(1 ./ (1 + exp(-x)))-1, ...
        x, 2*((x-min(x))./range(x))-1  )
legend({'hard' 'erf' 'tanh' 'normcdf' 'logit' 'linear'})

Une interpolation par morceaux peut être rapide et flexible. Il ne nécessite que quelques décisions suivies d'une multiplication et d'addition, et peut approcher une courbe. Il permet également d'éviter la courseness qui peut être introduit par des tables de consultation (ou le coût supplémentaire de deux suivie d'une lookups interpolation pour lisser ceci), bien que le LUT pourrait fonctionner parfaitement bien pour votre cas.

Avec seulement quelques segments, vous pouvez obtenir une assez bon match. Ici, il y aura courseness dans la couleur gradients , qui sera beaucoup plus difficile à détecter que courseness dans les couleurs absolues.

Eamon Nerbonne souligne dans les commentaires, la segmentation peut être optimisée par « choos [ant] vos points de segmentation basée sur quelque chose comme la dérivée seconde pour maximiser les détails », qui est, où la pente change le plus. Il est clair que, dans mon exemple affiché, ayant trois segments au milieu du cas de cinq segments n'ajoute pas beaucoup plus de détails.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top