본문 바로가기
IT, Software/Python

Python - PyQt + OpenCV로 동영상 파일 재생하기

by 기타마을이장 2021. 10. 18.

원래의 목표는 OpenCV를 활용해서 동영상 재생을 하면서 장면을 인식하는 프로그램을 만들어보고 싶었다.

그런데... 올해 회사 업무가 너무나도 정신없이 진행되면서 지난 6개월간 겨우 진행한 게 동영상 재생하기 뿐이었다ㅠ

아무래도 올해는 이정도에서 마무리하고 내년을 기약해봐야 하려나;;;

 

바로 전 포스팅... 이라지만 벌써 6개월 전에 진행했던;;;

PyQT5를 사용해서 PC캠의 영상을 출력하는 어플을 만들었었다.

그리고 이번엔 PC캠 영상이 아니라 동영상 파일을 재생하는 어플을 만들어봤다..

 

PC캠 영상을 재생하던 코드에서 변경되는 주요한 내용은 세 가지다.

  1. 기존 포스팅에서 PC캠의 영상을 출력하는 부분을 동영상 파일을 출력하도록 해준다.
  2. Player영역에 영상이 모두 표시되도록 resize 해서 출력해준다.
  3. 동영상이기 때문에 frame과 frame 사이에 sleep을 줘야 자연스럽게 재생이 된다.

 

웹캠 영상 재생하기 vs 동영상 재생하기 코드 비교

기존 웹캠 영상을 표시하던 코드

 

Python - Scene Detector 만들기 첫단계 OpenCV 설치하기

OpenCV를 활용해서 동영상의 장면 전환을 Detect 하는 프로그램을 만들어보기로 했다. 기존에 사용해서 UI를 만들었던 PyQt5를 이번에도 사용해서 UI를 만들고, OpenCV를 활용해서 동영상을 재생하면서

fidelislee.tistory.com

cap = cv2.VideoCapture(0)

while self.running:
    ret, img = cap.read()
    if ret:
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        h,w,c = img.shape
        qImg = QtGui.QImage(img.data, w, h, w*c, QtGui.QImage.Format_RGB888)
        pixmap = QtGui.QPixmap.fromImage(qImg)
        self.ui.label.setPixmap(pixmap)
    else:
        QtWidgets.QMessageBox.about(self, "Error", "Cannot read frame.")
        break
cap.release()

 

동영상을 재생하는 코드

cap = cv2.VideoCapture(self.videoSrc)
fps = cap.get(cv2.CAP_PROP_FPS)  # 또는 cap.get(5)
sleep_ms = int(numpy.round((1 / fps) * 500)) # frame 중간 sleep계산

while cap.isOpened():
    if(self.running == False):
        break

    ret, frame = cap.read()
    # 프레임이 올바르게 읽히면 ret은 True
    if not ret:
        break

    img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    h, w, c = img.shape
    qImg = QtGui.QImage(img.data, w, h, w * c, QtGui.QImage.Format_RGB888)
    pixmap = QtGui.QPixmap.fromImage(qImg)

    ## 출력영상을 resize해주기
    p = pixmap.scaled(int(w*480/h), 480, QtCore.Qt.IgnoreAspectRatio)
    self.ui.label.setPixmap(p)

    if(cv2.waitKey(sleep_ms) == ord('q')): # frame 중간에 sleep 주기
        break

cap.release()
cv2.destroyAllWindows()

 

1. 동영상의 frame을 QImage로 생성해서 Widget에 표시

기존 웹캠영상을 소스로 받았다면, 이번에는 동영상 파일을 소스로 받아

frame단위로 QImage를 생성한 후 Widget에 표시해줬다.

이번에 표시할 곳은 QLabel Widget을 사용했다.

 

2. QPixmap scaled함수로 출력 영상 resize 해주기

그리고 프로그램 창안에 맞춰서 영상을 출력해야 하기 때문에 영상을 resize 해준다.

resize를 해주지 않으면 영상의 크기가 player영역보다 커서 영상이 제대로 안 보인다.

(좌) resize를 안하면 영상의 왼쪽 윗부분만 재생 / (우) resize를 적용해서 실제 영상이 player영역에 표시되도록 조정

 

3. frame 사이에 sleep 주기

그냥 while문을 돌면서 재생을 하면 매우 빠르게 재생이 된다(빨리 감기 한 것처럼)

그래서 정말 제대로 된 play가 되게 하려면 frame 사이에 sleep을 줘야 한다.

이 sleep 값을 조정하면 영상에 대한 미세배속이 가능할 것 같다.

 

마지막으로 OpenCV는 영상에 대한 것을 다루는 전문 라이브러리이다 보니 소리 재생은 되지 않았다.(방법을 못 찾았음)

그래서 소래는 다른 라이브러리로 재생해주고 영상과 소리를 싱크 맞춰서 플레이해주면

진짜 동영상 Player가 되는 것 같다.

다만, 내가 하려는 건 결국 SceneDetector이니 우선은 영상을 다루는데 더 Focus를 맞춰보려 한다.

반응형

댓글