i
チャンネルの画像がありますimage
。チャンネルに適用できるf
フィルターもあります。画像のチャンネルにフィルターを選択的に適用して、チャンネル画像filters
を生成したいと考えています。私は現在これを2つのリストで定義しているので、処理は次のように行われますo
output
image_idx
filter_idx
for j in xrange(o) :
output[j] = filter[filter_idx[j]](image[image_idx[j]])
画像はかなり大きくなる可能性があるため、この処理をインプレースで行いたいと思うかもしれません。これには、後で必要になるデータの上書きを避けるために、特定の順序でチャネルを処理する必要がある場合があります。現在、次の関数を使用して、そのような注文が存在するかどうかを確認し、計算しています。
def in_place_sequence(indices) :
"""
Figure out a processing sequence for in-place computation.
"""
indices = [j for j in indices]
positions = set(range(len(indices)))
processing_order = []
change = True
while change and len(positions) :
change = False
for j in list(positions) :
val = indices[j]
if (j not in indices) or (indices.count(val) == 1 and val == j) :
indices[j] = None
positions.remove(j)
processing_order.append(j)
change = True
if len(positions) :
return None
return processing_order
例えば:
In [21]: in_place_sequence([4, 0, 3, 0, 4])
Out[21]: [1, 2, 3, 0, 4]
また、上書きを避けるために可能な処理順序は次のとおりです。
img[0] -> img[1]
img[3] -> img[2]
img[0] -> img[3]
img[4] -> img[0]
img[4] -> img[4]
これは次のように実装されています。
for j in in_place_sequence(image_idx) :
image[j] = filter[filter_idx[j]](image[image_idx[j]])
image_idx
シーケンスが見つからないのは、閉ループ順列を定義しているためだとほのめかし始めています。例えば:
In [29]: in_place_sequence([2, 0, 3, 1])
を返しますがNone
、1 チャネルの最小限のストレージでインプレースで実行できます。
img[0] -> temp
img[2] -> img[0]
img[3] -> img[2]
img[1] -> img[3]
temp -> img[1]
これを自動的に実装する方法を見つけるのに苦労しています。私は、現在のアルゴリズムを維持し、それが使い果たされない場合はpositions
、閉じたループを見つけ出し、それぞれに対して上記のようなことを行うことだと思います。ただし、ここで車輪を再発明している可能性があるという印象があります。コーディングに入る前に、中間ストレージを最小限に抑えるための処理順序を決定する最良の方法は何ですか?
編集Sam Mussmann の励ましで、私は先に進み、残りのサイクルを把握しました。私のコードは次のようになります。
def in_place_sequence(indices) :
"""
Figures out a processing sequence for in-place computation.
Parameters
----------
indices : array-like
The positions that the inputs will take in the output after
processing.
Returns
-------
processing_order : list
The order in which output should be computed to avoid overwriting
data needed for a later computation.
cycles : list of lists
A list of cycles present in `indices`, that will require a one
element intermediate storage to compute in place.
Notes
-----
If not doing the opearation in-place, if `in_` is a sequence of elements
to process with a function `f`, then `indices` would be used as follows to
create the output `out`:
>>> out = []
>>> for idx in indices :
... out.append(f(in_[idx]))
so that `out[j] = f(in_[indices[j]])`.
If the operation is to be done in-place, `in_place_sequence` could be used
as follows:
>>> sequence, cycles = in_place_sequence(indices)
>>> for j, idx in enumerate(sequence) :
... in_[j] = f(in_[idx])
>>> for cycle in cycles :
... temp = in_[cycle[0]]
... for to, from_ in zip(cycle, cycle[1:]) :
... in_[to] = f(in_[from_])
... in_[cycle[-1]] = f(temp)
"""
indices = [j for j in indices]
print indices
positions = set(range(len(indices)))
processing_order = []
change = True
while change and positions :
change = False
for j in list(positions) :
val = indices[j]
if (j not in indices) or (indices.count(val) == 1 and val == j) :
indices[j] = None
positions.remove(j)
processing_order.append(j)
change = True
cycles = []
while positions :
idx = positions.pop()
start = indices.index(idx)
cycle = [start]
while idx != start :
cycle.append(idx)
idx = indices[idx]
positions.remove(idx)
cycles.append(cycle)
return processing_order, cycles