(05)Dear PyGuiで画像表示アプリ

 2nd January 2023 at 9:30pm

Dear PyGuiを使って、画像ファイルを表示するアプリケーションを作ってみます。

後に、画像処理なども行う予定なので、表示以外はOpenCVを利用します。

画像を描画する手順としては、以下の通りです。

  1. 画像を「テクスチャー」にして、 「テクスチャーレジストリ」に追加します。
  2. 「テクスチャー」を描画コマンドを使って、描画用コンテナに追加します。
    • 追加できるコンテナは、ビューポート/ウィンドウ/ドローリスト(drawlist)です。
    • 画像を描画するコマンドには、dpg.draw_image()dpg.add_image()があります。

テクスチャー

Dear PyGuiでは、画像を「テクスチャー」にして「テクスチャーレジストリ」に追加する必要があります。

以下はテクスチャーレジストリの作成の例です。ウィンドウなどと同様です。

with dpg.texture_registry():
    dpg.add_static_texture(image_width, image_height, image_data, tag="texture_id")

テクスチャーには以下の3タイプがあります。

  • Static(静的)
    • 頻繁に変更されない画像に使用されます。
    • 一度読み込んだテクスチャーを変更することはできません。
  • Dynamic(動的)
    • 変化する可能性のあるテクスチャに使用されます。
    • テクスチャーを変更することが可能です。ただし、サイズを変更することはできません。
  • Raw(生データ)
    • 動的テクスチャと同じように利用します。
    • 主な違いは「テクスチャーにできるのは配列のみ」、「安全チェックは行われない」。

image_dataには、floatのRGBA形式の配列を入力する必要があります。

OpenCVを利用する場合は、cv2.cvtColor()を使ってRGBA形式にし255で割って、0から1の小数に変換する必要があります。

また、画像を描画するコマンドには、dpg.draw_image()dpg.add_image()があります。

今回は、dpg.add_image()を使います。

今回はドローリストは使わず、ウィンドウに直接に、画像を描画します。

サンプルスクリプト

上記の方法で作成したサンプルクリプト10です。

起動時に、実行するpyファイルと同じフォルダに以下の画像「Default.png」を入れてください。

DearPyGui_Sample10.py

# サンプルスクリプト10

import os
import dearpygui.dearpygui as dpg
import easygui as eg
import numpy as np
import cv2

# 実行するpyファイルのあるディレクトリ名の取得
DIR = os.path.dirname(__file__)

# DearPyGuiのアイテ「x」がすでにある場合は削除する関数
delItemIfExist = lambda x: dpg.delete_item(x) if dpg.does_item_exist(x) else ""

# 画像をRGBA形式で開く関数
imread_rgba = lambda x : cv2.cvtColor(cv2.imread(x), cv2.COLOR_BGR2RGBA)

# 画像ファイルをテクスチャーレジストリに登録し、描画する関数
def draw_image_opencv(img, tag_texture_registry, parent=None):
    h, w, ch = img.shape
    if ch != 4:
        return
    delItemIfExist("txtr_for_this_func")
    delItemIfExist("img_for_this_func")
    dpg.add_static_texture(w, h, img/255, parent=tag_texture_registry, tag="txtr_for_this_func")
    if parent is None:
        return dpg.add_image("txtr_for_this_func", tag ="img_for_this_func", width=w, height=h)
    else:
        return dpg.add_image("txtr_for_this_func", parent=parent, tag ="img_for_this_func", width=w, height=h)

# ボタンを押した時のコールバック
def button_callback(sender, app_data, user_data):
    fname = eg.fileopenbox()
    img = imread_rgba(fname)
    draw_image_opencv(img, "texture_registry_01", parent="window2")
 
# 以下、DearPyGuiの基本構成 
dpg.create_context()
dpg.create_viewport(title='Title', width=600, height=600)

# テクスチャーレジストリの作成
with dpg.texture_registry(tag="texture_registry_01"):
    pass

# window01の作成
with dpg.window(label="window01"):
    dpg.add_button(label="file open", callback=button_callback)

# windows02の作成(Default.pngを読み込みます)
with dpg.window(label="window02", pos=(100,0), width=400, height=400, tag="window2", horizontal_scrollbar=True):
    fname = DIR + "/Default.png"
    img = imread_rgba(fname)
    draw_image_opencv(img, "texture_registry_01")

dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()

実行すると、

[file open]ボタンを押して、画像ファイルを選択すると、

サンプル10を簡単に説明します。

ファイルオープンダイアログは「EasyGUI」を使っています。「pip install easygui」でインストールしておきましょう。とても簡単に汎用的なGUIを利用することができるモジュールです。

まず、ラムダ式を使って、DearPyGuiのアイテム「x」がすでにある場合は削除する関数「delItemIfExist」と、画像をRGBA形式で開く関数「imread_rgba」を作成します。

さらに、それらを利用して、画像ファイルをテクスチャーレジストリに登録し、描画する関数「draw_image_opencv」を作成します。すでにあるアイテム「txtr_for_this_func」「img_for_this_func」(本関数内でのみ使用します)を削除し、再作成しています。

ボタンが押されると、ファイルオープンダイアログが開き、次に「draw_image_opencv」関数が実行されます。

with window01()内で呼び出され、window01アイテムにテクスチャーを描画する場合はparent=Noneで構いません。

今回は、window01アイテムで呼び出されて、window02アイテムに描画するので、parent="window2"と指定する必要があります。

dpg.create_context()以降は、今まで繰り返してきたDearPyGuiのアイテムの作成や表示などの基本的な流れです。

dearpygui.dearpygui.window(**kwargs)の引数の1つの「tag」について少し説明します。

「tag」はプログラムでアイテムを参照するために使用されるユニークな IDです。「label 」が使用されていない場合は、これが「label 」になります。

サンプル10では以下のようにしています。

with dpg.window(tag="window01"):
    ・・・

つまり、「label 」もwindow01になります。


Homeへプログラミングの記事Topへ