簡體   English   中英

我想通過使用網絡攝像頭將捕獲圖像添加到我的 PyQt gui 窗口,並且網絡攝像頭圖像將出現在 gui 窗口中

[英]I wanted to add capturing image by using webcam to my PyQt gui window and webcam image will come on gui window

我想將網絡攝像頭圖像添加到我的主 GUI 窗口,該圖像將發送到電子郵件 ID。 如果這不可能,我還想保存該圖像,保存的圖像將發送到我的電子郵件 ID,在 3、2、1 倒計時,微笑它會通過網絡攝像頭單擊圖像。 這是我的代碼:

import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets, QtGui
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import cv2, time

DURATION_INT = 5


class MyMainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()

        self.time_left_int = DURATION_INT
        self.widget_counter_int = 0

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        vbox = QtWidgets.QVBoxLayout()
        central_widget.setLayout(vbox)

        self.pages_qsw = QtWidgets.QStackedWidget()
        vbox.addWidget(self.pages_qsw)
        self.time_passed_qll = QtWidgets.QLabel()
        vbox.addWidget(self.time_passed_qll)
        self.pushButton = QtWidgets.QPushButton()
        self.pushButton.setText("Push to start")
        self.yesbutton = QtWidgets.QToolButton()
        self.yesbutton.setText("yes")
        self.Nobutton = QtWidgets.QToolButton()
        self.Nobutton.setText("No")

        self.imageframe = QtWidgets.QLabel()
        self.imageframe.setText("fghkfhh")

        vbox.addWidget(self.Nobutton)
        vbox.addWidget(self.yesbutton)
        vbox.addWidget(self.pushButton)
        vbox.addWidget(self.imageframe)


        self.pushButton.clicked.connect(self.timer_start)
        self.yesbutton.clicked.connect(self.capturing_image)
        self.update_gui()

    def gmail_alert(self):
        email_user = 'user email_id'
        email_send = 'receiver email_id'

        subject = 'Alert system'

        msg = MIMEMultipart()
        msg['From'] = email_user
        msg['To'] = email_send
        msg['Subject'] = subject
        msg.preamble = "test"

        body = 'Hi there, sending this email from Python!'
        msg.attach(MIMEText(body, 'plain'))

        filename = 'alert.png'
        attachment = open(filename, 'rb')

        part = MIMEBase('application', 'octet-stream')
        part.set_payload((attachment).read())
        encoders.encode_base64(part)
        part.add_header('Content-Disposition', "attachment; 
                           filename= " + filename)

        msg.attach(part)
        text = msg.as_string()

        server = smtplib.SMTP('smtp.gmail.com', 587)
        server.starttls()
        server.login(email_user, 'user email_id password')
        server.sendmail(email_user, email_send, text)
        server.quit()

    def timer_start(self):
        self.time_left_int = DURATION_INT
        self.my_qtimer = QtCore.QTimer(self)
        self.my_qtimer.timeout.connect(self.timer_timeout)
        self.my_qtimer.start(1000)
        self.update_gui()

    def timer_timeout(self):
        if self.time_left_int > 0:
            self.time_left_int -= 1
        else:
            self.gmail_alert()
        self.update_gui()



    def update_gui(self):
        self.time_passed_qll.setText((str(self.time_left_int) if self.time_left_int >=1 else "Smile..!"))

    def capturing_image(self):
        video =cv2.VideoCapture(0)
        check, frame = video.read()

        print(check)
        print(frame)

        cv2.imshow("capturing", frame)
        video.release()

app = QtWidgets.QApplication(sys.argv)
main_window = MyMainWindow()
main_window.show()
sys.exit(app.exec_()

首先你不必在 PyQt 中使用cv2.imshow()因為它會阻塞 python 事件循環,如果你想在 PyQt 中顯示 opencv 的圖像你必須將它轉換為 QImage 或 QPixmap,下一個類實現opencv的數據采集,它允許獲取QImage,但必須在線程中執行。

OpencvQt.py

import cv2
import numpy as np
from PyQt5 import QtCore, QtGui, QtWidgets


class Capture(QtCore.QObject):
    started = QtCore.pyqtSignal()
    frameReady = QtCore.pyqtSignal(np.ndarray)

    def __init__(self, parent=None):
        super(Capture, self).__init__(parent)
        self._frame = None
        self.m_timer = QtCore.QBasicTimer()
        self.m_videoCapture = cv2.VideoCapture()

    @QtCore.pyqtSlot()
    def start(self, cam=0):
        if self.m_videoCapture is not None:
            self.m_videoCapture.release()
            self.m_videoCapture = cv2.VideoCapture(cam)
        if self.m_videoCapture.isOpened():
            self.m_timer.start(0, self)
            self.started.emit()

    @QtCore.pyqtSlot()
    def stop(self):
        self.m_timer.stop()

    def __del__(self):
        self.m_videoCapture.release()

    def frame(self):
        return self.m_frame

    def timerEvent(self, event):
        if event.timerId() != self.m_timer.timerId():
            return

        ret, val = self.m_videoCapture.read()
        if not ret:
            self.m_timer.stop()
            return
        self.m_frame = val    
        self.frameReady.emit(self.m_frame)

    frame = QtCore.pyqtProperty(np.ndarray, fget=frame, notify=frameReady, user=True)

class Converter(QtCore.QObject):
    imageReady = QtCore.pyqtSignal(QtGui.QImage)

    def __init__(self, parent=None):
        super(Converter, self).__init__(parent)
        self.m_frame = np.array([])
        self.m_timer = QtCore.QBasicTimer()
        self.m_processAll = True
        self.m_image = QtGui.QImage()

    def queue(self, frame):
        self.m_frame = frame
        if not self.m_timer.isActive():
            self.m_timer.start(0, self)

    def process(self, frame):
        w, h, _ = frame.shape
        rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        self.m_image = QtGui.QImage(rgbImage.data, h, w, QtGui.QImage.Format_RGB888)
        self.imageReady.emit(QtGui.QImage(self.m_image))

    def timerEvent(self, event):
        if event.timerId() != self.m_timer.timerId():
            return
        self.process(self.m_frame)
        self.m_timer.stop()

    def processAll(self):
        return self.m_processAll

    def setProcessAll(self, _all):
        self.m_processAll = _all

    def processFrame(self, frame):
        if self.m_processAll:
            self.process(frame)
        else:
            self.queue(frame)

    def image(self):
        return self.m_image

    image = QtCore.pyqtProperty(QtGui.QImage, fget=image, notify=imageReady, user=True)
    processAll = QtCore.pyqtProperty(bool, fget=processAll, fset=setProcessAll)

有了上面我們可以在 QLabel 中顯示相機,另一方面,我們必須將 QImage 轉換為字節,因為我們使用 QByteArray 和 QBuffer。 出現的另一個問題是電子郵件的發送需要一段時間,因此 GUI 可能會被阻塞,因此必須在線程中執行。 最后我添加了一個 QDialog,您必須在其中輸入郵件數據。

主文件

import sys
import threading
from PyQt5 import QtCore, QtGui, QtWidgets

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

from OpencvQt import Capture, Converter


config = {
    "DURATION_INT": 5
}

def send_email(user, pwd, recipient, subject, body, image_payload):
    msg = MIMEMultipart()
    msg['From'] = user
    msg['To'] = recipient
    msg['Subject'] = subject
    msg.attach(MIMEText(body, 'plain'))

    part = MIMEBase('application', 'octet-stream')

    part.set_payload(image_payload)
    encoders.encode_base64(part)
    filename = QtCore.QDateTime.currentDateTime().toString()+ '.png'
    part.add_header('Content-Disposition', "attachment; filename= " + filename)
    msg.attach(part)
    text = msg.as_string()

    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login(user, pwd)
    server.sendmail(user, recipient, text)
    server.quit()

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)

        lay = QtWidgets.QVBoxLayout(central_widget)
        self.view = QtWidgets.QLabel()
        self.btn_start = QtWidgets.QPushButton("Start")
        self.btn_stop = QtWidgets.QPushButton("Stop")
        self.btn_send = QtWidgets.QPushButton("Send Email")
        self.label_time = QtWidgets.QLabel()
        lay.addWidget(self.view, alignment=QtCore.Qt.AlignCenter)
        lay.addWidget(self.btn_start)
        lay.addWidget(self.btn_stop)
        lay.addWidget(self.btn_send)
        lay.addWidget(self.label_time, alignment=QtCore.Qt.AlignCenter)
        self.view.setFixedSize(640, 400)
        self.show()
        self.init_camera()
        self.init_email()

    def init_camera(self):
        self.capture = Capture()
        self.converter = Converter()
        captureThread = QtCore.QThread(self)
        converterThread = QtCore.QThread(self)
        self.converter.setProcessAll(False)
        captureThread.start()
        converterThread.start()
        self.capture.moveToThread(captureThread)
        self.converter.moveToThread(converterThread)
        self.capture.frameReady.connect(self.converter.processFrame)
        self.converter.imageReady.connect(self.setImage)
        self.capture.started.connect(lambda: print("started"))
        self.btn_start.clicked.connect(self.capture.start)
        self.btn_stop.clicked.connect(self.capture.stop)

    @QtCore.pyqtSlot(QtGui.QImage)
    def setImage(self, image):
        self.view.setPixmap(QtGui.QPixmap.fromImage(image))

    def init_email(self):
        timeline = QtCore.QTimeLine(config["DURATION_INT"]*1000, self)
        timeline.frameChanged.connect(self.onFrameChanged)
        timeline.setFrameRange(0, config["DURATION_INT"])
        timeline.setDirection(QtCore.QTimeLine.Backward)
        self.btn_send.clicked.connect(timeline.start)

        d = EmailDialog(self)
        if d.exec_() == EmailDialog.Accepted:
            self._info = d.get_data()

    def onFrameChanged(self, frame):
        if frame !=0:
            self.label_time.setNum(frame)
        else:
            self.label_time.setText("Smile...!")
            QtWidgets.QApplication.beep()
            image = QtGui.QImage(self.converter.image)
            ba = QtCore.QByteArray()
            buff = QtCore.QBuffer(ba)
            image.save(buff, "PNG")
            th = threading.Thread(target=send_email, args=(*self._info, ba))
            th.start()

    def closeEvent(self, event):
        self.capture.stop()
        super(MainWindow, self).closeEvent(event)


class EmailDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(EmailDialog, self).__init__(parent)
        lay = QtWidgets.QFormLayout(self)
        self.from_le = QtWidgets.QLineEdit()
        self.pass_le = QtWidgets.QLineEdit(echoMode=QtWidgets.QLineEdit.Password)
        self.to_le = QtWidgets.QLineEdit()
        self.subject_le = QtWidgets.QLineEdit()
        self.body_te = QtWidgets.QTextEdit()

        self.buttonBox = QtWidgets.QDialogButtonBox()
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        lay.addRow("From: ", self.from_le)
        lay.addRow("Password: ", self.pass_le)
        lay.addRow("To: ", self.to_le)
        lay.addRow("Subject: ", self.subject_le)
        lay.addRow("Body: ", self.body_te)
        lay.addRow(self.buttonBox)

        self.from_le.textChanged.connect(self.enable_button)
        self.pass_le.textChanged.connect(self.enable_button)
        self.to_le.textChanged.connect(self.enable_button)
        self.enable_button()

    def enable_button(self):
        disabled = self.from_le.text() == "" or self.pass_le.text() == "" or self.to_le.text() == ""
        self.buttonBox.setDisabled(disabled)

    def get_data(self):
        return self.from_le.text(), self.pass_le.text(), self.to_le.text(), self.subject_le.text(), self.body_te.toPlainText()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    sys.exit(app.exec_())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM