दिलचस्प पोस्ट
क्या SQLite डेटाबेस में एक समय में एकाधिक पंक्तियाँ सम्मिलित करना संभव है? क्या PHP5 ऑब्जेक्ट संदर्भ से पास हैं? आईओएस पर उपकरण बनाने और मॉडल कैसे प्राप्त करें? क्या पीएनजी में एक्सपी डाटा जैसे JPG होते हैं? आप इस सेवा का उपयोग करने के लिए अधिकृत नहीं हैं iTunes ऐप अपलोड त्रुटि मैं एक ऐसी वेबसाइट से PHP सामग्री में वेबसाइट की सामग्री कैसे स्क्रैप कर सकता हूं जिसके लिए कुकी लॉगिन की ज़रूरत है? SurfaceView का स्क्रीनशॉट लें वापस बटन फॉर्म डेटा पुनः सबमिट करें ($ _POST) एसक्यूएल 'की तरह' बनाम '=' प्रदर्शन मुझे ग्रहण एडीटी के पुराने संस्करण कहां मिल सकते हैं I गतिशील एसक्यूएल (पैरामीटर के रूप में तालिका का नाम देना) मुझे सी # में "ब्लॉकों का उपयोग करने" का उपयोग कब करना चाहिए? EL में scriptlet चर का मूल्यांकन कैसे करें? जब तक एक प्रभाव समाप्त होने तक प्रतीक्षा करने के लिए jQuery कैसे प्राप्त करें? एचटीएमएल.पार्टीअल बनाम एचटीएमएल.रेंडरपार्टीअल और एचटीएमएल.एक्शन बनाम एचटीएमएल.रेंडर एक्शन

कुशल चलती औसत फिल्टर के लिए प्रगति का उपयोग करना

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

अभी तक मेरे पास इतना ही है। यह मूल सरणी का एक दृश्य लेता है तो उसे आवश्यक राशि से रोल करता है और औसत की गणना करने के लिए कर्नेल मूल्यों को बताता है। मुझे पता है कि किनारों को सही ढंग से संभाला नहीं है, लेकिन मैं इसके बाद की देखभाल कर सकता हूँ … क्या कोई बेहतर और तेज़ तरीका है? इसका उद्देश्य आकार में 5000×5000 x 16 परतों तक बड़े फ़्लोटिंग बिंदु सरणियों को फ़िल्टर करना है, यह एक कार्य है जो scipy.ndimage.filters.convolve काफी धीमी है।

ध्यान दें कि मैं 8-पड़ोसी कनेक्टिविटी की तलाश कर रहा हूं, जो कि एक 3×3 फ़िल्टर 9 पिक्सल के औसत (8 फोकल पिक्सेल के चारों ओर) लेता है और उस छवि को नई छवि में पिक्सेल को निर्दिष्ट करता है।

 import numpy, scipy filtsize = 3 a = numpy.arange(100).reshape((10,10)) b = numpy.lib.stride_tricks.as_strided(a, shape=(a.size,filtsize), strides=(a.itemsize, a.itemsize)) for i in range(0, filtsize-1): if i > 0: b += numpy.roll(b, -(pow(filtsize,2)+1)*i, 0) filtered = (numpy.sum(b, 1) / pow(filtsize,2)).reshape((a.shape[0],a.shape[1])) scipy.misc.imsave("average.jpg", filtered) 

मैं यह काम कैसे देखता हूं, इस पर स्पष्टीकरण संपादित करें:

वर्तमान कोड:

  1. [[0,1,2], [1,2,3], [2,3,4] …] की तरह सरणी उत्पन्न करने के लिए स्ट्र्रेड_ट्रिक्स का उपयोग करें जो फ़िल्टर कर्नेल की शीर्ष पंक्ति से मेल खाती है।
  2. कर्नेल [[10,11,12], [11,12,13], [13,14,15] … की मध्य पंक्ति प्राप्त करने के लिए ऊर्ध्वाधर अक्ष के साथ रोल करें और इसे उस सरणी में जोड़ें जिसे मैं मिला 1)
  3. कर्नेल [[20,21,22], [21,22,23], [22,23,24] … की निचली पंक्ति को पाने के लिए दोहराएं। इस बिंदु पर, मैं प्रत्येक पंक्ति का योग लेता हूं और फिल्टर में तत्वों की संख्या से इसे विभाजित करता हूं, मुझे प्रत्येक पिक्सेल के लिए औसत (1 पंक्ति और 1 कर्नेल द्वारा स्थानांतरित किया जाता है, और किनारों के आसपास कुछ विषमताओं के साथ) देता है, लेकिन मैं उस पर ध्यान रखना)।

