PyQtでwebカメラを使って動画を録画し,保存するアプリでエラーが発生してしまいます
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 1,563
下のpyqt5で書かれたwebカメラから映像を取得し保存するアプリで,最初にendボタンを押すと
'NoneType' object has no attribute 'deleteLater'
とエラーが出てしまいます.これを解決する方法を教えてくださるとありがたいです.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import cv2
import os, zipfile, datetime
now = datetime.datetime.now()
dirname = 'test_{0:%Y%m%d}'.format(now)
class QtCapture(QtWidgets.QWidget):
def __init__(self, *args):
super(QtWidgets.QWidget, self).__init__()
self.fps = 24
self.cap = cv2.VideoCapture(*args)
self.video_frame = QtWidgets.QLabel()
lay = QtWidgets.QVBoxLayout()
lay.setContentsMargins(0,0,0,0)
lay.addWidget(self.video_frame)
self.setLayout(lay)
# ------ Modification ------ #
self.isCapturing = False
self.ith_frame = 1
# ------ Modification ------ #
def setFPS(self, fps):
self.fps = fps
def nextFrameSlot(self):
ret, frame = self.cap.read()
# ------ Modification ------ #
# Save images if isCapturing
if self.isCapturing:
if not(os.path.isdir(dirname)):
os.mkdir(dirname)
cv2.imwrite('./'+dirname+'/img_%05d.jpg'%self.ith_frame, frame)
self.ith_frame += 1
# ------ Modification ------ #
# My webcam yields frames in BGR format
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = QtGui.QImage(frame, frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888)
pix = QtGui.QPixmap.fromImage(img)
self.video_frame.setPixmap(pix)
def start(self):
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.nextFrameSlot)
self.timer.start(1000./self.fps)
def stop(self):
self.timer.stop()
# ------ Modification ------ #
def capture(self):
if not self.isCapturing:
self.isCapturing = True
else:
self.isCapturing = False
# ------ Modification ------ #
def deleteLater(self):
self.cap.release()
super(QtWidgets.QWidget, self).deleteLater()
class ControlWindow(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.capture = None
self.start_button = QtWidgets.QPushButton('Start')
self.start_button.clicked.connect(self.startCapture)
self.quit_button = QtWidgets.QPushButton('End')
self.quit_button.clicked.connect(self.endCapture)
self.end_button = QtWidgets.QPushButton('Stop')
# ------ Modification ------ #
self.capture_button = QtWidgets.QPushButton('Capture')
self.capture_button.clicked.connect(self.saveCapture)
# ------ Modification ------ #
vbox = QtWidgets.QVBoxLayout(self)
vbox.addWidget(self.start_button)
vbox.addWidget(self.end_button)
vbox.addWidget(self.quit_button)
# ------ Modification ------ #
vbox.addWidget(self.capture_button)
# ------ Modification ------ #
self.setLayout(vbox)
self.setWindowTitle('Control Panel')
self.setGeometry(100,100,200,200)
self.show()
def startCapture(self):
if not self.capture:
self.capture = QtCapture(0)
self.end_button.clicked.connect(self.capture.stop)
# self.capture.setFPS(1)
self.capture.setParent(self)
self.capture.setWindowFlags(QtCore.Qt.Tool)
self.capture.start()
self.capture.show()
def endCapture(self):
self.capture.deleteLater()
self.capture = None
# ------ Modification ------ #
def saveCapture(self):
if self.capture:
self.capture.capture()
# ------ Modification ------ #
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = ControlWindow()
sys.exit(app.exec_())
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
quit_buttonのclickedシグナルに紐づいているのはendCaptureですので、
endCaptureが呼び出された時点で、captureがNoneであることが問題ということです。
captureに具体的な値が与えられるのはstartCapture内ですね。
これを呼び出す前にメソッドを参照しようとすると当然エラーが生じます。
キャプチャしていない状態のcaptureをNoneとする現行の設計を保持するならば、
endCapture内の処理を、captureがNoneであるかどうかで分岐させれば良いです。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 89.99%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる