छवि में ज़ेबरा जैसा पैटर्न खोजना (फोटो से संरचित-प्रकाश फ्रिंज सेंटरलाइन का पता लगाना)


12

मैं एक ऐसे प्रोजेक्ट में काम कर रहा हूँ जहाँ किसी विषय के खिलाफ फ्रिंज का अनुमान लगाया जाता है, और एक तस्वीर ली जाती है। यह कार्य फ्रिंजेस के केंद्र बिंदु को खोजने के लिए है, जो कि, गणितीय रूप से, फ्रिंज विमान और विषय की सतह के बीच चौराहे के 3 डी वक्र का प्रतिनिधित्व करते हैं।

तस्वीर एक PNG (RGB) है, और पूर्व के प्रयासों ने ग्रेस्कलिंग का इस्तेमाल किया, फिर ब्लैक-एंड-व्हाइट, "ज़ेबरा जैसी" फोटोग्राफी पाने के लिए अंतर थ्रेसहोल्ड, जिससे प्रत्येक फ्रिंज के प्रत्येक पिक्सेल कॉलम के मध्य बिंदु को खोजना आसान था। समस्या यह है कि, थ्रेशोल्डिंग के द्वारा और असतत पिक्सेल कॉलम की औसत ऊंचाई लेने से, हमें कुछ सटीक नुकसान और मात्रा का ठहराव हो रहा है, जो बिल्कुल भी वांछित नहीं है।

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

नीचे एक वास्तविक नमूना छवि है:

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

किसी भी सुझाव बहुत सराहना की जाएगी!


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

@ जॉनीयंग: कृपया टिप्पणियों को उत्तर के रूप में न जोड़ें। मुझे लगता है कि आपको टिप्पणी करने से पहले प्रतिष्ठा की आवश्यकता है, लेकिन कृपया अपनी वर्तमान कार्रवाई से बचना चाहिए। मेरा सुझाव है कि अपने स्वयं के (संबंधित) सवाल पूछें या अपने प्रतिनिधि को बढ़ाने के लिए दूसरों के सवालों का जवाब दें।
पीटर के.एच.

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

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

जवाबों:


13

मैं निम्नलिखित चरणों का सुझाव देता हूं:

  1. पृष्ठभूमि से अग्रभूमि को अलग करने के लिए एक सीमा खोजें।
  2. बाइनरी इमेज (एक ज़ेबरा स्ट्राइप) में प्रत्येक बूँद के लिए, प्रत्येक के लिए दिशा xमें भारित केंद्र (पिक्सेल तीव्रता से) खोजें y
  3. संभवतः, yशोर को दूर करने के लिए मूल्यों को सुचारू करें ।
  4. (x,y)किसी प्रकार की वक्र फिटिंग करके बिंदुओं को कनेक्ट करें । यह लेख आपकी मदद कर सकता है। आप एक उच्च-स्तरीय बहुपद भी फिट कर सकते हैं, हालांकि यह मेरी राय में और भी बुरा है।

यहाँ एक Matlab कोड है जो 1,2 चरणों को दिखाता है और 4. मैंने स्वचालित सीमा चयन को छोड़ दिया है। इसके बजाय मैंने मैनुअल चुना th=40:

ये वक्र हैं जो प्रति स्तंभ भारित औसत ज्ञात करके पाए जाते हैं: यहाँ छवि विवरण दर्ज करें

बहुपद फिटिंग के बाद ये वक्र हैं: यहाँ छवि विवरण दर्ज करें

यहाँ कोड है:

function Zebra()
    im = imread('http://i.stack.imgur.com/m0sy7.png');
    im = uint8(mean(im,3));

    th = 40;
    imBinary = im>th;
    imBinary = imclose(imBinary,strel('disk',2));
    % figure;imshow(imBinary);
    labels = logical(imBinary);
    props =regionprops(labels,im,'Image','Area','BoundingBox');

    figure(1);imshow(im .* uint8(imBinary));
    figure(2);imshow(im .* uint8(imBinary));

    for i=1:numel(props)
        %Ignore small ones
        if props(i).Area < 10
            continue
        end
        %Find weighted centroids
        boundingBox = props(i).BoundingBox;
        ul = boundingBox(1:2)+0.5;
        wh = boundingBox(3:4);
        clipped = im( ul(2): (ul(2)+wh(2)-1), ul(1): (ul(1)+wh(1)-1) );
        imClip = double(props(i).Image) .* double(clipped);
        rows = transpose( 1:size(imClip,1) );
        %Weighted calculation
        weightedRows  = sum(bsxfun(@times, imClip, rows),1) ./ sum(imClip,1);
        %Calculate x,y
        x = ( 1:numel(weightedRows) ) + ul(1) - 1;
        y = ( weightedRows ) + ul(2) - 1;
        figure(1);
        hold on;plot(x,y,'b','LineWidth',2);
        try %#ok<TRYNC>
            figure(2);
            [xo,yo] = FitCurveByPolynom(x,y);
            hold on;plot(xo,yo,'g','LineWidth',2);
        end
        linkaxes( cell2mat(get(get(0,'Children'),'Children')) )
    end        
