Help us understand the problem. What is going on with this article?

PyQtでFileIO

概要

前回の記事は、Qt World Summit 2019の参加報告でした。その時に、PyQtに関心が高まってきているのを感じました。機械学習とかOpenCVをサクッと利用するのにPythonは適している。そこで、PyQtでちょろっと作業してみます。

対象読者

  • Pythonに興味がある
  • PythonのGUI作成に触れてみたい
  • Qtを使っているがPythonでは作業したこと無い

筆者の開発環境

  • Windows 10 Home
  • Anaconda 3 Python 3.7.4
  • Python 3.6.9(conda create)
  • PyQt 5.13.2
  • PySide2 5.13.2

Python環境は下記のコマンドで作成している。
ー Python3.6環境 (環境名:Pytyon36)
conda create -n python36 python=3.6 spyder pandas jupyter matplotlib numpy
ー Python3.7環境 (環境名:Pytyon37)
conda create -n python37 python=3.7 spyder pandas jupyter matplotlib numpy

今回はPython36の方を使用する。
その他にも下記のパッケージをインストールしておく。
pip install PyQt5
pip install PySide2
pip install opencv-python

PySide2でQApplicationの実行時エラー

image.png

下記のようなコードを書いて実行!!としてみたら上図のようなエラーが発生する。

import sys
from PySide2.QtWidgets import QApplication

if __name__ == "__main__":
    app = QApplication([])
    sys.exit(app.exec_())

調べてみると、Anaconda3/envs/python37/Library/pluginsの中のパスが正常に反映されないみたいだ。PyQt5を利用するとこのエラーは出なかった。

下記のようにおまじないを入れると、きちんとplatformsのパスが認識されて実行時のエラーがでなくなった。第1のつまづきポイントだった。

import sys,os
import PySide2

dirname = os.path.dirname(PySide2.__file__)
plugin_path = os.path.join(dirname, 'plugins', 'platforms')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path

おまじない以外の解決方法
① Anaconda3\envs\python37\Lib\site-packages\PySide2\plugins\platforms
② Anaconda3\envs\python37\Library\plugins\platforms

①のqwindows.qllを②のものに置き換えるとエラーなく動作した。

完成イメージ(Gif)

PyQtFileIo.gif

詳細

インポートするパッケージ

import sys
import os.path

import numpy as np
import cv2

from PyQt5.QtWidgets import QMainWindow, QAction, QApplication, QTextEdit, QFileDialog

今回はPySide2を使用せず、PyQt5を使います。使っている感触的に、PySide2だと動作するけど、PyQt5では動作しないみたいなことが多かったし、これからはどっちを使っていくべきなのか悩ましい。

QApplication

def main():
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

アプリケーションオブジェクトの生成。QApplicationを使用する。QMainWindowクラスを継承したMainWindowクラスのオブジェクトを呼び出す。

QMainWindowを継承したMainWindowクラス

class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()

        self.textEdit = QTextEdit()
        self.setCentralWidget(self.textEdit)
        self.statusBar()

        self.statusBar()

        openFile = QAction('&File', self)
        openFile.triggered.connect(self.show_file_dialog)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&Menu')
        fileMenu.addAction(openFile)

        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Menubar')
        self.show()

init関数の中で、ボタンやメニューバーなどの配置、Windowサイズの定義などを行う。

FileDialog

    def show_file_dialog(self):
        file_name = QFileDialog.getOpenFileName(self, 'Open file', '/home')

        if file_name[0]:
            print(file_name[0])
            self.identify_extension(file_name[0])

    def identify_extension(self, path):
        root, ext = os.path.splitext(path)
        print(path)
        if ext == '.txt':
            f = open(path, 'r')
            with f:
                data = f.read()
                self.textEdit.setText(data)
        elif ext == '.jpg' or ext == '.png':
            read_img = ReadImg(path)
            b, c = read_img.open_img()
            d = read_img.canny(b)
            cv2.imshow("", d)
            cv2.waitKey(0)
            cv2.destroyAllWindows()

Fileの読み込みをするのに、FileDialogを使用する。画像とテキストファイルの両方を読み込む。画像の読み込みにはOpenCVを使用する。

画像読み込みクラス

class ReadImg:
    def __init__(self, file):
        self.file = file
        print(self.file)

    def open_img(self):
        pic = cv2.imread(self.file)
        pic_color = cv2.cvtColor(pic, cv2.COLOR_BGR2RGB)
        return pic, pic_color

    def canny(self, pic):
        img = cv2.cvtColor(pic, cv2.COLOR_BGR2GRAY)
        edges = cv2.Canny(img, 100, 200)
        edges2 = np.zeros_like(pic)
        for i in (0, 1, 2):
            edges2[:, :, i] = edges
        add = cv2.addWeighted(pic, 1, edges2, 0, 4, 0)
        return add

まとめ

 C++とQMLでのアプリケーション作成はある程度慣れてきたので、Pythonの勉強もかねてPyQtの勉強を始めた。C++で作成するよりもエラーでつまづくことが多い。しかもパッケージのバージョンなどの整合性が取れないなどの面倒なタイプが多くて四苦八苦する。C++ではそんなことはほとんど経験がない。

 物体検出、APIを利用して株価などのデータをWebから取得、機械学習の利用などがPythonを使用することで簡単に行っていくことができる。YOLOとかQtで動かせたらいいなって考えながら。。。:thinking:

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away