윈도우에서 웹캠 영상을 얻어오기위해 파이썬의 OpenCV 패키지를 사용하여 테스트 하던중 이상하게도 실행하면 첫화면 뜨는데까지 너무 오랜 시간이 걸리는 문제가 발생하였습니다.
아래는 테스트에 사용된 파이썬 소스인데 일반적으로 OpenCV를 사용하여 웹캠 테스트시 사용되는 기본 코드입니다.
import cv2 cap = cv2.VideoCapture(0) while (True): ret, frame = cap.read() cv2.imshow('frame', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
어느 부분에서 시간이 오래걸리는지를 측정해 보니 VideoCapture(0)를 하는 부분에서 대략 1분 내외 정도의 시간이 걸리는 것으로 측정되었습니다.
너무 오래 걸려서 검색을 해 보니 아래와 같이 backend를 수정하면 괜찮을거라는 게시글을 보고 backend를 추가하여 실행해 보니 이전과 달리 바로 실행이 됩니다.
cap = cv2.VideoCapture(0 + cv2.CAP_DSHOW)
VideoCapture API 사용시 파라미터로 backend를 지정할 수 있는데 몇 가지 예를들면 아래와 같습니다.
cap = cv2.VideoCapture(0) # 백엔드(Backend) 를 자동으로 선택 cap = cv2.VideoCapture(0 + cv2.CAP_DSHOW) # DirectShow (Windows) cap = cv2.VideoCapture(0 + cv2.CAP_MSMF) # Media Foundation (Windows) cap = cv2.VideoCapture(0 + cv2.CAP_VFW) # Video for Windows cap = cv2.VideoCapture(0 + cv2.CAP_GSTREAMER) # GStreamer cap = cv2.VideoCapture(0 + cv2.CAP_FFMPEG) # FFmpeg cap = cv2.VideoCapture(0 + cv2.CAP_INTEL_MFX) # Intel Media SDK
자세한 내용은 아래 OpenCV 문서를 참고하시기 바랍니다.
(참고 : https://docs.opencv.org/4.x/d4/d15/group__videoio__flags__base.html#ga023786be1ee68a9105bf2e48c700294d)
윈도우의 경우 기본 backend가 MSMF(Microsoft Media Foundation)로 설정되는것 같은데 이 경우 웹캠 초기화 시간이 오래 걸리는 문제가 발생되어 backend를 DirectShow(CAP_DSHOW)로 설정시 이러한 문제가 발생되지 않았지만 다른 문제가 발생되었습니다.
시간은 짧게 걸리나 프레임 드랍이 발생하는건지 비디오 영상이 울렁울렁(?) 거리면서 자연스럽게 나오지 않습니다.
30fps 정도는 나와줘야 하는데 그 이하로 이미지를 가져오는것 같습니다.
로딩시간이 오래 걸리는 문제로 검색중 reddit에서 해결책을 찾을 수 있었는데 backend로 MSMF(Microsoft Media Foundation)을 사용하는 경우 OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS 속성을 “0”로 설정하면 이런 문제가 해결된다는 코멘트를 발견하였습니다.
import os os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0" import cv2 set the enviroment flag before importing cv2
특히나 설정 위치가 중요한데 위 소스와 같이 환경변수 OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS 비활성 설정을 cv2를 임포트하기 전에 해야한다고 되어 있습니다.
관련 내용 역시 OpenCV 문서에서 찾을 수 있었는데 아래 이미지를 참고하시기 바랍니다.
위 가이드대로 OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS 속성 값을 “0”으로 설정후 다시 테스트해 보았습니다.
import os os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0" import cv2 cap = cv2.VideoCapture(0) while (True): ret, frame = cap.read() cv2.imshow('frame', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
실행시키면 바로 비디오 영상이 나오며 프레임 드랍없이 쾌적하게 동작됨을 확인할 수 있습니다.
reddit의 댓글을 보면 lifesaver나 timesaver등 찬사를 보내던데 제 경우에도 이 문제로 시간을 너무 소비한터라 공감이 가는 댓글이었습니다.