`dtype`が`numpy.uint8`の配列をnumpy.arrayのインデックスに利用すると処理時間が長くなってしまいます。なぜでしょうか？


# 環境

  * Python 3.11.2
  * numpy 1.24.2

# やりたいこと

画像をPillowなどで読み込み、bool配列を使って、特定のピクセルを白色（`[255,255,255]`）にしたいです。

# 起きたこと

マスク用の配列の`dtype`を`bool`ではなく、間違えて`numpy.uint8`にしてしまいました。  
そのマスク用の配列を利用して、特定のピクセルを白色に設定しようとしたら、処理時間が1分以上かかりました。

[code]

    In [131]: height=1080; width=1920; channel=3
    
    # Pillowなどで画像を読み込むことを想定
    In [132]: data=numpy.random.randint(256, size=(height,width,channel))
    
    In [133]: correct_mask = numpy.zeros((height, width), dtype=bool)
    
    In [134]: %time data[correct_mask] = [255,255,255]
    CPU times: user 773 µs, sys: 0 ns, total: 773 µs
    Wall time: 526 µs
    
    
    # マスク用の配列の型を間違えて`numpy.uint8`にしてしまった
    In [135]: wrong_mask = numpy.zeros((height, width), dtype=numpy.uint8)
    
    # 処理に時間がかかる。なぜ？
    In [136]: %time data[wrong_mask] = [255,255,255]
    CPU times: user 2min 17s, sys: 0 ns, total: 2min 17s
    Wall time: 2min 17s
    
    
    
[/code]

# 質問

なぜ`dtype`が`numpy.uint8`の配列をインデックスに利用すると、`dtype`が`bool`の配列を利用するときと比較して、処理時間が長くなるのでしょうか  
また、`dtype`が`numpy.uint8`の配列をインデックスに利用すると、どのような処理になるのでしょうか？




> また、dtypeがnumpy.uint8の配列をインデックスに利用すると、どのような処理になるのでしょうか？

`Y[i]`とすれば`i`番目の要素が取れます。  
`Y[[i]]`とインデックスをリストにすると、  
最初の要素が`Y[i]`であるndarrayが取得できます。すなわち`[Y[i]]`  
このような感じで、`Y[X]`とすると、(Xは整数配列)  
Xの各要素x_iをY[x_i]に置き換えたndarrayが取得できます。  
例えば`Y[ [[0,1],[2,3]] ]`は`[[Y[0],Y[1]],[Y[2],Y[3]]]`

これを踏まえて質問文の`data[wrong_mask]`を考えると、  
`wrong_mask`の各要素は全部0ですので、  
これは`wrong_mask`の各要素を`data[0]`で置き換えたものとなります。

`shape`は  
`wrong_mask`が`(1080, 1920)`  
`data[0]`が`(1920, 3)`ですから、

結果`data[wrong_mask]`は`(1080, 1920, 1920, 3)`になってしまいます。

[Indexing on ndarrays — NumPy v1.24
Manual](https://numpy.org/doc/stable/user/basics.indexing.html#integer-array-
indexing)




> また、dtypeがnumpy.uint8の配列をインデックスに利用すると、どのような処理になるのでしょうか？

`Y[i]`とすれば`i`番目の要素が取れます。  
`Y[[i]]`とインデックスをリストにすると、  
最初の要素が`Y[i]`であるndarrayが取得できます。すなわち`[Y[i]]`  
このような感じで、`Y[X]`とすると、(Xは整数配列)  
Xの各要素x_iをY[x_i]に置き換えたndarrayが取得できます。  
例えば`Y[ [[0,1],[2,3]] ]`は`[[Y[0],Y[1]],[Y[2],Y[3]]]`

これを踏まえて質問文の`data[wrong_mask]`を考えると、  
`wrong_mask`の各要素は全部0ですので、  
これは`wrong_mask`の各要素を`data[0]`で置き換えたものとなります。

`shape`は  
`wrong_mask`が`(1080, 1920)`  
`data[0]`が`(1920, 3)`ですから、

結果`data[wrong_mask]`は`(1080, 1920, 1920, 3)`になってしまいます。

[Indexing on ndarrays — NumPy v1.24
Manual](https://numpy.org/doc/stable/user/basics.indexing.html#integer-array-
indexing)

