デジカメで撮った写真をRGB値を調べたくなることはないでしょうか。
先日、画像からRGB値のデータ化したり、逆に戻したりをしました。
今回はmatplotlibモジュールを使います。
RGB値のヒストグラムにしてグラフ表示して、視覚的に分析しやすくするところまでやってみたいと思います。
せっかくですので、画像を読み込んでRGB値に変換する際に、numpyモジュールで別のアプローチをしたいと思います。
解釈がしづらいですが、こちらの方がスマートに記述できます。
やること1
・画像を読み込んでRGB値に変換する
・ヒストグラムにする
・グラフ表示する
・RGB値をテキスト出力する
やること2
・RGB値を読み込んで画像に変換する
それでは順番に見ていきましょう!
やること1
最終的に次のようにグラフ表示したいと思います。
上段に元画像、下段にヒストグラム。
ヒストグラムはRGBに分けてそれぞれグラフ表示します。
サンプル画像はこちらのサイトからお借りしました。フリーの画像素材を提供してくださっています。
いつもお世話になっております。フリー素材 ぱくたそ – すぐに使える無料の写真素材・AI画像素材 「ぱくたそ」は、会員登録せずに今すぐダウンロードできる無料の写真素材・AI画像素材のフリー素材サイトです。一部を有料販売したり、枚数制限による課金など一切ありませ…
画像を読み込んでRGB値に変換する
今回使用するモジュールをインストールします。
どちらも少し時間が掛かるかもしれません。
pip install opencv-python
pip install matplotlib
まずは画像を読み込んでRGB値のリストとして取り込みます。
import cv2
import numpy as np
# 画像を読み込む
image = cv2.imread(image_path)
# R、G、Bそれぞれの値をリストに格納
r_values = image[:, :, 2].flatten()
g_values = image[:, :, 1].flatten()
b_values = image[:, :, 0].flatten()
画像の扱いにOpenCVモジュールを使いました。
Numpyモジュールだとこれだけでデータ変換完了です。
とてもシンプルになりました。
flatten()で一次元のデータとして取り出しています。
ヒストグラムにするのに都合が良いためです。
ヒストグラムにする
次の手順でmatplotlibでグラフ表示します。
・グラフデータを作成する
・グラフ表示する。
それではヒストグラムでにグラフデータを作成していきましょう。
import matplotlib.pyplot as plt
def plot_histogram(values, color_name):
plt.hist(values, bins=256, range=(0, 256), color=color_name, alpha=0.7)
plt.title(f'{color_name.upper()} Histogram')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.grid(True)
plot_histogram(r_values, 'red')
RGBそれぞれ実行したいので関数化しています。def ~がそうです。
r_valuesは先ほど抽出したRed値のリストです。
グラフ表示する
最後にグラフ表示部分です。
import cv2
import matplotlib.pyplot as plt
# ヒストグラムを1つのプロットにまとめて表示
plt.figure(figsize=(12, 6))
# plt.subplot(rows, columns, index)
plt.subplot(2, 3, 2)
plt.imshow(cv2.cvtColor(cv2.imread(image_path), cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 3, 4)
plot_histogram(r_values, 'red')
plt.subplot(2, 3, 5)
plot_histogram(g_values, 'green')
plt.subplot(2, 3, 6)
plot_histogram(b_values, 'blue')
plt.tight_layout()
plt.show()
subplotを使い、行列でグラフ位置を指定しています。
plt.subplot(2, 3, 2)は2行3列のグラフで、2番目の位置に指定する、という意味です。
この例だと、1~3が上段で、4~6が下段です。
最後にplt.show()で表示させています。
これらを実行すると、冒頭に示したグラフ表示になります。
後述のサンプルコードのところで再掲します。
RGB値をテキスト出力する
今回の目的に対して補助的になりますが、RGB値をテキスト出力したいと思います。
def save_to_txt(data, filename):
with open(filename, 'w') as file:
for value in data:
file.write(str(value) + '\n')
テキスト出力です。
特に追加モジュールは必要ありません。
1行1データで出力します。
jpgを出力すると、結構なサイズになります。
今回のサンプルで約8MB×3色分です。
オリジナル画像が532kBですので、いかにjpgの効率が優れているか!素晴らしいですね。
やること2
RGB値を読み込んで画像に変換する
こちらも、目的に対して補助的になります。
RGB値を読み込んで画像に変換します。
検算にもなりますので、やってみたいと思います。
ここまでの解説で触れませんでしたが、
一次元のRGBデータを画像に戻すには、幅や高さデータが必要です。
サンプルコードでは、あらかじめ「image_size.txt」として出力しています。
この「image_size.txt」に記載された幅と高さデータをもとに、
「r_values.txt」などを読み込み、
画像データに戻していきます。
import numpy as np
def load_image_from_txt(image_path):
# 画像サイズの読み込み
with open('image_size.txt', 'r') as file:
height = int(file.readline().split(':')[1])
width = int(file.readline().split(':')[1])
# R、G、Bそれぞれの値を読み込み
r_values = np.loadtxt('r_values.txt', dtype=np.uint8)
g_values = np.loadtxt('g_values.txt', dtype=np.uint8)
b_values = np.loadtxt('b_values.txt', dtype=np.uint8)
# 画像を復元, BGR
image = np.zeros((height, width, 3), dtype=np.uint8)
image[:, :, 2] = r_values.reshape((height, width))
image[:, :, 1] = g_values.reshape((height, width))
image[:, :, 0] = b_values.reshape((height, width))
return image
テキストの扱いには、特に追加モジュールは必要ありません。
データの扱いにnumpyモジュールを利用しています。
関数だけの登場なので、そういうものか~という感じですが、
これでimageデータに復元しています。
サンプルコード
サンプルコードその1
やること1で紹介したコードをまとめたサンプルコードがこちらです。
ファイル構成は次の想定です。
RGBデータと幅高さデータを出力します。
sample.py (実行ファイル)
example.jpg (読み込み対象)
image_size.txt (幅と高さデータ(実行結果))
r_values.txt (Redデータ(実行結果))
g_values.txt (Greenデータ(実行結果))
b_values.txt (Blueデータ(実行結果))
実行ファイルの記述は下記のとおりです。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def image_to_rgb_lists(image_path):
# 画像を読み込む
image = cv2.imread(image_path)
# 画像の高さと幅を取得
height, width, _ = image.shape
# R、G、Bそれぞれの値をリストに格納
r_values = image[:, :, 2].flatten()
g_values = image[:, :, 1].flatten()
b_values = image[:, :, 0].flatten()
return height, width, r_values, g_values, b_values
def save_to_txt(data, filename):
with open(filename, 'w') as file:
for value in data:
file.write(str(value) + '\n')
def plot_histogram(values, color_name):
plt.hist(values, bins=256, range=(0, 256), color=color_name, alpha=0.7)
plt.title(f'{color_name.upper()} Histogram')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.grid(True)
# 画像ファイルのパスを指定してRGBデータと画像のサイズを取得
image_path = 'example.jpg' # 画像ファイルのパスを適切に指定してください
height, width, r_values, g_values, b_values = image_to_rgb_lists(image_path)
# ヒストグラムを1つのプロットにまとめて表示
plt.figure(figsize=(12, 6))
# plt.subplot(rows, columns, index)
plt.subplot(2, 3, 2)
plt.imshow(cv2.cvtColor(cv2.imread(image_path), cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 3, 4)
plot_histogram(r_values, 'red')
plt.subplot(2, 3, 5)
plot_histogram(g_values, 'green')
plt.subplot(2, 3, 6)
plot_histogram(b_values, 'blue')
plt.tight_layout()
plt.show()
# 画像のサイズとRGB値をテキストファイルに出力
with open('image_size.txt', 'w') as file:
file.write(f'Height: {height}\n')
file.write(f'Width: {width}\n')
save_to_txt(r_values, 'r_values.txt')
save_to_txt(g_values, 'g_values.txt')
save_to_txt(b_values, 'b_values.txt')
実行した結果がこのようになります。
サンプルコードその2
ファイル構成は上記と同様で、次のファイルを出力します。
sample2.py
restored_image.jpg
import cv2
import numpy as np
def load_image_from_txt(image_path):
# 画像サイズの読み込み
with open('image_size.txt', 'r') as file:
height = int(file.readline().split(':')[1])
width = int(file.readline().split(':')[1])
# R、G、Bそれぞれの値を読み込み
r_values = np.loadtxt('r_values.txt', dtype=np.uint8)
g_values = np.loadtxt('g_values.txt', dtype=np.uint8)
b_values = np.loadtxt('b_values.txt', dtype=np.uint8)
# 画像を復元, BGR
image = np.zeros((height, width, 3), dtype=np.uint8)
image[:, :, 2] = r_values.reshape((height, width))
image[:, :, 1] = g_values.reshape((height, width))
image[:, :, 0] = b_values.reshape((height, width))
return image
def save_image(image, filename):
cv2.imwrite(filename, image)
# 画像を復元して表示
restored_image = load_image_from_txt('image_size.txt')
cv2.imshow('Restored Image', restored_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 画像をファイルに保存
save_image(restored_image, 'restored_image.jpg')
実行結果がこちらです。
無事、復元することができました。
以上となります。
この記事が少しでもお役に立てれば幸いです。
それでは、読んで頂きありがとうございました!