end

function [xo,yo] = FitCurveByPolynom(x,y)
   p = polyfit(x,y,15); 
   yo = polyval(p,x);
   xo = x;
end

मुझे यह बहुत दिलचस्प लगा। मैं पायथन का उपयोग करता हूं, लेकिन वैसे भी मुझे इस सब के औचित्य का अध्ययन करना है। एक स्वतंत्र टिप्पणी के रूप में, मैं क्लासिक इमेज प्रोसेसिंग (सीधे मात्रा में इमेज कंटेनर जैसे uint8 सरणियों पर) नहीं करता हूं, बल्कि संचालन को लागू करने से पहले फ्लोट एरेज़ के रूप में मेमोरी में सब कुछ लोड करता हूं। इसके अलावा, मैं आपकी छवि के निचले आधे हिस्से से परिणामों से हैरान हूं, नीली लाइनें अपेक्षित फ्रिंज मिडलाइन्स के साथ नहीं चल रही हैं ... (?)। अभी के लिए धन्यवाद, मैं कुछ परिणाम मिलते ही कुछ प्रतिक्रिया लाने वाला हूँ!
हेलटोनबीकर

@heltonbiker, अद्यतन किए गए उत्तर की जाँच करें। आप फ़्लोटिंग पॉइंट के बारे में सही हैं, मैंने इसका उपयोग तब किया जब मैं परिवर्तित हो गया double। निचले आधे में परिणामों के बारे में, मुझे जांचने की आवश्यकता है, यह एक सॉफ्टवेयर बग हो सकता है
एंड्री रुबेश्टिन

1
@heltonbiker, किया। यह वास्तव में 1 आधारित अनुक्रमण से संबंधित बग था।
एंड्री रुबेश्टिन

उत्कृष्ट! अद्भुत, वास्तव में। इस तकनीक के साथ, और मेरे उद्देश्यों के लिए, चौरसाई को न केवल ज़रूरत नहीं होगी, बल्कि हानिकारक भी होगा। आपकी रुचि के लिए बहुत बहुत धन्यवाद!
हेल्टनबीकर

3

मैं RGB छवि का उपयोग नहीं करूंगा। आमतौर पर रंगीन चित्र कैमरा सेंसर पर "बायर फ़िल्टर" लगाकर बनाए जाते हैं , जो आमतौर पर आपके द्वारा प्राप्त किए जा सकने वाले रिज़ॉल्यूशन को कम कर देता है।

यदि आप ग्रेस्केल छवि का उपयोग करते हैं, तो मुझे लगता है कि आपके द्वारा वर्णित कदम (द्वैध "ज़ेबरा" छवि, मिडलाइन ढूंढें) एक अच्छी शुरुआत है। अंतिम चरण के रूप में, मैं करूंगा

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

अच्छे विचार। मैं प्रत्येक पिक्सेल कॉलम के शिखर मूल्यों के साथ कुछ प्रकार के पेराबोला या स्पलाइन का उपयोग करने की योजना बना रहा हूं, लेकिन मैं अभी भी सोच रहा हूं कि क्या मुझे लाइन के साथ एक पिक्सेल कॉलम या इसके बजाय पिक्सेल "क्षेत्र" की जांच करनी चाहिए ... गोना के लिए कुछ और इंतजार करें अधिक जवाब। अभी के लिए धन्यवाद!
हेल्टनबिकर

@heltonbiker - एक त्वरित परीक्षण के रूप में केवल ग्रीन चैनल का उपयोग करें। एक रंग सेंसर पर सामान्य रूप से 2x कई हरे रंग के पिक्सेल होते हैं और यह लाल और नीले रंग की तुलना में बहुत कम होता है
मार्टिन बेकेट

