【PyQt5】キャンバスへの画像表示・動的差し替え、画像処理結果のリアルタイム表示【Python × GUI】

GUI eye_catch

OpenCVやOCRなどのライブラリを使用して画像処理を行う場合、アプリケーションを終了せずに入力画像や動画フレームを動的に差し替えられたら、デバッグ作業の効率が格段に向上します。

CUI形式でも入力ファイルのフォーマットを工夫することや、ユーザからの入力待ち状態を設けることで入力画像の差し替え自体は可能ですが、入力画像に対して実行する操作の量が増えてくるほど、コマンドラインが煩雑になり、作業効率がかえって下がる恐れがあります。

一方、GUI形式であれば、テキストボックスやメニューを使用して入力情報を更新したり、入力に対する出力情報をメインウィンドウ上にリアルタイムで表示することができるメリットがあります。デメリットとしては、GUIアプリケーション作成のための学習コストが高いことと、処理負荷が高いことが挙げられますが、OpenCVやTesseract(OCR)などの既存のライブラリを使用する上ではさほど問題とはなりません。

本記事では、PythonのPyQt5パッケージを使用して指定した入力画像や動画をGUI上のウィジェット内に表示することを導入として、入力画像を動的に差し替える方法や、画像処理結果のリアルタイム表示、OCR結果のリスト表示する方法を紹介します。※動画再生、動画のフレームを任意に切り替える方法やについては、別の記事にまとめる予定です。

以下のような方にご覧いただき、課題解決の一助となりましたら、幸いに思います。

  • GUIアプリケーションに興味がある方
  • 独自にカスタマイズ可能な画像表示、動画再生用のアプリケーションを開発したい方
  • 画像処理用のアプリケーション開発を効率化したい方

 

広告

動作確認済み環境


OS: Windows 10 Home (64bit)
CPU: Intel Core i7-9750H
Python: 3.8.5
プラットフォーム: Anaconda 3
パッケージ: pytesseract(0.3.7)※、pyqt(5.9.2)、opencv(4.0.1)
※Tesseract(64bit、v5.0.0)をこちらのwikiをもとに別途インストール済み

 

アプリケーション概要


具体的な実装内容を紹介する前に、私が実際に作成したアプリケーションの概要を紹介します。

アプリケーションのソースコードはGitHubで公開しています。

ソースコードはこちら

実行時に指定するコマンドライン引数と処理概要は以下の通りです。キャンバスサイズはスクリプト実行時にコマンドライン引数で指定するようにしていますが、ソースコードを改修することでGUI上から変更することも可能になります。

(コマンドライン引数)

オプション引数(省略可) デフォルト値 説明
-cw, –canvas_width 420 ウィジェットに表示する画像サイズ(横幅)
-ch, –canvas_height 300 ウィジェットに表示する画像サイズ(縦幅)

(機能概要(共通))

  • 「input_file_name」ラベル直下のテキストボックスに入力ファイル名を指定し、「Load」ボタンが押すと、キャンバス内に画像・動画が表示される
    (表示サイズはコマンドライン引数で指定したものにアスペクト比を保ったまま自動変換されます。動画は1フレーム目が表示されます。)
  • 「output_file_name」ラベル直下のテキストボックスに出力画像名を指定し、「Save」ボタンを押すと、キャンバス内の画像が保存される
  • ドロップダウンメニューで「RGB」を指定するとカラー画像、「MONO」を指定すると2値化画像がキャンバスに表示される
  • キャンバス内に表示されている画像からpytesseract(OCR)で文字変換した結果が、キャンバス直下のテーブルに表示される

(機能概要(動画のみ))

  • 「Start」ボタンを押すと、動画が再生される
  • 「Stop」ボタンを押すと、動画再生を停止する
  • スクロールバーを移動すると、キャンバス内に表示される動画フレームが切り替わる

(GUIイメージ)

※PNGフォーマットの画像を表示(左:カラー表示、右:2値化結果)

gui_input_rgb_imagegui_input_mono_image

※mp4フォーマットの動画を表示(左:カラー表示、右:2値化結果)

gui_input_rgb_moviegui_input_mono_movie

 

実装方法の解説

本章では、主にpyqt5_image_viewer_test.py内のウィジェットの作成方法について記載します。メインウィンドウやタブの実装方法(main.pymain_tab.py)については特筆すべき点がないため割愛します。

キャンバスへの画像表示、キャンバスの表示内容を画像出力


①入出力ファイル名を受け付けることができるようにテキストボックスを作成する

