OpenGL GLSL - सोबेल एज डिटेक्शन फ़िल्टर


9

इस विषय के संबंध में मैंने GLSL में Sobel Edge Detection फ़िल्टर को सफलतापूर्वक लागू किया है । यहाँ फिल्टर के टुकड़े shader कोड है:

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

और यहां सोबेल एज डिटेक्शन के साथ क्यूब का परिणाम है:

सोबेल एज डिटेक्शन फिल्टर के साथ क्यूब

यदि आप चित्र को बड़ा करते हैं, तो आप देखेंगे कि सोबेल द्वारा निर्मित "शोर" का एक बहुत कुछ है: नीले / सफेद ढाल के कारण दृश्य भर में ग्रे क्षैतिज पट्टियाँ हैं। फ़ुथर्मोर, प्रकाश शंकु घन पर एक अवांछित पैटर्न का उत्पादन करते हैं। क्यूब के बाईं ओर के काले किनारे भी घन के आधे भाग पर प्रकाश शंकु के कारण फीके लगते हैं।

इसलिए मैंने इस लेख को पढ़ा जिसमें कहा गया था कि किसी को पहले चित्र को स्केल करना चाहिए और किनारों को स्पष्ट करने के लिए गॉसियन ब्लर फ़िल्टर का उपयोग करना चाहिए। लेख के निचले भाग में, कैनी एज डिटेक्शन फ़िल्टर भी है जो बेहतर परिणाम देता है।

अब मेरे दो सवाल हैं:

  1. निम्न संभव चरणों का पता लगाने के लिए सबसे अच्छा संभव बढ़त का पता लगाने के परिणाम सही हैं:

    • ग्रेस्केल
    • गौस्सियन धुंधलापन
    • सोबेल / कैनी बढ़त का पता लगाने
  2. यदि हाँ, तो मैं संसाधित छवि के साथ मूल छवि को कैसे मर्ज करूँगा? मेरा मतलब है, ऊपर बताए गए चरणों को संसाधित करने के बाद, मुझे एक छवि मिलती है जो या तो पूरी तरह से सफेद किनारों के साथ काली होती है या इसके विपरीत। मैं किनारों को अपनी मूल छवि / बनावट पर कैसे रखूंगा?

आपकी सहायताके लिए धन्यवाद!


मुझे आश्चर्य है कि यदि आप किसी तरह से ओपनजीएल के किनारे के झंडे का उपयोग करके परिणाम प्राप्त कर सकते हैं । ऐसा लगता है कि लाइन मोड में होने पर किनारे वाले झंडे के बीच केवल किनारों को खींचा जाता है। नहीं है यहाँ एक विवरण । (मैंने खुद इसका उपयोग नहीं किया है या मैं एक उदाहरण पोस्ट
करूंगा

जवाबों:


9
  1. सर्वोत्तम परिणाम दृढ़ता से आपके उपयोग के मामले पर निर्भर करते हैं। वे इस बात पर भी निर्भर करते हैं कि आप किस प्रभाव को प्राप्त करना चाहते हैं। सोबेल सिर्फ एक बढ़त का पता लगाने वाला फिल्टर है: किनारों पर इनपुट सिग्नल निर्भर करेगा, यह चुनना कि इनपुट सिग्नल आपके ऊपर है।

    यहां आप इनपुट के रूप में रंगीन छवि का उपयोग कर रहे हैं, और फ़िल्टर नीले रंग के ढाल में बेहोश किनारों का पता लगाता है, जबकि क्यूब के किनारों को बाधित हो जाता है जहां इसका रंग पृष्ठभूमि के रंग से बहुत करीब है।

    चूंकि मुझे लगता है कि क्यूब को खींचने के लिए आपका कार्यक्रम भी जिम्मेदार है, इसलिए आपके पास अन्य जानकारी तक पहुंच है जो आप अपने सोबेल फिल्टर को खिला सकते हैं। उदाहरण के लिए गहराई और मानदंड बढ़त का पता लगाने के लिए अच्छे उम्मीदवार हैं। प्रकाश से पहले अल्बेडो का उपयोग किया जा सकता है। अलग-अलग इनपुट्स के साथ टेस्ट करें और तय करें कि आपको प्राप्त परिणामों के आधार पर किनका उपयोग करना है।

  2. किनारे की जानकारी को कैसे संयोजित किया जाए, इस बारे में आपके प्रश्न के बारे में, मेरा सुझाव है कि आप gइसका उपयोग करने से पहले थोड़ा फ़िल्टर करें । फिर आप इसका उपयोग मूल रंग और वांछित किनारे के रंग के बीच अंतर करने के लिए कर सकते हैं।

    उदाहरण के लिए आप कुछ इस तरह की कोशिश कर सकते हैं:

    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.);

परिशिष्ट

गहराई या मानदंडों का उपयोग करने के लिए, आपको उन्हें बनावट में सहेजने की आवश्यकता होगी यदि यह पहले से ही नहीं किया गया है। जब आप अपने नियमित रेंडरिंग पास के लिए फ्रेम बफ़र बनाते हैं, तो आप इसमें विभिन्न टेक्सचर संलग्न कर सकते हैं (देखें glFramebufferTexture2D) और दृश्य के रंग की तुलना में उन्हें अन्य जानकारी लिखें।

यदि आप एक गहराई बनावट (के साथ GL_DEPTH_ATTACHMENT) संलग्न करते हैं , तो इसका उपयोग स्वचालित रूप से गहराई के लिए किया जाएगा। यदि आप एक या कई रंग बनावट (साथ GL_COLOR_ATTACHMENTi) संलग्न करते हैं , तो आप उन्हें अपने टुकड़े टुकड़े करने के लिए कई आउटपुट घोषित करके लिख सकते हैं (यह उपयोग किया जाता था gl_FragData; वैसे भी, देखें glDrawBuffers)।

विषय पर अधिक जानकारी के लिए, "मल्टी रेंडर टारगेट" (MRT) देखें।


अच्छी जानकारी, धन्यवाद जुलिएन। एक और सवाल: मैं अपनी खंड छाया में गहराई या सामान्य जानकारी का उपयोग कैसे कर सकता हूं? मैं अभी भी GLSL के साथ काफी नया हूँ और इसलिए मुझे पता नहीं है कि सोबेल एल्गोरिथ्म में मूल्यों को कैसे शामिल किया जाए।
enne87

2
जब आप अपने रेंडरिंग पास के लिए फ्रेम बफ़र बनाते हैं, तो आप एक से अधिक बनावट संलग्न कर सकते हैं। यदि आप एक गहराई बनावट संलग्न करते हैं, तो इसका उपयोग स्वचालित रूप से गहराई के लिए किया जाएगा। यह आप एक और रंग बनावट संलग्न करते हैं जिसे आप इसे अलग से लिख सकते हैं (देखें opengl.org/sdk/docs/man/html/glDrawBuffers.xhtml ), "मल्टी रेंडर टारगेट" (MRT) नामक एक सुविधा।
जुलिएन गुर्टॉल्ट

@ enne87: मदद करने के लिए खुश। :)
जुलिएन गुर्टॉल्ट

@trichoplax: सुझाव के लिए धन्यवाद; किया हुआ।
जूलियन गुर्टॉल्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.