Question

Je suis en train d'appliquer une boîte flou à une image transparente, et que je reçois un « halo sombre » sur les bords.

Jerry Huxtable a une courte mention du problème , et une très bonne démonstration montrant le problème se produit:

entrer image description ici

Mais je, pour la vie de moi, ne peut pas comprendre comment « alpha prémultipliés » peut résoudre le problème. Maintenant, pour un exemple très simple. i ont une image de 3x3, contenant un rouge et un pixel vert:

entrer image description ici

En réalité, les pixels restants sont transparents:

entrer image description ici

Maintenant, nous allons appliquer un 3x3 Box Blur à l'image. Pour l'amour de simplicités, nous ne calculons la nouvelle valeur du pixel central. La façon dont un flou de boîte fonctionne est que, puisque nous avons un (appelé 3x3, le noyau) carré de position 9 nous prendre 1/9 chaque pixel dans le noyau, et l'ajouter jusqu'à:

entrer image description ici

finalRed =   1/9 * red1 + 1/9 * red2 + 1/9 * red3+ ... + 1/9 * red9
finalGreen = 1/9*green1 + 1/9*green2 + 1/9*green3+ ... + 1/9*green9
finalBlue =  1/9* blue1 + 1/9* blue2 + 1/9* blue3+ ... + 1/9* blue9
finalAlpha = 1/9*alpha1 + 1/9*alpha2 + 1/9*alpha3+ ... + 1/9*alpha9

Dans cet exemple très simplifié, les calculs deviennent très simples:

finalRed =   1/9 * 255
finalGreen = 1/9 * 255
finalBlue =  0
finalAlpha = 1/9*255 + 1/9*255

Cela me donne une valeur de couleur finale:

finalRed =   28
finalGreen = 28
finalBlue =  0
finalAlpha = 56 (22.2%)

entrer image description ici

Cette couleur est trop sombre. Lorsque j'effectue un 3px flou Box sur la même image de 3x3 pixels dans Photoshop, je reçois ce que je pense:

entrer image description ici

Ce qui est plus clair lors de l'affichage sur blanc:

entrer image description ici


En réalité, je joue une boîte flou sur un bitmap contenant du texte transparent, et le texte gagne le noir tell-tale autour des franges:

entrer image description ici

je commence avec un Bitmap GDI + qui est en format PixelFormat32bppARGB


Comment lors de l'application du noyau de convolution 3x3 utiliser "alpha prémultipliés"?

Toute réponse devra inclure de nouvelles forumla, depuis:

final = 1/9*(pixel1+pixel2+pixel3...+pixel9)

me faire la mauvaise réponse.


Modifier Un exemple plus simple est:

i va effectuer ce calcul avec des valeurs de couleur et alpha dans la gamme de 0..1:

entrer image description ici

Je vais appliquer la boîte filtre de convolution de flou au pixel milieu:

ARGB'
      = 1/9 * (0,1,0,1) + 1/9 * (0,0,0,0) + 1/9 * (0,0,0,0) + 
        1/9 * (0,1,0,1) + 1/9 * (0,0,0,0) + 1/9 * (0,0,0,0) + 
        1/9 * (0,1,0,1) + 1/9 * (0,0,0,0) + 1/9 * (0,0,0,0);

      = (0, 0.11, 0, 0.11) + (0,0,0,0) + (0,0,0,0) +
        (0, 0.11, 0, 0.11) + (0,0,0,0) + (0,0,0,0) +
        (0, 0.11, 0, 0.11) + (0,0,0,0) + (0,0,0,0)

      = (0, 0.33, 0, 0.33)

Ce qui donne un vert foncé assez transparent.

entrer image description ici

Ce qui est pas ce que j'attends de voir. Et par comparaison Blur Box de Photoshop est:

entrer image description ici

Si je suppose (0, 0.33, 0, 0.33) est l'alpha prémultipliés, et non se multiplient, je reçois:

(0, 1, 0, 0.33)

entrer image description ici

Ce qui semble bon pour mon exemple tout opaque; mais je ne sais pas quoi faire quand je commence à impliquer les pixels partiellement transparents.

Voir aussi

Était-ce utile?

La solution

tkerwin a déjà fourni réponse correcte, mais il semble avoir besoin d'autres explications.

Les mathématiques que vous avez montré dans votre question est tout à fait correcte jusqu'à, jusqu'à la fin. Il est là que vous manque une étape - les résultats sont encore en mode alpha prémultipliés, et doit être « non multipliée » au format PixelFormat32bppARGB. L'inverse d'une multiplication est une division, donc:

finalRed = finalRed * 255 / finalAlpha;
finalGreen = finalGreen * 255 / finalAlpha;
finalBlue = finalBlue * 255 / finalAlpha;

Vous avez exprimé une préoccupation que le fossé pourrait créer un résultat qui est follement hors de portée, mais cela ne se produira pas. Si vous tracez le calcul, vous remarquerez que les valeurs de rouge, vert et bleu ne peut pas être supérieure à la valeur alpha, en raison de l'étape de pré-multiplication. Si vous utilisez un filtre plus compliqué qu'une simple boîte flou, il est peut-être une possibilité, mais ce serait le cas même si vous ne l'utilisez alpha! La réponse correcte consiste à serrer le résultat, en tournant les nombres négatifs en 0 et toute valeur supérieure à 255 255 en.

Autres conseils

En suivant les conseils de votre lien, vous prémultiplier avant le flou et non prémultiplier après le flou. Dans votre exemple, pré-multiplication ne fait rien, car il n'y a pas de pixels semi-transparents. Vous avez le flou, alors vous avez besoin vous non prémultiplier en faisant (en supposant des valeurs de couleur normalisées de 0 à 1):

RGB' = RGB/A  (if A is > 0)
A' = A

vous obtiendrez une image finale floue non prémultipliés.

Les deux réponses apparaissent mal ici.

Utiliser le mode de fusion approprié, qui, selon Porter Duff est:

FG.RGB + (1.0 - FG.Alpha)*BG.RGB

Je ne sais pas où le reste des réponses viennent, mais wow.

L'alpha codant dicte le fonctionnement au-dessus de.

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