2013-08-25 5 views
6

मैं एक स्लाइडिंग विंडो ऑपरेशन को सदिश बनाने की कोशिश कर रहा हूं। 1-डी मामले के लिए एक उपयोगी उदाहरण की तर्ज पर जा सकते हैं:पायथन - एक स्लाइडिंग विंडो वेक्टरिंग

x[1,:]=np.where((x[0,:]<2)&(x[0,:]>0),x[1,x[0,:]+1],x[1,:]) 
IndexError: index (10) out of range (0<=index<9) in dimension 1 

:

x= vstack((np.array([range(10)]),np.array([range(10)]))) 

x[1,:]=np.where((x[0,:]<5)&(x[0,:]>0),x[1,x[0,:]+1],x[1,:]) 

n + 1 सूचकांक < 5. के लिए प्रत्येक वर्तमान मूल्य के लिए मूल्य लेकिन मैं इस त्रुटि मिलती है

x[1,:]=np.where((x[0,:]<5)&(x[0,:]>0),x[1,x[0,:]-1],x[1,:]) 

print(x) 

[[0 1 2 3 4 5 6 7 8 9] 
[0 0 1 2 3 5 6 7 8 9]] 

इस के आसपास वैसे भी वहाँ है: मजे की बात है मैं n-1 मूल्य जो 0. की तुलना में छोटे सूचकांकों का मतलब होगा के लिए इस त्रुटि यह मन नहीं लगता नहीं मिलेगा? क्या मेरा दृष्टिकोण पूरी तरह से गलत है? किसी भी टिप्पणी की सराहना की जाएगी।

संपादित करें:

matriz = np.array([[1,2,3,4,5], 
    [6,5,4,3,2], 
    [1,1,2,2,3], 
    [3,3,2,2,1], 
    [3,2,1,3,2], 
    [1,2,3,1,2]]) 

# matrix to vector 
vector2 = ndarray.flatten(matriz) 

ncols = int(shape(matriz)[1]) 
nrows = int(shape(matriz)[0]) 

vector = np.zeros(nrows*ncols,dtype='float64') 


# Interior pixels 
if ((i % ncols) != 0 and (i+1) % ncols != 0 and i>ncols and i<ncols*(nrows-1)): 

    vector[i] = np.mean(np.array([vector2[i-ncols-1],vector2[i-ncols],vector2[i-ncols+1],vector2[i-1],vector2[i+1],vector2[i+ncols-1],vector2[i+ncols],vector2[i+ncols+1]])) 
:

यह मैं प्राप्त करने के लिए, मैं एक numpy सरणी के लिए एक मैट्रिक्स है जिस पर मैं प्रत्येक कोशिका के 6x6 पड़ोस की संकरी गणना करना चाहते समतल चाहते हैं क्या है

+0

स्पष्टीकरण के लिए आप 'vector2 [i] 'मतलब में शामिल नहीं करना चाहते हैं या यह कोड में एक गलती थी? – Daniel

+0

मैं नहीं करता हूं। धन्यवाद। – JEquihua

+0

आपका कोड प्रत्येक सेल के 3x3 पड़ोस के औसत की गणना करता है, न कि 6x6 पड़ोस; क्या यह जानबूझकर था? – nneonneo

उत्तर

8

यदि मैं सही ढंग से समस्या को समझता हूं तो आप इंडेक्स के चारों ओर सभी नंबरों का मतलब लेना चाहते हैं, सूचकांक की उपेक्षा करते हैं।

मैं काम करने के लिए अपने समारोह समझौता किया है, मेरा मानना ​​है कि आप कुछ इस तरह के लिए जा रहे थे:

def mean_around(arr): 
    arr=arr.astype(np.float64) 

    out= np.copy(arr[:-2,:-2]) #Top left corner 
    out+= arr[:-2,2:]   #Top right corner 
    out+= arr[:-2,1:-1]   #Top center 
    out+= arr[2:,:-2]   #etc 
    out+= arr[2:,2:] 
    out+= arr[2:,1:-1] 
    out+= arr[1:-1,2:] 
    out+= arr[1:-1,:-2] 

    out/=8.0 #Divide by # of elements to obtain mean 

    cout=np.empty_like(arr) #Create output array 
    cout[1:-1,1:-1]=out  #Fill with out values 
    cout[0,:]=0;cout[-1,:]=0;cout[:,0]=0;cout[:,-1]=0 #Set edges equal to zero 

    return cout 

