OpenGL - Kenarların algılanması


12

Rasgele ağlar yüklemek ve kenarlar boyunca kalın siyah çizgiler çizmek istiyorum. Şablon tamponunu kullanarak nesnelerin etrafına siyah bir siluet çizmeyi başardım. Sonucu burada görebilirsiniz:

resim açıklamasını buraya girin

Ancak eksik olan, nesnenin kendisindeki siyah çizgilerdir. Normal süreksizlikleri kontrol etmeyi düşündüm: Komşu bir pikselin geçerli olandan farklı bir normal vektör olup olmadığını kontrol etme. Evetse, bir kenar bulundu. Ne yazık ki, ne OpenGL'de ne de GLSL köşe / fragman gölgesinde bu yaklaşımı nasıl uygulayabileceğim hakkında hiçbir fikrim yok.

Bu yaklaşımla ilgili bazı yardımlar veya kenar tespiti ile ilgili herhangi bir yardım için çok mutlu olurum

Düzenleme: Kafeslerim için herhangi bir doku kullanmıyorum.

Daha kesin olmak gerekirse, mümkün olduğunca çok benzeyen bir CAD / CAM çözümü oluşturmak istiyorum (Top Solid https://www.youtube.com/watch?v=-qTJZtYUDB4'ten alınmıştır ):

resim açıklamasını buraya girin


"Edge" i daha ayrıntılı olarak tanımlamanız gerektiğine inanıyorum. Basit bir tel çerçeveden farkı nedir? Cifz cevabında, işlem sonrası ekran alanının iyi bir açıklaması var, ancak sorunuzdan uygulanabilir olup olmadığını belirlemek zor.
Andreas

Kenar ile katıları oluşturan "kırışıklıklar" ve "çıkıntılar" demek istiyorum. Bir tel kafes tüm üçgen yüzleri görüntülerdi, bu benim istediğim şey değil.
enne87

Tamam, tam olarak ne istediğini :-) Bu kırışıklıklar ve sırtlar bir tel kafes oluşturmak istiyorum. Zor kısmı hala bir kırışıklık / sırtın ne olduğunu belirlemektir. Bunun nasıl yapılacağı hakkında bir fikrin var mı?
Andreas

1
Cad programları bunu çoğunlukla gölgelendirici ile yapmaz. Bunun yerine, modelin sert kenarlarını bilirler ve bu bilgi formunun üst kısmına bir çizgi çizerler.
joojaa

joojaa Bu teknik hakkında daha fazla bilginiz var mı? Çift kavisli serbest formlu yüzeylerde ne yapılır? Ayrıca bir koni veya serbest bir formla kesilen / kesilen bir silindiriniz olduğunda ne olacağından emin değilim. stackoverflow.com/questions/43795262/…
Dusan Bosnjak 'pailhead'

Yanıtlar:


18

Genellikle kenar algılama, görüntüdeki yüksek gradyan değerine sahip alanları tespit etmek için kaynar.

Bizim durumumuzda, degradeyi görüntü işlevinin türevi olarak kabaca görebiliriz, bu nedenle degradenin büyüklüğü, görüntünüzün yerel olarak ne kadar değiştiği hakkında (komşu pikseller / metinler açısından) bilgi verir.
Şimdi, bir kenar, süreksizlik belirtisi olarak, şimdi de tanımladığımız gibi, bu bilginin ihtiyacımız olan tek şey olduğu açıktır. Bir görüntünün gradyanını bulduktan sonra, bir ikili değer kenar / kenar olmayan elde etmek için ona bir eşik uygulamak meselesidir.

Bu gradyanı gerçekten nasıl soruyorsun ve nasıl cevaplayacağım :)

Birçok yol! İşte bir çift :)

Yerleşik gölgelendirici işlevleri

Hem hlsl hem de glsl türev fonksiyonları sunar. GLSL olarak sahip dFdx ve dFdy x ve y yönünde, sırasıyla gradyan bilgi verir. Tipik olarak bu fonksiyonlar 2x2'lik bir blok halinde değerlendirilir.
Eğer tek bir doğrultuda ilgilenen sürece, iyi bir şekilde bölgede degrade olduğunu ne kadar güçlü olduğunu gösteren bir kompakt sonuç için fwidth size başka bir şey ama dFdy ve dFdy mutlak değerinin toplamını verir.
Belirli bir kanal yerine genel görüntünün kenarıyla ilgilenme olasılığınız yüksektir, bu nedenle görüntü işlevinizi luma'ya dönüştürmek isteyebilirsiniz. Bunu akılda tutarak, kenar tespiti söz konusu olduğunda gölgelendiriciniz aşağıdakilere benzer bir şey içerebilir:

  float luminance = dot(yourFinalColour,vec3(0.2126, 0.7152, 0.0722));
  float gradient = fwidth(luminance );
  float isEdge = gradient > threshold;

