OpenGL - การตรวจจับขอบ


12

ฉันต้องการที่จะโหลดตาข่ายโดยพลการและวาดเส้นสีดำหนาตามขอบเพื่อให้ได้รูปเงาแบบตูน ฉันจัดการวาดเงาดำรอบ ๆ วัตถุโดยใช้ stencil buffer คุณสามารถดูผลลัพธ์ได้ที่นี่:

ป้อนคำอธิบายรูปภาพที่นี่

แต่สิ่งที่ขาดหายไปคือเส้นสีดำในวัตถุนั้นเอง ฉันคิดเกี่ยวกับการตรวจสอบความไม่ต่อเนื่องตามปกติ: การตรวจสอบว่าพิกเซลข้างเคียงมีเวกเตอร์ปกติแตกต่างจากพิกเซลปัจจุบันหรือไม่ ถ้าใช่พบขอบแล้ว น่าเสียดายที่ฉันไม่รู้ว่าฉันจะใช้วิธีการนี้ได้อย่างไรทั้งใน OpenGL และใน GLSL เวอร์เท็กซ์ / ส่วนแยก

ฉันยินดีเป็นอย่างยิ่งสำหรับความช่วยเหลือเกี่ยวกับวิธีการนี้หรือการตรวจจับขอบอื่น ๆ

แก้ไข: ฉันไม่ได้ใช้พื้นผิวใด ๆ สำหรับตาข่ายของฉัน

แม่นยำยิ่งกว่านี้ฉันต้องการสร้างโซลูชัน CAD / CAM ที่ดูมากที่สุดเช่นนี้ (นำมาจาก Top Solid https://www.youtube.com/watch?v=-qTJZtYUDB4 ):

ป้อนคำอธิบายรูปภาพที่นี่


ฉันเชื่อว่าคุณต้องกำหนด "ขอบ" เพิ่มเติมในรายละเอียด มันแตกต่างจากโครงลวดธรรมดาอย่างไร ในคำตอบ cifz มีคำอธิบายที่ดีเกี่ยวกับกระบวนการโพสต์พื้นที่หน้าจอ แต่จากคำถามของคุณมันเป็นเรื่องยากที่จะตรวจสอบว่ามันใช้ได้หรือไม่
Andreas

ด้วยขอบฉันหมายถึง "รอยพับ" และ "สันเขา" ที่ก่อตัวเป็นของแข็ง โครงลวดจะแสดงใบหน้ารูปสามเหลี่ยมทั้งหมดซึ่งไม่ใช่สิ่งที่ฉันต้องการ
enne87

ตกลงสิ่งที่ฉันขอ :-) ฉันจะสร้างโครงร่างจากรอยย่นและสันเขา ส่วนที่ยุ่งยากยังคงเป็นตัวกำหนดว่ารอยพับ / สันคืออะไร คุณมีความคิดเกี่ยวกับวิธีการทำเช่นนั้น?
Andreas

1
โปรแกรม CAD ไม่ได้ทำด้วย shader เป็นส่วนใหญ่ แต่พวกเขารู้ขอบแข็งจากแบบจำลองและลากเส้นบนสุดของแบบตาข่ายที่เป็นข้อมูล
joojaa

joojaa คุณมีข้อมูลเพิ่มเติมเกี่ยวกับเทคนิคนี้ไหม? จะทำอย่างไรในกรณีที่พื้นผิวแบบอิสระโค้งคู่? ฉันเองก็ไม่แน่ใจเหมือนกันว่าจะเกิดอะไรขึ้นเมื่อคุณมีรูปกรวยหรือรูปทรงกระบอกที่ถูกตัด / ตัดแต่งโดยรูปแบบอิสระ stackoverflow.com/questions/43795262/…
Dusan Bosnjak 'pailhead'

คำตอบ:


18

การตรวจจับขอบโดยทั่วไปจะลดลงเพื่อตรวจจับพื้นที่ของภาพด้วยค่าการไล่ระดับสีสูง

