python - एक 2 डी सरणी में पीक पहचान




image-processing (14)

उपाय

डेटा फ़ाइल: paw.txt । सोर्स कोड:

from scipy import *
from operator import itemgetter

n = 5  # how many fingers are we looking for

d = loadtxt("paw.txt")
width, height = d.shape

# Create an array where every element is a sum of 2x2 squares.

fourSums = d[:-1,:-1] + d[1:,:-1] + d[1:,1:] + d[:-1,1:]

# Find positions of the fingers.

# Pair each sum with its position number (from 0 to width*height-1),

pairs = zip(arange(width*height), fourSums.flatten())

# Sort by descending sum value, filter overlapping squares

def drop_overlapping(pairs):
    no_overlaps = []
    def does_not_overlap(p1, p2):
        i1, i2 = p1[0], p2[0]
        r1, col1 = i1 / (width-1), i1 % (width-1)
        r2, col2 = i2 / (width-1), i2 % (width-1)
        return (max(abs(r1-r2),abs(col1-col2)) >= 2)
    for p in pairs:
        if all(map(lambda prev: does_not_overlap(p,prev), no_overlaps)):
            no_overlaps.append(p)
    return no_overlaps

pairs2 = drop_overlapping(sorted(pairs, key=itemgetter(1), reverse=True))

# Take the first n with the heighest values

positions = pairs2[:n]

# Print results

print d, "\n"

for i, val in positions:
    row = i / (width-1)
    column = i % (width-1)
    print "sum = %f @ %d,%d (%d)" % (val, row, column, i)
    print d[row:row+2,column:column+2], "\n"

ओवरलैपिंग स्क्वायर के बिना Output । ऐसा लगता है कि आपके क्षेत्र में वही क्षेत्र चुने गए हैं।

कुछ टिप्पणियां

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

इसे बेहतर समझने के लिए, 3x3 सरणी इमेजिंग:

>>> a = arange(9).reshape(3,3) ; a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

फिर आप इसकी स्लाइस ले सकते हैं:

>>> a[:-1,:-1]
array([[0, 1],
       [3, 4]])
>>> a[1:,:-1]
array([[3, 4],
       [6, 7]])
>>> a[:-1,1:]
array([[1, 2],
       [4, 5]])
>>> a[1:,1:]
array([[4, 5],
       [7, 8]])

अब कल्पना करें कि आप उन्हें एक दूसरे से ऊपर और समान पदों पर तत्वों को ढेर करते हैं। ये रकम एक ही स्थिति में शीर्ष बाएं कोने के साथ 2x2 वर्गों पर बिल्कुल वही रकम होगी:

>>> sums = a[:-1,:-1] + a[1:,:-1] + a[:-1,1:] + a[1:,1:]; sums
array([[ 8, 12],
       [20, 24]])

जब आपके पास 2x2 वर्गों से अधिक रकम होती है, तो आप चोटी को खोजने के लिए अधिकतम, या sort या sorted करने के लिए max का उपयोग कर सकते हैं।

चोटियों की स्थिति को याद रखने के लिए मैं प्रत्येक मूल्य (योग) को एक सामान्य सरणी ( zip देखें) में अपनी सामान्य स्थिति के साथ जोड़ता हूं। फिर जब मैं परिणाम प्रिंट करता हूं तो मैं फिर से पंक्ति / कॉलम स्थिति की गणना करता हूं।

टिप्पणियाँ

मैंने 2x2 वर्गों को ओवरलैप करने की अनुमति दी। संपादित संस्करण उनमें से कुछ को फ़िल्टर करता है जैसे कि परिणामों में केवल गैर-ओवरलैपिंग वर्ग दिखाई देते हैं।

उंगलियों का चयन (एक विचार)

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

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

छद्म कोड:

select the top N finger candidates (not too many, 10 or 12)
consider all possible combinations of 5 out of N (use itertools.combinations)
for each combination of 5 fingers:
    for each finger out of 5:
        fit the best circle to the remaining 4
        => position of the center, radius
        check if the selected finger is inside of the circle
        check if the remaining four are evenly spread
        (for example, consider angles from the center of the circle)
        assign some cost (penalty) to this selection of 4 peaks + a rear finger
        (consider, probably weighted:
             circle fitting error,
             if the rear finger is inside,
             variance in the spreading of the front fingers,
             total intensity of 5 peaks)
choose a combination of 4 peaks + a rear peak with the lowest penalty

यह एक क्रूर बल दृष्टिकोण है। यदि एन अपेक्षाकृत छोटा है, तो मुझे लगता है कि यह करने योग्य है। एन = 12 के लिए, सी_12 ^ 5 = 792 संयोजन, पिछली उंगली का चयन करने के 5 तरीके हैं, इसलिए प्रत्येक पंजा के लिए 3 9 60 मामले मूल्यांकन करने के लिए।

मैं कुत्तों के पंजे के नीचे एक पशु चिकित्सा क्लिनिक मापने के दबाव में मदद कर रहा हूं। मैं अपने डेटा विश्लेषण के लिए पायथन का उपयोग करता हूं और अब मैं पंजे को (रचनात्मक) उप-वर्गों में विभाजित करने की कोशिश कर रहा हूं।

मैंने प्रत्येक पंजा की 2 डी सरणी बनाई, जिसमें प्रत्येक सेंसर के लिए अधिकतम मान होते हैं जो समय के साथ पंजा द्वारा लोड किया गया है। यहां एक पंजा का एक उदाहरण दिया गया है, जहां मैंने एक्सेल का उपयोग उन क्षेत्रों को आकर्षित करने के लिए किया था जिन्हें मैं 'पहचान' करना चाहता हूं। ये स्थानीय अधिकतममा के साथ सेंसर के चारों ओर 2 से 2 बक्से हैं, जिनके साथ सबसे बड़ा योग है।

तो मैंने कुछ प्रयोग करने की कोशिश की और बस प्रत्येक कॉलम और पंक्ति की अधिकतम सीमाओं को देखने का फैसला किया (पंजा के आकार के कारण एक दिशा में नहीं देख सकता)। ऐसा लगता है कि अलग पैर की उंगलियों का स्थान काफी अच्छी तरह से पता चलता है, लेकिन यह पड़ोसी सेंसर भी चिह्नित करता है।

तो पाइथन को बताने का सबसे अच्छा तरीका क्या होगा जो इन अधिकतमताओं में से हैं जिन्हें मैं चाहता हूं?

नोट: 2x2 वर्ग ओवरलैप नहीं हो सकते हैं, क्योंकि उन्हें अलग पैर की अंगुली होनी चाहिए!

इसके अलावा मैंने एक सुविधा के रूप में 2x2 लिया, किसी भी उन्नत समाधान का स्वागत है, लेकिन मैं बस एक मानव आंदोलन वैज्ञानिक हूं, इसलिए मैं न तो असली प्रोग्रामर या गणितज्ञ हूं, इसलिए कृपया इसे 'सरल' रखें।

यहां एक संस्करण है जिसे np.loadtxt लोड किया जा सकता है

परिणाम

तो मैंने @ जेएक्सटीई समाधान की कोशिश की (नीचे दिए गए परिणाम देखें)। जैसा कि आप देख सकते हैं, यह सामने के पंजे पर बहुत काम करता है, लेकिन यह हिंद पैर के लिए कम अच्छी तरह से काम करता है।

अधिक विशेष रूप से, यह चौथे पैर की अंगुली की छोटी चोटी को पहचान नहीं सकता है। यह स्पष्ट रूप से इस तथ्य से निहित है कि लूप सबसे कम मूल्य की तरफ नीचे देखता है, यह ध्यान में रखे बिना कि यह कहां है।

क्या किसी को पता होगा कि @ jextee के एल्गोरिदम को कैसे ट्विक करें, ताकि यह चौथा पैर भी ढूंढ सके?

चूंकि मैंने अभी तक किसी अन्य परीक्षण को संसाधित नहीं किया है, इसलिए मैं किसी अन्य नमूने की आपूर्ति नहीं कर सकता। लेकिन मैंने जो डेटा दिया था वह प्रत्येक पंजा का औसत था। यह फ़ाइल प्लेट के साथ संपर्क करने के क्रम में 9 पंजा के अधिकतम डेटा के साथ एक सरणी है।

