Spaces:
Sleeping
Sleeping
#coding=utf-8 | |
import os | |
import cv2 # OpenCV 라이브러리 | |
import numpy as np | |
from PIL import Image | |
# -- IO utils | |
# 텍스트 라인 불러오기 | |
def read_txt_lines(filepath): | |
# 파일이 있는지 확인, 없으면 AssertionError 메시지를 띄움 | |
assert os.path.isfile( filepath ), "Error when trying to read txt file, path does not exist: {}".format(filepath) # 원하는 조건의 변수값을 보증하기 위해 사용 | |
# 파일 불러오기 | |
with open( filepath ) as myfile: | |
content = myfile.read().splitlines() # 문자열을 '\n' 기준으로 쪼갠 후 list 생성 | |
return content | |
# npz 저장 | |
def save2npz(filename, data=None): | |
# 데이터가 비어있는지 확인, 없으면 AssertionError 메시지를 띄움 | |
assert data is not None, "data is {}".format(data) | |
# 파일 없을 경우 | |
if not os.path.exists(os.path.dirname(filename)): | |
os.makedirs(os.path.dirname(filename)) # 디렉토리 생성 | |
np.savez_compressed(filename, data=data) # 압축되지 않은 .npz 파일 형식 으로 여러 배열 저장 | |
def save2npz(filename, data=None): | |
"""save2npz. | |
:param filename: str, the fileanme where the data will be saved. | |
:param data: ndarray, arrays to save to the file. | |
""" | |
assert data is not None, "data is {}".format(data) | |
if not os.path.exists(os.path.dirname(filename)): | |
os.makedirs(os.path.dirname(filename)) | |
np.savez_compressed(filename, data=data) | |
# 비디오 불러오기 | |
def read_video(filename): | |
cap = cv2.VideoCapture(filename) # 영상 객체(파일) 가져오기 | |
while(cap.isOpened()): # 영상 파일(카메라)이 정상적으로 열렸는지(초기화되었는지) 여부 | |
# ret: 정상적으로 읽어왔는가? | |
# frame: 한 장의 이미지(frame) 가져오기 | |
ret, frame = cap.read() # BGR | |
if ret: # 프레임 정보를 정상적으로 읽지 못하면 | |
yield frame # 프레임을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보 | |
else: # 프레임 정보를 정상적으로 읽지 못하면 | |
break # while 빠져나가기 | |
cap.release() # 영상 파일(카메라) 사용 종료 | |
# Video 정보 가져오기 | |
def get_video_info(infilename, is_print=False): | |
cap = cv2.VideoCapture(infilename) | |
if not cap.isOpened(): | |
print("could not open : ", infilename) | |
cap.release() | |
exit(0) | |
length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) | |
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) | |
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) | |
fps = cap.get(cv2.CAP_PROP_FPS) | |
cap.release() | |
if is_print: | |
print('length : ', length) | |
print('width : ', width) | |
print('height : ', height) | |
print('fps : ', fps) | |
video_info = { | |
'length': length, | |
'width': width, | |
'height': height, | |
'fps': fps, | |
} | |
return video_info | |
# Video -> Numpy | |
# 참고 깃허브 코드: https://github.com/khazit/Lip2Word/blob/master/lipReader.py#L22 | |
def videoToArray(video_pathname, is_gray=True) : | |
cap = cv2.VideoCapture(video_pathname) # 영상 객체(파일) 가져오기 | |
# 영상 파일(카메라)이 정상적으로 열리지 않은 경우 | |
if not cap.isOpened(): | |
print("could not open : ", video_pathname) | |
cap.release() # 영상 파일(카메라) 사용 종료 | |
exit(0) # 빠져나가기 | |
n_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 영상 프레임 개수 | |
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # 영상 너비 | |
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 영상 높이 | |
fps = cap.get(cv2.CAP_PROP_FPS) # 영상 FPS(Frames Per Second) | |
if is_gray: | |
video = np.zeros((n_frames, height, width)) # gray | |
else: | |
n_channels=3 | |
video = np.zeros((n_frames, height, width, n_channels)) # color | |
video = video.astype(np.uint8) | |
i = 0 | |
while True : | |
success, frame = cap.read() | |
if not success : | |
break | |
else : | |
# gray scale 적용 | |
if is_gray: | |
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) | |
video[i] = frame | |
i += 1 | |
cap.release() # 영상 파일(카메라) 사용 종료 | |
return video # 영상 정보 앞에 영상 프레임 개수를 추가한 numpy 반환 | |
# Frame Sampling (프레임 개수 맞추기) | |
# 참고 깃허브 코드: https://github.com/khazit/Lip2Word/blob/master/lipReader.py#L62 | |
def frameAdjust(video, target_frames=29): | |
n_frames = video.shape[0] # 영상 프레임 개수 | |
if target_frames == n_frames : | |
return video # 영상 그대로 반환 | |
else : | |
# 영상 프레임 개수 > 원하는 프레임 개수 | |
if n_frames > target_frames : | |
idx = np.linspace(0, n_frames-1, target_frames) # 숫자 시퀀스 생성 # 구간 시작점, 구간 끝점, 구간 내 숫자 개수 | |
idx = np.around(idx, 0).astype(np.int32) # 반올림하고 dtype 을 정수로 변경 | |
return video[idx] # 원하는 프레임 개수로 sampling 한 영상 | |
# 영상 프레임 개수 < 원하는 프레임 개수 | |
else : | |
output_video = np.zeros((target_frames, *video.shape[1:])).astype(np.uint8) # 원하는 프레임 개수에 맞춰서 0으로 초기화한 numpy 생성 | |
output_video[:n_frames] = video # 영상 프레임 개수까지 그대로 영상 정보 저장 | |
# 원하는 프레임 개수만큼 마지막 프레임 복제 | |
for i in range(target_frames-n_frames+1) : | |
output_video[i+n_frames-1] = output_video[n_frames-1] | |
return output_video # 원하는 프레임 개수로 sampling 한 영상 | |