np.empty_like का उपयोग करते हुए और फिर भरने:

def original(matriz): 

    vector2 = np.ndarray.flatten(matriz) 

    nrows, ncols= matriz.shape 
    vector = np.zeros(nrows*ncols,dtype='float64') 

    # Interior pixels 
    for i in range(vector.shape[0]): 
     if ((i % ncols) != 0 and (i+1) % ncols != 0 and i>ncols and i<ncols*(nrows-1)): 

      vector[i] = np.mean(np.array([vector2[i-ncols-1],vector2[i-ncols],\ 
         vector2[i-ncols+1],vector2[i-1],vector2[i+1],\ 
         vector2[i+ncols-1],vector2[i+ncols],vector2[i+ncols+1]])) 

मैं इस टुकड़ा करने की क्रिया और विचारों का उपयोग का उपयोग कर दुबारा लिखा किनारों को थोड़ा तेज लग रहा था तो np.zeros_like। सबसे पहले दोहरी जांच करें कि वे आपके matriz सरणी का उपयोग करके वही चीज़ देते हैं।

print np.allclose(mean_around(matriz),original(matriz)) 
True 

print mean_around(matriz) 
[[ 0.  0.  0.  0.  0. ] 
[ 0.  2.5 2.75 3.125 0. ] 
[ 0.  3.25 2.75 2.375 0. ] 
[ 0.  1.875 2.  2.  0. ] 
[ 0.  2.25 2.25 1.75 0. ] 
[ 0.  0.  0.  0.  0. ]] 

कुछ समय:

a=np.random.rand(500,500) 

print np.allclose(original(a),mean_around(a)) 
True 

%timeit mean_around(a) 
100 loops, best of 3: 4.4 ms per loop 

%timeit original(a) 
1 loops, best of 3: 6.6 s per loop 

मोटे तौर पर ~ 1500x speedup।

def mean_numba(arr): 
    out=np.zeros_like(arr) 
    col,rows=arr.shape 

    for x in xrange(1,col-1): 
     for y in xrange(1,rows-1): 
      out[x,y]=(arr[x-1,y+1]+arr[x-1,y]+arr[x-1,y-1]+arr[x,y+1]+\ 
         arr[x,y-1]+arr[x+1,y+1]+arr[x+1,y]+arr[x+1,y-1])/8. 
    return out 

nmean= autojit(mean_numba) 

अब सभी प्रस्तुत तरीकों के खिलाफ तुलना करने देता है: एक अच्छी जगह Numba उपयोग करने के लिए की तरह

लग रहा है।

a=np.random.rand(5000,5000) 

%timeit mean_around(a) 
1 loops, best of 3: 729 ms per loop 

%timeit nmean(a) 
10 loops, best of 3: 169 ms per loop 

#CT Zhu's answer 
%timeit it_mean(a) 
1 loops, best of 3: 36.7 s per loop 

#Ali_m's answer 
%timeit fast_local_mean(a,(3,3)) 
1 loops, best of 3: 4.7 s per loop 

#lmjohns3's answer 
%timeit scipy_conv(a) 
1 loops, best of 3: 3.72 s per loop 

Numba अप के साथ एक 4x गति का संकेत है कि numpy कोड के बारे में के रूप में अच्छा है अपनी होने वाली के रूप में बहुत नाममात्र है। मैंने प्रस्तुत किए गए अन्य कोड खींच लिया, हालांकि मुझे अलग-अलग सरणी आकारों को शामिल करने के लिए @ सीटीज़ू के जवाब को बदलना पड़ा।

+1

अच्छा। यह मेरे संस्करण की तुलना में 'n = 3' के दो कारकों से तेज़ है, हालांकि यह उस विशिष्ट मामले के लिए अत्यधिक ट्यून किया गया है;)। – nneonneo

+0

मुझे यह बहुत पसंद है। मैं अभी छुट्टी पर हूं लेकिन मैं इसे अपनी विशेष समस्या पर आज़माउंगा और आपको वापस आऊंगा। मैं इसे 5000 * 5000 मैट्रिक्स के लिए उपयोग करना चाहता हूं और देख सकता हूं कि यह कैसा करता है। – JEquihua

