2017-01-01 4 views
3

現在、私は、画像内の接続されたコンポーネントを決定するために、より最適な解決策を見つけようとしています。現在、特定の値を持つ座標を持つ配列があります。私は彼らが触れている場合に基づいて、これらの座標のグループを作成したいと思います。私はnumpyの配列を使用していますが、現在、各値(左上、上中央、右上、中央左、中央右、左下、下中央、右下)が配列内にあるかどうかをチェックする必要があります。隣り合った値がかっこいい行列であるかどうかを確認する

for x in range (0, groupCoords.shape[0]): 
      global tgroup 
      xCoord = groupCoords.item((x,0)) 
      yCoord = groupCoords.item((x,1)) 
      new = np.array([[xCoord, yCoord]]) 
      if np.equal(Arr,[xCoord, yCoord+1]).all(1).any(): 
       tgroup = np.append(tgroup, [[xCoord,yCoord+1]], axis=0) 
       new = np.append(new, [[xCoord,yCoord+1]], axis=0) 
       index = np.argwhere((Arr == [xCoord,yCoord+1]).all(1)) 
       Arr = np.delete(Arr, (index), axis=0) 

      if np.equal(Arr,[xCoord, yCoord-1]).all(1).any(): 
       tgroup = np.append(tgroup, [[xCoord, yCoord-1]],axis=0) 
       new = np.append(new, [[xCoord,yCoord-1]], axis=0) 
       index = np.argwhere((Arr == [xCoord,yCoord-1]).all(1)) 
       Arr = np.delete(Arr, (index), axis=0) 

      if np.equal(Arr,[xCoord+1, yCoord]).all(1).any(): 
       tgroup = np.append(tgroup, [[xCoord+1,yCoord]],axis=0) 
       new = np.append(new, [[xCoord+1,yCoord]], axis=0) 
       index = np.argwhere((Arr == [xCoord+1,yCoord]).all(1)) 
       Arr = np.delete(Arr, (index), axis=0) 

      if np.equal(Arr,[xCoord+1, yCoord+1]).all(1).any(): 
       tgroup = np.append(tgroup, [[xCoord+1,yCoord+1]],axis=0) 
       new = np.append(new, [[xCoord+1,yCoord+1]], axis=0) 
       index = np.argwhere((Arr == [xCoord+1,yCoord+1]).all(1)) 
       Arr = np.delete(Arr, (index), axis=0) 

      if np.equal(Arr,[xCoord+1, yCoord-1]).all(1).any(): 
       tgroup = np.append(tgroup, [[xCoord+1,yCoord-1]],axis=0) 
       new = np.append(new, [[xCoord+1,yCoord-1]], axis=0) 
       index = np.argwhere((Arr == [xCoord+1,yCoord-1]).all(1)) 
       Arr = np.delete(Arr, (index), axis=0) 

      if np.equal(Arr,[xCoord-1, yCoord]).all(1).any(): 
       tgroup = np.append(tgroup, [[xCoord-1,yCoord]],axis=0) 
       new = np.append(new, [[xCoord-1,yCoord]], axis=0) 
       index = np.argwhere((Arr == [xCoord-1,yCoord]).all(1)) 
       Arr = np.delete(Arr, (index), axis=0) 

      if np.equal(Arr,[xCoord-1, yCoord+1]).all(1).any(): 
       tgroup = np.append(tgroup, [[xCoord-1,yCoord+1]],axis=0) 
       new = np.append(new, [[xCoord-1,yCoord+1]], axis=0) 
       index = np.argwhere((Arr == [xCoord-1,yCoord+1]).all(1)) 
       Arr = np.delete(Arr, (index), axis=0) 

      if np.equal(Arr,[xCoord-1, yCoord-1]).all(1).any(): 
       tgroup = np.append(tgroup, [[xCoord-1,yCoord-1]],axis=0) 
       new = np.append(new, [[xCoord-1,yCoord-1]], axis=0) 
       index = np.argwhere((Arr == [xCoord-1,yCoord-1]).all(1)) 
       Arr = np.delete(Arr, (index), axis=0) 

ただし、画像が大きい場合、これには明らかに時間がかかります。私はイメージの幅と高さの次元を持つブール値行列を作成し、イメージのピクセルに対応する行列の値に値 "true"を割り当てます(画像は黒です)。

このような各値をチェックする代わりに、別の「真の」値を直接囲む要素が真であるかどうかを判断することは可能でしょうか?出力が「真」の値が触れている場合、私は改善するために期待しています関数はチェックでしょう

[ 
[0 0] 
[0 1] 
[0 2] 
] 

ようになり

[ 
[0 0] 
[0 1] 
[0 2] 
[10 2] 

] 

これは、入力配列は次のようになります。新しい値が見つかるたびに実行されるすべての値の「ネットワーク」を作成します。

+0

はい座標の順序は重要ですか?私たちはそこで座標を取り除いていると思います。あなたは、彼らが片方の側から別の側へ(もしあれば)、または他の何らかの基準で接続されている順序でそれらを必要としていますか? – Divakar

+0

入力の小さな例(4x4配列など)と期待される出力を与えることができますか? –

+0

@Divakar順序は関係ありません。配列にグループ化するだけです。私はこれをOCRメソッドとして使用しています。そのため、接続されているコンポーネントのリストを作成して、イメージの各文字になります。 –

答えて

1

アプローチ#1

私たちは、ユークリッド距離を取得し、距離のいずれかがdistance = 1distance = sqrt(2)と対角線でup-downをカバーするsqrt(2)、内であれば見ることができました。これは私たちにマスクを与え、グループ座標配列にインデックスされると、それから連結されたものを与えるでしょう。

