import cv2 import numpy as np from moviepy.editor import VideoFileClip from huggingface_hub import hf_hub_download # 1. 그레이스케일 변환 def grayscale(frame): """ 그레이스케일 변환 함수. 입력된 BGR 이미지를 그레이스케일로 변환한 후 다시 BGR로 변환하여 차원을 유지합니다. """ gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) return cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) # 2차원을 3차원으로 변환 # 2. 네거티브 이미지 변환 def negative(frame): """ 네거티브 변환 함수. 입력된 BGR 이미지를 네거티브 이미지로 변환합니다 (색상 반전). """ return cv2.bitwise_not(frame) # 3. 안정된 밝기 조절 def adjust_brightness(frame, value): """ 밝기 조절 함수. 입력된 BGR 이미지에서 HSV로 변환 후, 밝기 채널(v)에 value 값을 더해 밝기를 조절합니다. value 값은 음수면 어둡게, 양수면 밝게 조절합니다. """ hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # BGR -> HSV로 변환 h, s, v = cv2.split(hsv) # HSV로 분리 # v 채널에 밝기 조정 값 추가, 0~255 사이로 클리핑하여 안전하게 조절 v = np.clip(v.astype(np.int16) + value, 0, 255).astype(np.uint8) # 다시 합쳐서 HSV -> BGR로 변환 final_hsv = cv2.merge((h, s, v)) return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR) # 4. 안정된 대비 조절 def adjust_contrast(frame, alpha): """ 대비 조절 함수. 입력된 BGR 이미지에서 alpha 값을 곱하여 대비를 조절합니다. alpha 값이 클수록 이미지의 대비가 강해집니다 (1.0~3.0 정도가 적절). """ adjusted = cv2.convertScaleAbs(frame, alpha=alpha, beta=0) # 대비 조정 후 값이 0~255 범위를 유지하는지 확인 (이미 convertScaleAbs가 처리하지만 안정성 추가) return np.clip(adjusted, 0, 255) # 5. 블러링 def blur_image(frame, kernel_size=5): """ 가우시안 블러링 함수. 입력된 BGR 이미지를 커널 크기만큼 흐리게 만듭니다. kernel_size 값은 반드시 홀수여야 하며, 커널 크기가 클수록 더 흐려집니다. """ blurred = cv2.GaussianBlur(frame, (kernel_size, kernel_size), 0) return blurred # BGR 차원 유지 (추가 변환 불필요) # 6. 엣지 검출 def edge_detection(frame): """ 엣지 검출 함수. 입력된 BGR 이미지에서 그레이스케일로 변환한 후 Sobel 연산을 통해 엣지를 검출합니다. 이후, 2차원으로 변환된 엣지 이미지를 다시 BGR 3차원으로 변환하여 반환합니다. """ gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) sobelx = cv2.Sobel(gray_frame, cv2.CV_64F, 1, 0, ksize=5) sobely = cv2.Sobel(gray_frame, cv2.CV_64F, 0, 1, ksize=5) edges = cv2.magnitude(sobelx, sobely) edges = np.uint8(edges) # 2차원 이미지로 변환 return cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR) # 다시 3차원 BGR로 변환 # 필터를 선택해서 적용하는 함수 """ 필터 적용 함수. 입력된 이미지에 선택한 필터 (그레이스케일, 네거티브, 밝기 조절, 대비 조절, 블러링, 엣지 검출)를 적용합니다. 사용 가능한 필터: - grayscale: 그레이스케일 변환 - negative: 네거티브 변환 - brightness: 밝기 조절 (기본값: 50) - contrast: 대비 조절 (기본값: alpha=1.5, 1.0~3.0 범위 사용 권장) - blur: 블러링 (기본 커널 크기: 5, 홀수만 사용 가능) - edge: 엣지 검출 """ def apply_filter(frame, filter_name, **kwargs): if filter_name == 'grayscale': return grayscale(frame) elif filter_name == 'negative': return negative(frame) elif filter_name == 'brightness': return adjust_brightness(frame, kwargs.get('value', 50)) # 기본 밝기 조절 값 elif filter_name == 'contrast': return adjust_contrast(frame, kwargs.get('alpha', 1.5)) # 기본 대비 값 1.0~3.0 정도가 적절 elif filter_name == 'blur': return blur_image(frame, kwargs.get('kernel_size', 5)) # 기본 커널 크기 elif filter_name == 'edge': return edge_detection(frame) else: return frame # 필터를 선택하지 않으면 원본을 반환 # MoviePy로 원본과 변환된 영상 소리 포함해서 저장하고 재생 (프리뷰 크기와 저장 크기 분리) def process_and_play_with_audio(input_video, output_video, filter_name, **kwargs): """ 선택한 필터를 적용하여 원본과 변환된 영상을 나란히 배치하고, 소리와 함께 재생 및 저장합니다. 프리뷰에서는 원본의 50% 크기로 보여주며, 최종 저장된 파일은 원본 크기 그대로 저장됩니다. """ # 원본 비디오 불러오기 (소리 포함) clip = VideoFileClip(input_video) # 프레임을 MoviePy에서 처리하는 방식으로 변환 def make_frame(img): # 선택한 필터를 적용 filtered_img = apply_filter(img, filter_name, **kwargs) # 원본과 변환된 프레임을 나란히 배치 combined_frame = np.hstack((img, filtered_img)) return combined_frame # 변환된 프레임으로 새로운 영상 클립 생성 new_clip = clip.fl_image(make_frame) # 프리뷰할 때는 크기 조정 (0.5 = 원본의 50% 크기로 재생) preview_clip = new_clip.resize(0.5) # 소리를 포함해 새로운 영상으로 저장 (원본 크기로 저장) new_clip.write_videofile(output_video, codec='libx264', audio=True) # 프리뷰 때만 축소된 크기로 재생 preview_clip.preview() # 비디오 처리 및 실행 repo_id = 'Nagase-Kotono/CheckAppVersion' # Hugging Face에서 네 리포지토리 ID file_name = 'DECO_27_ネバーランド_feat_初音ミク.mp4' # 다운로드할 파일 이름 # Hugging Face에서 파일 다운로드 input_video = hf_hub_download(repo_id=repo_id, filename=file_name) # 변환된 영상 파일을 저장할 경로 output_video = 'output_video_with_audio.mp4' # 변환된 영상 저장 + 소리 포함하여 재생 (필터 적용) process_and_play_with_audio(input_video, output_video, filter_name='edge') # 필터 선택