2012-04-15 11 views
7

तो मैं पता लगा मैं इस तरह स्केल के लिए एक छवि में बदल सकते हैं:ग्रेस्केल छवि में पिक्सल की औसत "दिशा" को कुशलतापूर्वक गणना कैसे करें?

public static Bitmap GrayScale(this Image img) 
{ 
    var bmp = new Bitmap(img.Width, img.Height); 
    using(var g = Graphics.FromImage(bmp)) 
    { 
     var colorMatrix = new ColorMatrix(
      new[] 
       { 
        new[] {.30f, .30f, .30f, 0, 0}, 
        new[] {.59f, .59f, .59f, 0, 0}, 
        new[] {.11f, .11f, .11f, 0, 0}, 
        new[] {0, 0, 0, 1.0f, 0}, 
        new[] {0, 0, 0, 0, 1.0f} 
       }); 

     using(var attrs = new ImageAttributes()) 
     { 
      attrs.SetColorMatrix(colorMatrix); 
      g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height), 
       0, 0, img.Width, img.Height, GraphicsUnit.Pixel, attrs); 
     } 
    } 
    return bmp; 
} 

अब, मैं गणना करने के लिए पिक्सल के औसत "दिशा" चाहते हैं।

मेरा मतलब यह है कि मैं 3x3 क्षेत्र कहना चाहता हूं, और फिर बाएं तरफ दाएं तरफ से गहरा है, तो दिशा सही होगी, अगर नीचे की तुलना में गहरा है शीर्ष, तो दिशा ऊपर की ओर होगी, अगर नीचे-बाएं ऊपर-दाएं से गहरा है, तो दिशा ऊपर-सही होगी। (हर 3x3 क्षेत्र में छोटे वेक्टर तीरों के बारे में सोचें)। शायद एक बेहतर उदाहरण यह है कि यदि आप फ़ोटोशॉप में ग्रेस्केल ढाल खींचते हैं, और आप गणना करना चाहते हैं कि उन्होंने किस कोण को खींचा है।

मैंने इस MatLab की तरह सामान किया है, लेकिन वह साल पहले था। मुझे लगता है कि मैं गणना करने के लिए ColorMatrix के समान मैट्रिक्स का उपयोग कर सकता हूं, लेकिन मुझे पूरा यकीन नहीं है कि कैसे। ऐसा लगता है कि this function ऐसा हो सकता है जो मैं चाहता हूं; क्या मैं इसे ग्रेस्केल (ऊपर के रूप में) में परिवर्तित कर सकता हूं और फिर इन दिशाओं की गणना करने के लिए ग्रेस्केल मैट्रिक्स के साथ कुछ कर सकता हूं?

आईआईआरसी, जो मैं चाहता हूं वह edge detection के समान है।

मैं इन दिशा वैक्टरों की गणना करने के बाद, मैं बस उन पर लूप करने जा रहा हूं और छवि की औसत दिशा की गणना कर रहा हूं।

अंतिम लक्ष्य मैं छवियों को घुमाने के लिए चाहता हूं ताकि उनकी औसत दिशा हमेशा ऊपर की ओर हो; इस तरह यदि मेरे पास दो समान छवियां हैं, तो एक को घुमाया गया है (90,180 या 270 डिग्री), वे उसी तरह उन्मुख हो जाएंगे (यदि कोई व्यक्ति उल्टा हो जाता है तो मुझे कोई चिंता नहीं है)।


* कटाव * कुछ स्पैम हटाया जा रहा है। आप अपने बाकी के प्रयासों को पढ़ना चाहते हैं के संशोधन देख सकते हैं। en.wikipedia.org/wiki/Image_gradient

+0

मुझे लगता है कि अगर आप प्रत्येक छवि टाइल निर्देशांक बनाम के सहसंबंध की गणना (जैसे 'meshgrid') आप अपने" दिशा "मिलना चाहिए। मुझे यह भी संदेह है कि टाइल दिशानिर्देशों का औसत एक ही जवाब देने जा रहा है जैसे कि आप पूरी छवि को एक टाइल के रूप में सहसंबंधित करते हैं। यदि आपके पास अभी भी MatLab है, तो मैं इसे आपके एल्गोरिदम का परीक्षण करने के लिए उपयोग करूंगा, फिर अंतिम संस्करण को सी # पर पोर्ट करूँगा। –

+0

@BenVoigt: एक मेष्रिड क्या है? अगर मैं जानता था कि मैं पूरी तरह से छवि पर दिशा की खुशी से गणना करूंगा। मेरे पास अब Matlab की एक प्रति नहीं है ... मैंने केवल यूनी में कुछ सेमेस्टर के लिए इसका इस्तेमाल किया; मुझे यकीन नहीं है कि मुझे याद होगा कि इसका उपयोग कैसे करें। सोचने का एक अलग तरीका चाहिए। – mpen

+0

लगता है कि आप जो चाहते हैं वह ढाल है। क्या आपने अभी तक कोशिश की है? – dranxo

उत्तर

9

कोणों का मतलब गिना जा रहा है आम तौर पर एक बुरा विचार है एक कोण सही इंगित करता है। क्या तुम यही चाहते हो? "अप" मानना ​​+ पीआई है, तो दो कोणों के बीच का मतलब लगभग इंगित करना एक कोण होगा, यदि एक कोण पीआई- [कुछ छोटा मूल्य], दूसरा -पीआई + [कुछ छोटा मूल्य] है। शायद यह नहीं है कि आप क्या चाहते हैं। इसके अलावा, आप किनारे की ताकत को पूरी तरह से अनदेखा कर रहे हैं - आपकी वास्तविक जीवन छवियों में से अधिकांश पिक्सल बिल्कुल किनारों पर नहीं हैं, इसलिए ढाल दिशा अधिकतर शोर है।

यदि आप "औसत दिशा" की तरह कुछ गणना करना चाहते हैं, तो आपको कोणों के बजाय वैक्टर जोड़ने की आवश्यकता है, फिर लूप के बाद एटान 2 की गणना करें। समस्या यह है कि: वेक्टर योग आपको छवि के अंदर वस्तुओं के बारे में कुछ भी नहीं बताता है, क्योंकि विपरीत दिशाओं में इंगित ग्रेडियेंट एक-दूसरे को रद्द करते हैं। यह आपको केवल पहली/आखिरी पंक्ति और छवि के पहले/अंतिम कॉलम के बीच चमक में अंतर के बारे में कुछ बताता है। शायद यह नहीं है कि आप क्या चाहते हैं।

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