मैं जो उम्मीद कर रहा था वह पूरी सरणी के लिए, 9 मानों या कर्नेल तत्वों की राशि सीधे प्राप्त करने के लिए स्ट्राइड_ट्रिक्स का बेहतर इस्तेमाल होता है, या कोई मुझे मुझे और अधिक कुशल तरीके से समझ सकता है …

वेब के समाधान से एकत्रित समाधान "कुशल चलती औसत फिल्टर के लिए प्रगति का उपयोग करना"

इसके लायक होने के लिए, यहां बताया गया है कि आप इसे "फैंसी" स्ट्रिंग ट्रिक्स का उपयोग कैसे कर सकते हैं। मैं कल इसे पोस्ट करने जा रहा था, लेकिन वास्तविक काम से विचलित हो गया! 🙂

@ पॉल और @ दोनों ने यह करने के कई अन्य तरीकों का उपयोग करके अच्छा क्रियान्वयन किया है। बस पहले प्रश्नों से चीजों को जारी रखने के लिए, मुझे लगा कि मैं एन-आयामी समकक्ष

आप 1 डी सरणियों के लिए काफी scipy.ndimage हराया नहीं जा सकते हैं, हालांकि 1 डी सरणियों के लिए। ( scipy.ndimage.uniform_filter को scipy.ndimage.uniform_filter को हरा देना चाहिए, हालांकि)

इसके अलावा, यदि आप एक बहुआयामी चलती खिड़की पाने की कोशिश कर रहे हैं, तो आप को याद रखना चाहिए कि जब भी आप अनजाने में अपने सरणी की प्रतिलिपि बनाते हैं, तब तक मेमोरी का उपयोग उड़ा जाएगा। जबकि प्रारंभिक "रोलिंग" सरणी आपके मूल सरणी की स्मृति में सिर्फ एक दृश्य है, कोई भी मध्यवर्ती कदम जो सरणी की प्रतिलिपि बनाते हैं, वह प्रतिलिपि बना देगा जो आपके मूल सरणी से बड़ा परिमाण के आदेश है (यानी हम कहते हैं कि आप इसके साथ काम कर रहे हैं एक 100×100 मूल सरणी … इसमें दृश्य (एक फ़िल्टर आकार (3,3) के लिए) 98x98x3x3 होगा लेकिन मूल के समान मेमोरी का उपयोग करें। हालांकि, किसी भी प्रतियां मेमोरी की मात्रा का उपयोग करेंगे जो एक पूर्ण 98x98x3x3 सरणी !! होगा)

असल में, पागल घुमक्कड़ चाल का उपयोग करना जब आप एक ndarray के एक अक्ष पर खिड़की के संचालन को गतिशील करना चाहते हैं, तब के लिए बहुत अच्छा है। यह वास्तव में आसान है कि चलती मानक विचलन जैसी चीजों की गणना करना आदि बहुत कम ऊपरी हिस्से के साथ। जब आप इसे कई अक्षों के साथ करना शुरू करना चाहते हैं, तो यह संभव है, लेकिन आप आम तौर पर अधिक विशेष कार्यों के साथ बेहतर हैं (जैसे कि scipy.ndimage , आदि)

किसी भी दर पर, यह है कि आप इसे कैसे करते हैं:

 import numpy as np def rolling_window_lastaxis(a, window): """Directly taken from Erik Rigtorp's post to numpy-discussion. <http://www.mail-archive.com/numpy-discussion@scipy.org/msg29450.html>""" if window < 1: raise ValueError, "`window` must be at least 1." if window > a.shape[-1]: raise ValueError, "`window` is too long." shape = a.shape[:-1] + (a.shape[-1] - window + 1, window) strides = a.strides + (a.strides[-1],) return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides) def rolling_window(a, window): if not hasattr(window, '__iter__'): return rolling_window_lastaxis(a, window) for i, win in enumerate(window): if win > 1: a = a.swapaxes(i, -1) a = rolling_window_lastaxis(a, win) a = a.swapaxes(-2, i) return a filtsize = (3, 3) a = np.zeros((10,10), dtype=np.float) a[5:7,5] = 1 b = rolling_window(a, filtsize) blurred = b.mean(axis=-1).mean(axis=-1) 

