सोबेल एज डिटेक्टर


12

आपका कार्य एक प्रोग्राम लिखना है जो एक इनपुट इमेज लेता है और इसे आउटपुट इमेज बनने के लिए एज-डिटेक्शन के माध्यम से चलाता है।

एज-डिटेक्शन निम्नानुसार काम करता है (यदि अस्पष्ट हो, तो सोबेल एज डिटेक्शन देखें ):

  • एक पिक्सेल के लिए मूल्य एक पिक्सेल की कुल चमक है, इसलिए यदि यह रंग में है, तो आपको इसे पहले ग्रेस्केल में बदलने की आवश्यकता होगी (चीजों को सरल और गोल्फ-सक्षम रखने के लिए, आप आर, जी और के लिए औसत मूल्य ले सकते हैं। बी)।
  • पिक्सेल x के लिए G x और G y के सूत्र (i, j) हैं:
    • G x = -1 * p (i-1, j-1) - 2 * p (i-1, j) - 1 * p (i-1, j + 1) + 1 * p (i + 1, j) -1) + 2 * p (i + 1, j) + 1 * p (i + 1, j + 1)
    • G y = -1 * p (i-1, j-1) - 2 * p (i, j-1) - 1 * p (i + 1, j-1) + 1 * p (i-1, j) +1) + 2 * p (i, j + 1) + 1 * p (i + 1, j + 1)
  • उस पिक्सेल पर किनारे के आकार का मान तब है: G (G x 2 + G y 2 )

आउटपुट छवि प्रत्येक पिक्सेल के लिए किनारे G (G x 2 + G y 2 ) के आकार के रूप में होती है।

बोनस:

  • एज-डिटेक्शन किक से पहले किसी भी छोटे किनारों को हटाने के लिए छवि को सुचारू करने के लिए एक गाऊसी धब्बा का प्रदर्शन करें। यह अंतिम परिणाम पर -30% का बोनस देता है।
  • किनारे के कोण को ध्यान में रखें। आप आउटपुट पिक्सेल को कुछ रंग देते हैं, उसी ग्रेस्केल वैल्यू को ले कर और फॉर्मूला arctan (G y / G x ) से प्राप्त कोण का उपयोग करके रंग व्हील से रंग जोड़ते हैं । यह अंतिम परिणाम पर -30% का एक और बोनस देता है।

नियम:

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

क्या आप गाऊसी धब्बा को वास्तव में निर्दिष्ट कर सकते हैं? क्या इनपुट ग्रेस्केल के समान है, यदि नहीं, तो हमें रंगीन चित्रों में इस किनारे का पता कैसे लगाना चाहिए? क्या यह सही है कि आउटपुट छवि में इनपुट के समान आकार होता है, लेकिन इनपुट केवल आंतरिक पिक्सेल पर ही होता है (वह नहीं जिसे हमने शून्य पर सेट किया है)?
दोष

क्या आपने Computerphile से एज डिटेक्शन के बारे में वीडियो देखा है ? मैं वहाँ एक कनेक्शन सूँघ सकता हूँ :)
GiantTree

@flawr मुझे यह पता लगाना है कि गॉसियन ब्लर एज डिटेक्शन के लिए क्या अच्छा है, इसलिए मैं वास्तव में नहीं जानता कि एक अच्छा मूल्य क्या है। गॉसियन कलंक पर यहाँ और अधिक । इनपुट छवि रंग में है, और यदि आप किनारे का पता लगाना चाहते हैं तो आपको इसे पहले ग्रेस्केल में बदलना होगा। किनारे का पता लगाने या तो ए: आंतरिक पिक्सल पर प्रदर्शन किया जाता है, और आप आउटपुट छवि की बाहरी 1px सीमा को काले, या बी: सभी पिक्सल पर सेट करते हैं, और आप छवि के बाहर किसी भी पिक्सेल के लिए 0 मान लेते हैं।
vrwim

@GiantTree nooooooo वीडियो पूरी तरह से संबंधित नहीं है :)
vrwim

4
यह नीचे मतदान क्यों किया गया है? यह पूरी तरह से वैध सवाल लगता है।
Addison Crump

जवाबों:


13

जे, 166 164 161 154 150 144 143 बाइट्स।

बहुत अधिक गोल्फ नहीं; मैंने ज्यादातर अपने लंबे कार्यान्वयन को ढहा दिया (नीचे देखें), इसलिए सुधार के लिए शायद बहुत जगह है। बीएमपी पुस्तकालय का उपयोग करता है। फ़ाइल में परिणाम सहेजता है o। मैंने केवल पूर्ण 3x3 कोशिकाओं का उपयोग करके एजपिक्सल को संभाला है, इसलिए अंतिम छवि की चौड़ाई और ऊंचाई 2 पिक्सेल से कम है।

