-
[OpenCV] Frame latency 문제공부/A.I 2024. 8. 17. 17:09
OpenCV로 카메라의 영상을 녹화할 때 녹화된 영상의 재생 속도가 맞지 않는 경우가 종종 있다.
cv2.VideoWriter로 영상 생성 시, 프레임 지연으로 인해 적절한 속도로 프레임을 write하지 못하기 때문일 수 있다.
책상 옆에 굴러다니던 라이언...
아래 예시 코드를 보면
카메라의 fps는 30이고 30fps로 생성된 VideoWriter에 frame을 write한다.
하지만 추론모델을 거치기 때문에 아래와 같이 각 프레임에 지연이 발생한다.
즉, 아래 그림과 같이 VideoWriter에 쌓이게 된다.
즉 실제로는 4~5fps만 write하고 있지만, VideoWriter를 30fps로 생성하게 되면 7초 이상이 지나야 1초의 영상이 생성된다.
따라서 frame latency를 고려한 VideoWriter의 fps를 주게되면 정상적인 속도의 영상을 얻을 수 있다.
코드1
더보기테스트 코드(before)
from ultralytics import YOLO import cv2 import datetime # opencv draw 변수들 정의 red = (0, 0, 255) green = (0, 255, 0) width = 640 height = 480 def create_video_writer(video_cap, output_filename, record_fps): frame_width = int(video_cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(video_cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = int(video_cap.get(cv2.CAP_PROP_FPS)) fourcc = cv2.VideoWriter_fourcc(*'m', 'p', '4', 'v') return cv2.VideoWriter(output_filename, fourcc, fps, (frame_width, frame_height)) ########### main ########## # Load the YOLOv8 model model = YOLO(".venv/yolov8m-pose.pt") #width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) #height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) #cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) # 가로 #cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height cap = cv2.VideoCapture(0) name = datetime.datetime.now().strftime("%y%m%d_%H%M%S") + "_output" writer = create_video_writer(cap, "./" + name + ".mp4", 4) program_start_sec = datetime.datetime.now() sec_sum = 0 sec_cnt = 0 is_first_frame = True while cap.isOpened(): # Read a frame from the video predict_start_sec = datetime.datetime.now() success, frame = cap.read() if success: # Run YOLOv8 inference on the frame results = model(frame, verbose=False, conf=0.6) annotated_frame = results[0].plot() # Display the annotated frame cv2.imshow("show", annotated_frame) writer.write(annotated_frame) if is_first_frame: program_start_sec = datetime.datetime.now() is_first_frame = False continue # latency 계산, 추론 지연 시간 계산 predict_end_sec = datetime.datetime.now() predict_sec_total = (predict_end_sec - predict_start_sec).total_seconds() sec_cnt += 1 sec_sum += predict_sec_total print(f'time to predict 1 frame: {predict_sec_total * 1000: .0f} milliseconds') if cv2.waitKey(1) & 0xFF == ord("q"): break program_end_sec = datetime.datetime.now() else: break program_sec_total = (program_end_sec - program_start_sec).total_seconds() writer.release() print(f'mp4 play time: {format(program_sec_total, "10.2f")} seconds') print(f'result: {sec_sum / sec_cnt * 1000: .0f} milliseconds') # Release the video capture object and close the display window cap.release() cv2.destroyAllWindows()
코드2
더보기코드(after)
from ultralytics import YOLO import cv2 import datetime # opencv draw 변수들 정의 red = (0, 0, 255) green = (0, 255, 0) width = 640 height = 480 def create_video_writer(video_cap, output_filename, record_fps): frame_width = int(video_cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(video_cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fourcc = cv2.VideoWriter_fourcc(*'m', 'p', '4', 'v') return cv2.VideoWriter(output_filename, fourcc, record_fps, (frame_width, frame_height)) ########### main ########## # Load the YOLOv8 model model = YOLO(".venv/yolov8m-pose.pt") #width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) #height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) #cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) # 가로 #cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height cap = cv2.VideoCapture(0) name = datetime.datetime.now().strftime("%y%m%d_%H%M%S") + "_output" writer = create_video_writer(cap, "./" + name + ".mp4", 4) program_start_sec = datetime.datetime.now() sec_sum = 0 sec_cnt = 0 is_first_frame = True while cap.isOpened(): # Read a frame from the video predict_start_sec = datetime.datetime.now() success, frame = cap.read() if success: # Run YOLOv8 inference on the frame results = model(frame, verbose=False, conf=0.6) annotated_frame = results[0].plot() # Display the annotated frame cv2.imshow("show", annotated_frame) writer.write(annotated_frame) if is_first_frame: program_start_sec = datetime.datetime.now() is_first_frame = False continue # latency 계산, 추론 지연 시간 계산 predict_end_sec = datetime.datetime.now() predict_sec_total = (predict_end_sec - predict_start_sec).total_seconds() sec_cnt += 1 sec_sum += predict_sec_total print(f'time to predict 1 frame: {predict_sec_total * 1000: .0f} milliseconds') if cv2.waitKey(1) & 0xFF == ord("q"): break program_end_sec = datetime.datetime.now() else: break program_sec_total = (program_end_sec - program_start_sec).total_seconds() writer.release() print(f'mp4 play time: {format(program_sec_total, "10.2f")} seconds') print(f'result: {sec_sum / sec_cnt * 1000: .0f} milliseconds') # Release the video capture object and close the display window cap.release() cv2.destroyAllWindows()
'공부 > A.I' 카테고리의 다른 글
[LLM] 프롬프트 엔지니어링 - 2 (1) 2024.10.21 [LLM] 프롬프트 엔지니어링 (1) 2024.10.20 [YOLOv8] Hyperparameter Tuning (0) 2024.07.27 [YOLOv8] 라벨링부터 모델 테스트까지 (0) 2024.07.27 [Jetson Orin Nano] Csicam과 YOLOv8을 위한 기본 세팅 (2) 2024.07.27