angleHistogram[src_] := 
(
    Lx = GaussianFilter[ImageData[src], 2, {0, 1}]; 
    Ly = GaussianFilter[ImageData[src], 2, {1, 0}]; 
    angleAndOrientation = 
    MapThread[{Round[ArcTan[#1, #2]*180/\[Pi]], 
     Sqrt[#1^2 + #2^2]} &, {Lx, Ly}, 2]; 
    angleAndOrientationFlat = Flatten[angleAndOrientation, 1]; 
    bins = BinLists[angleAndOrientationFlat , 1, 5]; 
    histogram = 
    Total /@ Flatten[bins[[All, All, All, 2]], {{1}, {2, 3}}]; 
    maxIndex = Position[histogram, Max[histogram]][[1, 1]]; 
    Labeled[ 
    Show[ 
    ListLinePlot[histogram, PlotRange -> All], 
    Graphics[{Red, Point[{maxIndex, histogram[[maxIndex]]}]}] 
    ], "Maximum at " <> ToString[maxIndex] <> "\[Degree]"] 
) 

परिणाम नमूना छवियों के साथ:

enter image description here

कोण भी histograms

यहाँ एक-का-प्रमाण अवधारणा मेथेमेटिका कार्यान्वयन मैं एक साथ फेंक दिया गया है कि अगर यह काम करेगा देखने के लिए है दिखाएं कि औसत कोण क्यों काम नहीं कर सकता है: हिस्टोग्राम अनिवार्य रूप से एक तेज चोटी है, अन्य कोण लगभग समान हैं। इस हिस्टोग्राम का मतलब हमेशा वर्दी "पृष्ठभूमि शोर" का प्रभुत्व होगा। यही कारण है कि आप अपने वर्तमान एल्गोरिदम के साथ "असली लाइव" छवियों में से प्रत्येक के लिए लगभग एक ही कोण (लगभग 180 डिग्री) प्राप्त कर चुके हैं।

पेड़ की छवि में एक ही प्रभावशाली कोण (क्षितिज) है, इसलिए इस मामले में, आप हिस्टोग्राम (सबसे लगातार कोण) के मोड का उपयोग कर सकते हैं। लेकिन यह है कि हर छवि के लिए काम नहीं करेगा:

enter image description here

यहाँ आप दो चोटियों की है। चक्रीय सहसंबंध अभी भी एक दूसरे के लिए दो छवियों को उन्मुख करना चाहिए, लेकिन बस मोड का उपयोग करना पर्याप्त नहीं है।

यह भी ध्यान रखें कि कोण हिस्टोग्राम में शिखर "ऊपर" नहीं है: ऊपर पेड़ की छवि में, कोण हिस्टोग्राम में चोटी शायद क्षितिज है। तो यह इंगित कर रहा है। लेना छवि में, यह पृष्ठभूमि में लंबवत सफेद पट्टी है - इसलिए यह दाईं ओर इशारा कर रहा है। बस सबसे लगातार कोण का उपयोग कर छवियों को उन्मुख करना दाहिने तरफ इशारा करते हुए प्रत्येक छवि को चालू करें। मोड (या, शायद, किसी एक कोण) इस छवि को उन्मुख करने के लिए अविश्वसनीय हो जाएगा का उपयोग करना:

enter image description here

इस छवि को और भी अधिक चोटियों है।लेकिन पूरी तरह से कोण हिस्टोग्राम आपको अभी भी एक विश्वसनीय अभिविन्यास देना चाहिए।

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

जोड़ें: इस हिस्टोग्राम, क्या तुम करोगी

  1. मानक के अनुसार सभी हिस्टोग्राम का उपयोग कर दो छवियों उन्मुख करने के लिए, तो हिस्टोग्राम के तहत क्षेत्र प्रत्येक छवि के लिए एक ही है (भले ही कुछ, उज्जवल गहरा या blurrier हैं)
  2. छवियों के हिस्टोग्राम ले लो, और उन्हें एक रोटेशन में आपकी रुचि है के लिए तुलना:

उदाहरण के लिए, सी # में:

0,123,
for (int rotationAngle = 0; rotationAngle < 360; rotationAngle++) 
{ 
    int difference = 0; 
    for (int i = 0; i < 360; i++) 
     difference += Math.Abs(histogram1[i] - histogram2[(i+rotationAngle) % 360]); 
    if (difference < bestDifferenceSoFar) 
    { 
     bestDifferenceSoFar = difference; 
     foundRotation = rotationAngle; 
    } 
} 

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

+0

उत्कृष्ट जवाब; लिखने और परीक्षण करने के लिए समय निकालने के लिए धन्यवाद। मैं एक अभिविन्यास पर निश्चित रूप से निर्णय लेने के लिए पूरी तरह से हिस्टोग्राम का उपयोग कैसे कर सकता हूं? आपका आखिरी उदाहरण सुंदर जगह दिखता है; अधिकतम * बिल्कुल * 9 0 डिग्री अलग है, हालांकि मैं देख सकता हूं कि अगर अधिकतमता थोड़ा अलग हो गई तो यह एक अलग चोटी का चयन कर सकता था। – mpen

+0

@ मार्क: अधिकतम अधिकतम 90 डिग्री अलग है, क्योंकि यह बिल्कुल वही छवि है, जो 9 0 डिग्री से घिरा हुआ है, इसलिए ग्रेडियेंट्स में बिल्कुल समान परिमाण है और यह 90 डिग्री घुमाए गए हैं। यदि आप छवि का आकार बदल देंगे, या हानिकारक संपीड़न के साथ इसे संपीड़ित करेंगे, तो मोड एक अलग चोटी भी हो सकता है। – Niki

+0

हां, यह मेरा मुद्दा था - वे बाहर निकले * बिल्कुल * सही, यहां तक ​​कि थोड़ा सा भी नहीं। मैंने 90 डिग्री घूर्णन छवियों के साथ कुछ प्रयोग चलाए हैं, और जवाब हमेशा बाहर आ गए हैं। मैं हानिकारक जेपीईजी संपीड़न के साथ कोशिश करूँगा और बाद में उम्मीद कर रहा हूं। – mpen

0

दिशा आप चाहते हैं की गणना करने के अपनी छवि के ढाल का उपयोग कर विचार करें। हालांकि सुंदर नहीं होगा लेकिन आशा है कि यह आपके लिए काम करेगा।

इसकी संभावना है कि आपकी गणना ठीक है। बस एक बार ग्रेडियेंट एक औसत औसत मूल्य में समाप्त होता है जो आप अपेक्षा करते हैं। इसलिए मुझे लगता है कि उस छवि को देखकर मुझे संदेह है कि इसमें एक अलग औसत कोण होना चाहिए। इसलिए;

  • छवि को बाइनरी में कनवर्ट करें।
  • आटा परिवर्तन
  • का उपयोग करके लाइनें खोजें सबसे लंबी लाइन लें और इसके कोण की गणना करें। यह आपको कोण प्रदान करना चाहिए जो सबसे प्रमुख है।
  • आपको लाइनों को सही करने के लिए कुछ पूर्व/पोस्ट प्रोसेसिंग की आवश्यकता हो सकती है।

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

... 
     sum += Math.Atan2(yi, xi); 
    } 
} 
double avg = sum/(img.Width * img.Height); 

कोण का एक सेट का मतलब कोई स्पष्ट अर्थ है: उदाहरण के लिए, एक कोण की संकरी ओर इशारा करते हुए और एक कोण नीचे की ओर इशारा करते है

+2

यह बहुत अच्छा है, लेकिन आपने अनिवार्य रूप से मुझे केवल एक नाम दिया है जो मैंने वर्णित किया है। अभी भी कार्यान्वयन के साथ परेशानी है। – mpen

+0

जब आप सभी कोणों को एकसाथ औसत करते हैं तो एक कार्यान्वयन कठिनाई आती है। ढाल एक छवि में लेता है और फिर एक वेक्टर क्षेत्र outputs। कुछ स्थानों पर (उदाहरण के लिए, आपकी छवियों में काले क्षेत्र) ढाल 0 होगा और औसत कुछ अनपेक्षित आउटपुट करेगा। इसके बजाय मोड या औसत का उपयोग करने पर विचार करें। वैसे, यह क्या है? ऐसा लगता है कि आपका अंतिम लक्ष्य छवि पंजीकरण है जो बहुत ही nontrival cf है http://l3.lcarrasco.com/2010/04/image-registration/ – dranxo

+0

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

1

खैर मैं तुम्हें यह करने का एक अन्य तरीका प्रदान कर सकते हैं:

+0

मुझे लगता है कि यह वही समस्या होगी जिसके बारे में निकी बताती है: क्या कोई मुख्य रेखा नहीं है? – mpen

+0

तब कोई अच्छी तरह परिभाषित दिशा नहीं होगी। यही कारण है कि आपको दिशा खोजने के लिए संदर्भ छवि की आवश्यकता होगी। –

+0

@ मार्क - भी गस्ट आज़माएं। –

0

आपको अपनी छवि को दो गॉसियन डेरिवेटिव कर्नेल (एक्स में से एक और वाई में एक) के साथ घूमने की आवश्यकता है। यह वास्तव में उपरोक्त उत्तर में एलएक्स और ली है।

स्लाइडिंग विंडो (आपकी मूल छवि का सबमिटेज) और पहले क्रम गॉसियन व्युत्पन्न कार्यों के बीच समेकित उत्पाद की गणना करने से पहले औसत पिक्सेल तीव्रता को पहले से घटाएं।

उदाहरण के लिए देखें इस ट्यूटोरियल: http://bmia.bmt.tue.nl/people/bromeny/MICCAI2008/Materials/05%20Gaussian%20derivatives%20MMA6.pdf

चुनें इष्टतम समरेखण कारक सिग्मा> = 1.

गाऊसी कर्नेल की गणना करने के लिए, एक बार 2 डी-गाऊसी समारोह (सामान्य वितरण से जाना जाता है) को अलग 1 डी-वेरिएबल '(x-0)^2' द्वारा प्रतिस्थापित (x^2 + y^2)। आप इसे 2 डी में आकर्षित कर सकते हैं, उदाहरण के लिए एमएस एक्सेल में।

शुभकामनाएं!

माइकल

संबंधित मुद्दे