Saya ingin memuat jerat sewenang-wenang dan menggambar garis hitam tebal di sepanjang tepi untuk mendapatkan tampilan seperti toon-shading. Saya berhasil menggambar siluet hitam di sekitar objek dengan menggunakan buffer stensil. Anda dapat melihat hasilnya di sini:
Namun yang hilang adalah garis-garis hitam pada objek itu sendiri. Saya berpikir untuk memeriksa diskontinuitas normal: Memeriksa apakah piksel tetangga memiliki vektor normal yang berbeda dari yang ada sekarang. Jika ya, tepi telah ditemukan. Sayangnya, saya tidak tahu bagaimana saya bisa menerapkan pendekatan ini, baik di OpenGL maupun di GLSL vertex / fragment shader.
Saya akan sangat senang atas bantuan tentang pendekatan ini atau lainnya tentang deteksi tepi.
Sunting: Saya tidak menggunakan tekstur apa pun untuk jerat saya.
Terlalu lebih tepat, saya ingin membuat solusi CAD / CAM yang terlihat sebanyak mungkin seperti ini (diambil dari Top Solid https://www.youtube.com/watch?v=-qTJZtYUDB4 ):
sumber
Jawaban:
Deteksi tepi biasanya dilakukan untuk mendeteksi area gambar dengan nilai gradien tinggi.
Dalam kasus kami, kami dapat dengan kasar melihat gradien sebagai turunan dari fungsi gambar, oleh karena itu besarnya gradien memberi Anda informasi tentang seberapa banyak gambar Anda berubah secara lokal (dalam hal piksel / texels tetangga).
Sekarang, edge adalah seperti yang Anda katakan indikasi diskontinuitas, jadi sekarang kita mendefinisikan gradien jelas bahwa info inilah yang kita butuhkan. Setelah kami menemukan gradien gambar, itu hanya masalah menerapkan ambang batas untuk mendapatkan tepi nilai biner / non-tepi.
Bagaimana Anda menemukan gradien ini benar-benar apa yang Anda minta dan saya belum menjawab :)
Banyak cara! Di sini pasangan :)
Fungsi shader bawaan
Baik hlsl dan glsl menawarkan fungsi turunan. Dalam GLSL Anda memiliki dFdx dan dFdy yang memberi Anda masing-masing informasi gradien dalam arah x dan y. Biasanya fungsi-fungsi ini dievaluasi dalam blok fragmen 2x2.
Kecuali jika Anda tertarik pada satu arah, cara yang baik untuk memiliki hasil yang ringkas yang menunjukkan seberapa kuat gradien di wilayah adalah fwidth yang tidak memberi Anda apa pun selain jumlah nilai absolut dari dFdy dan dFdy.
Anda mungkin tertarik pada keunggulan pada keseluruhan gambar daripada pada saluran tertentu, jadi Anda mungkin ingin mengubah fungsi gambar Anda menjadi luma. Dengan mengingat hal ini, ketika datang ke deteksi tepi shader Anda dapat mencakup sesuatu seperti:
Dengan ambang tinggi Anda akan menemukan tepi kasar dan Anda mungkin kehilangan beberapa, sebaliknya, dengan ambang rendah Anda mungkin mendeteksi tepi palsu. Anda harus bereksperimen untuk menemukan ambang yang lebih sesuai dengan kebutuhan Anda.
Alasan mengapa fungsi-fungsi ini layak disebutkan tetapi saya tidak punya waktu untuk itu sekarang, saya kemungkinan akan memperbarui jawaban ini nanti :)
Ruang layar pasca proses
Anda bisa menjadi lebih hebat dari ini, sekarang bidang deteksi Edge dalam pemrosesan gambar sangat besar. Saya bisa mengutip Anda puluhan cara bagus untuk mendeteksi deteksi tepi sesuai dengan kebutuhan Anda, tetapi mari kita tetap sederhana untuk saat ini, jika Anda tertarik, saya dapat mengutip Anda lebih banyak pilihan!
Jadi idenya akan mirip dengan yang di atas, dengan perbedaan bahwa Anda bisa melihat lingkungan yang lebih luas dan menggunakan satu set bobot pada sampel sekitarnya jika Anda mau. Biasanya, Anda menjalankan konvolusi pada gambar Anda dengan kernel yang memberi Anda info gradien yang baik.
Pilihan yang sangat umum adalah kernel Sobel
Yang masing-masing memberi Anda gradien dalam arah x dan y:
Maka Anda bisa mengirik seperti cara yang saya sebutkan di atas.
Kernel ini seperti yang Anda lihat memberi bobot lebih pada pixel pusat, jadi secara efektif menghitung gradien + sedikit smoothing yang secara tradisional membantu (seringkali gambar buram untuk menghilangkan tepi kecil).
Cara di atas berfungsi dengan baik, tetapi jika Anda tidak suka smoothing, Anda bisa menggunakan kernel Prewitt:
(Catatan saya sedang terburu-buru, akan segera menulis teks yang diformat alih-alih gambar!)
Benar-benar ada lebih banyak kernel dan teknik untuk menemukan deteksi tepi dalam proses gambar-y daripada grafis waktu nyata, jadi saya telah mengecualikan metode yang lebih berbelit-belit (pun tidak dimaksudkan) karena mungkin Anda akan baik-baik saja dengan fungsi dFdx / y .
sumber
Untuk berjaga-jaga jika ada yang juga perlu mendeteksi tepi: Berikut ini adalah artikel yang bagus tentang cara menampilkan bingkai gambar dan artikel ini menjelaskan cara hanya menampilkan tepi.
sumber