よちよちpython

独習 python/Qpython/Pydroid3/termux/Linux

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")

f:id:chayarokurokuro:20200118053603p:plain



左右を入れ替えて結合


右と左を繋げる陰謀的処理。



元の画像

# JupyterNotebookに画像表示させる用
from IPython.display import Image

# 元の画像表示
Image("UDLR.png")

f:id:chayarokurokuro:20200118053648p:plain

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")

f:id:chayarokurokuro:20200118053739p:plain



上下を右左に結合


最終手段のガラガラポン的処理。

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")

f:id:chayarokurokuro:20200118053831p:plain



上下入れ替え


真ん中で上下に切って入れ替えて繋げる革命的処理。

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")

f:id:chayarokurokuro:20200118053930p:plain

黒を白にする


地獄の沙汰も金次第。ニューヨーク敏腕弁護士事務所的・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")

f:id:chayarokurokuro:20200118054017p:plain

行列を転置 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")

f:id:chayarokurokuro:20200118054103p:plain



画像の上半分だけ同じようにしてみる。

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")

f:id:chayarokurokuro:20200118054157p:plain

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")

f:id:chayarokurokuro:20200118054245p:plain



ネガポジ反転


ジミヘンの画像をネガポジ反転。変なクスリを飲むとアップとダウンの起伏が激しくなる。

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

20200118054331

べつの画像ではどうか

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

20200118054420



ネット上の画像から読み込む


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")

f:id:chayarokurokuro:20200118054613p:plain



同じモナリザを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")

f:id:chayarokurokuro:20200118054805p:plain

上下反転と180度回転では、モナリザの向きが違っている。