【numpy】opencvで読み込んだ画像を縦・横方向にシフトさせる
概要
opencvで読み込んだ画像を縦・横方向に移動させる方法について調べたので,こちらにメモを残しておきます.
またその際に,はみ出た部分については無視するような処理についても検討してみました.
これを行うことでCutMixのような前処理を実装することが可能です.
あまり綺麗な方法ではないため,より良い実装がございましたら,ご教授いただけると幸いです.
numpy配列をシフトさせる方法
numpy配列をシフトさせる関数として,np.roll
という関数が提供されています.
これを用いることで容易に配列のシフトが可能です.
a = np.arange(10) print(a) # [0 1 2 3 4 5 6 7 8 9] res1 = np.roll(a, shift=5) print(res1) # [5 6 7 8 9 0 1 2 3 4] res2 = np.roll(a, shift=2) print(res2) # [2 3 4 5 6 7 8 9 0 1]
こちらは多次元配列にも適用できます.
a = np.zeros((3, 3), dtype=np.uint8) a[1, 1] = 1 print(a) # [[0 0 0] # [0 1 0] # [0 0 0]] print(np.roll(a, shift=(1, 1), axis=(0, 1))) # [[0 0 0] # [0 0 0] # [0 0 1]]
opencvで読み込んだ画像をシフトさせる
opencvで読み込んだ画像はnumpy配列となるので,上記と同じ手順でシフトさせることができます.
まず画像を読み込みます.
# 画像の読み込み img_path = "cat.jpg" img = cv2.imread(img_path)
次に画像をシフトさせてみます.
# どれだけ画像をシフトさせるか x_diff = 150 y_diff = -100 # 画像をシフト shifted_img = np.roll(img, shift=(y_diff, x_diff), axis=(0, 1))
結果
画像を縦・横方向にシフトさせることができました.
次にこのシフトの際に,はみ出た部分を削除してみます.
こちらは配列のスライスで実装可能です.
# はみ出た部分を削除 (黒塗り) if x_diff >= 0: shifted_img[:, :x_diff] = 0 else: shifted_img[:, w + x_diff:] = 0 if y_diff >= 0: shifted_img[:y_diff] = 0 else: shifted_img[h + y_diff:] = 0
結果
CutMixで作られるような画像を生成する
最後にこのシフトした画像と,下の画像を用いて,CutMixを実装してみます.
img_path2 = "dog.jpg" img2 = cv2.imread(img_path2) # 黒塗りになっているインデックスを取得 bg_inds = np.where(shifted_img == 0) # 黒塗りの部分に,別の画像を埋め込む shifted_img[bg_inds] = img2[bg_inds]
結果
このように画像のシフトを使用することで,CutMixのような画像処理も実装できました!
CutMixで必要となるラベルも,二つの画像の面積比から簡単に算出することができます.
参考
- NumPy配列ndarrayをシフト(スクロール)させるnp.roll | note.nkmk.me
- [1905.04899] CutMix: Regularization Strategy to Train Strong Classifiers with Localizable Features
リンク