PyQt5のインストール
*Mac
$brew install pyqt5
*windows
リンク先参照。
とりあえずPyQt5でwindowを作る
#!/usr/bin/env python
from PyQt5.QtWidgets import (QApplication, QWidget, QComboBox, QDialog,
QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
QVBoxLayout)
import sys
class MainWindow(QWidget):
def __init__(self,parent=None):
#super() でスーパークラスのインスタンスメソッドを呼び出す
super(MainWindow, self).__init__(parent)
#ボタンの作成
button=QPushButton("Print")
#ボタンをクリックした場合、Print_text()を実行する
button.clicked.connect(self.Print_text)
#レイアウト、QVBoxLayoutのインスタンス
mainLayout = QVBoxLayout()
#Widget追加
mainLayout.addWidget(button)
#QVBoxLayoutをaddWidgetを追加したものに更新
self.setLayout(mainLayout)
#windowのタイトル変更
self.setWindowTitle("Test App")
def Print_text(self):
print('You have pushed the button')
if __name__ == '__main__':
app = QApplication(sys.argv)
P = MainWindow()
P.show()
sys.exit(app.exec_())
メモ
super() でスーパークラスを取得します。
button.clicked.connect(self.Print_text)を使うことでクリックした際に他の関数を呼ぶことができます。
レイアウトはQVBoxLayout()を使うことで自動で配置されるようにしています。
self.setLayout(mainLayout)について理解をしきれていないのでリンク先を参照ください。
QGraphicsViewを使ってみる
PyQt5で画像を取り扱う方法はいくつかあるようですが、QGraphicsViewを使ってみます。
QPenとQBrushの使いかたが情報がすくなく大変でした。PySideのほうが情報が多いかもしれません。共にPythonバインディングなので非常に参考になります。
#!/usr/bin/env python
from PyQt5.QtWidgets import (QApplication, QWidget, QComboBox, QDialog,
QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
QVBoxLayout, QGraphicsView, QGraphicsScene, QGraphicsItem, QGraphicsPixmapItem)
from PyQt5.QtGui import (QIcon, QPixmap, QBrush, QPen, QColor)
from PyQt5 import QtCore
import sys
import os
import re
class MainWindow(QWidget):
def __init__(self,parent=None):
#super() でスーパークラスのインスタンスメソッドを呼び出す
super(MainWindow, self).__init__(parent)
path = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'ico.png')
view = QGraphicsView()
scene = QGraphicsScene()
item = QGraphicsPixmapItem(QPixmap(path))
#画像の位置調整
item.setOffset (10, 10)
scene.addItem(item)
#円をいっぱい描く。20×20
for i in range(0,200,10):
for j in range(0,200,10):
#QPenの設定
pen = QPen(QtCore.Qt.green, 1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
#QBrushの設定
brush = QBrush(QColor(255, 0, 0, 127),QtCore.Qt.Dense1Pattern)
scene.addEllipse(i,j,10,10,pen,brush)
view.setScene(scene)
mainLayout = QVBoxLayout()
mainLayout.addWidget(view)
self.setLayout(mainLayout)
#windowのタイトル変更
self.setWindowTitle("Test App5")
if __name__ == '__main__':
app = QApplication(sys.argv)
path = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'ico.png')
app.setWindowIcon(QIcon(path))
P = MainWindow()
P.show()
sys.exit(app.exec_())
QGraphicsViewとPillowでgifアニメーションをつくる
PyQt5でGUIをつくります。画像をタイマー動かしgifアニメーションにするプログラムです。 QGraphicsViewとPillow (PIL) 使います。
Pillow (PIL)はanacondaならインストールされていると思います。
インストールしていない人pipからできるようですが、簡単にインストールできない場合もあるようなので事前にネットで情報を確認したほうがいいかもしれません。
プログラムのポイントとしてはQGraphicsViewをタイマーによって動かしてアニメーションさせます。
その際に画像をpngで保存をして、movieボタンを押した際にアニメーションをストップさせます。
PILでgifを作成して、不要のファイルを削除しています。
#!/usr/bin/env python
from PyQt5.QtWidgets import (QApplication, QWidget, QComboBox, QDialog,
QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
QVBoxLayout, QGraphicsView, QGraphicsScene, QGraphicsItem, QGraphicsPixmapItem)
from PyQt5.QtGui import (QIcon, QPixmap, QBrush, QPen, QColor)
from PyQt5 import QtCore
from PyQt5.QtCore import (QLineF, QPointF, QRectF, Qt, QTimer)
from PIL import Image, ImageDraw
from glob import glob
import sys
import os
import re
class Test_graphics(QGraphicsItem):
def __init__(self):
super(Test_graphics, self).__init__()
self.time = 0
self.a = 1
def paint(self, painter, option, widget):
painter.setPen(Qt.black)
i = self.time
painter.drawEllipse(i, i, 10, 10)
def boundingRect(self):
return QRectF(0,0,400,400)
def redraw(self):
if self.time == 0:
self.a = 1
elif self.time >= 390:
self.a = -1
else:
pass
x = self.time + 10*self.a
self.time = x
self.update()
class MainWindow(QWidget):
def __init__(self,parent=None):
super(MainWindow, self).__init__(parent)
self.movieButton = QPushButton("&movie")
self.movieButton.clicked.connect(self.make_movie)
buttonLayout = QVBoxLayout()
buttonLayout.addWidget(self.movieButton)
path = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'ico.png')
self.view = QGraphicsView()
scene = QGraphicsScene()
self.item = Test_graphics()
self.view.setSceneRect(0, 0, 400, 400);
item = QGraphicsPixmapItem(QPixmap(path))
item.setOffset (110, 110)
scene.addItem(item)
scene.addItem(self.item)
self.view.setScene(scene)
mainLayout = QVBoxLayout()
mainLayout.addWidget(self.view)
mainLayout.addLayout(buttonLayout)
self.setLayout(mainLayout)
#windowのタイトル変更
self.setWindowTitle("Test App7")
self.plot_times = 0
self.timer = QTimer(self)
self.timer.timeout.connect(self.time_Event)
self.timer.start(100)
if os.path.isdir("./png") == False :
os.mkdir("./png")
else:
pass
def time_Event(self):
self.item.redraw()
self.plot_times = self.plot_times + 1
if self.plot_times >= 10000 :
plot_times_str = str(self.plot_times)
elif self.plot_times >= 1000 :
plot_times_str = "0" + str(self.plot_times)
elif self.plot_times >= 100 :
plot_times_str = "00" + str(self.plot_times)
elif self.plot_times >= 10 :
plot_times_str = "000" + str(self.plot_times)
else :
plot_times_str = "0000" + str(self.plot_times)
self.view.grab().save("png/test_" + plot_times_str +".png")
def make_movie(self):
self.timer.stop()
images = []
file_num= glob("./png/**.png")
file_num.sort()
for i in range(0, len(file_num), 1):
im =Image.open(file_num[i], 'r')
fp = im.copy()
im.close()
images.append(fp)
#duraton uints is micro seconds
images[0].save("image.gif",
save_all=True, append_images=images[1:], optimize=False, duration=100, loop=0)
for i in range(0, len(file_num), 1):
os.remove(file_num[i])
self.plot_times = 0
if __name__ == '__main__':
app = QApplication(sys.argv)
path = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'ico.png')
app.setWindowIcon(QIcon(path))
P = MainWindow()
P.show()
sys.exit(app.exec_())
QGraphicsViewとOpenCVで動画作成
*OpenCV をインストールする。
環境は以下です。
MacBook Air MAC OSX Sierra 10.12.6
Python 3.6.1 :: Anaconda 4.4.0 (x86_64)
OpenCV3.3
Anacondaでpythonはインストール。homebrewもインストールしてある条件です。
インストールの参考にしたサイト
$brew tap homebrew/science
$brew install opencv3 –with-contrib –with-python3 –without-python
cv2.soファイルをインストールしたら
/usr/local/Cellar/opencv/3.3.0_3/lib/python3.6/site-packages/cv2.cpython-36m-darwin.so
にあったのanacondaのsite-packagesにシンボリックリンクの作成を作成する。
バージョンなどが違う可能性がありますが、$open /usr/local/Cellar/opencv でfinderを開き、次々フォルダーを開いていくと見つかると思います。homebrewでインストールしたものは/usr/local/Cellar/配下に入る。(リンク先参照)
シンボリックリンクじゃなくて、PYTHONPATHに追加してもたぶん大丈夫だと思う。(未実行未確認)
シンボリックリンクの作成
(hogeはユーザー名)
$ln -s /usr/local/Cellar/opencv/3.3.0_3/lib/python3.6/site-packages/cv2.cpython-36m-darwin.so /Users/hoge/anaconda3/lib/python3.6/site-packages
実行してみる。
$python
>>import cv2
RuntimeError: module compiled against API version 0xb but this version of numpy is 0xa
Traceback (most recent call last):
File "", line 1, in
ImportError: numpy.core.multiarray failed to import
私はnumpyのverが古いとのエラーがでたので アップデートした。
$pip install numpy -U
$python
ここで問題なければ、インストールはできたことと思う。
上のGIFアニメーションの作成プログラムから def make_movie()を変更します。
変更は以下です。
#OpenCVを呼び出す。
import cv2
#~省略~
def make_movie(self):
self.timer.stop()
images = []
file_num= glob("./png/**.png")
file_num.sort()
#fourcc = cv2.VideoWriter_fourcc('m', 'p', 'g', '4’)
#上記のようにfourccで指定するが、エラーがでたため、直接タグ0x00000020指定
video = cv2.VideoWriter('video.mp4', 0x00000020, 10.0, (400, 400))
for i in range(0, len(file_num), 1):
img = cv2.imread(file_num[i].format(i))
img = cv2.resize(img, (400,400))
video.write(img)
video.release()
for i in range(0, len(file_num), 1):
os.remove(file_num[i])
self.plot_times = 0
#~省略~
作成動画
以下参考にしたサイト。