【Python】画像内でクリックした箇所のRBG・HSVの値を取得しExcelに出力する方法

※このサイトの記事内では広告を掲載している場合があります。

今回は、Pythonを用いて、画像内でクリックした箇所のRGBやHSVの値の色情報を、自動的にExcelに出力するプログラムを作成しました。

もちろん、Excelに出力させずに値を出力する方法も解説していますので参考にしてみてください。

実行環境
C:\...>Python --version
Python 3.5.2 :: Anaconda 4.2.0 (64-bit)

※Anacondaは特に必要ないです。

無料オンライン相談を活用しよう!

Pythonというプログラミング言語は機械学習の人気の高まりなどもあり、様々なスクールが無料説明会を開催しています。

その中でも「Freeks(フリークス)|業界初!10,780円のサブスク型プログラミングスクール」がオススメです。Pythonを効率よく学びたいという方はまずは適性を知るためにも無料説明会を利用しましょう。

無料説明会を参加してみる!

RGBとHSV色空間について

普段の生活の中で、「淡いピンク」とか、「藤の色」など似た色や曖昧な色を表現することがあると思います。それらは、光の三原色をもとにした、「赤」、「緑」、「青」の色を、数字で表した場合にも、私たちが見ている性質と似たような傾向をとることがあります。

一方で、別の色空間で見た時には、先ほどの似たような色も、全く異なる性質として表現できる場合があり、色でクラス分けをするための閾値を設定する際にも便利なことがあります。

今回扱う色空間は2つあります。「RGB色空間」と「HSV色空間」です。

RGB色空間は、普段人間が見ている世界です。R:Red、G:Green、B:Blueの頭文字をとってRGBです。一方で、HSVは、美術の時間で習ったかと思いますが、H:Hue(色相)、S:Saturation(彩度)、V:Value(明度)の頭文字です。

似た色の性質

先ほどの、「似た色でも性質が異なる」とはどういうことでしょうか?具体例を示します。以下の2つの色を見てください。


カラーコード:#99A7A8

(R, G, B)=(153, 167, 168)
(H, S, V)=(184, 8, 65)


カラーコード:#AEA7A8

(R, G, B)=(174, 167, 168)
(H, S, V)=(351, 4, 68)

比較すると、全然色が違うと思うかもしれませんが、単体で見た時には両方とも「ネズミ色」と答える方もいるのではないでしょうか?

1枚目の画像に少しだけ赤の要素を強くしたのが2枚目になります。ここで、RGB色空間では、Rの値が21の差がありますが、HSV色空間で見た時、Hの値は167も異なります。

別の色空間で見た時には、似た色でも異なる性質として分類することが出来るとはこういう理由です。

さて、今回は、各パラメータの値をExcelに出力していくので、それぞれの値の範囲を確認していきます。

パラメータ値の範囲
R, G, B0 ~ 255(2 ^ 8種)
H0 ~ 360
S, V0 ~ 100

カラースポイトによって求められたRGBの値からHSVへの変換が可能です。変換式が多少複雑ではありますが紹介していきます。(プログラムによって直接HSVの値を求めるとこも当然可能ですが、今回は変換式を利用しました。)

色について詳しく知りたい方は以下の本を参考にしてみてください!

RGBからHSVの変換式

ここは変換公式の紹介なので、興味がある方は読んでみてください。
画像出典:プチモンテさん

Hue(色相)の変換

※Max = max(R, G, B)、Min = min(R, G, B)とします。

Rが最大値の時: H = 60 × ((G – B) ÷ (Max – Min))
Gが最大値の時: H = 60 × ((B – R) ÷ (Max – Min)) + 120
Bが最大値の時: H = 60 × ((R – G) ÷ (Max – Min)) + 240


3つとも同じ値の時: H = 0

ただし、求めた値が負の数だった場合、360を足して正の数にします。(H += 360)

Saturation(彩度)の変換

※Max = max(R, G, B)、Min = min(R, G, B)とします。

S = 100 × (Max – Min) ÷ Max

Value(明度)の変換

※Max = max(R, G, B)、Min = min(R, G, B)とします。

V = 100 × Max ÷ 255

コード紹介

ここからが本題ですね。

改めて、今回の目的は、「画像内でクリックした箇所の色情報を、自動的にExcelに出力する」でした。画像を扱ったり、Excelを扱うためライブラリを準備していきましょう!

必要なライブラリ


import cv2
import pandas
import numpy

実行した際にエラーが出てくる場合は、ライブラリをインストールしてください。コマンドプロンプト(Anaconda)で以下のコードを入力するとデータがダウンロードされます。


pip install cv2
pip install pandas
pip install numpy

全体のコード

最初に、Pythonの実行環境と同じフォルダに画像とExcelファイルを準備してください。サンプルコードでの名前はそれぞれ、”picture_filename”, “Excel_filename”としました。


import cv2
import pandas as pd
import numpy as np

picture_filename = "colorful.jpg"
Excel_filename = "RGB_HSV.xlsx"
num = 10