ในกรณีของเราเราสามารถมองเห็นการไล่ระดับสีอย่างคร่าวๆในฐานะที่เป็นอนุพันธ์ของฟังก์ชั่นภาพดังนั้นขนาดของการไล่ระดับสีจะให้ข้อมูลว่าภาพของคุณมีการเปลี่ยนแปลงในระดับท้องถิ่นเท่าใด
ตอนนี้ขอบเป็นอย่างที่คุณบอกว่าบ่งบอกถึงความไม่ต่อเนื่องดังนั้นตอนนี้เราจึงกำหนดให้การไล่ระดับสีเป็นที่ชัดเจนว่าข้อมูลนี้เป็นสิ่งที่เราต้องการ เมื่อเราพบการไล่ระดับสีของรูปภาพมันเป็นเพียงเรื่องของการใช้เก ​​ณ ฑ์เพื่อให้ได้ค่าขอบไบนารี / ไม่ใช่ขอบ

คุณจะพบว่าการไล่ระดับสีนี้เป็นสิ่งที่คุณถามจริง ๆ และฉันยังตอบ :)

มีหลายวิธี! ที่นี่สองสาม :)

ฟังก์ชัน shader ในตัว

ทั้ง hlsl และ glsl เสนอฟังก์ชันอนุพันธ์ ใน GLSL คุณมีdFdx และ dFdyที่ให้ข้อมูลการไล่ระดับสีตามลำดับในทิศทาง x และ y โดยทั่วไปฟังก์ชั่นเหล่านี้จะถูกประเมินในบล็อกของ 2x2 แฟรกเมนต์
หากคุณไม่สนใจทิศทางเดียววิธีที่ดีที่จะได้ผลลัพธ์ที่มีขนาดกะทัดรัดซึ่งบ่งบอกว่าการไล่ระดับสีในภูมิภาคนั้นแข็งแกร่งเพียงใดคือความกว้างที่ให้คุณไม่มีอะไรนอกจากผลรวมของค่าสัมบูรณ์ของ dFdy และ dFdy
คุณน่าจะสนใจขอบภาพโดยรวมมากกว่าในช่องเฉพาะดังนั้นคุณอาจต้องการเปลี่ยนฟังก์ชั่นภาพเป็น luma เมื่อคำนึงถึงการตรวจจับที่ขอบเครื่อง Shader ของคุณอาจรวมถึงบางสิ่งที่คล้ายกับ:

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

ด้วยเกณฑ์ที่สูงคุณจะได้พบกับ coarser edge และคุณอาจจะพลาดบางส่วนในทางกลับกันด้วย threshold ที่ต่ำคุณอาจตรวจจับ edge false คุณต้องทดลองเพื่อหาเกณฑ์ที่เหมาะสมกับความต้องการของคุณมากขึ้น

เหตุผลที่ฟังก์ชั่นเหล่านี้ใช้งานได้คุ้มค่าที่จะกล่าวถึง แต่ตอนนี้ฉันไม่มีเวลาเลยฉันน่าจะอัพเดตคำตอบนี้ในภายหลัง :)

กระบวนการหน้าจอพื้นที่โพสต์

คุณสามารถไปได้ไกลกว่านี้ตอนนี้สนามของการตรวจจับขอบในการประมวลผลภาพนั้นใหญ่โต ฉันสามารถบอกคุณได้หลายวิธีที่ดีในการตรวจจับการตรวจจับขอบตามความต้องการของคุณ แต่ตอนนี้ให้มันง่ายถ้าคุณสนใจฉันสามารถอ้างอิงตัวเลือกเพิ่มเติม!

ดังนั้นความคิดจะคล้ายกับที่กล่าวมาข้างต้นด้วยความแตกต่างที่คุณสามารถมองไปที่บริเวณใกล้เคียงที่กว้างขึ้นและใช้ชุดน้ำหนักของตัวอย่างที่ทำให้ขุ่นเคืองหากคุณต้องการ โดยทั่วไปแล้วคุณจะใช้รูปแบบการแปลงภาพของคุณด้วยเคอร์เนลที่ให้ข้อมูลการไล่ระดับสีที่ดี
ตัวเลือกทั่วไปคือเคอร์เนล Sobel

                                   ป้อนคำอธิบายรูปภาพที่นี่

ซึ่งตามลำดับให้การไล่ระดับสีในทิศทาง x และ y:

                                  จากไฟล์เก่าฉันเขียนมานานแล้ว

คุณสามารถรับค่าเดียวจากการไล่ระดับสีเป็นGRadผมอีnเสื้อMaก.nผมเสื้อยูdอี=(GRadผมอีnเสื้อx)2+(GRadผมอีnเสื้อY)2

จากนั้นคุณสามารถกำหนดเกณฑ์เช่นเดียวกับที่ฉันกล่าวไว้ข้างต้น