@MartinBeckett आपकी रुचि के लिए धन्यवाद, मैंने पहले ही प्रत्येक चैनल का विश्लेषण किया है, और वास्तव में हरे रंग की तुलना में अधिक हल किया गया है, कहते हैं, लाल वाला। प्रत्येक चैनल के लिए ऊर्ध्वाधर क्रॉस सेक्शन के तीव्रता मानों को प्लॉट करते हुए, हालांकि, "स्ट्राइप-पैटर्न" चैनलों के बीच इतना परिवर्तन नहीं लगता है, और मैं वर्तमान में उन्हें स्केल में रूपांतरण पर समान रूप से मिला रहा हूं। हालांकि, मैं अभी भी सबसे अच्छा-विपरीत परिणाम प्राप्त करने के लिए चैनलों के बीच सबसे अच्छा रैखिक संयोजन का अध्ययन करने की योजना बना रहा हूं, या पहले से ही चित्रों में प्राप्त करने के लिए। एक बार फिर धन्यवाद!
हेल्टनबाइकर

3

अपने प्रश्न को 'पथ अनुकूलन समस्या' के रूप में बताकर यहां अभी तक आपकी समस्या का एक वैकल्पिक समाधान है। हालांकि यह सरल द्विप्रदीकरण-और-तब-क्यूरफिटिंग समाधान की तुलना में अधिक जटिल है, यह अभ्यास में अधिक मजबूत है।

बहुत उच्च स्तर से, हमें इस छवि को एक ग्राफ के रूप में मानना ​​चाहिए, जहां

  1. प्रत्येक चित्र पिक्सेल इस ग्राफ पर एक नोड है

  2. प्रत्येक नोड को कुछ अन्य नोड्स से जोड़ा जाता है, जिन्हें पड़ोसियों के रूप में जाना जाता है, और इस कनेक्शन परिभाषा को अक्सर इस ग्राफ की टोपोलॉजी के रूप में संदर्भित किया जाता है।

  3. प्रत्येक नोड में एक वजन (सुविधा, लागत, ऊर्जा, या जिसे आप इसे कॉल करना चाहते हैं) है, इस संभावना को दर्शाता है कि यह नोड एक इष्टतम केंद्रीय-रेखा में है जिसे हम खोज रहे हैं।

जब तक हम इस संभावना को मॉडल कर सकते हैं, तब तक center फ्रिंजेस की सेंटरलाइन्स ’को खोजने की आपकी समस्या ग्राफ पर स्थानीय इष्टतम रास्तों को खोजने के लिए समस्या बन जाती है , जिसे डायनेमिक प्रोग्रामिंग, जैसे वीटरबी एल्गोरिदम द्वारा प्रभावी रूप से हल किया जा सकता है।

इस दृष्टिकोण को अपनाने के कुछ नियम इस प्रकार हैं:

  1. आपके सभी परिणाम निरंतर होंगे (दहलीज विधि के विपरीत जो एक केंद्र रेखा को टुकड़ों में तोड़ सकते हैं)

  2. इस तरह के एक ग्राफ का निर्माण करने के लिए बहुत सारी स्वतंत्रता है, आप विभिन्न विशेषताओं, और ग्राफ टोपोलॉजी का चयन कर सकते हैं।

  3. आपके परिणाम पथ अनुकूलन के अर्थ में इष्टतम हैं

  4. आपका समाधान शोर के खिलाफ और अधिक मजबूत होगा, क्योंकि जब तक शोर सभी पिक्सेल के बीच समान रूप से वितरित किया जाता है, तब तक उन इष्टतम पथ स्थिर रहते हैं।

यहाँ उपरोक्त विचार का एक छोटा प्रदर्शन है। चूंकि मैं यह बताने के लिए किसी भी पूर्व ज्ञान का उपयोग नहीं करता कि क्या शुरू करना और नोड्स को समाप्त करना संभव है, इसलिए मैं बस हर संभव शुरुआती नोड को डीकोड करता हूं। डिकोडेड विटर्बी पथ

फजी एंडिंग के लिए, यह इस तथ्य के कारण होता है कि हम हर संभव समाप्ति नोड्स के लिए इष्टतम मार्ग ढूंढ रहे हैं। परिणामस्वरूप, हालांकि अंधेरे क्षेत्रों में स्थित कुछ नोड्स के लिए, हाइलाइट किया गया पथ अभी भी इसका स्थानीय इष्टतम है।

फ़ज़ी रास्ते के लिए, आप इसे ढूंढने के बाद या तो इसे चिकना कर सकते थे या कच्ची तीव्रता के बजाय कुछ चिकनी सुविधाओं का उपयोग कर सकते थे।

शुरू और समाप्त नोड्स को बदलकर आंशिक पथ को पुनर्स्थापित करना संभव है।

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

