GUI/PyQT

카메라 영상 출력/저장

Zero Coding 2022. 7. 12. 13:40

1. UI 구성

  • PyQt5로 아래와 같이 기본 틀 설계 (배경이미지는 Main 코드에서 추가)
  • 각 버튼 클래스명 별도 지정 (아래 예제에서 CAM OFF버튼은 camButton, Capture 버튼은 captureButton)

2. main.py 모듈

import sys
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import *
from video import *

form_class = uic.loadUiType("layout.ui")[0]

class MainWindow(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.pixmap = QtGui.QPixmap('face.jpg')
        self.backgroundImage.setPixmap(self.pixmap) # backgroundImage 라벨에 배경입히기
        self.video = video(self, QSize(640,480), 1)
        self.camButton.setCheckable(True)
        self.camButton.clicked.connect(self.onoffCam) # 클릭시 onoffCam 함수 호출
        self.captureButton.setCheckable(True)
        self.captureButton.clicked.connect(self.captureCam) # 클릭시 captureCam 함수 호출
 
    def recvImage(self, img):
    	#camView 라벨에 영상입히기. video클래스로부터 sendImage 변수 받아옴
        self.camView.setPixmap(QPixmap.fromImage(img)) 
    
    def closeEvent(self, e):
        self.video.stopCam()

    def captureCam(self, e):
        if self.camButton.isChecked():
            self.video.captureCam()
        else:
            print('카메라 켜주세요!')
            
    def onoffCam(self, e):
        if self.camButton.isChecked():
            self.camButton.setText('CAM OFF')
            self.video.startCam()
        else:
            self.camButton.setText('CAM ON')
            self.video.stopCam()

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

3. video.py 모듈 (main.py 에서 호출)

import cv2
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from threading import Thread
import time

class video(QObject): # QObject 클래스를 상속
    sendImage = pyqtSignal(QImage) # sendImage 객체 생성, 전역변수(객체변수)로 활용

	def __init__(self, widget, size, channel):
        super().__init__() # 변수를 상속받아와서 초기화
        self.widget = widget # 추가 변수 오버라이딩
        self.size = size
        self.channel = channel
        self.sendImage.connect(self.widget.recvImage) #위젯의 recvImage 메서드에 연결

    def startCam(self):
        try:
            self.cap = cv2.VideoCapture(self.channel, cv2.CAP_DSHOW)
        except Exception as e:
            print('Cam Error : ', e)
        else:
            self.bThread = True # True값을 갖는 bThread 변수생성
            self.thread = Thread(target=self.threadFunc) # thread 객체 생성
            self.thread.start() #thread 활성화

    def captureCam(self):
        try:
            myimage = 'image/image_' + time.strftime('%Y%m%d_%H%M%S') + '.jpg'
            cv2.imwrite(myimage, self.image)
        except Exception as e:
            print('Error', e)

    def stopCam(self):
        self.bThread = False # False 값을 갖는 bThread 변수생성
        try:
            self.cap.release()
        except Exception as e:
            print('Error', e)

    def threadFunc(self): # thread로 돌릴 함수 지정
        while self.bThread: # b.Thread가 True가 되면 수행
            ret, img = self.cap.read()
            if ret:
                img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
                h, w, ch = img.shape
                bytesPerLine = ch * w
                qimg = QImage(img.data, w, h, bytesPerLine, QImage.Format_RGB888)
                self.sendImage.emit(qimg)
                self.image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            else:
                print('Camera Read Error')
            time.sleep(0.01)

        print('thread finished')