したがって、それらのユークリッド距離を取得するためScipy's cdistを使用して実装は、だろう -

from scipy.spatial.distance import cdist 

out = groupCoords[(cdist(groupCoords,Arr)<1.5).any(1)] 

サンプル実行 -

In [401]: Arr 
Out[401]: 
array([[ 5, 4], 
     [11, 12], 
     [ 5, 3], 
     [ 1, 3], 
     [15, 8], 
     [55, 21]]) 

In [402]: groupCoords 
Out[402]: 
array([[2, 3], # In neighbourhood of (1,3) 
     [5, 6], 
     [6, 2], # In neighbourhood of (5,3) 
     [5, 3], # In neighbourhood of (5,4) 
     [5, 8]]) 

In [403]: groupCoords[(cdist(groupCoords,Arr)<1.5).any(1)] 
Out[403]: 
array([[2, 3], 
     [6, 2], 
     [5, 3]]) 

アプローチ#2

別の方法チェックするだろう2つの配列の最初の列の間に絶対的な要素ごとの差異があり、同様に2番目の列の要素的な違いがあります。最後に、これらの2つのマスクからジョイントマスクを取得し、フィルタリングされた座標のグループ配列に一致とインデックスを再度チェックします。

したがって、このようなメソッドの実装は次のようになります -

col0_mask = (np.abs(groupCoords[:,0,None] - Arr[:,0])<=1) 
col1_mask = (np.abs(groupCoords[:,1,None] - Arr[:,1])<=1) 
out = groupCoords[(col0_mask & col1_mask).any(1)] 

アプローチ#3

別のアプローチとあなたがboolean型配列としてArrを持っている代わりの場合は、おそらく良いだろう2列の座標配列として扱います。考えはdilate this boolean arrayArrであり、次にどの座標がgroupCoordsからもこの拡張された画像内にあるのを見る。拡張のために、それらの近隣の場所のすべてをカバーするためにすべてのものの3 x 3カーネルを使用します。これらの共通点を検出するには、groupCoordsの画像を描画する必要があります。

したがって、コードは次のようになり -

from scipy.ndimage.morphology import binary_dilation 

img = np.zeros(Arr.shape,dtype=bool) 
img[groupCoords[:,0],groupCoords[:,1]] = 1 
out = np.argwhere(binary_dilation(Arr,np.ones((3,3))) & img) 

サンプル実行 -

In [444]: # Inputs : groupCoords and let's create a sample array for Arr 
    ...: groupCoords = np.array([[2,3],[5,6],[6,2],[5,3],[5,8]]) 
    ...: 
    ...: Arr_Coords = np.array([[5,4],[11,12],[5,3],[1,3],[15,8],[55,21]]) 
    ...: Arr = np.zeros(Arr_Coords.max(0)+1,dtype=bool) 
    ...: Arr[Arr_Coords[:,0], Arr_Coords[:,1]] = 1 
    ...: 

In [445]: img = np.zeros(Arr.shape,dtype=bool) 
    ...: img[groupCoords[:,0],groupCoords[:,1]] = 1 
    ...: out = np.argwhere(binary_dilation(Arr,np.ones((3,3))) & img) 
    ...: 

In [446]: out 
Out[446]: 
array([[2, 3], 
     [5, 3], 
     [6, 2]]) 
1

あなたのコードの究極の目標に応じて、scipy.ndimage.labelとその親族が役立つかもしれません。例えば

、2つの値を返すlabel

In [44]: from scipy.ndimage import label 

In [45]: x 
Out[45]: 
array([[ True, True, False, False, True], 
     [False, False, False, True, True], 
     [False, True, False, True, False], 
     [ True, True, False, False, False]], dtype=bool) 

In [46]: x.astype(int) # More concise, easier to read 
Out[46]: 
array([[1, 1, 0, 0, 1], 
     [0, 0, 0, 1, 1], 
     [0, 1, 0, 1, 0], 
     [1, 1, 0, 0, 0]]) 

。最初の配列は、入力配列と同じサイズの配列です。入力内の個々に接続されたコンポーネントには、1から始まる整数値が割り当てられます。バックグラウンドは0です.2番目の戻り値は、検出されたコンポーネントの数です。二つの配列を含むタプルを返すwhere(labeled_array = i) follwingにおいて

In [47]: labeled_arr, nlabels = label(x) 

In [48]: nlabels 
Out[48]: 3 

In [49]: labeled_arr 
Out[49]: 
array([[1, 1, 0, 0, 2], 
     [0, 0, 0, 2, 2], 
     [0, 3, 0, 2, 0], 
     [3, 3, 0, 0, 0]], dtype=int32) 

。これらのアレイは、RESP、行と列のインデックスであり、連結成分の:

In [50]: for i in range(1, nlabels+1): 
    ...:  print(where(labeled_arr == i)) 
    ...:  
(array([0, 0]), array([0, 1])) 
(array([0, 1, 1, 2]), array([4, 3, 4, 3])) 
(array([2, 3, 3]), array([1, 0, 1])) 

あなたは(行、列)ペアのリストにそれらを変換するために一緒にそれらを圧縮することができる:

In [52]: for i in range(1, nlabels+1): 
    ...:  print(list(zip(*where(labeled_arr == i)))) 
    ...:  
[(0, 0), (0, 1)] 
[(0, 4), (1, 3), (1, 4), (2, 3)] 
[(2, 1), (3, 0), (3, 1)] 
関連する問題