OpenGL GLSL - Sobel Kenar Algılama Filtresi


9

Bu konuyla ilgili olarak , GLSL'de Sobel Kenar Algılama filtresini başarıyla uyguladım . Filtrenin parça gölgelendirici kodu:

#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);
} 

Ve işte Sobel kenar algılamalı bir küpün sonucu:

Sobel kenar algılama filtreli küp

Resmi büyütürseniz, Sobel tarafından üretilen çok sayıda "gürültü" olduğunu göreceksiniz: Mavi / beyaz renk geçişi nedeniyle sahnenin her yerinde gri yatay çizgiler var. Dahası, ışık konileri küp üzerinde istenmeyen bir desen üretir. Küpün solundaki siyah kenarlar, küpün sol yarısındaki ışık konisi nedeniyle solmuş gibi görünüyor.

Bu yüzden kişinin önce görüntüyü gri tonlamalı ve kenarları daha belirgin hale getirmek için Gauss bulanıklaştırma filtresi kullanması gerektiğini belirten bu makaleyi okudum . Makalenin alt kısmında, daha iyi sonuçlar verdiği anlaşılan kenar kenarı algılama filtresi de var.

Şimdi iki sorum var:

  1. Mümkün olan en iyi kenar algılama sonuçlarını üretmek için aşağıdaki adımlar doğru mu?

    • Gri tonlama
    • Gauss Bulanıklığı
    • Sobel / Canny kenar algılama
  2. Evetse, orijinal görüntüyü işlenen görüntüyle nasıl birleştiririm? Yani, yukarıda belirtilen adımları işledikten sonra, tamamen beyaz kenarlı siyah bir görüntü veya yardımcı verca alıyorum. Kenarları orijinal görüntüme / dokuma nasıl yerleştiririm?

Yardımın için teşekkürler!


Acaba OpenGL'nin kenar bayrağını bir şekilde kullanarak istediğiniz sonuçları elde edip edemeyeceğinizi merak ediyorum . Çizgi modundayken yalnızca kenar bayrağı açık köşeler arasındaki kenarlar çizilir. Burada bir açıklama var . (Kendim kullanmadım veya bir örnek
gönderirim

Yanıtlar:


9
  1. En iyi sonuçlar büyük ölçüde kullanım durumunuza bağlıdır. Ayrıca hangi etkiye ulaşmak istediğinize de bağlıdırlar. Sobel sadece bir kenar algılama filtresidir: kenarlar, giriş sinyalinin size bağlı olduğunu seçerek giriş sinyaline bağlı olacaktır.

    Burada renkli görüntüyü giriş olarak kullanıyorsunuz ve filtre mavi degradede soluk kenarları doğru bir şekilde tespit ederken, küpün kenarları, rengi arka plan renginden çok yakın olduğunda kesiliyor.

    Programınızın küpü çizmekten de sorumlu olduğunu düşündüğüm için, Sobel filtrenize besleyebileceğiniz diğer bilgilere erişiminiz var. Örneğin derinlik ve normaller kenar tespiti için iyi adaylardır. Aydınlatma öncesi albedo kullanılabilir. Farklı girişlerle test edin ve elde ettiğiniz sonuçlara bağlı olarak hangilerini kullanacağınıza karar verin.

  2. Kenar bilgilerinin nasıl birleştirileceği ile ilgili sorunuzla ilgili olarak, gkullanmadan önce biraz filtrelemenizi öneririz . Ardından, orijinal renk ile istenen kenar rengi arasında enterpolasyon yapmak için kullanabilirsiniz.

    Örneğin şöyle bir şey deneyebilirsiniz:

    float g = sqrt(pow(gx, 2.0)+pow(gy, 2.0));

    // Try different values and see what happens
    g = smoothstep(0.4, 0.6, g);

    vec3 edgeColor = vec3(1., 0., 0.2);
    color = vec4(mix(diffuse, edgeColor, g), 1.);

ek

Derinlik veya normalleri kullanmak için, henüz yapılmadıysa onları bir dokuya kaydetmeniz gerekir. Düzenli oluşturma geçişiniz için çerçeve arabelleği oluşturduğunuzda, ona çeşitli dokular ekleyebilir (bkz. glFramebufferTexture2D) Ve bunlara yalnızca sahnenin renginden başka bilgiler yazabilirsiniz.

Bir derinlik dokusu (ile GL_DEPTH_ATTACHMENT) eklerseniz , derinlik için otomatik olarak kullanılır. Bir veya daha fazla renk dokusu (ile GL_COLOR_ATTACHMENTi) eklerseniz, parça gölgelendiricilerinize birkaç çıktı bildirerek bunlara yazabilirsiniz (bu eskiden yapılır gl_FragData; her iki şekilde de, bkz. glDrawBuffers).

Konu hakkında daha fazla bilgi için "Çoklu İşleme Hedefi" (MRT) konusuna bakın .


Güzel bilgi, teşekkürler Julien. Bir soru daha: Parça gölgelendiricimdeki derinliği veya normal bilgileri nasıl kullanabilirim? GLSL ile hala oldukça yeniyim ve bu nedenle Sobel algoritmasına değerleri nasıl ekleyeceğimi bilmiyorum.
enne87

2
Render geçişiniz için çerçeve tamponu oluşturduğunuzda, ona birden fazla doku ekleyebilirsiniz. Bir derinlik dokusu eklerseniz, derinlik için otomatik olarak kullanılır. Ayrı olarak yazabileceğiniz başka bir renk dokusu eklersiniz (bkz. "Çoklu İşleme Hedefi" (MRT) adlı bir özellik olan opengl.org/sdk/docs/man/html/glDrawBuffers.xhtml ).
Julien Guertault

@ enne87: Yardım etmekten mutluluk duyarız. :)
Julien Guertault

@trichoplax: öneriniz için teşekkürler; yapılır.
Julien Guertault
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.