0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

macの画面上のドットのHSV(openCV)の値を検出するアプリをGPT4で作る

Posted at

アプリを作った目的

macの画面上のドットの色を検出するdigital color meterで、RGBしか見られないため、HSV(openCV)を見られるアプリをGPT4で作る。

本記事の目的

  • macの画面上のドットのHSV(openCV)の値を検出するアプリを作ったので、内容をメモ
  • python初心者がGPT4でそれなりに意味のあるアプリを作れるかどうかを検証する

技術

macOS
python
openCV

openCVのHSVの範囲

HSV色空間は、色相(Hue)、彩度(Saturation)、明度(Value)の3つの成分で色を表わす。
これはRGB色空間(Red、Green、Blueで表現)とは異なり、人間の色覚に近い方法で色を扱うことができる。
pythonのopenCVライブラリでは、通常のHSVとは範囲の指定方法が異なる。
以下の表は、通常のHSV色空間とOpenCVでのHSV色空間の範囲の表現方法の違いをまとめたもの。

成分 通常のHSV色空間 OpenCVのHSV色空間
色相(Hue) 0度から360度 0から180
彩度(Saturation) 0%から100% 0から255
明度(Value) 0%から100% 0から255

リアルタイムの色検出の代替策

マウスカーソルが指している最前面のアプリの画面上の点の色をリアルタイムで認識するには、macOSの特別な機能を利用する必要がある。
もし、この特別な機能を利用せずに色を検出しようとすると、アプリの色ではなく、デスクトップの背景色を誤って検出することになる。
これは、Macのセキュリティがアプリ間の干渉を防ぐために厳しく設定されているためだ。
調査の結果、Macのこの機能をPythonで使用するのは難しいことがわかったため、代わりにアップロードされた画像の色を分析する方法を選んだ。

GPT4でのコード生成

大体以下のような指示を出した。

GUIでユーザーからのファイルを受け取り、それを画面の左側表示するようにする。
画像をマウスオーバーしたドットの、openCV仕様のHSVの値を、画面右の中央に表示する。

諸々微調整して、変数名や関数名の改善、リファクタリングなどを施した結果、以下のようなコードができた。

import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import cv2
import numpy as np


class ColorMeterApp:
    """
    HSV値とRGB値を表示するためのデジタルカラーメーターアプリ。
    PILとOpenCVを利用して、選択した画像上でマウスカーソルが指す位置の色情報を表示します。
    """

    def __init__(self, master):
        self.master = master
        self.master.title("Digital Color Meter")

        self.initialize_ui()
        self.initialize_image_variables()

    def initialize_ui(self):
        """UIコンポーネントの初期化と配置を行います。"""
        self.master.geometry("300x100")
        self.label_message = tk.Label(self.master, text="画像を選択してください")
        self.label_message.pack(side=tk.TOP, pady=10)

        self.btn_open = tk.Button(self.master, text="Open", command=self.open_image)
        self.btn_open.pack(side=tk.LEFT, padx=120, pady=10)

        self.canvas = tk.Canvas(self.master, width=300, height=600)
        self.canvas.pack(side=tk.LEFT, padx=30)

        self.rgb_label = tk.Label(self.master, text="")
        self.rgb_label.place(relx=0.8, rely=0.45, anchor="center")

        self.hsv_label = tk.Label(self.master, text="")
        self.hsv_label.place(relx=0.8, rely=0.5, anchor="center")

        self.converted_hsv_label = tk.Label(self.master, text="")
        self.converted_hsv_label.place(relx=0.8, rely=0.55, anchor="center")

    def initialize_image_variables(self):
        """画像処理用の変数の初期化を行います。"""
        self.photo_image = None
        self.cv_image = None
        self.hsv_image = None

    def open_image(self):
        """画像ファイルを開くためのダイアログを表示し、選択された画像を処理します。"""
        file_path = filedialog.askopenfilename()
        if not file_path:
            return

        image = Image.open(file_path)
        self.adjust_ui_for_image(image)
        self.process_image(image)

    def adjust_ui_for_image(self, image):
        """画像選択後のUIの調整を行います。"""
        self.master.geometry("800x800")
        self.label_message.destroy()
        self.btn_open.pack(side=tk.BOTTOM, padx=10, pady=30)

    def process_image(self, image):
        """画像の処理とマウスイベントバインドを行います。"""
        resized_image = image.resize(
            (image.width // 2, image.height // 2), Image.Resampling.LANCZOS
        )
        self.photo_image = ImageTk.PhotoImage(resized_image)
        self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo_image)
        self.canvas.bind("<Motion>", self.show_values)

        # OpenCVでの画像処理
        self.cv_image = cv2.cvtColor(np.array(resized_image), cv2.COLOR_RGB2BGR)
        self.hsv_image = cv2.cvtColor(self.cv_image, cv2.COLOR_BGR2HSV)

    def show_values(self, event):
        """マウスカーソル位置の色情報を表示します。"""
        if self.hsv_image is not None:
            x, y = event.x, event.y
            if x < self.cv_image.shape[1] and y < self.cv_image.shape[0]:
                self.display_color_values(x, y)

    def display_color_values(self, x, y):
        """指定された位置のRGBとHSVの色情報を表示します。"""
        hsv_value = self.hsv_image[y, x]
        rgb_value = self.cv_image[y, x]

        h, s, v = hsv_value
        b, g, r = rgb_value

        h_converted, s_converted, v_converted = h * 2, s / 255 * 100, v / 255 * 100

        self.rgb_label.config(text=f"RGB: ({r}, {g}, {b})")
        self.hsv_label.config(text=f"OpenCV HSV: ({h}, {s}, {v})")
        self.converted_hsv_label.config(
            text=f"HSV: ({h_converted:.0f}, {s_converted:.0f}, {v_converted:.0f})"
        )


def main():
    root = tk.Tk()
    app = ColorMeterApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()

実際に動かすと、画像を受け取り、マウスカーソルを合わせると、ドットのRGB,HSV,openCVでのHSVがとれるアプリが立ち上がる。

image.png image.png

まとめ

python初心者が、GPT4を使って、入力画像のopenCVでのHSVの値を検出するアプリを作ることができた。
これを機に、pythonも勉強していこうかと思った。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?