啟動WebCam

      在〈啟動WebCam〉中尚無留言

安裝套件

WebCam的影像擷取, 使用 opencv 就可以很簡單的取得影像, 請先安裝如下套件

Windows: pip install PyQt5 opencv-python

Linux : sudo apt-get install python3-opencv python3-pyqt5 qt5-default qttools5-dev-tools

權限

WebCam的驅動代號為 /dev/video0~X, 其擁有者:群組為 root:video
所以必需先下執如下指令, 將你的帳號歸入video群組, 如此才能開啟web cam

usermod -a -G video ${USER}

坑洞

1. 請注意樹莓派的 wifi ip 是否正確, pi4 raspbin有bug, 有時會跑掉
2. 注意是否將帳號加入 video群組, 否則無法開啟 web cam
3. Python 變更照片品質時, 以 '.jpg' 傳送
4. C#接收端, 需轉換成 .jpg, 不能用 .png
5. fps 是告知播放器一秒要放映幾張的意思, 比如30fps, 是告知播放器一秒要放映30張. 
   但如果檔案裏並沒有這麼多張, 播放器還是拼命抓取, 就會造成影片快速播放的現像.
   所以fps是要以實際sdcard存放的時間為主, 樹莓派每秒約7張

主程式 MahalVideo.py

#!/usr/bin/python3
import sys
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtWidgets import QMainWindow, QApplication
from Camera import Camera
from ui.ui_mainwindow import *
class MainWindow(QMainWindow,Ui_MainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.CamThread=Camera()
        self.CamThread.callback.connect(self.refreshWindow)
        self.CamThread.start()
        self.bytesPerLine = 3 * 1920
        self.btnExit.clicked.connect(self.btnExit_click)
    def refreshWindow(self, img):
        w=self.img.width()
        h=self.img.height()
        qimg = QImage(img.data, 1920, 1080, self.bytesPerLine, QImage.Format_RGB888).rgbSwapped().scaled(w, h, transformMode=QtCore.Qt.SmoothTransformation)
        self.img.setPixmap(QPixmap.fromImage(qimg))
    def btnExit_click(self):
        app.closeAllWindows()
if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainwindow = MainWindow()
    #mainwindow.show()
    mainwindow.showFullScreen()
    #mainwindow.showMaximized()
    app.exec()

Camera.py

from PyQt5.QtCore import QThread, pyqtSignal
import cv2
import time

class Camera(QThread):
    callback = pyqtSignal(object)  # 自定義訊號, Qt的文件中有說明, 必需為類別變數
    def __init__(self, parent=None):
        super().__init__(parent)
        self.runFlag = True
    def __del__(self):
        self.runFlag = False
        cv2.destroyAllWindows()
        self.wait()
    def run(self):
        cam = cv2.VideoCapture(0)
        cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
        cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
        while self.runFlag:
            try:
                ret, img = cam.read()
                if ret:
                    self.callback.emit(img)
                    #cv2.imshow('frame', img)
                    #time.sleep(0.01)
                QThread.msleep(40)
            except Exception as e:
                print(str(e))

ui_mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
 <property name="geometry">
 <rect>
 <x>0</x>
 <y>0</y>
 <width>800</width>
 <height>600</height>
 </rect>
 </property>
 <property name="windowTitle">
 <string>MainWindow</string>
 </property>
 <widget class="QWidget" name="centralwidget">
 <layout class="QVBoxLayout" name="verticalLayout">
 <property name="spacing">
 <number>1</number>
 </property>
 <property name="leftMargin">
 <number>0</number>
 </property>
 <property name="topMargin">
 <number>0</number>
 </property>
 <property name="rightMargin">
 <number>0</number>
 </property>
 <property name="bottomMargin">
 <number>0</number>
 </property>
 <item>
 <widget class="QLabel" name="img">
 <property name="sizePolicy">
 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
 <horstretch>0</horstretch>
 <verstretch>0</verstretch>
 </sizepolicy>
 </property>
 <property name="text">
 <string/>
 </property>
 </widget>
 </item>
 <item>
 <widget class="QFrame" name="frame">
 <property name="sizePolicy">
 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
 <horstretch>0</horstretch>
 <verstretch>0</verstretch>
 </sizepolicy>
 </property>
 <property name="minimumSize">
 <size>
 <width>0</width>
 <height>80</height>
 </size>
 </property>
 <property name="frameShape">
 <enum>QFrame::Panel</enum>
 </property>
 <property name="frameShadow">
 <enum>QFrame::Sunken</enum>
 </property>
 <layout class="QHBoxLayout" name="horizontalLayout">
 <property name="spacing">
 <number>2</number>
 </property>
 <property name="leftMargin">
 <number>0</number>
 </property>
 <property name="topMargin">
 <number>0</number>
 </property>
 <property name="rightMargin">
 <number>0</number>
 </property>
 <property name="bottomMargin">
 <number>0</number>
 </property>
 <item>
 <widget class="QFrame" name="frame_2">
 <property name="sizePolicy">
 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
 <horstretch>0</horstretch>
 <verstretch>0</verstretch>
 </sizepolicy>
 </property>
 <property name="frameShape">
 <enum>QFrame::StyledPanel</enum>
 </property>
 <property name="frameShadow">
 <enum>QFrame::Raised</enum>
 </property>
 </widget>
 </item>
 <item>
 <widget class="QPushButton" name="btnSetting">
 <property name="sizePolicy">
 <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
 <horstretch>0</horstretch>
 <verstretch>0</verstretch>
 </sizepolicy>
 </property>
 <property name="text">
 <string>設定</string>
 </property>
 </widget>
 </item>
 <item>
 <widget class="QPushButton" name="btnRecord">
 <property name="sizePolicy">
 <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
 <horstretch>0</horstretch>
 <verstretch>0</verstretch>
 </sizepolicy>
 </property>
 <property name="text">
 <string>錄影</string>
 </property>
 </widget>
 </item>
 <item>
 <widget class="QPushButton" name="btnExit">
 <property name="sizePolicy">
 <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
 <horstretch>0</horstretch>
 <verstretch>0</verstretch>
 </sizepolicy>
 </property>
 <property name="text">
 <string>離開</string>
 </property>
 </widget>
 </item>
 <item>
 <widget class="QFrame" name="frame_3">
 <property name="sizePolicy">
 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
 <horstretch>0</horstretch>
 <verstretch>0</verstretch>
 </sizepolicy>
 </property>
 <property name="frameShape">
 <enum>QFrame::StyledPanel</enum>
 </property>
 <property name="frameShadow">
 <enum>QFrame::Raised</enum>
 </property>
 </widget>
 </item>
 </layout>
 </widget>
 </item>
 </layout>
 </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *