よちよちpython

独習 python/Qpython/Pydroid3/termux

画像をExcelモザイク画像に変換する

画像からExcelのモザイク画像に変換するアホなPythonプログラムを作りますた。
元画像(jpg)はモザイク画像としてExcelファイルのシートに保存されます。



方法と手順の説明

◆ 画像をmatplotlibで読み込むとNumpy配列に変換されます。jpg画像は三次元配列になっており、三次元方向にRGB色情報が、赤なら[255,0,0]のように入っている。

◆ そのリストを16進数のカラーコードに変換する。先ほどの赤なら#ff0000
色の変換は次のように行う。

# 10進数→16進数の二桁表示に変換
print("{:02x}".format(255))
print("{:02x}".format(0))
ff
00

10進数の255は16進数でff、10進数の00は16進数で00に文字列として変換される。



◆ 全てのRGB色リストを16進数カラーコードに変換すると二次元になる。これをPandasでデータフレームにする。値がカラーコードの文字列が入った二次元のデータフレームができる。



◆ できたデータフレームの背景色を、値=カラーコードにスタイル変換する。背景色のついたデータフレームのテーブルが出来上がる。



◆ あとはpandas.to_excel(保存ファイル名)Excelファイルに保存して完成。



画像の読み込みと配列への変換

◆ 元の画像

20210228201551


これがExcelシートでモザイク画像にする。



import numpy as np
import matplotlib.pyplot as plt

# 元の画像ファイル
fname = "hannya.jpeg"  

# 画像をmatplotlibでNumpy配列に変換
img = plt.imread(fname)



配列のRGBを16進数に変換

# 画像のRGB配列を16進数カラーコードに変換する関数
def make_color(img):
    x = img.shape[0]
    y = img.shape[1]

    rgb_list = [img[i][j] for i in range(x) for j in range(y)]

    color_code_list = []
    for rgb in rgb_list:
        color_code = []
        for v in rgb:
            color_code.append("{:02x}".format(v))
    
        color_code = ["#" + "".join(color_code)]
        color_code_list.append(color_code)
        

    return color_code_list

この辺はもう少しスッキリ書けそうです。だがこのまま行く。



データフレームに変換

# 画像をカラーコードの配列に変換
code_list = make_color(img)

# 画像と同じサイズの二次元配列にする  
color_style = np.array(code_list).reshape(img.shape[:2])

# データフレームにする
color_style = pd.DataFrame(color_style)

# データフレームの表示
color_style
0 1 2 3 4 5 6 7 8 9 ... 173 174 175 176 177 178 179 180 181 182
0 #2a323f #2a323f #2a323f #29313e #29313e #29313e #28303d #28303d #29313e #29313e ... #191c25 #191c25 #191c25 #1a1d26 #1a1d26 #1a1d26 #191c25 #191c25 #181b24 #181b24
1 #2a323f #2a323f #2a323f #29313e #29313e #29313e #28303d #28303d #29313e #29313e ... #191c25 #191c25 #191c25 #1a1d26 #1a1d26 #191c25 #191c25 #191c25 #181b24 #181b24
2 #2a323f #2a323f #2a323f #29313e #29313e #29313e #28303d #28303d #29313e #29313e ... #191c25 #191c25 #191c25 #191c25 #191c25 #191c25 #191c25 #181b24 #181b24 #181b24
3 #2a323f #2a323f #2a323f #29313e #29313e #29313e #28303d #28303d #29313e #29313e ... #191c25 #191c25 #191c25 #191c25 #191c25 #191c25 #181b24 #181b24 #171a23 #171a23
4 #2a323f #2a323f #2a323f #29313e #29313e #29313e #28303d #28303d #29313e #29313e ... #191c25 #191c25 #191c25 #191c25 #181b24 #181b24 #181b24 #171a23 #171a23 #171a23
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
271 #0a0c18 #0a0c18 #0b0d19 #0b0d19 #0c0e1a #0c0e1a #0c0e1a #0c0e1a #0d0f1b #0d0f1b ... #0f0c15 #0f0c15 #0f0c15 #100e19 #100e19 #100e19 #100e19 #100e19 #100e19 #100e19
272 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0d0f1b #0d0f1b ... #110e19 #110e19 #110e19 #100e19 #100e19 #100e19 #100e19 #100e19 #100e19 #100e19
273 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0d0f1b #0d0f1b ... #110e19 #110e19 #110e19 #100e19 #100e19 #100e19 #100e19 #100e19 #100e19 #100e19
274 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0d0f1b #0d0f1b ... #110e19 #110e19 #110e19 #100e19 #100e19 #100e19 #100e19 #100e19 #100e19 #100e19
275 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0b0d19 #0d0f1b #0d0f1b ... #110e19 #110e19 #110e19 #100e19 #100e19 #100e19 #100e19 #100e19 #100e19 #100e19

276 rows × 183 columns

画像と同じサイズの二次元配列ができた。
それぞれの値は画像のRGBを16進数カラーコードに変換したそのものが入っている。



背景色をつける

上記のテーブルの値が背景色のカラーコードになっている。それらの値をデータフレームの背景色として関数で置換する。

# Pandasをインポート
import pandas as pd

# 背景色をカラーコードに変換する関数
def func(val):
    color = val
    return "background-color:%s" % color

# 背景色を変換実行
df = color_style.style.applymap(func)



Excelファイルに保存して完成

# データフレームテーブルをExcelファイルに保存
df.to_excel("img_excel_mosaic.xlsx")

◆ パソコンで開いたモザイク画Excelシートのキャプチャ

f:id:chayarokurokuro:20210228201900j:plain



シートを拡大すると、

f:id:chayarokurokuro:20210228201959j:plain



元の画像が276×183のサイズでしたが、Excelシートにすると相当デカくなる。セル幅の縦横のせいか、モザイク画像が横広い。
元画像はもう少し小さい物を使った方が良かったかな。



以上です。