यह छवि दिखाती है कि वे प्लेट पर कैसे फैल गए थे।

अद्यतन करें:

मैंने रुचि रखने वाले किसी के लिए एक ब्लॉग स्थापित किया है और मैंने सभी कच्चे माप के साथ स्काईडाइव स्थापित किया है। तो किसी और को अधिक डेटा का अनुरोध करने के लिए: आपको अधिक शक्ति!

नई अपडेट:

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

यहां एक अच्छा उदाहरण दिया गया है कि यह कहां गलत हो जाता है: एक नाखून को पैर की अंगुली के रूप में पहचाना जा रहा है और 'एड़ी' इतनी व्यापक है, यह दो बार पहचाना जाता है!

पंजा बहुत बड़ा है, इसलिए बिना किसी ओवरलैप के 2x2 आकार लेना, कुछ पैर की उंगलियों को दो बार पता चला है। दूसरी तरफ, छोटे कुत्तों में यह अक्सर 5 वें पैर की अंगुली खोजने में विफल रहता है, जो मुझे संदेह है कि 2x2 क्षेत्र बहुत बड़ा होने के कारण होता है।

मेरे सभी मापों पर वर्तमान समाधान की कोशिश करने के बाद मैं चौंकाने वाले निष्कर्ष पर आया कि लगभग सभी छोटे कुत्तों के लिए इसे 5 वां पैर नहीं मिला और बड़े कुत्तों के 50% से अधिक प्रभावों में यह और अधिक पाएगा!

तो स्पष्ट रूप से मुझे इसे बदलने की जरूरत है। मेरा खुद का अनुमान neighborhood के आकार को छोटे कुत्तों के लिए छोटे और बड़े कुत्तों के लिए बड़ा बदल रहा था। लेकिन generate_binary_structure मुझे सरणी के आकार को बदलने नहीं देगा।

इसलिए, मैं उम्मीद कर रहा हूं कि किसी और के पास पैर की उंगलियों का पता लगाने के लिए बेहतर सुझाव है, शायद पंजा आकार के साथ पैर की अंगुली क्षेत्र पैमाने है?


अपने डेटा सेट का विश्लेषण करने के लिए लगातार होमोलॉजी का उपयोग करके मुझे निम्नलिखित परिणाम मिलते हैं (विस्तृत करने के लिए क्लिक करें):

यह इस SO उत्तर में वर्णित चरम पहचान विधि का 2 डी संस्करण है। उपर्युक्त आंकड़ा दृढ़ता से क्रमबद्ध 0-आयामी लगातार होमोलॉजी कक्षाओं को दिखाता है।

मैंने scipy.misc.imresize () का उपयोग कर 2 के कारक द्वारा मूल डेटासेट को अपस्केल किया था। हालांकि, ध्यान दें कि मैंने चार पंजाों को एक डेटासेट के रूप में माना था; इसे चार में विभाजित करना समस्या को आसान बना देगा।

क्रियाविधि। इस काफी सरल के पीछे विचार: फ़ंक्शन के फ़ंक्शन ग्राफ़ पर विचार करें जो प्रत्येक पिक्सेल को अपना स्तर निर्दिष्ट करता है। यह इस तरह दिख रहा है:

अब ऊंचाई 255 पर पानी के स्तर पर विचार करें जो लगातार निम्न स्तर तक गिरता है। स्थानीय मैक्सिमा द्वीपों में पॉप अप (जन्म)। सैडल पॉइंट्स पर दो द्वीप मर्ज करते हैं; हम निचले द्वीप को उच्च द्वीप (मृत्यु) में विलय करने पर विचार करते हैं। तथाकथित दृढ़ता आरेख (0-वें आयामी होमोलॉजी कक्षाओं, हमारे द्वीपों) में सभी द्वीपों के जन्म-मूल्यों पर मृत्यु दर्शाती है:

एक द्वीप की दृढ़ता तब जन्म और मृत्यु-स्तर के बीच का अंतर है; ग्रे मुख्य विकर्ण के लिए एक बिंदु की ऊर्ध्वाधर दूरी। यह आंकड़ा दृढ़ता से कम करके द्वीपों को लेबल करता है।

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


एक मोटा रूपरेखा ...