def Calc_HSV(R, G, B):
    Max = max(R, G, B)
    Min = min(R, G, B)

    #グレースケール画像の時RGBは同じ値。不定形によるNaNエラーの回避?の想定。
    if R == G == B:
        if Max == 255:#真っ白の時
            return 0, 0, 100
        if Max == 0:#真っ黒の時
            return 0, 0, 0

    try:
        if R == Max:#Rが最大の時
            H = int(60 * (G - B) / (Max - Min))
        if G == Max:#Gが最大の時
            H = int(60 * (B - R) / (Max - Min) + 120)
        if B == Max:#Bが最大の時
            H = int(60 * (R - G) / (Max - Min) + 240)
        if H < 0:   #Hが負の時+360
            H += 360
    except ZerodivisionError:#passではなく、何かしらの処理はしたほうが良い
        pass

    S = int(100 * (Max - Min) / Max)
    V = int(100 * Max / 255)

    return H, S, V

def onMouse(event, x, y, flags, params):
    global value, count #グローバル変数の利用
    
    if event == cv2.EVENT_LBUTTONDOWN:#左クリックがされたら
        count += 1
        crop_img = img[[y], [x]]
        B = crop_img.T[0].flatten().mean()#返り値はBGRの順番
        G = crop_img.T[1].flatten().mean()
        R = crop_img.T[2].flatten().mean()

        H, S, V = Calc_HSV(R, G, B)#自作関数の利用
        value.append([R, G, B, H, S, V])
            
        print("{}回目, R: {}, G: {}, B: {}, S: {}, S: {}, V: {}".format(count, R, G, B, H, S, V))

        if num <= count:#一定回数後にExcelに出力
            Print_Excel()
            cv2.destroyAllWindows()

def Print_Excel():#出力内容の決定
    df = pd.DataFrame([rows for rows in value])
    df.columns = ['R', 'G', 'B' ,'H', 'S', 'V']#列の設定
    df.index = [i for i in range(1, num + 1)]  #行の設定
    df.to_excel(Excel_filename)                #Excelへ出力
    df

    
if __name__ == "__main__":#メイン関数
    value = []#RGB, HSVの値の格納用配列
    count = 0
    img = cv2.imread(picture_filename, cv2.IMREAD_COLOR)
    window_name = 'img'
    cv2.imshow(window_name, img)
    cv2.setMouseCallback(window_name, onMouse)
    cv2.waitKey(0)

Excelに出力するのがたったの5行でかけてしまうのがすごいですね。実行する際に各自でファイル名やクリック数を調整しやすいように最初のほうに記述しました。

関数は全部で3つあります。関数「Calc_HSV」は、受け取ったRBGの値からHSVの値を返り値とする関数です。グレースケール画像(白や黒、灰色など)に関しては、返り値は事前に設定しました。

また、この場合RGBの値はすべて同じになるので、(Max – Min)が0になるのですが、Hを計算する際に0で割る可能性があるので、例外処理を設けました。

ただ、その前に真っ黒と真っ白の時の処理を入れたので意味はないように思います。。。

今回使った画像はこちらです。自由にダウンロードしてください。

画像

今回のコードの場合、メモリのことをあまり考えていないので、もっと大量のデータをExcelに出力したい場合は、クリックしたときに、逐一データを出力する手法がいいと思います。

出力結果

"""
1回目, R: 210.0, G: 145.0, B: 227.0, S: 287, S: 36, V: 89
2回目, R: 255.0, G: 204.0, B: 255.0, S: 300, S: 20, V: 100
3回目, R: 242.0, G: 3.0, B: 88.0, S: 339, S: 98, V: 94
4回目, R: 117.0, G: 48.0, B: 33.0, S: 10, S: 71, V: 45
5回目, R: 188.0, G: 71.0, B: 124.0, S: 333, S: 62, V: 73
6回目, R: 231.0, G: 214.0, B: 64.0, S: 53, S: 72, V: 90
7回目, R: 129.0, G: 59.0, B: 59.0, S: 0, S: 54, V: 50
8回目, R: 239.0, G: 139.0, B: 211.0, S: 317, S: 41, V: 93
9回目, R: 97.0, G: 6.0, B: 11.0, S: 357, S: 93, V: 38
10回目, R: 56.0, G: 41.0, B: 10.0, S: 40, S: 82, V: 21
"""
エクセル

ランダムな10箇所から値を出力した結果です。データがちゃんと入っていない場合は、Excelのファイル名が間違っているか、実行環境と同じフォルダにファイルが存在していないなどが考えられます。

まとめ

今回は、画像内でクリックした箇所のRGBの値を取得し、得られた値からHSV色空間の値の変換を行いました。

また、それらのデータをExcelに出力する方法も解説しました。

次の記事では、「Excelファイルを用いて、3D散布図を作成」することにより、画像の特徴を抽出していきます。

こちらも参考になれば嬉しいです。

今回の記事で、Excelへの出力がこんなにも簡単にできるんだと思われた方も多いと思います。これが可能なのもモジュールがあるからですね!感謝です笑。

最後に、下の本は昔読んでわかりやすかった代物です。よろしければどうぞ!

無料の説明会を有効活用しよう!

独学での学習は孤独感を感じやすく挫折してしまう初心者も多いです。また、参考書を購入しても全く読む気にならないという方も多いはずです。

それでも、なんとかPythonの勉強を行い、高スキルなエンジニアを目指したいという方は無料で受けられるオンライン説明会に参加してみることも一つの手です。

Pythonというプログラミング言語は機械学習の人気の高まりなどもあり、様々なスクールが無料説明会を開催しています。

その中でも「Freeks(フリークス)|業界初!10,780円のサブスク型プログラミングスクール」がオススメです。Pythonを効率よく学びたいという方はまずは適性を知るためにも無料説明会を利用しましょう。

無料説明会を参加してみる!

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

CAPTCHA