अधिक जानकारी के लिए, आप कागज का संदर्भ ले सकते हैं।

 Wu, Y.; Zha, S.; Cao, H.; Liu, D., & Natarajan, P.  (2014, February). A Markov Chain Line Segmentation Method for Text Recognition. In IS&T/SPIE 26th Annual Symposium on Electronic Imaging (DRR), pp. 90210C-90210C.

यहाँ उपरोक्त ग्राफ बनाने के लिए अजगर कोड का एक छोटा टुकड़ा दिया गया है।


import cv2
import numpy as np
from matplotlib import pyplot
# define your image path
image_path = ;
# read in an image
img = cv2.imread( image_path, 0 );
rgb = cv2.imread( image_path, -1 );

# some feature to reflect how likely a node is in an optimal path
img = cv2.equalizeHist( img ); # equalization
img = img - img.mean(); # substract DC
img_pmax = img.max(); # get brightest intensity
img_nmin = img.min(); # get darkest intensity
# express our preknowledge
img[ img > 0 ] *= +1.0  / img_pmax; 
img[ img = 1 :
    prev_idx = vt_path[ -1 ].astype('int');
    vt_path.append( path_buffer[ prev_idx, time ] );
    time -= 1;
vt_path.reverse();    
vt_path = np.asarray( vt_path ).T;

# plot found optimal paths for every 7 of them
pyplot.imshow( rgb, 'jet' ),
for row in range( 0, h, 7 ) :
    pyplot.hold(True), pyplot.plot( vt_path[row,:], c=np.random.rand(3,1), lw = 2 );
pyplot.xlim( ( 0, w ) );
pyplot.ylim( ( h, 0 ) );

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

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

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

3

सोचा कि मुझे अपना उत्तर पोस्ट करना चाहिए क्योंकि यह अन्य दृष्टिकोणों से थोड़ा अलग है। मैंने मतलाब में यह कोशिश की।

  • सभी चैनलों को योग करें और एक छवि बनाएं, इसलिए सभी चैनलों को समान रूप से भारित किया जाता है
  • इस छवि पर रूपात्मक समापन और गाऊसी फ़िल्टरिंग करें
  • परिणामी छवि के प्रत्येक कॉलम के लिए, स्थानीय मैक्सिमा ढूंढें और एक छवि का निर्माण करें
  • इस छवि के जुड़े घटकों को खोजें

एक नुकसान मैं यहाँ देख रहा हूँ कि यह दृष्टिकोण धारियों के कुछ झुकावों के लिए अच्छा प्रदर्शन नहीं करेगा। उस मामले में हमें इसके उन्मुखीकरण को सही करना होगा और इस प्रक्रिया को लागू करना होगा।

यहाँ Matlab कोड है:

im = imread('m0sy7.png');
imsum = sum(im, 3); % sum all channels
h = fspecial('gaussian', 3);
im2 = imclose(imsum, ones(3)); % close
im2 = imfilter(im2, h); % smooth
% for each column, find regional max
mx = zeros(size(im2));
for c = 1:size(im2, 2)
    mx(:, c) = imregionalmax(im2(:, c));
end
% find connected components
ccomp = bwlabel(mx);

उदाहरण के लिए, यदि आप छवि के मध्य स्तंभ को लेते हैं, तो इसका प्रोफ़ाइल इस तरह दिखना चाहिए: (नीले रंग में प्रोफ़ाइल है। हरे रंग में स्थानीय मैक्सिमा हैं) मध्य प्रोफ़ाइल और स्थानीय मैक्सीमा

और सभी कॉलमों के लिए स्थानीय मैक्सीमा वाली छवि इस तरह दिखती है: यहाँ छवि विवरण दर्ज करें

यहां जुड़े हुए घटक हैं (हालांकि कुछ धारियां टूटी हुई हैं, उनमें से अधिकांश को एक निरंतर क्षेत्र मिलता है):

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


यह वास्तव में अब हम क्या कर रहे हैं, केवल एक अंतर के साथ प्रत्येक पिक्सेल कॉलम के लिए स्थानीय मैक्सिमा को खोजने के लिए: हम अधिकतम मूल्य और इसके ऊपरी और निचले पड़ोसियों के साथ पिक्सेल से गुजरने वाले परबोला के सटीक शीर्ष को खोजने के लिए एक परवलयिक प्रक्षेप का उपयोग करते हैं। । यह परिणाम को "बीच" पिक्सेल के लिए अनुमति देता है, जो बेहतर रूप से लाइनों की सूक्ष्म चिकनाई का प्रतिनिधित्व करता है। आपके उत्तर के लिए धन्यवाद!
हेल्टनबाइकर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.