背景
- つまらない間違えで躓き、1時間近く悩んでしまった
- 画像をPillowで読み込み、色々処理を行った経験があったので、ノリでできるだろうと思っていた。
目的
- つまらない間違えを公衆の面前にさらし赤っ恥を書くことで、二度と間違えないように自らを戒める。
- numpyで画像を取り扱う際のポイントを把握する
何を間違えていたか
やりたかったこと
- 100×100の画像を作り、色を指定する
こう考えた
- 画像だから2次元配列でしょ~
np.zeros((100,100))
を作って、ここの要素にRGB値入れればいいじゃん - スライスで全要素指定して、RGB値ぶっこめばべた塗できるはず!
im = np.zeros((100,100)) #間違えポイント1
im[:,:] = (255, 128, 54)
- 怒られた
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
in
1 im = np.zeros((100,100))
----> 2 im[:,:] = (255, 128, 54)
ValueError: could not broadcast input array from shape (3) into shape (100,100)
-
なんかよくわからん。
-
そうか、きっと要素にタプルを入れようとしたので怒られたんだ(間違えポイント2)
-
よし、タプルはオブジェクトだから....ググるググる
-
np.full((100,100), object)
で100×100のオブジェクトを用意してここにタプルを・・・・
だめだぁああああああ
奥の手を使うか・・・
100×100サイズの画像'img001.png'
を用意してっと(某pなんとかラーニング風)
import cv2
im = cv2.imread('img001.png')
im[:,:] = (255, 128, 54)
print(im[50,50])
(255, 128, 54)
- ふ、思い通りだ・・・
何がいけなかったか
- 間違えポイント1
カラー画像は3次元のデータです。位置情報2Dと色情報1D。
しかし、私が定義したのはnp.zeros((100,100))
2次元の配列でした。
ここに、要素数3のタプルをネジ込もうとしていたのです。
- 間違えポイント2
エラーメッセージを読んでいない
メッセージはちゃんと親切に教えてくれているジャマイカ
ValueError: could not broadcast input array from shape (3) into shape (100,100)
値が間違ってるよ。要素数3の配列は、100×100にブロードキャストできないよ。
優しい。
その優しさを無視してあらぬ方向にさまよい続けた私。
まるで さまようよろい のようだ
なぜ間違えに気が付かなかったか
このコードが正しく動作するのを知っていたが、中で何がなされているのか理解していなかったからである。
import cv2
im = cv2.imread('img001.png')
im[:,:] = (255, 128, 54)
im[:,:]
を見て2次元☆彡って思ってしまっていた。この早とちりがすべての元凶だった。
まず、imはshape(n,m,3)のndarrayである。次元数は3である。だってカラー画像だもん。
im[:,:]は要素数3である。nとmの全てを取得し残りの次元の配列を表していたのであった。
そして、タプルでそれぞれの要素に値を代入していたのだった。
どうすべきだったか
もはや言うまでもありませんが・・・
い、一行・・・
im = np.full((100,100,3), (255, 128, 54), dtype='uint8')
opencvで処理をすることを考慮するとuint8形式が良いでしょう