Yüksek bir eşik ile daha kaba kenarlar bulacaksınız ve tersini, düşük bir eşik ile yanlış kenarları tespit edebilirsiniz. İhtiyaçlarınıza daha uygun olan eşiği bulmak için denemeniz gerekir.

Bu işlevlerin çalışmasının nedeni söz etmeye değer, ancak şimdi bunun için zamanım yok, bu cevabı daha sonra güncelleyeceğim :)

İşlem sonrası ekran alanı

Bundan daha meraklı olabilirsiniz, şimdi görüntü işlemede Edge algılama alanı muazzam. İhtiyaçlarınıza göre kenar algılamayı tespit etmek için onlarca iyi yol gösterebilirim, ancak şimdilik basit tutalım, eğer ilgileniyorsanız size daha fazla seçenek gösterebilirim!

Bu nedenle, fikir, daha geniş bir mahalleye bakabilmeniz ve isterseniz çevreleyen örneklerde bir dizi ağırlık kullanabilmeniz ile yukarıdaki fikre benzer olacaktır. Genellikle, sonuç olarak size iyi bir degrade bilgisi veren bir çekirdek ile görüntünüz üzerinde bir kıvrım çalıştırırsınız.
Çok yaygın bir seçim Sobel çekirdeğidir

                                   resim açıklamasını buraya girin

Sırasıyla x ve y yönlerindeki degradeleri verir:

                                  Eski bir pdf'den uzun zaman önce yazdım.

Tek değeri olarak gradyandan çıkarabilirsiniz.GradientMagnitude=(Gradientx)2+(Gradienty)2

Sonra yukarıda bahsettiğim gibi eşikleyebilirsiniz.

Gördüğünüz gibi bu çekirdek merkezi piksele daha fazla ağırlık verir, böylece degradeyi + geleneksel olarak yardımcı olan biraz yumuşatma hesaplar (genellikle görüntü küçük kenarları ortadan kaldırmak için gauss bulanıklığıdır).

Yukarıdakiler oldukça iyi çalışıyor, ancak yumuşatmayı sevmiyorsanız Prewitt çekirdeklerini kullanabilirsiniz:

                                                   resim açıklamasını buraya girin

(Acele ediyorum, yakında görüntüler yerine doğru biçimlendirilmiş metin yazacağım!)

Gerçekten, gerçek zamanlı grafiklerden ziyade bir görüntü işlemi-y yolunda kenar algılamayı bulmak için çok daha fazla çekirdek ve teknik var, bu yüzden muhtemelen dFdx / y işlevleriyle iyi olacağınız için daha kıvrımlı (punto amaçlanmamış) yöntemleri hariç tuttum .


Çok güzel bir açıklama cifz, ama belli bir durumda hiçbir degrade görünür değilse? Örneğin, küpün arkasında ışık kaynağı yoktur ve bu nedenle degrade görünmez. O zaman tarif ettiğiniz bu görüntü tabanlı kenar algılama işlemi işe yaramaz, değil mi?
enne87

Ertelenmiş bir oluşturucu kullanıyorsanız, aynısını yapabilirsiniz, ancak normal arabellekte veya bir kez daha, bir ön geçişiniz varsa algoritmayı derinliğe uygulayabilirsiniz. Yine de haklısınız, bir ekran alanı yaklaşımı her durumda ideal olmayabilir :) Hangi çözümün uygulanabilir olduğu, bu etki için bütçenizin ne olduğuna, sahnenizin ne kadar karmaşık olduğuna bağlıdır.
cifz

Potansiyel olarak bu oyununuz için gerçekten merkezi ise, çok kolay, ancak potansiyel olarak vergilendirilmesi, her bir tepe noktası (yükleme zamanında çevrimdışı) için komşu normalleriniz üzerinde bir degrade hesaplar ve bu faktörü ek köşe niteliği olarak geçirir.
cifz

Thangs yardımınız için tekrar cifz. Peki, elde etmek istediğim şuna benzer bir CAD / CAM çözümü geliştirmektir: youtube.com/watch?v=-qTJZtYUDB4 Ve gerçekten tüm siyah kenarları, kırışıklıkları oluşturmayı nasıl başardıklarını bilmek istiyorum ve sırtlar. cifz, sizce ekran görünümü yaklaşımlarınızdan birini kullanarak bu görünümü elde ettikleri bir grafik programlama uzmanı mısınız? Ya da belki komşu normaller üzerinde bir degrade hesaplayarak? Bunun nasıl yapılabileceğini gerçekten bilmek istiyorum. Tekrar teşekkürler!
enne87

1
Kimseye ödeme yapmanıza gerek yok, sadece birkaç öğretici çevrimiçi okumaya başlayın, bazı kitaplar satın alın ve sıkı çalışın :) Sonunda çok ödüllendirici olacak!
cifz

3

Herkesin de kenarları algılaması gerektiğinde: İşte tel kafesin nasıl görüntüleneceği güzel bir makale ve bu makalede sadece kenarların nasıl gösterileceği açıklanmaktadır.

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.