En ce qui concerne ce sujet, j'ai réussi à implémenter le filtre de détection des bords Sobel dans GLSL. Voici le fragment shader code du filtre:
#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);
}
Et voici le résultat d'un cube avec détection de bords Sobel:
Si vous agrandissez l'image, vous verrez qu'il y a beaucoup de "bruit" produit par Sobel: Il y a des rayures horizontales grises sur toute la scène en raison du dégradé bleu / blanc. De plus, les cônes lumineux produisent un motif indésirable sur le cube. Les bords noirs à gauche du cube semblent également s'estomper à cause du cône de lumière sur la moitié gauche du cube.
J'ai donc lu cet article qui disait qu'il fallait d'abord mettre l'image en niveaux de gris et utiliser un filtre de flou gaussien pour rendre les bords plus apparents. Au bas de l'article, il y a aussi le filtre de détection de bord rusé qui semble produire de meilleurs résultats.
Maintenant, j'ai deux questions:
Les étapes suivantes sont-elles correctes pour produire les meilleurs résultats de détection de bord possibles:
- Niveaux de gris
- Flou gaussien
- Détection des bords Sobel / Canny
Si oui, comment fusionnerais-je l'image originale avec l'image traitée? Je veux dire, après avoir traité les étapes décrites ci-dessus, j'obtiens une image qui est soit complètement noire avec des bords blancs, soit vice-versa. Comment placer les bords sur mon image / texture d'origine?
Merci de votre aide!
la source
Réponses:
Les meilleurs résultats dépendent fortement de votre cas d'utilisation. Ils dépendent également de l'effet que vous souhaitez obtenir. Sobel n'est qu'un filtre de détection de bord: les bords dépendront du signal d'entrée, en choisissant le signal d'entrée qui vous appartient.
Ici, vous utilisez l'image couleur comme entrée, et le filtre détecte à juste titre les bords faibles dans le dégradé bleu, tandis que les bords du cube sont interrompus là où sa couleur est trop proche de la couleur d'arrière-plan.
Comme je suppose que votre programme est également responsable du dessin du cube, vous avez accès à d'autres informations que vous pouvez alimenter dans votre filtre Sobel. Par exemple, la profondeur et les normales sont de bons candidats pour la détection des bords. L'albédo avant l'éclairage peut être utilisé. Testez avec différentes entrées et décidez lesquelles utiliser en fonction des résultats que vous obtenez.
En ce qui concerne votre question sur la façon de combiner les informations de bord, je vous suggère de filtrer
g
un peu avant de les utiliser. Ensuite, vous pouvez l'utiliser pour interpoler entre la couleur d'origine et la couleur de bord souhaitée.Par exemple, vous pouvez essayer quelque chose comme ceci:
Addenda
Pour utiliser la profondeur ou les normales, vous devez les enregistrer dans une texture si ce n'est pas déjà fait. Lorsque vous créez le tampon d'image pour votre passage de rendu normal, vous pouvez y attacher diverses textures (voir
glFramebufferTexture2D
) et y écrire d'autres informations que la couleur de la scène.Si vous attachez une texture de profondeur (avec
GL_DEPTH_ATTACHMENT
), elle sera utilisée automatiquement pour la profondeur. Si vous attachez une ou plusieurs textures de couleur (avecGL_COLOR_ATTACHMENTi
), vous pouvez y écrire en déclarant plusieurs sorties à vos shaders de fragment (cela se faisait auparavant avecgl_FragData
; de toute façon, voirglDrawBuffers
).Pour plus d'informations sur le sujet, recherchez «Multi Render Target» (MRT).
la source