आप शायद प्रत्येक पंजा क्षेत्र को अलग करने के लिए एक कनेक्टेड घटक एल्गोरिदम का उपयोग करना चाहते हैं। विकी का यहां एक सभ्य वर्णन है (कुछ कोड के साथ): http://en.wikipedia.org/wiki/Connected_Component_Labeling

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

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

केंद्रीय क्षण: अनुवाद invariant सामान्यीकृत क्षण: स्केलिंग और अनुवाद invariant hu क्षण: अनुवाद, पैमाने, और रोटेशन invariant

क्षणों के बारे में अधिक जानकारी विकी पर "छवि क्षण" खोजकर पाई जा सकती है।


कच्चे डेटा के लिए धन्यवाद। मैं ट्रेन में हूं और जहां तक ​​मुझे मिल गया है (मेरा स्टॉप आ रहा है)। मैंने आपकी txt फ़ाइल को regexps के साथ मालिश किया है और विज़ुअलाइज़ेशन के लिए कुछ जावास्क्रिप्ट के साथ इसे HTML पृष्ठ में फेंक दिया है। मैं इसे यहां साझा कर रहा हूं क्योंकि कुछ, खुद की तरह, इसे पाइथन से अधिक आसानी से हैक करने योग्य लगता है।

मुझे लगता है कि एक अच्छा दृष्टिकोण स्केल और रोटेशन इनवेरिएंट होगा, और मेरा अगला कदम गॉसियन के मिश्रण की जांच करेगा। (प्रत्येक पंजा पैड एक गाऊशियन का केंद्र होता है)।

    <html>