+1

@nneonneo 'uniform_filter' वास्तव में उत्तर था जिसका मैंने इस पोस्ट के पहले पुनरावृत्ति में उपयोग किया था, मुझे खुशी है कि आपने इसे कुछ प्रश्न पहले अपने बेहद शक्तिशाली और अविश्वसनीय रूप से तेज़ी से लाया था। – Daniel

2

समस्या x[1,x[0,:]+1] में है, दूसरी अक्ष के लिए सूचकांक: x[0,:]+1[1 2 3 4 5 6 7 8 9 10] है, जिसमें सूचकांक 10 x के आयाम से बड़ा है।

x[1,x[0,:]-1] के मामले में, 2 अक्ष के सूचकांक [-1 0 1 2 3 4 5 6 7 8 9] है, तो आप [9 0 1 2 3 4 5 6 7 8] हो रही अंत, के रूप में 9 पिछले तत्व है और -1 का एक सूचकांक है। अंत से दूसरे तत्व की अनुक्रमणिका -2 है और इसी तरह।

np.where((x[0,:]<5)&(x[0,:]>0),x[1,x[0,:]-1],x[1,:]) और x[0,:]=[0 1 2 3 4 5 6 7 8 9] साथ

, क्या अनिवार्य रूप से चल रहा है कि पहले सेल प्रपत्र x[1,:] लिया जाता है क्योंकि x[0,0] 0 और x[0,:]<5)&(x[0,:]>0False है। अगले चार तत्व x[1,x[0,:]-1] से लिया गया है। शेष x[1,:] से हैं। अंत में परिणाम है [0 0 1 2 3 4 5 6 7 8]

यह सिर्फ 1 सेल की रपट खिड़की के लिए ठीक प्रतीत हो सकता है, लेकिन इसके साथ आश्चर्य करने वाले तुम हो:

>>> np.where((x[0,:]<5)&(x[0,:]>0),x[1,x[0,:]-2],x[1,:]) 
array([0, 9, 0, 1, 2, 5, 6, 7, 8, 9]) 

आप दो कोशिकाओं के एक खिड़कियों से इसे स्थानांतरित करने का प्रयास करते हैं ।

इस विशिष्ट समस्या के लिए, यदि हम एक पंक्ति में हर चीज रखना चाहते हैं, इस, क्या करेंगे:

>>> for i in [1, 2, 3, 4, 5, 6]: 
    print hstack((np.where(x[1,x[0,:]-i]<x[0, -i], x[1,x[0,:]-i], 0)[:5], x[0,5:])) 

[0 0 1 2 3 5 6 7 8 9] 
[0 0 0 1 2 5 6 7 8 9] 
[0 0 0 0 1 5 6 7 8 9] 
[0 0 0 0 0 5 6 7 8 9] 
[0 0 0 0 0 5 6 7 8 9] 
[0 0 0 0 0 5 6 7 8 9] 

संपादित करें: अब मैं अपने मूल प्रश्न को बेहतर समझते हैं, मूल रूप से आप एक 2D ले जाना चाहते हैं सरणी और प्रत्येक सेल के चारों ओर एन * एन सेल औसत की गणना करें। यह काफी आम है। सबसे पहले आप संभवतः एन को विषम संख्याओं तक सीमित करना चाहते हैं, अन्यथा सेल के चारों ओर 2 * 2 औसत जैसी चीज को परिभाषित करना मुश्किल है। मान लीजिए हम चाहते हैं 3 * 3 औसत:

#In this example, the shape is (10,10) 
>>> a1=\ 
array([[3, 7, 0, 9, 0, 8, 1, 4, 3, 3], 
    [5, 6, 5, 2, 9, 2, 3, 5, 2, 9], 
    [0, 9, 8, 5, 3, 1, 8, 1, 9, 4], 
    [7, 4, 0, 0, 9, 3, 3, 3, 5, 4], 
    [3, 1, 2, 4, 8, 8, 2, 1, 9, 6], 
    [0, 0, 3, 9, 3, 0, 9, 1, 3, 3], 
    [1, 2, 7, 4, 6, 6, 2, 6, 2, 1], 
    [3, 9, 8, 5, 0, 3, 1, 4, 0, 5], 
    [0, 3, 1, 4, 9, 9, 7, 5, 4, 5], 
    [4, 3, 8, 7, 8, 6, 8, 1, 1, 8]]) 
#move your original array 'a1' around, use range(-2,2) for 5*5 average and so on 
>>> movea1=[a1[np.clip(np.arange(10)+i, 0, 9)][:,np.clip(np.arange(10)+j, 0, 9)] for i, j in itertools.product(*[range(-1,2),]*2)] 
#then just take the average 
>>> averagea1=np.mean(np.array(movea1), axis=0) 
#trim the result array, because the cells among the edges do not have 3*3 average 
>>> averagea1[1:10-1, 1:10-1] 
array([[ 4.77777778, 5.66666667, 4.55555556, 4.33333333, 3.88888889, 
    3.66666667, 4.  , 4.44444444], 
    [ 4.88888889, 4.33333333, 4.55555556, 3.77777778, 4.55555556, 
    3.22222222, 4.33333333, 4.66666667], 
    [ 3.77777778, 3.66666667, 4.33333333, 4.55555556, 5.  , 
    3.33333333, 4.55555556, 4.66666667], 
    [ 2.22222222, 2.55555556, 4.22222222, 4.88888889, 5.  , 
    3.33333333, 4.  , 3.88888889], 
    [ 2.11111111, 3.55555556, 5.11111111, 5.33333333, 4.88888889, 
    3.88888889, 3.88888889, 3.55555556], 
    [ 3.66666667, 5.22222222, 5.  , 4.  , 3.33333333, 
    3.55555556, 3.11111111, 2.77777778], 
    [ 3.77777778, 4.77777778, 4.88888889, 5.11111111, 4.77777778, 
    4.77777778, 3.44444444, 3.55555556], 
    [ 4.33333333, 5.33333333, 5.55555556, 5.66666667, 5.66666667, 
    4.88888889, 3.44444444, 3.66666667]]) 

मुझे लगता है कि आप आप 2 डी सरणी, कि भ्रम का कारण बनता समतल की जरूरत नहीं है। साथ ही, यदि आप किनारे के तत्वों को अलग-अलग ट्रिम करने के अलावा अलग-अलग हिस्सों को संभालना चाहते हैं, तो 'अपने मूल सरणी को चारों ओर ले जाएं' में np.ma का उपयोग करके मास्क किए गए सरणी बनाने पर विचार करें।

+0

यह दूसरी तरफ क्यों काम नहीं करता है, 10 फिर से पहला तत्व है? या मैं तब क्या कर सकता हूं जो मैं चाहता हूं? – JEquihua

+0

ओह, मैटलैब के विपरीत, पायथन की अनुक्रमणिका 0 से शुरू होती है। इसलिए यदि आप सकारात्मक 'int' का उपयोग करते हैं, तो लंबाई 10 के वेक्टर के लिए अधिकतम अनुक्रमणिका 9 है और यदि आप x [10] को आज़माते हैं तो आपको' indexError' मिलता है। 'X = [0 1 2 3 4 5 6 7 8 9]' के लिए, 9 प्राप्त करने के लिए, या तो 'x [-1] 'या' x [9] 'करेगा, लेकिन' x [10] 'will नहीं। –

+0

मैं यह दिखाने के लिए अपने प्रश्न को संपादित करने जा रहा हूं कि मैं वास्तव में क्या हासिल करना चाहता हूं। मैं अभी एक लंबा सवाल नहीं चाहता था लेकिन यहां जाता है। जैसा कि मुझे लगता है कि आप मुझे थोड़ा गलत समझ रहे हैं। – JEquihua

4

ऐसा लगता है कि आप एक 2 डी घुमाव की गणना करने के प्रयास कर रहे हैं। आप scipy उपयोग करने के लिए सक्षम हैं, तो मैं scipy.signal.convolve2d आजमाने का सुझाव देते हैं:

matriz = np.random.randn(10, 10) 

# to average a 3x3 neighborhood 
kernel = np.ones((3, 3), float) 

# to compute the mean, divide by size of neighborhood 
kernel /= kernel.sum() 

average = scipy.signal.convolve2d(matriz, kernel) 

कारण यह सब 3x3 पड़ोस के मतलब की गणना करता देखा जा सकता है अगर आप अपने घटक छोरों में convolve2d "उतारना"। प्रभावी ढंग से (और अनदेखी क्या स्रोत और गिरी सरणियों के किनारों पर होता है), यह है कंप्यूटिंग:

X, Y = kernel.shape 
for i in range(matriz.shape[0]): 
    for j in range(matriz.shape[1]): 
     for ii in range(X): 
      for jj in range(Y): 
       average[i, j] += kernel[ii, jj] * matriz[i+ii, j+jj] 

इसलिए यदि आपके कर्नेल में प्रत्येक मान है 1/(1 + 1 + 1 + 1 + 1 + 1

for i in range(matriz.shape[0]): 
    for j in range(matriz.shape[1]): 
     average[i, j] = 1./9 * matriz[i:i+X, j:j+Y].sum() 

बिल्कुल Matriz में मूल्यों के औसत की गणना एक 3x3 क्षेत्र में, पर शुरू करने के समान है कौन सा: + 1 + 1 + 1) == 1/9, आप कोड के ऊपर के रूप में फिर से लिखने कर सकते हैं i, j

इस तरह से काम करने का एक फायदा यह है कि आप आसानी से अपने कर्नेल में मूल्यों को सेट करके अपने पड़ोस से जुड़े वजन को आसानी से बदल सकते हैं। तो, उदाहरण के लिए, यदि आप दूसरों के रूप में ज्यादा वजन के रूप में दो बार प्रत्येक पड़ोस में केंद्र मूल्य देना चाहता था, तो आप अपने कर्नेल इस तरह बना सकते हैं:

kernel = np.ones((3, 3), float) 
kernel[1, 1] = 2. 
kernel /= kernel.sum() 

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

3

बस इतना ही ऐसा लगता है कि सिसिसी मानक लाइब्रेरी में एक फ़ंक्शन होता है जो स्लाइडिंग विंडो पर बहुत तेजी से गणना करता है। इसे uniform_filter कहा जाता है। आप इस प्रकार अपने मतलब के-पड़ोस समारोह को लागू करने के लिए इसका इस्तेमाल कर सकते हैं:

from scipy.ndimage.filters import uniform_filter 
def neighbourhood_average(arr, win=3): 
    sums = uniform_filter(arr, win, mode='constant') * (win*win) 
    return ((sums - arr)/(win*win - 1)) 

यह एक सरणी X जहां X[i,j]arr में i,j के सभी पड़ोसियों की औसत i,j ही छोड़कर वापस आती है। ध्यान दें कि पहला और अंतिम कॉलम और पहली और आखिरी पंक्ति सीमा स्थितियों के अधीन हैं, और इसलिए आपके आवेदन के लिए अमान्य हो सकता है (यदि आवश्यक हो तो सीमा नियम को नियंत्रित करने के लिए आप mode= का उपयोग कर सकते हैं)।

uniform_filter (केवल arr के आकार में रैखिक) एक अत्यधिक कुशल रैखिक समय एल्गोरिथ्म सीधे सी में लागू उपयोग करता है, यह आसानी से किसी भी अन्य समाधान मात चाहिए, खासकर जब win बड़ी है।

+0

बहुत दिलचस्प है।सीमाएं किस स्थितियों के अधीन हैं? मुझे लगता है कि मुझे सामान्य परिस्थितियां चाहिए लेकिन मैंने इसे अपने प्रश्न में पोस्ट नहीं किया। यह कैसे छोड़ रहा है (मैं, जे) खुद? क्या आप थोड़ा सा कोड समझाएंगे? – JEquihua

+0

'uniform_filter' डिफ़ॉल्ट रूप से, खिड़की प्रत्येक' (i, j) पर केंद्रित है ', इतना है कि यह उदाहरण के लिए औसत एक 3x3 विंडो '(i-1: i + 2, j-1: j + 2)'। मूल सरणी के बाहर स्थित मानों के लिए, 'uniform_filter' भरने वाले मान का उपयोग करता है जिसे' मोड' द्वारा निर्धारित किया जाता है। यदि आपको अपूर्ण विंडो की परवाह नहीं है, तो आप पहली और आखिरी पंक्ति और पहले और अंतिम कॉलम को हटा या शून्य कर सकते हैं। – nneonneo

+1

इसमें '(i, j)' '- arr' बिट की वजह से शामिल है, जो विंडो मान से मूल मान को हटा देता है। – nneonneo

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