背景
- github などにある他者の python(numpy, cv2)で画像データを処理しているコードが読解できない
-
[...,::-1]
とかで記号的なので検索もしづらい
BGR -> RGB
cv2 だと標準で BGR 画像として処理するようです. 保存や matplotlib で表示時に RGB に並び替える必要あります.
(H, W, C) な配列とします.
[:, :, ::-1]
で C 次元(チャンネル)の要素が入れ替わります.
:
は slice((start, end, step)
) でその次元の全要素を指す (None, None, 1)
(?) or (0, n-1, 1)
相当.
::-1
も slice で (0, n-1, -1)
で end から start へと逆方向に 1 づつ進む.
RGB(3 要素) の場合は [2, 1, 0]
のインデクシングとなる.
したがって BGR -> RGB と並び替えができます.
...
img[...,::-1]
なケース.
初見者からすると謎すぎてまったくわかりません.
...
は検索性低くてつらいですね.
...
= :, :
の省略形でした. 各次元で全要素選択という感じでしょうか.
[..., ::-1]
= [:, :, ::-1]
= [:, :, [2, 1, 0]]
という感じです.
特定の channel だけに処理をしたい
たとえば G channel だけ 1 を設定したいなど
img[:, :, 1] = 1
とします.
alpha を RGB にブロードキャストしたい
numpy だけかも.
rgb(3 channels) と alpha(1 channel) の画像があるときに, 単純に rgb * alpha
では乗算できません.
alpha の値を RGB にブロードキャスト(複製)する必要があります.
fg * alpha[:, :, None]
として, None
を指定するとブロードキャストしてくれます.
None = np.newaxis として次元を一つ増やす振る舞いになっています(わかりずらい...)
ast(構文木)をきちんと考慮しているようで,
bg * (1 - alpha[:, :, None])
みたいになにか演算してから RGB と乗算もうまく行きます.
画素要素を判定して代入するなど
for i in range(len(pixels)):
pixels[i] = pixels[i] < 0.5 ? 0 : pixels[i]
みたいな操作をしたい.
pixels[pixels < 0.5] = 0
とすると, 全画素で処理してくれます.
shape(画像サイズやチャネル数)があっていれば, 他の ndarray を使うのも可能です.
e.g.
alpha[trimap_np[:, :, 0] == 1] = 0
alpha 画像で, trimap_np の R channel が 1 の画素位置の値を 0 にする
fg[alpha == 1] = image_np[alpha == 1]
T.B.W.
画像を部分領域(tile)に分割する
slice 記法では, step で 4 ピクセルおきなどは指定できますが, 4 pixel づつというのはできないので, for 文などで slide (start, end, 1)
で start, end をそれぞれ指定するか, numpy, cv2 あたりで部分領域に分割する関数を使います.
(ちなみに numpy.tile は画像を tile 状にリピートして並べる関数なので分割には使えない)
その他
視覚的に説明してくれている記事
Numpy’s indexing and slicing notation explained visually
https://medium.com/@buch.willi/numpys-indexing-and-slicing-notation-explained-visually-67dc981c22c1