2022.8.02 pyqt5 웹캠 캡처프로그램

정성우·2022년 8월 2일
0

학습내용
pyqt5로 윈도우창에서 gui를 보여주려고 한다.

import cv2
import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5 import QtGui

class ImageViewer(QtWidgets.QWidget):
    # parent 가 없어도 단독으로 사용가능하게
    # super parent를 상속받음
    def __init__(self, parent=None):
        super(ImageViewer, self).__init__(parent)
        self.image = QtGui.QImage()
        self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent)

    # 다시 위젯을 그려줌 여기서 웹캠 화면을 출력
    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.drawImage(0, 0, self.image)

    # 웹캠 사이즈에 맞춰 조절
    def setImage(self, image):
        # 이미지가 안넘어오면 출력
        if image.isNull():
            print("Viewer Dropped frame!")

        self.image = image
        #size가 다르면 fixed
        #image 사이즈는 640 480 웹캠 크기
        if image.size() != self.size():
            self.setFixedSize(image.size())
        self.update()


class ShowVideo(QtCore.QObject):
    flag = 1 #이미지 경로를 각각 다르게 해주기위해
    # 캠화면 3개 출력
    VideoSignal1 = QtCore.pyqtSignal(QtGui.QImage)
    VideoSignal2 = QtCore.pyqtSignal(QtGui.QImage)
    VideoSignal3 = QtCore.pyqtSignal(QtGui.QImage)
    def __init__(self, parent=None):
        super(ShowVideo, self).__init__(parent)
        self.run_video = True
        self.camera = cv2.VideoCapture(0)

    def startVideo(self):
        #run_video가 true인 동안 실행
        while self.run_video:
            #웹캠 영상 이미지 가져옴
            self.ret, self.image = self.camera.read()
            #웹캠 영상 이미지 크기 가져옴
            height, width = self.image.shape[:2]
            #rgb형태로 변환
            color_swapped_image = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB)
            gray_image = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)
            hsv_image = cv2.cvtColor(self.image, cv2.COLOR_BGR2HSV)
            self.qt_image = QtGui.QImage(color_swapped_image.data,
                                    width,
                                    height,
                                    color_swapped_image.strides[0],
                                    QtGui.QImage.Format_RGB888)
            self.qt_image1 = QtGui.QImage(gray_image.data,
                                    width,
                                    height,
                                    gray_image.strides[0],
                                    QtGui.QImage.Format_Grayscale8)
            self.qt_image2 = QtGui.QImage(hsv_image.data,
                                     width,
                                     height,
                                     hsv_image.strides[0],
                                     QtGui.QImage.Format_RGB888)
            #각각의 화면에 웹캠 영상 이미지 내보냄
            self.VideoSignal1.emit(self.qt_image)
            self.VideoSignal2.emit(self.qt_image1)
            self.VideoSignal3.emit(self.qt_image2)

            #영상 이미지 갱신 간격
            loop = QtCore.QEventLoop()
            QtCore.QTimer.singleShot(25, loop.quit) #25 ms
            loop.exec_()

    def stopVideo(self):
        self.run_video = False
        self.ret, self.image = self.camera.read()

    def restartVideo(self):
        self.run_video = True
        self.startVideo()

    def savePicture(self, text):
        print("HERE :", text)
        if self.run_video == False:
            filename = './webcam_image_{}_{}.png'.format(text, self.flag)
            filename1 = './webcam_grayimage_{}_{}.png'.format(text, self.flag)
            filename2 = './webcam_hsvimage_{}_{}.png'.format(text, self.flag)
            self.qt_image.save(filename)
            self.qt_image1.save(filename1)
            self.qt_image2.save(filename2)
            self.flag = self.flag + 1

        self.run_video = True
        self.startVideo()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    thread = QtCore.QThread()
    thread.start()
    vid = ShowVideo()
    vid.moveToThread(thread)

    image_viewer1 = ImageViewer()
    image_viewer2 = ImageViewer()
    image_viewer3 = ImageViewer()

    vid.VideoSignal1.connect(image_viewer1.setImage)
    vid.VideoSignal2.connect(image_viewer2.setImage)
    vid.VideoSignal3.connect(image_viewer3.setImage)

    push_button2 = QtWidgets.QPushButton('캡쳐')
    input_box = QtWidgets.QLineEdit('팀명')
    push_button3 = QtWidgets.QPushButton('저장')
    push_button4 = QtWidgets.QPushButton('취소')
    push_button2.clicked.connect(vid.stopVideo)
    push_button3.clicked.connect(lambda: vid.savePicture(input_box.text()))
    push_button4.clicked.connect(vid.restartVideo)

    layout = QtWidgets.QHBoxLayout()
    box01 = QtWidgets.QVBoxLayout()
    box02 = QtWidgets.QVBoxLayout()

    box01.addWidget(image_viewer1)
    box01.addWidget(image_viewer2)
    box02.addWidget(push_button2)
    box02.addWidget(input_box)
    box02.addWidget(push_button3)
    box02.addWidget(push_button4)
    # box01 imageviewer2개 추가
    layout.addLayout(box01)
    # imageviewr1개 추가
    layout.addWidget(image_viewer3)
    # button3개와 입력창 추가
    layout.addLayout(box02)
    layout_widget = QtWidgets.QWidget()

    layout_widget.setLayout(layout)

    main_window = QtWidgets.QMainWindow()
    main_window.setCentralWidget(layout_widget)
    main_window.show()
    # 바로 웹캠 영상 시작
    vid.startVideo()


    sys.exit(app.exec_())

실행결과
rgb, gray, hsv 로 각각 영상을 출력하고있다
캡쳐 버튼을 누르면 영상이 정지하고 저장을 누를경우
rgb, gray, hsv 각각 한장씩 총 세장의 파일이 저장되며
2번째 input칸에 있는 값을 포함해 파일명이 정해진다
한글을 넣을경우 인식이 되지않아 파일이 저장되지 않는다
여러번 캡처할경우 마지막숫자가 1씩 늘어난다
취소할경우 다시 화면을 재생한다
캡처를 누르지않고 저장했을 경우 이미지는 저장되지않는다





다음과 같이 이미지파일이 저장된다

학습한 내용 중 어려웠던 점 또는 해결못한 것들
pyqtsignal pyqtslot 으로 데이터를 주고 받는데 제대로 작동하지 않아 삭제하였다.

해결방법 작성
다시한번 공부해서 코드를 좀더 간결하게 써보고싶다.

학습 소감
조원이 기초 코드를 작성해줘서 보고 공부해서 출력이미지의 스케일을 변경해 각각 다른이미지를 재생하고 하나의 이미지만 저장하는 것에서 각각 총 3개의 이미지를 저장하도록 수정하였다.

0개의 댓글