2012-06-05 11 views
5

画像があります。画像上に3x3スライドウィンドウを見つける

イメージのすべてのピクセルについて3x3ウィンドウ(隣接ピクセル)を取得したいとします。

私はこのPythonコードを持っている:

for x in range(2,r-1,1): 
    for y in range(2,c-1,1): 
     mask5=numpy.array([cv.Get2D(copy_img,x-1,y-1),cv.Get2D(copy_img,x-1,y),cv.Get2D(copy_img,x-1,y+1),cv.Get2D(copy_img,x,y-1),cv.Get2D(copy_img,x,y),cv.Get2D(copy_img,x,y+1),cv.Get2D(copy_img,x+1,y-1),cv.Get2D(copy_img,x+1,y),cv.Get2D(copy_img,x+1,y+1)]) 
     cent=[cv.Get2D(copy_img,x,y)] 

mask5は、3x3のウィンドウです。セントは中央のピクセルです。

これを行うためのより効率的な方法がありますか?つまり、マップ、イテレータを使用して、使用した2つのネストループ以外のものはありますか?

+0

(...)MATLAB関数im2colとして、次のコードを試してみてください?たぶん畳み込みをしたいのですか? 'mask5'で何をしようとしているのか、教えてください。 – fraxel

+0

@fraxel:ウィンドウを取得した後、3x3ウィンドウ内のピクセルを輝度でソートし、このリストの上に別の(1次元の)スライディングウィンドウを作成し、複雑な条件に基づいてこれらの(1-d)スライドは、元の中心ピクセルをそれに従って修正する。 –

+0

