Sehubungan dengan topik ini, saya telah berhasil mengimplementasikan filter Sobel Edge Detection di GLSL. Berikut ini adalah kode shader fragmen filter:
#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);
}
Dan ini adalah hasil dari sebuah kubus dengan deteksi tepi Sobel:
Jika Anda memperbesar gambar, Anda akan melihat bahwa ada banyak "noise" yang dihasilkan oleh Sobel: Ada garis-garis horizontal abu-abu di seluruh adegan karena gradien biru / putih. Selanjutnya, kerucut cahaya menghasilkan pola yang tidak diinginkan pada kubus. Tepi hitam di sebelah kiri kubus juga tampaknya memudar karena kerucut cahaya di bagian kiri kubus.
Jadi saya membaca artikel ini yang menyatakan bahwa orang harus menggunakan skala abu-abu terlebih dahulu dan menggunakan filter Gaussian blur untuk membuat bagian tepi lebih jelas. Di bagian bawah artikel, ada juga filter deteksi tepi cerdik yang tampaknya menghasilkan hasil yang lebih baik.
Sekarang saya punya dua pertanyaan:
Apakah langkah-langkah berikut ini benar untuk menghasilkan hasil deteksi tepi sebaik mungkin:
- Skala abu-abu
- Gaussian Blur
- Deteksi tepi Sobel / Canny
Jika ya, bagaimana saya menggabungkan gambar asli dengan gambar yang diproses? Maksudku, setelah memproses langkah-langkah yang disebutkan di atas, saya mendapatkan gambar yang benar-benar hitam dengan tepi putih atau sebaliknya. Bagaimana saya menempatkan ujung pada gambar / tekstur asli saya?
Terima kasih atas bantuan Anda!
sumber
Jawaban:
Hasil terbaik sangat tergantung pada kasus penggunaan Anda. Mereka juga bergantung pada efek apa yang ingin Anda capai. Sobel hanyalah filter deteksi tepi: tepi akan tergantung pada sinyal input, memilih sinyal input terserah Anda.
Di sini Anda menggunakan gambar warna sebagai input, dan filter dengan tepat mendeteksi tepi yang samar dalam gradien biru, sedangkan tepi kubus terganggu di mana warnanya terlalu dekat dari warna latar belakang.
Karena saya menganggap program Anda juga bertanggung jawab untuk menggambar kubus, Anda memiliki akses ke informasi lain yang dapat Anda masukkan ke filter Sobel Anda. Misalnya kedalaman dan normals adalah kandidat yang baik untuk deteksi tepi. Albedo sebelum penerangan bisa digunakan untuk itu. Tes dengan input berbeda dan putuskan mana yang akan digunakan tergantung pada hasil yang Anda dapatkan.
Mengenai pertanyaan Anda tentang cara menggabungkan informasi tepi, saya sarankan Anda menyaring
g
sedikit sebelum menggunakannya. Kemudian Anda dapat menggunakannya untuk menginterpolasi antara warna asli dan warna tepi yang diinginkan.Misalnya, Anda dapat mencoba sesuatu seperti ini:
Tambahan
Untuk menggunakan kedalaman atau normals, Anda harus menyimpannya dalam tekstur jika itu belum dilakukan. Saat Anda membuat buffer bingkai untuk pass rendering reguler Anda, Anda dapat melampirkan berbagai tekstur padanya (lihat
glFramebufferTexture2D
) dan menulis informasi lain kepada mereka daripada hanya warna adegan.Jika Anda memasang tekstur kedalaman (dengan
GL_DEPTH_ATTACHMENT
), itu akan digunakan secara otomatis untuk kedalaman. Jika Anda melampirkan satu atau beberapa tekstur warna (denganGL_COLOR_ATTACHMENTi
), Anda dapat menulis kepada mereka dengan mendeklarasikan beberapa output ke shader fragmen Anda (ini biasanya dilakukan dengangl_FragData
; bagaimanapun, lihatglDrawBuffers
).Untuk informasi lebih lanjut tentang topik ini, lihat "Multi Render Target" (MRT).
sumber