Что касается этой темы, я успешно внедрил фильтр Sobel Edge Detection в GLSL. Вот фрагмент кода шейдера фильтра:
#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);
}
И вот результат куба с обнаружением края Собеля:
Если вы увеличите изображение, вы увидите, что Sobel производит много «шума»: по всей сцене присутствуют серые горизонтальные полосы из-за сине-белого градиента. Кроме того, световые конусы создают нежелательный узор на кубе. Черные края слева от куба также кажутся блеклыми из-за светового конуса на левой половине куба.
Поэтому я прочитал эту статью, в которой говорилось, что сначала нужно откорректировать изображение в оттенках серого и использовать фильтр размытия по Гауссу, чтобы сделать края более заметными. В нижней части статьи также есть фильтр обнаружения краев, который, кажется, дает лучшие результаты.
Теперь у меня есть два вопроса:
Правильны ли следующие шаги для получения наилучших результатов обнаружения края:
- Оттенки серого
- Gaussian Blur
- Sobel / Canny edge обнаружения
Если да, как мне объединить исходное изображение с обработанным изображением? Я имею в виду, что после обработки описанных выше шагов я получаю изображение, которое либо полностью черное с белыми краями, либо наоборот. Как бы я поместил края на исходное изображение / текстуру?
Спасибо за вашу помощь!