あなたは[adaptive threshold](http://opencv.willowgarage.com/documentation/python/imgproc_miscellaneous_image_transformations.html?highlight=adaptivethreshold#AdaptiveThreshold)をやろうとしているようですね。それを見て、あなたが望むことをするかもしれません。 – fraxel

答えて

2

im = np.arange(81).reshape(9,9) 
print np.swapaxes(im.reshape(3,3,3,-1),1,2) 

これはあなたの全体tessalates 3枚の* 3のタイルの配列を与えます表面:

[[[[ 0 1 2] [[ 3 4 5] [[ 6 7 8] 
    [ 9 10 11] [12 13 14] [15 16 17] 
    [18 19 20]] [21 22 23]] [24 25 26]]] 

[[[27 28 29] [[30 31 32] [[33 34 35] 
    [36 37 38] [39 40 41] [42 43 44] 
    [45 46 47]] [48 49 50]] [51 52 53]]] 

[[[54 55 56] [[57 58 59] [[60 61 62] 
    [63 64 65] [66 67 68] [69 70 71] 
    [72 73 74]] [75 76 77]] [78 79 80]]]] 

vstackとの組み合わせを使用することにより、重複我々はこの8さらに回繰り返す必要があるタイルが、「ラッピング」の配列を取得するには。右と下のタイル配列は(あなたがエッジ状態を治療する方法に応じて、またはあなたが望むものであってもなくてもよい)の周りにラップしていることに注意してください:

im = np.vstack((im[1:],im[0])) 
im = np.column_stack((im[:,1:],im[:,0])) 
print np.swapaxes(im.reshape(3,3,3,-1),1,2) 

#Output: 
[[[[10 11 12] [[13 14 15] [[16 17 9] 
    [19 20 21] [22 23 24] [25 26 18] 
    [28 29 30]] [31 32 33]] [34 35 27]]] 

[[[37 38 39] [[40 41 42] [[43 44 36] 
    [46 47 48] [49 50 51] [52 53 45] 
    [55 56 57]] [58 59 60]] [61 62 54]]] 

[[[64 65 66] [[67 68 69] [[70 71 63] 
    [73 74 75] [76 77 78] [79 80 72] 
    [ 1 2 3]] [ 4 5 6]] [ 7 8 0]]]] 

それを使用すると、配列の9セットで羽目この方法を行いますので、それらを一緒に戻ってジップする必要があります。この、およびすべての整形は、(寸法が3で割り切れる配列に対して)、これに一般化:

def new(im): 
    rows,cols = im.shape 
    final = np.zeros((rows, cols, 3, 3)) 
    for x in (0,1,2): 
     for y in (0,1,2): 
      im1 = np.vstack((im[x:],im[:x])) 
      im1 = np.column_stack((im1[:,y:],im1[:,:y])) 
      final[x::3,y::3] = np.swapaxes(im1.reshape(rows/3,3,cols/3,-1),1,2) 
    return final 

が速く、timeitを使用して、すべてのスライス(以下)をループへの約4倍をこのnew機能を比較します300 * 300アレイ用。

def old(im): 
    rows,cols = im.shape 
    s = [] 
    for x in xrange(1,rows): 
     for y in xrange(1,cols): 
      s.append(im[x-1:x+2,y-1:y+2]) 
    return s 
+0

ありがとうございます。残念ながら、MATLAB(im2col関数)では、これをすべて短いコード行に正確に縮小することができました。この関数はPythonで直接同等の機能を持っていますか? –

+0

@VelvetGhost im2colは、[私のような]実装(上記のhttp://stackoverflow.com/a/10900022/709852)または上記の実装(ただし少し磨かれています)をラップする単なる関数です。 MATLAB実装は、魔法のようにコードを削除しません。独自の関数を使用することができれば、高価なツールボックスに頼らずに作業することができます(MATLABの喜びなど)。また、ツールボックス内にあるため、速くて効率的だとは思わないでください。 –

+0

@HenryGomersall:ありがとう!はい、私はMATLABが魔法のようにコードを削除しないことを知っています。デッドラインの下でコードを書くときに、もっと簡単かつ迅速に見つかりました。あなたのPythonの実装にはありがとうございます。私はちょっとした時間があれば、Pythonについてもっと学ぶのに役立ちます。 –

1

私はあなたが何をしているかは次のようだと思います。ループは9つの要素にしかありません。私はそれをベクトル化する方法があると確信していますが、おそらく努力の価値はありません。これは、このように、再形成および軸を交換した後、すべてのカーネル要素をオーバー繰り返すことで、より迅速に行うことができます

import numpy 

im = numpy.random.randint(0,50,(5,7)) 

# idx_2d contains the indices of each position in the array 
idx_2d = numpy.mgrid[0:im.shape[0],0:im.shape[1]] 

# We break that into 2 sub arrays 
x_idx = idx_2d[1] 
y_idx = idx_2d[0] 

# The mask is used to ignore the edge values (or indeed any values). 
mask = numpy.ones(im.shape, dtype='bool') 
mask[0, :] = False 
mask[:, 0] = False 
mask[im.shape[0] - 1, :] = False 
mask[:, im.shape[1] - 1] = False 

# We create and fill an array that contains the lookup for every 
# possible 3x3 array. 
idx_array = numpy.zeros((im[mask].size, 3, 3), dtype='int64') 

# Compute the flattened indices for each position in the 3x3 grid 
for n in range(0, 3): 
    for m in range(0, 3): 
     # Compute the flattened indices for each position in the 
     # 3x3 grid 
     idx = (x_idx + (n-1)) + (y_idx + (m-1)) * im.shape[1] 

     # mask it, and write it to the big array 
     idx_array[:, m, n] = idx[mask] 


# sub_images contains every valid 3x3 sub image 
sub_images = im.ravel()[idx_array] 

# Finally, we can flatten and sort each sub array quickly 
sorted_sub_images = numpy.sort(sub_images.reshape((idx[mask].size, 9))) 
1

あなたの意図は何ですか

import numpy as np 

def im2col(Im, block, style='sliding'): 
    """block = (patchsize, patchsize) 
     first do sliding 
    """ 
    bx, by = block 
    Imx, Imy = Im.shape 
    Imcol = [] 
    for j in range(0, Imy): 
     for i in range(0, Imx): 
      if (i+bx <= Imx) and (j+by <= Imy): 
       Imcol.append(Im[i:i+bx, j:j+by].T.reshape(bx*by)) 
      else: 
       break 
    return np.asarray(Imcol).T 

if __name__ == '__main__': 
    Im = np.reshape(range(6*6), (6,6)) 
    patchsize = 3 
    print Im 
    out = im2col(Im, (patchsize, patchsize)) 
    print out 
    print out.shape 
    print len(out) 
関連する問題