load'bmp'
S=:s,.0,.-s=:1 2 1
p=:([:*:[:+/[:,*)"2
'o'writebmp~256#.3#"0<.255<.%:(S&p+(|:S)&p)3 3,.;._3(3%~])+/"1(3#256)#:readbmp}:stdin''
exit''

उपयोग:

echo 'image.bmp' | jconsole golf.ijs

विस्तारित:

load 'bmp'

sobel1 =: 3 3 $ 1 0 _1 2 0 _2 1 0 _1
NB. transposed
sobel2 =: |: sobel1
NB. read image
image =: readbmp }: stdin''
NB. convert default representation to R,G,B arrays
rgbimage =: (3 # 256) #: image
NB. convert to grayscale
greyimage =: 3 %~ (+/"1) rgbimage
NB. 3x3 cells around each pixel
cells =: 3 3 ,.;._3 greyimage
NB. multiply 3x3 cell by 3x3 sobel, then sum all values in it
partial =: 4 : '+/"1 +/"1 x *"2 y'
NB. square partial (vertical and horizontal) results, sum and root
combine =: [: %: *:@[ + *:@]
NB. limit RGB values to 255
limit =: 255 <. ]
newimage =: limit (sobel1&partial combine sobel2&partial) cells
NB. convert back to J-friendly representation
to_save =: 256 #. 3 #"0 <. newimage
to_save writebmp 'out.bmp'
NB. jconsole stays open by default
exit''

नमूना इनपुट और आउटपुट:

मूल किनारे का पता लगाना


यह ;._3सबर्रे ऑपरेटर का एक अच्छा उदाहरण है । मैंने देखा है कि आपने pउन्हें बनाने के बाद रत्नों पर काम करने के लिए रैंक 2 के साथ एक क्रिया को परिभाषित किया था। जब आप काटते हैं, तो आप प्रत्येक सबर्रे पर काम कर सकते हैं। आपके काम के आधार पर इसे लागू करने की मेरी कोशिश है 256#.3#"0<.255<.3 3((|:S)&*+&.*:&(+/)&,S&*);._3%&3(3#256)+/@#:। इसे कुल 126 बाइट्स तक ले जाना चाहिए।
मीलों

मैंने यह 'o'writebmp~256#.3#"0<.255<.3 3(*+&.*:&(+/)&,(*|:))&((-,.0,.])1 2 1);._3%&3(3#256)+/@#:readbmp]stdin''मानकर 119 बाइट्स के लिए नीचे ले लिया है कि स्टड पर केवल फ़ाइल नाम इनपुट है। आप इसका उपयोग करके प्रदर्शन कर सकते हैं echo -nताकि स्टडिन में एक अतिरिक्त न्यूलाइन शामिल न हो। मेरे कंप्यूटर पर स्क्रिप्ट के लिए एक पाइप किए गए इनपुट का उपयोग करते समय स्क्रिप्ट स्वचालित रूप से बाहर निकल जाती है, जिसका अर्थ है कि मुझे इसमें शामिल नहीं करना है exit''और अतिरिक्त 6 बाइट्स बचा सकता है, लेकिन मुझे यकीन नहीं है कि यह सभी के लिए सही है।
मील

1

पायथन, 161 * 0.7 = 112.7 बाइट्स

गॉसियन ब्लर बोनस के साथ।

जैसा कि आपने स्पष्ट रूप से अंतर्निहित तरीकों से मना नहीं किया था, यहाँ OpenCV है:

from cv2 import*
from numpy import*
g=GaussianBlur(cvtColor(imread(raw_input()),6),(3,3),sigmaX=1)
x,y=Sobel(g,5,1,0),Sobel(g,5,0,1)
imwrite('s.png',sqrt(x*x+y*y))

बोनस के बिना, 136 बाइट्स

from cv2 import*
from numpy import*
g=cvtColor(imread(raw_input()),6)
x,y=Sobel(g,5,1,0),Sobel(g,5,0,1)
imwrite('s.png',sqrt(x*x+y*y))
  • Edit1: नामांकित स्थिरांक को उनके मूल्यों द्वारा प्रतिस्थापित किया गया।
  • Edit2: अपलोड किए गए नमूने

मूल छाना हुआ


क्या आप संभवतः एक नमूना इनपुट और आउटपुट छवि दे सकते हैं?
आर। काप

@ R.Kap बेहतर देर से कभी नहीं।
कार्ल नैप

0

MATLAB, 212 * 0.4 = 84.8 बाइट्स

फ़िल्टर टूलबॉक्स और एचएसवी कलरस्पेस का उपयोग करना

function f(x);f=@(i,x)imfilter(i,x);s=@(x)fspecial(x);S=s('sobel');A=f(double(rgb2gray(imread(x)))/255,s('gaussian'));X=f(A,S);Y=f(A,S');imwrite(hsv2rgb(cat(3,atan2(Y,X)/pi/2+0.5,0*A+1,sqrt(X.^2+Y.^2))),'t.png')

या अपुष्ट

function f(x)
f=@(i,x)imfilter(i,x);
s=@(x)fspecial(x);
S=s('sobel');
A=f(double(rgb2gray(imread(x)))/255,s('gaussian'));
X=f(A,S);
Y=f(A,S');
imwrite(hsv2rgb(cat(3,atan2(Y,X)/pi/2+0.5,0*A+1,sqrt(X.^2+Y.^2))),'t.png')

0

लव 2 डी लुआ, 466 बाइट्स

A=arg[2]i=love.image.newImageData q=math t=i(A)g=i(t:getWidth()-2,t:getHeight()-2)m={{-1,-2,-1},{0,0,0},{1,2,1}}M={{-1,0,1},{-2,0,2},{-1,0,1}}t:mapPixel(function(_,_,r,g,b)a=(r+g+b)/3 return a,a,a end)g:mapPixel(function(x,y)v=0 for Y=0,2 do for X=0,2 do v=v+(t:getPixel(x+X,y+Y)*m[Y+1][X+1])end end V=0 for Y=0,2 do for X=0,2 do V=V+(t:getPixel(x+X,y+Y)*M[Y+1][X+1])end end v=q.max(q.min(q.sqrt(V^2+v^2),255),0)return v,v,v end)g:encode('png',"o")love.event.quit()

कमांड लाइन इनपुट लेता है, आपके Love2D appsdata फ़ोल्डर के तहत "ओ" नामक फ़ाइल के लिए आउटपुट करता है। Love2D आप कहीं और फ़ाइलों को बचाने के लिए नहीं होगा।

बस के रूप में के रूप में मैं यह मिल सकता है, शायद आगे गोल्फ जा सकता है।

व्याख्या की

-- Assign the Input to A
A=arg[2]


-- Assign some macros to save FUTURE BYTES™
i=love.image.newImageData
q=math

-- t is the original image, g is the new output image. g is two pixels smaller, which is easier and better looking than a border.
t = i(A)
g = i(t:getWidth()-2,t:getHeight()-2)

-- m and M are our two sobel kernals. Fairly self explanitary.
m = {{-1,-2,-1}
    ,{0,0,0}
    ,{1,2,1}}

M = {{-1,0,1}
    ,{-2,0,2}
    ,{-1,0,1}}

-- Convert t to grayscale, to save doing this math later.
t:mapPixel(function(_,_,r,g,b)a=(r+g+b)/3 return a,a,a end)

-- Execute our kernals
g:mapPixel(function(x,y)
    -- v refers to the VERTICAL output of the Kernel m.
    v=0
    for Y=0,2 do
        for X=0,2 do
            v=v+(t:getPixel(x+X,y+Y)*m[Y+1][X+1])
        end
    end

    -- V is the HORIZONTAL of M
    V=0
    for Y=0,2 do
        for X=0,2 do
            V=V+(t:getPixel(x+X,y+Y)*M[Y+1][X+1])
        end
    end

    -- Clamp the values and sum them.
    v = q.max(q.min(q.sqrt(V^2 + v^2),255),0)
    -- Return the grayscale.
    return v,v,v
end)

-- Save, renaming the file. The golfed version just outputs as 'o'
g:encode('png',"S_".. A:gsub("(.*)%....","%1.png"))

-- Quit. Not needed, but I'm a sucker for self contained LOVE2D
love.event.quit()

परीक्षा

इनपुट उत्पादन

तथा...

हालांकि यह वास्तव में मेरे स्कोर में सुधार नहीं करता है (यह इसे और अधिक खराब बनाता है), यहाँ रंग पहिया के साथ संस्करण लागू किया गया है।

900 - 270 = 630 बाइट्स

A=arg[2]i=love.image.newImageData q=math t=i(A)g=i(t:getWidth()-2,t:getHeight()-2)m={{-1,-2,-1},{0,0,0},{1,2,1}}M={{-1,0,1},{-2,0,2},{-1,0,1}}function T(h,s,v)if s <=0 then return v,v,v end h,s,v=h*6,s,v/255 local c=v*s local x=(1-q.abs((h%2)-1))*c local m,r,g,b=(v-c),0,0,0 if h < 1 then r,g,b=c,x,0 elseif h < 2 then r,g,b=x,c,0 elseif h < 3 then r,g,b=0,c,x elseif h < 4 then r,g,b=0,x,c elseif h < 5 then r,g,b=x,0,c else r,g,b=c,0,x end return(r+m)*255,(g+m)*255,(b+m)*255 end t:mapPixel(function(_,_,r,g,b)a=(r+g+b)/3 return a,a,a end)g:mapPixel(function(x,y)v=0 for Y=0,2 do for X=0,2 do v=v+(t:getPixel(x+X,y+Y)*m[Y+1][X+1])end end V=0 for Y=0,2 do for X=0,2 do V=V+(t:getPixel(x+X,y+Y)*M[Y+1][X+1])end end h=v H=V v=q.max(q.min(q.sqrt(V^2+v^2),255),0)h=q.atan2(H,h)/q.pi*2 return T(h,1,v,255)end)g:encode('png',"S_".. A:gsub("(.*)%....","%1.png"))G=love.graphics.newImage(g)love.event.quit()

यहाँ छवि विवरण दर्ज करें

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