<head>
    <script type="text/javascript" src="http://vis.stanford.edu/protovis/protovis-r3.2.js"></script> 
    <script type="text/javascript">
    var heatmap = [[[0,0,0,0,0,0,0,4,4,0,0,0,0],
[0,0,0,0,0,7,14,22,18,7,0,0,0],
[0,0,0,0,11,40,65,43,18,7,0,0,0],
[0,0,0,0,14,61,72,32,7,4,11,14,4],
[0,7,14,11,7,22,25,11,4,14,65,72,14],
[4,29,79,54,14,7,4,11,18,29,79,83,18],
[0,18,54,32,18,43,36,29,61,76,25,18,4],
[0,4,7,7,25,90,79,36,79,90,22,0,0],
[0,0,0,0,11,47,40,14,29,36,7,0,0],
[0,0,0,0,4,7,7,4,4,4,0,0,0]
],[
[0,0,0,4,4,0,0,0,0,0,0,0,0],
[0,0,11,18,18,7,0,0,0,0,0,0,0],
[0,4,29,47,29,7,0,4,4,0,0,0,0],
[0,0,11,29,29,7,7,22,25,7,0,0,0],
[0,0,0,4,4,4,14,61,83,22,0,0,0],
[4,7,4,4,4,4,14,32,25,7,0,0,0],
[4,11,7,14,25,25,47,79,32,4,0,0,0],
[0,4,4,22,58,40,29,86,36,4,0,0,0],
[0,0,0,7,18,14,7,18,7,0,0,0,0],
[0,0,0,0,4,4,0,0,0,0,0,0,0],
],[
[0,0,0,4,11,11,7,4,0,0,0,0,0],
[0,0,0,4,22,36,32,22,11,4,0,0,0],
[4,11,7,4,11,29,54,50,22,4,0,0,0],
[11,58,43,11,4,11,25,22,11,11,18,7,0],
[11,50,43,18,11,4,4,7,18,61,86,29,4],
[0,11,18,54,58,25,32,50,32,47,54,14,0],
[0,0,14,72,76,40,86,101,32,11,7,4,0],
[0,0,4,22,22,18,47,65,18,0,0,0,0],
[0,0,0,0,4,4,7,11,4,0,0,0,0],
],[
[0,0,0,0,4,4,4,0,0,0,0,0,0],
[0,0,0,4,14,14,18,7,0,0,0,0,0],
[0,0,0,4,14,40,54,22,4,0,0,0,0],
[0,7,11,4,11,32,36,11,0,0,0,0,0],
[4,29,36,11,4,7,7,4,4,0,0,0,0],
[4,25,32,18,7,4,4,4,14,7,0,0,0],
[0,7,36,58,29,14,22,14,18,11,0,0,0],
[0,11,50,68,32,40,61,18,4,4,0,0,0],
[0,4,11,18,18,43,32,7,0,0,0,0,0],
[0,0,0,0,4,7,4,0,0,0,0,0,0],
],[
[0,0,0,0,0,0,4,7,4,0,0,0,0],
[0,0,0,0,4,18,25,32,25,7,0,0,0],
[0,0,0,4,18,65,68,29,11,0,0,0,0],
[0,4,4,4,18,65,54,18,4,7,14,11,0],
[4,22,36,14,4,14,11,7,7,29,79,47,7],
[7,54,76,36,18,14,11,36,40,32,72,36,4],
[4,11,18,18,61,79,36,54,97,40,14,7,0],
[0,0,0,11,58,101,40,47,108,50,7,0,0],
[0,0,0,4,11,25,7,11,22,11,0,0,0],
[0,0,0,0,0,4,0,0,0,0,0,0,0],
],[
[0,0,4,7,4,0,0,0,0,0,0,0,0],
[0,0,11,22,14,4,0,4,0,0,0,0,0],
[0,0,7,18,14,4,4,14,18,4,0,0,0],
[0,4,0,4,4,0,4,32,54,18,0,0,0],
[4,11,7,4,7,7,18,29,22,4,0,0,0],
[7,18,7,22,40,25,50,76,25,4,0,0,0],
[0,4,4,22,61,32,25,54,18,0,0,0,0],
[0,0,0,4,11,7,4,11,4,0,0,0,0],
],[
[0,0,0,0,7,14,11,4,0,0,0,0,0],
[0,0,0,4,18,43,50,32,14,4,0,0,0],
[0,4,11,4,7,29,61,65,43,11,0,0,0],
[4,18,54,25,7,11,32,40,25,7,11,4,0],
[4,36,86,40,11,7,7,7,7,25,58,25,4],
[0,7,18,25,65,40,18,25,22,22,47,18,0],
[0,0,4,32,79,47,43,86,54,11,7,4,0],
[0,0,0,14,32,14,25,61,40,7,0,0,0],
[0,0,0,0,4,4,4,11,7,0,0,0,0],
],[
[0,0,0,0,4,7,11,4,0,0,0,0,0],
[0,4,4,0,4,11,18,11,0,0,0,0,0],
[4,11,11,4,0,4,4,4,0,0,0,0,0],
[4,18,14,7,4,0,0,4,7,7,0,0,0],
[0,7,18,29,14,11,11,7,18,18,4,0,0],
[0,11,43,50,29,43,40,11,4,4,0,0,0],
[0,4,18,25,22,54,40,7,0,0,0,0,0],
[0,0,4,4,4,11,7,0,0,0,0,0,0],
],[
[0,0,0,0,0,7,7,7,7,0,0,0,0],
[0,0,0,0,7,32,32,18,4,0,0,0,0],
[0,0,0,0,11,54,40,14,4,4,22,11,0],
[0,7,14,11,4,14,11,4,4,25,94,50,7],
[4,25,65,43,11,7,4,7,22,25,54,36,7],
[0,7,25,22,29,58,32,25,72,61,14,7,0],
[0,0,4,4,40,115,68,29,83,72,11,0,0],
[0,0,0,0,11,29,18,7,18,14,4,0,0],
[0,0,0,0,0,4,0,0,0,0,0,0,0],
]
];
</script>
</head>
<body>
    <script type="text/javascript+protovis">    
    for (var a=0; a < heatmap.length; a++) {
    var w = heatmap[a][0].length,
    h = heatmap[a].length;
var vis = new pv.Panel()
    .width(w * 6)
    .height(h * 6)
    .strokeStyle("#aaa")
    .lineWidth(4)
    .antialias(true);
vis.add(pv.Image)
    .imageWidth(w)
    .imageHeight(h)
    .image(pv.Scale.linear()
        .domain(0, 99, 100)
        .range("#000", "#fff", '#ff0a0a')
        .by(function(i, j) heatmap[a][j][i]));
vis.render();
}
</script>
  </body>
</html>