तो हम क्या करते हैं जब हम b = rolling_window(a, filtsize) एक 8x8x3x3 सरणी करते हैं, तो वास्तव में मूल 10×10 सरणी के समान स्मृति में एक दृश्य है। हम जैसे ही आसानी से विभिन्न अक्षों के साथ अलग-अलग फिल्टर आकार का इस्तेमाल कर सकते हैं या केवल एक एन-आयामी सरणी के चयनित अक्षों (यानी filtsize = (0,3,0,3) पर 4-आयामी सरणी पर filtsize = (0,3,0,3) हो सकते हैं, हमें एक 6 आयामी राय)।

फिर हम आखिरी अक्ष को एक मनमाना समारोह को बार-बार लागू कर सकते हैं ताकि लगातार चलती विंडो में चीजों की गणना कर सकें।

हालांकि, क्योंकि हम अस्थायी सरणियों को संग्रहीत कर रहे हैं जो कि प्रत्येक मूल (या std या जो भी) पर हमारी मूल सरणी से बहुत बड़ी हैं, ये सभी स्मृति कुशल नहीं है! यह भी बहुत तेज होने वाला नहीं है, या तो

ndimage लिए समकक्ष बस है:

 blurred = scipy.ndimage.uniform_filter(a, filtsize, output=a) 

यह सीमा की विभिन्न स्थितियों को संभालता है, सरणी की अस्थायी प्रति की आवश्यकता के बिना "धुंधला" जगह में, और बहुत तेज हो। स्ट्रिंग ट्रिक्स एक फ़ंक्शन को एक अक्ष के साथ चलती खिड़की पर लागू करने का एक अच्छा तरीका है, लेकिन ये आमतौर पर कई अक्षों के साथ ऐसा करने का अच्छा तरीका नहीं है ….

बस मेरी $ 0.02, किसी भी दर पर …

मैं इसके लिए कोड लिखने के लिए पर्याप्त परिचित नहीं हूं, लेकिन संकल्प को गति देने के दो सर्वोत्तम तरीके या तो फ़िल्टर को अलग करना है या फूरियर ट्रांसफ़ॉर्म का उपयोग करना है।

पृथक फ़िल्टर : कनवल्शन है ओ (एम * एन), जहां एम और एन छवि और फ़िल्टर में पिक्सल की संख्या क्रमशः हैं। चूंकि 3-बाय-3 कर्नेल के साथ औसत फ़िल्टरिंग पहले 3-बाय-1 कर्नेल के साथ फ़िल्टरिंग के बराबर है और फिर 1-बाय-3 कर्नेल, आप (3+3)/(3*3) = ~ प्राप्त कर सकते हैं दो 1-डी कर्नेल के साथ लगातार कन्फोल्यूशन से 30% की गति में सुधार (यह स्पष्ट रूप से बेहतर होता है क्योंकि कर्नेल बड़ा हो जाता है)। आप निश्चित रूप से अभी भी बहुत सी चालें इस्तेमाल कर सकते हैं।

फूरियर रूपांतरण : conv(A,B) ifft(fft(A)*fft(B)) समतुल्य है, अर्थात सीधी स्थान में एक कैंवल्यूशन फूरियर स्पेस में गुणा हो जाती है, जहां A आपकी छवि है और B आपका फिल्टर है फूरियर रूपांतरण (तत्व-वार) गुणन के बाद से ए और बी समान आकार की आवश्यकता होती है, बी छवि के बहुत केंद्र और हर जगह शून्य पर आपके कर्नेल के size(A) का एक सरणी होता है एक सरणी के केंद्र में 3-बाय-3 कर्नेल को रखने के लिए, आपको पैड A को अजीब आकार में पड़ सकता है। फूरियर ट्रांसफ़ॉर्मेशन के आपके कार्यान्वयन के आधार पर, यह रूपांतरण के मुकाबले बहुत तेजी से हो सकता है (और यदि आप एक ही बार फ़िल्टर करते हैं, तो आप fft(B) को पूर्व-गणना कर सकते हैं, गणना के 30% का समय बचा सकते हैं)।

मुझे यकीन है कि एक चीज तय करने की जरूरत है, आपका दृश्य सरणी b

इसे अनअलोकेटेड स्मृति से कुछ आइटम हैं, इसलिए आप क्रैश पाएँगे

