Numpyで画像処理するメモ
今回もNumpyで画像をいじる。
実行環境
Androidスマホ
termux
Python3.8
JupyterNotebook
一番最後の画像処理でネット接続がいります。
はじめに
from IPython.display import Image
というコードを何回も書いておりますが、書かないと実行時にエラーが出た為にそうしました。理由は分かりません。
いろいろコピーして使い回しているので変数も複数で被っています。コピペして実行の際はご注意くださいませ。
グレイスケール
カラー写真をpillowのconvert("L")を使って仏壇用白黒写真にした。この処理を行うと次元が1つ減って時が止まったようになる。減らされているのは時間の次元か。
import numpy as np from PIL import Image file = "jimi.jpg" # Numpy配列化 im = np.array(Image.open(file)) # 形状確認 im.shape
(498, 385, 3)
# グレイスケール化 im_gray = np.array(Image.open(file).convert("L")) # 形状確認 print("形状", im_gray.shape) print("型", im_gray.dtype)
形状 (498, 385)
型 uint8
三次元目の色チャンネルのデータが無くなり、二次元に変換されました。
注意
二次元配列を保存する際は、配列をnp.uint8(配列)などでuint8型にしてからImage.fromarray()に渡すこと。
他のを渡すとOsError
が出て保存できない。
# 画像オブジェクトに変換
im_gray_file = Image.fromarray(im_gray)
# 画像を保存 im_gray_file.save("gray.png") # 画像のモード確認 im_gray_file.mode
'L'
# JupyterNotebookに画像表示させる用 from IPython.display import Image # 画像を表示 Image("gray.png")
左右を入れ替えて結合
右と左を繋げる陰謀的処理。
元の画像
# JupyterNotebookに画像表示させる用 from IPython.display import Image # 元の画像表示 Image("UDLR.png")
import numpy as np from PIL import Image file = "UDLR.png" # 画像をNumpy配列化 im = np.array(Image.open(file)) # 形状表示 im.shape
(406, 728, 3)
# 左半分をスライスで抽出 im_left = im[:, 0:364] # 形状確認 im_left.shape
(406, 364, 3)
# 右半分をスライスで抽出 im_right = im[:, 364:] # 形状確認 im_right.shape
(406, 364, 3)
# 左右入れ替え横に結合 im_rightside_left = np.hstack((im_right, im_left)) # 形状確認 im_rightside_left.shape
(406, 728, 3)
# 画像に変換
im_rl = Image.fromarray(im_rightside_left)
# 画像保存 im_rl.save("rightside_left.png")
# JupyterNotebookに画像表示させる用 from IPython.display import Image # 画像表示 Image("rightside_left.png")
上下を右左に結合
最終手段のガラガラポン的処理。
import numpy as np from PIL import Image file = "UDLR.png" im = np.array(Image.open(file)) im.shape
(406, 728, 3)
# 上半分をスライスで抽出 im_up = im[0:203, : ] # 形状確認 im_up.shape
(203, 728, 3)
# 下半分をスライスで抽出 im_down = im[203:, : ] # 形状確認 im_down.shape
(203, 728, 3)
# 横に結合 im_upside_right = np.hstack((im_down, im_up)) # 形状確認 im_upside_right.shape
(203, 1456, 3)
# 画像に変換 im_ur = Image.fromarray(im_upside_right) # 画像保存 im_ur.save("upside_right.png")
# JupyterNotebookに画像表示させる用 from IPython.display import Image # 画像表示 Image("upside_right.png")
上下入れ替え
真ん中で上下に切って入れ替えて繋げる革命的処理。
import numpy as np from PIL import Image file = "UDLR.png" im = np.array(Image.open(file)) im.shape
(406, 728, 3)
# 上半分をスライスで抽出 im_up = im[0:203, : ] # 形状確認 im_up.shape # 下半分をスライスで抽出 im_down = im[203:, : ] # 形状確認 im_down.shape
(203, 728, 3)
# 上下を入れ替えて結合 im_upside_down = np.vstack((im_down, im_up)) # 形状確認 im_upside_down.shape
(406, 728, 3)
# 画像に変換 im_ud = Image.fromarray(im_upside_down) # save im_ud.save("upside_down.png")
# JupyterNotebookに画像表示させる用 from IPython.display import Image Image("upside_down.png")
黒を白にする
地獄の沙汰も金次第。ニューヨーク敏腕弁護士事務所的・FBI司法取引的・腐敗司法的なナウい処理。
import numpy as np from PIL import Image file = "UDLR.png" im = np.array(Image.open(file)) print(im.dtype)
uint8
# 黒を白にする im_wb = np.where(im==0,255,im) print(im_wb.dtype)
uint8
# 画像に変換 im_wb = Image.fromarray(im_wb) # 画像保存 im_wb.save("whiteside_black.png")
# JupyterNotebookに画像表示させる用 from IPython.display import Image # 画像表示 Image("whiteside_black.png")
行列を転置 transpose()
斜めの軸で転覆させるトリッキーな処理。
多次元配列を転置する.T
を画像の配列で使うと0軸と2軸が入れ替わり、配列を再び画像に変換し直す時にエラーになる。
それを避けるためにtranspose(次元の並び替え)
を使うと行(0軸)と列(1軸)のみを入れ替えることが出来る。
画像を転置するときはtranspose(1,0,2)
で。
トリッキーなわりには正統派か。
import numpy as np from PIL import Image file = "UDLR.png" im = np.array(Image.open(file)) print(im.dtype)
uint8
行と列の次元を入れ替える(転置)
im_t=im.transpose(1,0,2)
im_t.shape
(728, 406, 3)
# 画像に変換 im_t = Image.fromarray(im_t) # save im_t.save("t.png")
# JupyterNotebookに画像表示させる用 from IPython.display import Image Image("t.png")
画像の上半分だけ同じようにしてみる。
import numpy as np from PIL import Image file = "UDLR.png" im = np.array(Image.open(file)) # 上下半分に切り上側のみ取り出し im_upper = im[0:203, :] # 形状確認 im_upper.shape
(203, 728, 3)
# 転置 im_t2array = im_upper.transpose(1,0,2) # 形状確認 im_t2array.shape # (728,203,4)
(728, 203, 3)
# 画像に変換 im_t2 = Image.fromarray(im_t2array) # 画像保存 im_t2.save("t2.png")
# JupyterNotebookに画像表示させる用 from IPython.display import Image # 画像表示 Image("t2.png")
np.rot90 配列を回転する
np.rot90(元の配列, 回数)とすると、元の配列が指定回数だけ左回りに90度回転する。
例として行列を回してみます。
import numpy as np from PIL import Image im = np.arange(1,10).reshape(3,3) # 配列表示 im
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 配列を反時計回りに90度回転 np.rot90(im, 1)
array([[3, 6, 9],
[2, 5, 8],
[1, 4, 7]])
数字の場所が左回りに移動していることがわかる。
これを踏まえて
import numpy as np from PIL import Image file = "UDLR.png" im = np.array(Image.open(file)) im.shape
(406, 728, 3)
左回りに90度だけ画像を回転させる。
# 左回り90度回転 im_90 = np.rot90(im, 1)
# 配列を画像化して保存 image_90 = Image.fromarray(np.uint8(im_90)) image_90.save("im_90.png")
# 表示 from IPython.display import Image Image("im_90.png")
ネガポジ反転
ジミヘンの画像をネガポジ反転。変なクスリを飲むとアップとダウンの起伏が激しくなる。
import numpy as np from PIL import Image file="jimi.jpg" im = np.array(Image.open(file)) print("形状",im.shape) print("型",im.dtype) im=255-im im_f = Image.fromarray(im) im_f.save("jimi_ngpj.jpg") from IPython.display import Image Image("jimi_ngpj.jpg")
形状 (498, 385, 3)
型 uint8
べつの画像ではどうか
from PIL import Image file="UDLR.png" im = np.array(Image.open(file)) print("形状",im.shape) print("型",im.dtype) im=255-im im_f = Image.fromarray(im) im_f.save("irochigai.png") from IPython.display import Image Image("irochigai.png")
形状 (406, 728, 3)
型 uint8
ネット上の画像から読み込む
requestsとioモジュールを使う。requestsは標準モジュールではないのでインストールが必要。
実行時にネットの接続もいります。
import numpy as np from PIL import Image import requests import io
# Wikipediaのモナリザの画像url url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg/687px-Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg' # urlからダウンロードし画像に保存 a_img = Image.open(io.BytesIO(requests.get(url).content))
実行する度にダウンロードする。ネット接続されていない状態で実行すると、ConnectionError
ってのが出ます。
実行毎にダウンロードして非効率。
# Numpy配列に変換 array = np.array(a_img) # 形状表示 array.shape
(1024, 687, 3)
逆さまにしてみる。
# 上下反転 array_ud = array[::-1] # 画像として保存 Image.fromarray(array_ud).save("image_ud.png") from IPython.display import Image Image("image_ud.png")
同じモナリザを180度回転させると
import numpy as np from PIL import Image import requests import io # Wikipediaのモナリザの画像url url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg/687px-Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg' # urlからダウンロードし画像に保存 a_img = Image.open(io.BytesIO(requests.get(url).content)) # Numpy配列に変換 array = np.array(a_img) # 形状表示 array.shape
(1024, 687, 3)
# 180度回転 array180 = np.rot90(array, 2) # 画像として保存 Image.fromarray(array180).save("image_180.png") from IPython.display import Image Image("image_180.png")
上下反転と180度回転では、モナリザの向きが違っている。