भौतिक विज्ञानी का समाधान:
अपने पद X_i द्वारा पहचाने गए 5 पंजा-मार्करों को परिभाषित करें और यादृच्छिक स्थितियों के साथ X_i करें। मार्करों के ओवरलैप के लिए कुछ सजा के साथ पंजा के पदों में मार्करों के स्थान के लिए कुछ पुरस्कारों को संयोजित करने वाले कुछ ऊर्जा कार्यों को परिभाषित करें; हम कहते हैं:

E(X_i;S)=-Sum_i(S(X_i))+alfa*Sum_ij (|X_i-Xj|<=2*sqrt(2)?1:0)

( S(X_i) आसपास 2x2 वर्ग में औसत बल है, alfa प्रयोगात्मक रूप से X_i वाला पैरामीटर है)

अब कुछ मेट्रोपोलिस-हेस्टिंग्स जादू करने का समय:
1. यादृच्छिक मार्कर का चयन करें और इसे एक पिक्सेल द्वारा यादृच्छिक दिशा में ले जाएं।
2. डीई की गणना करें, इस कदम के कारण ऊर्जा का अंतर।
3. 0-1 से एक समान यादृच्छिक संख्या प्राप्त करें और इसे आर कहते हैं।
4. यदि dE<0 या exp(-beta*dE)>r , चाल को स्वीकार करें और 1 पर जाएं; यदि नहीं, तो चाल को पूर्ववत करें और 1 पर जाएं।
यह तब तक दोहराया जाना चाहिए जब तक मार्कर पंजे तक नहीं पहुंच जाएंगे। बीटा ट्रेडऑफ को अनुकूलित करने के लिए स्कैनिंग को नियंत्रित करता है, इसलिए इसे प्रयोगात्मक रूप से भी अनुकूलित किया जाना चाहिए; यह सिमुलेशन (अनुरूपित एनीलिंग) के समय भी लगातार बढ़ाया जा सकता है।


भौतिकविदों द्वारा कुछ गहराई में इस समस्या का अध्ययन किया गया है। ROOT में एक अच्छा कार्यान्वयन है। TSpectrum कक्षाओं (विशेष रूप से आपके मामले के लिए TSpectrum2 2) और उनके लिए प्रलेखन देखें।

संदर्भ:

  1. एम। मोरहाक एट अल .: बहुआयामी संयोग गामा-रे स्पेक्ट्रा के लिए पृष्ठभूमि उन्मूलन विधियां। भौतिकी अनुसंधान परमाणु उपकरण और तरीके ए 401 (1 99 7) 113-132।
  2. एम। मोरहाक एट अल .: कुशल एक- और द्वि-आयामी गोल्ड deconvolution और इसके आवेदन गामा-रे स्पेक्ट्रा अपघटन के लिए। भौतिकी अनुसंधान परमाणु उपकरण और तरीके ए 401 (1 99 7) 385-408।
  3. एम। मोरहाक एट अल .: बहुआयामी संयोग गामा-रे स्पेक्ट्रा में चोटियों की पहचान। अनुसंधान भौतिकी में परमाणु उपकरण और तरीके ए 443 (2000), 108-125।

... और उन लोगों के लिए जिनके पास एनआईएम की सदस्यता तक पहुंच नहीं है:


मेरे सिर के शीर्ष से बस कुछ विचार:

  • स्कैन के ढाल (व्युत्पन्न) को लें, देखें कि क्या यह झूठी कॉल को समाप्त करता है
  • स्थानीय अधिकतम अधिकतम ले लो

आप ओपनसीवी पर भी एक नज़र डालना चाहते हैं, इसे काफी सभ्य पायथन एपीआई मिला है और इसमें कुछ ऐसे फ़ंक्शन हो सकते हैं जो आपको उपयोगी लगे।


मैंने स्थानीय अधिकतम फ़िल्टर का उपयोग करके चोटियों का पता लगाया। 4 पंजा के आपके पहले डेटासेट पर परिणाम यहां दिया गया है:

मैंने इसे 9 पंजा के दूसरे डेटासेट पर भी चलाया और यह भी काम किया

इसे कैसे करना है इसके बारे में यहां बताया गया है:

import numpy as np
from scipy.ndimage.filters import maximum_filter
from scipy.ndimage.morphology import generate_binary_structure, binary_erosion
import matplotlib.pyplot as pp

#for some reason I had to reshape. Numpy ignored the shape header.
paws_data = np.loadtxt("paws.txt").reshape(4,11,14)

#getting a list of images
paws = [p.squeeze() for p in np.vsplit(paws_data,4)]


def detect_peaks(image):
    """
    Takes an image and detect the peaks usingthe local maximum filter.
    Returns a boolean mask of the peaks (i.e. 1 when
    the pixel's value is the neighborhood maximum, 0 otherwise)
    """

    # define an 8-connected neighborhood
    neighborhood = generate_binary_structure(2,2)

    #apply the local maximum filter; all pixel of maximal value 
    #in their neighborhood are set to 1
    local_max = maximum_filter(image, footprint=neighborhood)==image
    #local_max is a mask that contains the peaks we are 
    #looking for, but also the background.
    #In order to isolate the peaks we must remove the background from the mask.

    #we create the mask of the background
    background = (image==0)

    #a little technicality: we must erode the background in order to 
    #successfully subtract it form local_max, otherwise a line will 
    #appear along the background border (artifact of the local maximum filter)
    eroded_background = binary_erosion(background, structure=neighborhood, border_value=1)

    #we obtain the final mask, containing only peaks, 
    #by removing the background from the local_max mask (xor operation)
    detected_peaks = local_max ^ eroded_background

    return detected_peaks


#applying the detection and plotting results
for i, paw in enumerate(paws):
    detected_peaks = detect_peaks(paw)
    pp.subplot(4,2,(2*i+1))
    pp.imshow(paw)
    pp.subplot(4,2,(2*i+2) )
    pp.imshow(detected_peaks)

pp.show()

सभी को अलग-अलग ऑब्जेक्ट्स लेबल करने के लिए मास्क पर scipy.ndimage.measurements.label का उपयोग करने के बाद आपको बस इतना करना है। फिर आप व्यक्तिगत रूप से उनके साथ खेल सकेंगे।

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


यह एक छवि पंजीकरण समस्या है । सामान्य रणनीति है:

  • एक ज्ञात उदाहरण है, या डेटा पर किसी तरह का पूर्व है
  • उदाहरण के लिए अपने डेटा फिट करें, या अपने डेटा के उदाहरण फिट करें।
  • यह आपकी मदद करता है यदि आपका डेटा मोटे तौर पर पहले स्थान पर गठबंधन किया गया है।

यहां एक मोटा और तैयार दृष्टिकोण है , "सबसे कमजोर चीज जो संभवतः काम कर सकती है":

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

अभिविन्यास की समस्या का सामना करने के लिए, आपके पास मूल दिशाओं (उत्तर, उत्तर पूर्व, आदि) के लिए 8 या तो प्रारंभिक सेटिंग्स हो सकती हैं। प्रत्येक व्यक्ति को व्यक्तिगत रूप से चलाएं और किसी भी परिणाम को फेंक दें जहां दो या दो से अधिक पैर एक ही पिक्सेल पर समाप्त होते हैं। मैं इसके बारे में कुछ और सोचूंगा, लेकिन इस तरह की चीज अभी भी छवि प्रसंस्करण में शोध की जा रही है - कोई सही जवाब नहीं है!

थोड़ा अधिक जटिल विचार: (भारित) के-मतलब क्लस्टरिंग। इतना खराब नहीं है।

  • पांच पैर की अंगुली निर्देशांक के साथ शुरू करें, लेकिन अब ये "क्लस्टर सेंटर" हैं।

फिर अभिसरण तक फिर से शुरू करें:

  • प्रत्येक पिक्सेल को निकटतम क्लस्टर पर असाइन करें (केवल प्रत्येक क्लस्टर के लिए एक सूची बनाएं)।
  • प्रत्येक क्लस्टर के द्रव्यमान के केंद्र की गणना करें। प्रत्येक क्लस्टर के लिए, यह है: योग (समन्वय * तीव्रता मान) / योग (समन्वय)
  • प्रत्येक क्लस्टर को द्रव्यमान के नए केंद्र में ले जाएं।

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