เคอร์เนลนี้ตามที่คุณเห็นจะให้น้ำหนักมากขึ้นกับพิกเซลกลางดังนั้นการคำนวณลาดแบบค่อยเป็นค่อยไป + การปรับให้เรียบซึ่งช่วยตามประเพณี (บ่อยครั้งที่ภาพจะเป็นแบบเกาส์เบลอเพื่อกำจัดขอบขนาดเล็ก)

การทำงานด้านบนค่อนข้างดี แต่ถ้าคุณไม่ชอบความราบเรียบคุณสามารถใช้ Prewitt Kernels ได้:

                                                   ป้อนคำอธิบายรูปภาพที่นี่

(หมายเหตุฉันรีบเร่งจะเขียนข้อความที่จัดรูปแบบที่เหมาะสมแทนภาพเร็ว ๆ นี้!)

จริง ๆ แล้วมีเมล็ดและเทคนิคต่าง ๆ มากมายในการค้นหาการตรวจจับขอบในกระบวนการภาพมากกว่ากราฟิกแบบเรียลไทม์ดังนั้นฉันจึงได้แยกวิธีที่ซับซ้อนมากขึ้น .


คำอธิบายที่ดีมาก cifz แต่ถ้าหากไม่มีการไล่ระดับสีปรากฏในสถานการณ์บางอย่าง? ตัวอย่างเช่นไม่มีแหล่งกำเนิดแสงที่ด้านหลังของคิวบ์และดังนั้นจึงไม่มีการไล่ระดับสีที่มองเห็นได้ จากนั้นขั้นตอนการตรวจจับขอบภาพที่คุณอธิบายนี้จะไม่ทำงานใช่ไหม
enne87

หากคุณใช้ตัวเรนเดอร์ที่เลื่อนออกไปคุณสามารถทำเช่นนั้นได้ แต่ในบัฟเฟอร์ปกติหรืออีกครั้งหากคุณมีการเตรียมการคุณสามารถใช้อัลกอริทึมกับความลึกได้ คุณยังคงถูกต้องแนวทางพื้นที่หน้าจออาจไม่เหมาะในทุกกรณี :) วิธีแก้ปัญหาที่ทำงานได้นั้นขึ้นอยู่กับงบประมาณของคุณสำหรับเอฟเฟกต์นี้มากแค่ไหนฉากของคุณซับซ้อนแค่ไหน
cifz

อาจเป็นไปได้ว่านี่เป็นศูนย์กลางสำหรับเกมของคุณง่ายมาก แต่อาจต้องเสียภาษีจะคำนวณการไล่ระดับสีตามบรรทัดฐานใกล้เคียงของคุณสำหรับแต่ละจุดสุดยอด (ออฟไลน์ขณะโหลด) และส่งผ่านปัจจัยนี้เป็นแอตทริบิวต์จุดสุดยอดเพิ่มเติม
cifz

ขอบคุณอีกครั้งสำหรับความช่วยเหลือของคุณ สิ่งที่ฉันต้องการบรรลุคือการพัฒนาโซลูชัน CAD / CAM ที่มีลักษณะคล้ายกับนี้: youtube.com/watch?v=-qTJZtYUDB4และฉันอยากรู้ว่าพวกเขาจัดการมันอย่างไรเพื่อให้ขอบดำเป็นรอยย่น และสันเขา ถ้าอย่างนั้น, คุณคิดว่าเป็นพิเศษการเขียนโปรแกรมกราฟิกที่พวกเขาประสบความสำเร็จในลักษณะนี้โดยใช้หนึ่งในพื้นที่หน้าจอของคุณ? หรืออาจใช้วิธีการไล่ระดับสีตามบรรทัดฐานที่อยู่ใกล้เคียง? ฉันต้องการทราบวิธีการนี้สามารถทำได้ ขอบคุณอีกครั้ง!
enne87

1
ไม่จำเป็นต้องจ่ายทุกคนเพียงแค่เริ่มอ่านบทเรียนออนไลน์ซื้อหนังสือและเรียนอย่างหนัก :) มันจะคุ้มค่ามากในตอนท้าย!
cifz

3

เพียงในกรณีที่คน elso ยังต้องมีการตรวจสอบขอบ: นี่เป็นบทความที่ดีวิธีการแสดงโครงร่างและนี้บทความอธิบายถึงวิธีการแสดงเฉพาะขอบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.