画像のヒストグラム取得とcsvファイルへの書き出し cv2.calcHist()


画像のヒストグラムを取得し、CSVファイルに出力する方法を紹介します。

開発環境はjupyter notebook、言語はpythonです。

今回使用した画像・コード一式はgoogle driveにも保存しておりますので、必要に応じてお使いください。

作成したコード

#モジュールのインポート
import cv2
import glob
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import os
%matplotlib inline

#RGB画像のヒストグラム取得
filename = glob.glob("*.jpg")
df = pd.DataFrame()
for num in range(len(filename)):
    print((os.path.split(filename[num])[1]))
    img = cv2.imread(filename[num])
    color = ['b','g','r']
    for index, item in enumerate(color):
        histgram = cv2.calcHist(img,[index],None,[256],[0,256])
        df[(os.path.split(filename[num])[1])+"_"+item] = pd.Series(np.reshape(histgram,-1))
    df.to_csv("hist_RGB.csv")   

#グレースケール画像のヒストグラム取得
filename = glob.glob("*.jpg")
df_gray = pd.DataFrame()
for num in range(len(filename)):
    print((os.path.split(filename[num])[1]))
    img = cv2.imread(filename[num])
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    histgram = cv2.calcHist(img,[0],None,[256],[0,256])
    df_gray[(os.path.split(filename[num])[1])] = pd.Series(np.reshape(histgram,-1))
    df_gray.to_csv("hist_gray.csv")  

#RGBグラフ表示
filename = glob.glob("*.jpg")
img = cv2.imread(filename[0])
for i,col in enumerate(color):
    hist = cv2.calcHist(img,[i],None,[256],[0,256])
    plt.plot(hist,color = col)
    plt.xlim([0,256])
plt.show()

処理の解説

ヒストグラムの取得

今回のプログラムのポイントは次の処理になります!
histgram = cv2.calcHist(img,[index],None,[256],[0,256])
opencvの公式サイトを見ると、本コマンドは次の要素で構成されていると解説されています。
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])

それぞれの変数については、次の表にまとめています。

imagesヒストグラムを取得する画像を指定
channelsヒストグラムを取得するチャンネル(色)の指定 
[0]:B(青)
[1]:G(緑)
[2]:R(赤)
mask特定の領域のヒストグラムを取得する場合、使用する
今回は全体の画素を取得するためNone
histSizeヒストグラム取得時の諧調数を指定
rangesヒストグラムを計測する画素値の範囲を指定

今回のプログラムではBGRの3チャンネルの0~256の画素値のヒストグラムを取得するような処理になっています。

CSVファイルへの書き出し

さらに取得したヒストグラムをpandasのデータフレームに追加して、CSVファイルとして保存する処理を行います。
まずは下記のコマンドによって、空のデータフレームを用意します。
df = pd.DataFrame()
次に下記のpd.Series()のコマンドによって、取得したヒストグラムをデータフレームに追加していきます。
df[(os.path.split(filename[num])[1])+"_"+item] = pd.Series(np.reshape(histgram,-1))
df[カラム名] = pd.series(追加したいデータ)という記述方法になります。
今回カラム名は画像名+チャンネル名(RGB)にしています。
なおcv2.calcHistで取得したデータでは、そのままデータフレームに追加できなかったため、今回は別途np.reshapeで配列を1次元に変更しています。

最終的にデータフレームを下記コマンドで、CSVファイルにすることで完成です。
df.to_csv("hist_RGB.csv")  
トップの画像はヒストグラムを取得しグラフ化したものですが、どういう理由でこのような分布になっているのか、見た目で考えるのは難しいですね。

グレースケール画像で見ると、数値と画像の関連性が把握しやすいかなと思います。

今回使用した画像:台湾まぜそば/麺屋まぜはる

ニラ、ニンニクなどが入ったガツンと来る感じの油そばです!
麺を食べ終わった後にどんぶりに入れてもらう白ご飯もめちゃくちゃ美味しいです。

コメント