(फिर से, आपने क्लस्टर को आगे की संख्या निर्दिष्ट कर दी है। क्लस्टरिंग के साथ आपको घनत्व को एक या दूसरे तरीके से निर्दिष्ट करना होगा: या तो क्लस्टर की संख्या चुनें, इस मामले में उपयुक्त है, या क्लस्टर त्रिज्या चुनें और देखें कि आप कितने अंत हैं साथ में। उत्तरार्द्ध का एक उदाहरण mean-shift ।)

कार्यान्वयन विवरण या अन्य विनिर्देशों की कमी के बारे में खेद है। मैं इसे कोड दूंगा लेकिन मुझे समय सीमा मिली है। अगर अगले हफ्ते कुछ भी काम नहीं करता है तो मुझे बताएं और मैं इसे एक शॉट दूंगा।


यहां एक विचार है: आप छवि के (असतत) Laplacian की गणना। मैं उम्मीद करता हूं कि यह अधिकतम (नकारात्मक और) अधिकतम में अधिकतम होगा, जो कि मूल छवियों की तुलना में अधिक नाटकीय है। इस प्रकार, अधिकतमता को ढूंढना आसान हो सकता है।

यहां एक और विचार है: यदि आप उच्च दबाव वाले स्पॉट के सामान्य आकार को जानते हैं, तो आप इसे अपनी छवि को उसी आकार के गॉसियन के साथ घूमकर पहली बार चिकनी बना सकते हैं। यह आपको प्रक्रिया करने के लिए सरल छवियां दे सकता है।


I am not sure this answers the question, but it seems like you can just look for the n highest peaks that don't have neighbors.

Here is the gist. Note that it's in Ruby, but the idea should be clear.

require 'pp'

NUM_PEAKS = 5
NEIGHBOR_DISTANCE = 1

data = [[1,2,3,4,5],
        [2,6,4,4,6],
        [3,6,7,4,3],
       ]

def tuples(matrix)
  tuples = []
  matrix.each_with_index { |row, ri|
    row.each_with_index { |value, ci|
      tuples << [value, ri, ci]
    }
  }
  tuples
end

def neighbor?(t1, t2, distance = 1)
  [1,2].each { |axis|
    return false if (t1[axis] - t2[axis]).abs > distance
  }
  true
end

# convert the matrix into a sorted list of tuples (value, row, col), highest peaks first
sorted = tuples(data).sort_by { |tuple| tuple.first }.reverse

# the list of peaks that don't have neighbors
non_neighboring_peaks = []

sorted.each { |candidate|
  # always take the highest peak
  if non_neighboring_peaks.empty?
    non_neighboring_peaks << candidate
    puts "took the first peak: #{candidate}"
  else
    # check that this candidate doesn't have any accepted neighbors
    is_ok = true
    non_neighboring_peaks.each { |accepted|
      if neighbor?(candidate, accepted, NEIGHBOR_DISTANCE)
        is_ok = false
        break
      end
    }
    if is_ok
      non_neighboring_peaks << candidate
      puts "took #{candidate}"
    else
      puts "denied #{candidate}"
    end
  end
}

pp non_neighboring_peaks

Interesting problem. The solution I would try is the following.

  1. Apply a low pass filter, such as convolution with a 2D gaussian mask. This will give you a bunch of (probably, but not necessarily floating point) values.

  2. Perform a 2D non-maximal suppression using the known approximate radius of each paw pad (or toe).

This should give you the maximal positions without having multiple candidates which are close together. Just to clarify, the radius of the mask in step 1 should also be similar to the radius used in step 2. This radius could be selectable, or the vet could explicitly measure it beforehand (it will vary with age/breed/etc).

Some of the solutions suggested (mean shift, neural nets, and so on) probably will work to some degree, but are overly complicated and probably not ideal.


Maybe a naive approach is sufficient here: Build a list of all 2x2 squares on your plane, order them by their sum (in descending order).

First, select the highest-valued square into your "paw list". Then, iteratively pick 4 of the next-best squares that don't intersect with any of the previously found squares.


What if you proceed step by step: you first locate the global maximum, process if needed the surrounding points given their value, then set the found region to zero, and repeat for the next one.





image-processing