अपने एल्गोरिथ्म के आपके नए विवरण को देखते हुए, फिक्सिंग की आवश्यकता वाली पहली बात यह है कि आप किसी के आवंटन के बाहर आगे बढ़ रहे हैं:

 bshape = (a.size-filtsize+1, filtsize) bstrides = (a.itemsize, a.itemsize) b = numpy.lib.stride_tricks.as_strided(a, shape=bshape, strides=bstrides) 

अद्यतन करें

क्योंकि मैं अभी भी विधि को समझ नहीं रहा हूं और इस समस्या को सुलझाने के लिए सरल तरीके से लगता है, मैं इसे यहां रखूंगा:

 A = numpy.arange(100).reshape((10,10)) shifts = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] B = A[1:-1, 1:-1].copy() for dx,dy in shifts: xstop = -1+dx or None ystop = -1+dy or None B += A[1+dx:xstop, 1+dy:ystop] B /= 9 

… जो सीधा दृष्टिकोण की तरह लगता है एकमात्र अप्रत्यक्ष ऑपरेशन यह है कि उसे केवल एक बार B को आवंटित किया गया है। सभी अतिरिक्त, विभाजन और अनुक्रमण पर ध्यान दिए बिना किया जाना चाहिए। यदि आप 16 बैंड कर रहे हैं, तो अभी भी केवल एक बार आवंटित करने की आवश्यकता है अगर आपका इरादा किसी छवि को सहेजना है। यहां तक ​​कि अगर यह कोई मदद नहीं है, तो यह स्पष्ट हो सकता है कि मैं इस समस्या को क्यों नहीं समझता, या कम से कम दूसरे तरीकों की गति बढ़ाने के लिए बेंचमार्क के रूप में सेवा करता हूं। यह मेरे लैपटॉप पर 2.6 सेकेंड में फ्लोट 64 के 5k x 5k सरणी पर चलता है, जिसमें से 0.5 का निर्माण B

चलो देखते हैं:

यह आपके प्रश्न को स्पष्ट नहीं करता है, लेकिन अब मैं मान रहा हूं कि आप इस प्रकार की औसत औसत में सुधार करना पसंद करेंगे।

 import numpy as np from numpy.lib import stride_tricks as st def mf(A, k_shape= (3, 3)): m= A.shape[0]- 2 n= A.shape[1]- 2 strides= A.strides+ A.strides new_shape= (m, n, k_shape[0], k_shape[1]) A= st.as_strided(A, shape= new_shape, strides= strides) return np.sum(np.sum(A, -1), -1)/ np.prod(k_shape) if __name__ == '__main__': A= np.arange(100).reshape((10, 10)) print mf(A) 

अब, आप किस प्रकार के प्रदर्शन में सुधार की उम्मीद करेंगे?

अद्यतन करें:
सबसे पहले, एक चेतावनी: यह वर्तमान स्थिति में कोड 'कर्नेल' आकृति के अनुसार ठीक से अनुकूल नहीं करता है। हालांकि, यह अभी तक मेरी प्राथमिक चिंता नहीं है (वैसे भी यह विचार पहले से ही ठीक से कैसे अनुकूल है)।

मैंने एक 4 डी ए के नए आकार को एक सहज रूप से चुना है, मेरे लिए यह वास्तव में एक 2 डी 'कर्नेल' केंद्र के बारे में सोचने का मतलब है जो मूल 2 डी ए की प्रत्येक ग्रिड स्थिति में केन्द्रित है।

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

अपडेट 2:
यहां mf का एक थोड़ा संशोधित संस्करण है। जाहिर है, यह पहली बार एक 3D सरणी के लिए नयी आकृति प्रदान करना बेहतर होता है और फिर बस डॉट उत्पाद को संक्षेप में प्रस्तुत करने के बजाय (यह सब इतना फायदा है, कि कर्नेल मनमानापूर्ण हो सकता है)। हालांकि यह अभी भी पॉल की अद्यतन समारोह से 3x धीमी (मेरी मशीन पर) है

 def mf(A): k_shape= (3, 3) k= np.prod(k_shape) m= A.shape[0]- 2 n= A.shape[1]- 2 strides= A.strides* 2 new_shape= (m, n)+ k_shape A= st.as_strided(A, shape= new_shape, strides= strides) w= np.ones(k)/ k return np.dot(A.reshape((m, n, -1)), w)