(使用するQtWidgets関連クラス)

  • QLabel: テキストボックスの説明書きを出力するために使用
  • QLineEdit: テキストボックスに入力された文字列を制御するために使用

(該当コード(抜粋・コメント追記))

QLabelのコンストラクタに引数渡しした文字列がウィジェット上に表示されます。

 

テキストボックス内の文字列を編集すると、QLineEdit::textChanged.connectメソッドで指定した関数がコールされます。テキストボックス内の文字列はQLineEdit::displayTextメソッドで取得できます。

 

②画像表示用のキャンバスを作成する

(使用するQtWidgets関連クラス)

  • QLabel: キャンバスの背景に設定する白色画像を表示するために使用
  • QImageQPixmap: QLabelに設定可能な画像表示用ウィンドウを作成するために使用

(該当コード(抜粋・コメント追記))

背景画像はOpenCVのimreadメソッドでカラー画像を読み込むことを想定して、8 ビット符号なし整数かつ3チャンネルで定義しています。OpenCVで読み込んだ画像は直接QLabelウィジェット上に表示することはできないため、QImage形式に変換した上で、変換後の画像をQPixmapに設定する必要があります。

 

③キャンバスに画像を設定する

(使用するQtWidgets関連クラス)

  • ②と同じ

(該当コード(抜粋・コメント追記))

②で作成した背景画像の一部に入力画像をコピーすることで、キャンバスの表示内容を更新できるように実装しています。入力画像のファイル名は上記①で作成したテキストボックスで指定することを想定しています。

 

④キャンバスの表示内容を更新するボタン(Load)を作成する

(使用するQtWidgets関連クラス)

  • QPushButton: キャンバスへの画像設定、レイアウト更新のトリガとなる「Load」ボタンを作成するために使用

(該当コード(抜粋・コメント追記))

ボタンを押下すると、QPushButton::clicked.connectメソッドで指定した関数がコールされます。コールされた関数内で、上記③の方法でキャンバスに画像を設定し、レイアウトを更新することで、キャンバスへの表示内容を変更できるように実装しています。

 

⑤キャンバスの表示内容を画像として出力するボタン(Save)を作成する

(使用するQtWidgets関連クラス)

  • ④と同じ

(該当コード(抜粋・コメント追記))

上記④と同様の方法でボタンを押下時にコールされる関数内で画像を出力できるように実装しています。
広告

 

ドロップダウンメニュー(コンボボックス)による画像処理内容の変更


①内部変数を動的に更新できるように、ドロップダウンメニューを作成する

(使用するQtWidgets関連クラス)

  • QComboBox: テキストボックスの説明書きを出力するために使用

(該当コード(抜粋・コメント追記))

コンボボックスで表示中のメニューを切り替えると、QComboBox::currentTextChanged.connectメソッドで指定した関数がコールされます。選択したメニューの表示名はQComboBox::currentTextメソッドで取得できるため、この表示名をもとにアプリケーション内の処理内容を動的にスイッチできます。

 

OCRによる文字変換結果をテーブル形式で表示


①OCRにより画像を文字列に変換し、リスト形式で格納する

(使用するQtWidgets関連クラス)

  • なし

(該当コード(抜粋・コメント追記))

pytesseractパッケージのimage_to_stringメソッドで画像ファイルを文字列に変換することができます。pytesseractパッケージを使用する場合は、事前に文字認識エンジンのTesseractをインストールし、パスを通しておく必要があります。image_to_stringメソッドの引数に「lang=”jpn”」を指定することで日本語にも対応可能です。デフォルトでは英語「lang=”eng”」が使用されます。

 

②テーブルを作成し、文字列変換結果を設定する

(使用するQtWidgets関連クラス)

  • QTableWidget: 文字列変換結果をテーブル形式で表示するために使用
  • QTableWidgetItem: テーブルの1セルに表示するアイテムを設定するために使用

(該当コード(抜粋・コメント追記))

テーブルへのアイテムの追加はQTableWidget::setItemメソッドに、行列数とQTableWidgetItem型のオブジェクトを指定すること行うことができます。以下の記事でテーブルのアイテムが変換された場合の処理やcsv形式で保存する方法を紹介していますので、興味がある方はこちらも合わせてご覧ください。
関連記事

PyQt5で作成したGUIウィンドウで、メインタブのイベントをトリガーとして、複数タブの情報を制御する方法を紹介します。 開発環境は以下の通りです。 OS: Windows 10 64ビット 開発言語: Python […]

communicate-between-multiple-tabs-on-pyqt5
広告