Pregunta

Estoy tratando de aplicar un borde de caja a una imagen transparente, y estoy obteniendo un "halo oscuro" alrededor de los bordes.

Jerry Huxtable tiene una breve mención del problema, y una muy buena demostración que muestra el problema sucede:

enter image description here

Pero yo, por mi vida, no puedo entender cómo "alfa previamente multiplicado"Puede solucionar el problema. Ahora para un ejemplo muy simple. Tengo una imagen 3x3, que contiene un píxel rojo y un verde:

enter image description here

En realidad, los píxeles restantes son transparentes:

enter image description here

Ahora aplicaremos un desenfoque de caja de 3x3 a la imagen. Por simplicidades, solo calcularemos el nuevo valor del píxel central. La forma en que funciona un borde de caja es que, dado que tenemos un cuadrado de 9 posición (3x3, llamado núcleo), tomamos 1/9 de cada píxeles en el núcleo, y lo agregamos:

enter image description here

Asi que

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

En este ejemplo muy simplificado, los cálculos se vuelven muy simples:

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

Esto me da un valor de color final de:

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

enter image description here

Este color es demasiado oscuro. Cuando realizo un desenfoque de 3px en la misma imagen de 3x3 píxeles en Photoshop, obtengo lo que espero:

enter image description here

Que es más claro cuando se muestra sobre blanco:

enter image description here


En realidad, estoy realizando un cuadro desenfoque en un mapa de bits que contiene texto transparente, y el texto gana el oscuro y revelador alrededor de las franjas:

enter image description here

Estoy empezando con un mapa de bits GDI+ que está en PixelFormat32bppARGB formato


¿Cómo uso el "alfa pre-multiplicado" al aplicar el núcleo de convolución 3x3?

Cualquier respuesta tendrá que incluir nueva Forumla, ya que:

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

Me está dando la respuesta incorrecta.


Editar: Un ejemplo más simple es:

Realizaré esta matemática con color y valores alfa en el rango de 0..1:

enter image description here

Voy a aplicar el filtro de convolución blur de caja al píxel medio:

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)

Que da un verde oscuro bastante transparente.

enter image description here

Que no es lo que espero ver. Y en comparación, la caja de la caja de Photoshop es:

enter image description here

Si asumo (0, 0.33, 0, 0.33) es alfa pre-multiplicado, y sin múltiples, obtengo:

(0, 1, 0, 0.33)

enter image description here

Que se ve bien para mi ejemplo de todo opaco; Pero no sé qué hacer cuando empiezo a involucrar píxeles parcialmente transparentes.

Ver también

¿Fue útil?

Solución

Tkerwin tiene ya proporcioné la respuesta correcta, pero parece necesitar más explicación.

Las matemáticas que ha mostrado en su pregunta son absolutamente correctas, hasta el final. Es allí donde te estás perdiendo un paso: los resultados todavía están en un modo alfa pre -multiplicado, y deben estar "sin múltiples" al formato PixAlformat32BPParGB. Lo contrario de una multiplicada es una división, por lo tanto:

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

Has expresado la preocupación de que la división podría crear un resultado que esté muy fuera de rango, pero eso no sucederá. Si rastrea las matemáticas, notará que los valores rojos, verdes y azules no pueden ser mayores que el valor alfa, debido al paso previo a la multiplicación. Si estuviera usando un filtro más complicado que un simple desenfoque de caja, podría ser una posibilidad, ¡pero ese sería el caso incluso si no usara Alpha! La respuesta correcta es sujetar el resultado, convirtiendo los números negativos en 0 y cualquier cosa mayor que 255 en 255.

Otros consejos

Siguiendo el consejo en su enlace, pre-multiplicado antes de desenfoque y sin ser multiplicado después de desenfoque. En su ejemplo, el pre-multiplicador en realidad no hace nada, ya que no hay píxeles semitransparentes. Hiciste el desenfoque, luego necesitas que no te presentes (suponiendo valores de color normalizados de 0 a 1):

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

Esto le dará una imagen final borrosa no múltiple.

Ambas respuestas parecen mal aquí.

Use el modo de mezcla adecuado, que según Porter Duff es:

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

No estoy seguro de dónde provienen el resto de las respuestas, pero wow.

La codificación alfa dicta la operación excesiva.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top