Con respecto a este tema , he implementado con éxito el filtro de detección de bordes Sobel en GLSL. Aquí está el código del sombreador de fragmentos del filtro:
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D screenTexture;
mat3 sx = mat3(
1.0, 2.0, 1.0,
0.0, 0.0, 0.0,
-1.0, -2.0, -1.0
);
mat3 sy = mat3(
1.0, 0.0, -1.0,
2.0, 0.0, -2.0,
1.0, 0.0, -1.0
);
void main()
{
vec3 diffuse = texture(screenTexture, TexCoords.st).rgb;
mat3 I;
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
vec3 sample = texelFetch(screenTexture, ivec2(gl_FragCoord) + ivec2(i-1,j-1), 0 ).rgb;
I[i][j] = length(sample);
}
}
float gx = dot(sx[0], I[0]) + dot(sx[1], I[1]) + dot(sx[2], I[2]);
float gy = dot(sy[0], I[0]) + dot(sy[1], I[1]) + dot(sy[2], I[2]);
float g = sqrt(pow(gx, 2.0)+pow(gy, 2.0));
color = vec4(diffuse - vec3(g), 1.0);
}
Y aquí está el resultado de un cubo con detección de bordes Sobel:
Si amplía la imagen, verá que Sobel produce mucho "ruido": hay franjas horizontales grises en toda la escena debido al gradiente azul / blanco. Además, los conos de luz producen un patrón no deseado en el cubo. Los bordes negros a la izquierda del cubo también parecen desvanecerse debido al cono de luz en la mitad izquierda del cubo.
Entonces leí este artículo que decía que primero se debería escalar la imagen en escala de grises y usar un filtro de desenfoque gaussiano para hacer que los bordes sean más aparentes. Al final del artículo, también está el filtro de detección de bordes astutos que parece producir mejores resultados.
Ahora tengo dos preguntas:
¿Son correctos los siguientes pasos para producir los mejores resultados posibles de detección de bordes?
- Escala de grises
- Desenfoque gaussiano
- Detección de bordes Sobel / Canny
En caso afirmativo, ¿cómo fusionaría la imagen original con la imagen procesada? Quiero decir, después de procesar los pasos indicados anteriormente, obtengo una imagen que es completamente negra con bordes blancos o viceversa. ¿Cómo pondría los bordes en mi imagen / textura original?
¡Gracias por tu ayuda!
fuente
Respuestas:
Los mejores resultados dependen en gran medida de su caso de uso. También dependen del efecto que quieras lograr. Sobel es solo un filtro de detección de bordes: los bordes dependerán de la señal de entrada, la elección de esa señal de entrada depende de usted.
Aquí está utilizando la imagen en color como entrada, y el filtro detecta correctamente los bordes débiles en el degradado azul, mientras que los bordes del cubo se interrumpen cuando su color está demasiado cerca del color de fondo.
Como supongo que su programa también es responsable de dibujar el cubo, tiene acceso a otra información que puede alimentar a su filtro Sobel. Por ejemplo, la profundidad y las normales son buenas candidatas para la detección de bordes. El albedo antes de la iluminación podría estar acostumbrado. Pruebe con diferentes entradas y decida cuáles usar según los resultados que obtenga.
Con respecto a su pregunta sobre cómo combinar la información de borde, le sugiero que filtre
g
un poco antes de usarla. Luego puede usarlo para interpolar entre el color original y el color del borde deseado.Por ejemplo, podrías probar algo como esto:
Apéndice
Para usar profundidad o normales, necesitaría guardarlas en una textura si eso no se ha hecho ya. Cuando crea el búfer de cuadro para su pase de representación regular, puede adjuntarle varias texturas (ver
glFramebufferTexture2D
) y escribirles otra información que no sea solo el color de la escena.Si adjunta una textura de profundidad (con
GL_DEPTH_ATTACHMENT
), se usará automáticamente para la profundidad. Si adjunta una o varias texturas de color (conGL_COLOR_ATTACHMENTi
), puede escribirles declarando varias salidas a sus sombreadores de fragmentos (esto solía hacerse congl_FragData
; de cualquier manera, verglDrawBuffers
).Para obtener más información sobre el tema, busque "Multi Render Target" (MRT).
fuente