From c4d8d96e81e2f719900a02a75c7d00d60e80b24a Mon Sep 17 00:00:00 2001 From: carbox Date: Wed, 27 Mar 2024 15:41:58 +0900 Subject: [PATCH 1/9] Feat : Add data V1 OLKAVS refine function --- data/audio/audio_wav_cropping.py | 107 ++++++++++++++++++++ data/{ => image}/image_clipseg2.py | 0 data/image/image_face_frame.py | 78 ++++++++++++++ data/{ => total}/total_audio_video_image.py | 0 data/total/total_origin_remove.py | 60 +++++++++++ 5 files changed, 245 insertions(+) create mode 100644 data/audio/audio_wav_cropping.py rename data/{ => image}/image_clipseg2.py (100%) create mode 100644 data/image/image_face_frame.py rename data/{ => total}/total_audio_video_image.py (100%) create mode 100644 data/total/total_origin_remove.py diff --git a/data/audio/audio_wav_cropping.py b/data/audio/audio_wav_cropping.py new file mode 100644 index 0000000..fc52070 --- /dev/null +++ b/data/audio/audio_wav_cropping.py @@ -0,0 +1,107 @@ +import os +import json +from pydub import AudioSegment + +def process_wav_and_json(wav_file: str, json_file: str, wav_file_name: str, save_folder: str): + """ wav 파일을 받아 json 에서 필요한 부분을 잘라내 형태에 맞게 저장할 코드 + + Args: + wav_file (str): json 파일과 매칭되는 wav_file 경로 + json_file (str): wav_file croping에 사용될 json_file 경로 + wav_file_name (str): folder명 지정에 사용할 wav_file 자체 이름 + save_folder (str): 정제된 파일을 저장할 경로 + """ + count = 1 + audio = AudioSegment.from_wav(wav_file) + + # 저장할 폴더 생성 + wav_file_folder = wav_file_name.split("_")[:-2] + wav_file_folder = "_".join(wav_file_folder) + wav_file_folder = os.path.join(save_folder,'data', wav_file_folder,'audio') + os.makedirs(wav_file_folder, exist_ok=True) + + # json 파일 열기 + with open(json_file, 'r') as f: + data = json.load(f) + data= data[0] + + # 각 시간대별로 돌아가며 동영상 croping + for sentence_info in data['Sentence_info']: + start_time = round(int(sentence_info['start_time']), 3) + end_time = round(int(sentence_info['end_time']), 3) + time = end_time - start_time + if time <3 or time > 10 : + continue + + start_time_ms = start_time * 1000 + end_time_ms = end_time * 1000 + + + segment = audio[start_time_ms:end_time_ms] + output_wav_file = f"{wav_file_name.split('_')[-1]}_{count:03d}.wav" + + output_wav_path = os.path.join(wav_file_folder, output_wav_file) + + segment.export(output_wav_path, format='wav') + count += 1 + + print(f"Saved {output_wav_path}") + + +def find_matching_json(file_name: str, json_folder: str) ->str : + """wav 파일과 파일명이 똑같은 json 파일을 찾아 경로 반환, + 만약 없다면 None 반환 + + Args: + file_name (str): wav 파일 이름 가져오기 + json_folder (str): json이 저장된 위치 확인 + + Returns: + str: wav 파일에 해당하는 json 파일 반환 + """ + + for root, dirs, files in os.walk(json_folder): + for file in files: + if file.split('.')[0] == file_name: + json_file = os.path.join(root, file) + return json_file + return None + +def find_wav(wav_folder: str, json_folder: str, save_folder: str): + """ 처음 정제할 wav 파일 찾기 + 이후 json 파일을 찾아 wav를 정제한다. + + Args: + wav_folder (str): wav 파일들이 저장된 폴더 위치 + json_folder (str): json 파일들이 저장된 폴더 위치 + save_folder (str): croping 된 파일들을 저장할 위치 + """ + + for root,_,files in os.walk(wav_folder): + for file in files: + if file.endswith('.wav'): + wav_file = os.path.join(root, file) + wav_file_name = wav_file.split('/')[-1].split('.')[0] + json_file = find_matching_json(wav_file_name, json_folder) + + if json_file: + process_wav_and_json(wav_file, json_file, wav_file_name, save_folder) + os.remove(wav_file) + + +def main(wav_folder: str, json_folder: str, save_folder: str): + find_wav(wav_folder, json_folder, save_folder) + print('End of processing') + + + + +if __name__ == '__main__': + # WAV 파일이 들어있는 폴더 경로 + wav_folder = '/home/carbox/Desktop/data/009.립리딩(입모양) 음성인식 데이터/01.데이터/2.Validation/원천데이터' + # JSON 파일이 들어있는 폴더 경로 + json_folder = '/home/carbox/Desktop/data/009.립리딩(입모양) 음성인식 데이터/01.데이터/2.Validation/라벨링데이터' + # 원천데이터를 저장할 폴더 경로 + save_folder = '/home/carbox' + + main(wav_folder, json_folder, save_folder) diff --git a/data/image_clipseg2.py b/data/image/image_clipseg2.py similarity index 100% rename from data/image_clipseg2.py rename to data/image/image_clipseg2.py diff --git a/data/image/image_face_frame.py b/data/image/image_face_frame.py new file mode 100644 index 0000000..56bb442 --- /dev/null +++ b/data/image/image_face_frame.py @@ -0,0 +1,78 @@ +import cv2 +import os +from rembg import remove + +def process_video(video_path: str, save_folder: str): + """Video 에서 사람의 얼굴이 정면이고, 눈을 뜨고 잇을 때 캡쳐 및 배경 제거 + + Args: + video_path (str): 타겟 비디오 파일경로 + save_folder (str): 이미지를 저장할 위치 + """ + face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_alt2.xml') + eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye_tree_eyeglasses.xml') + + cap = cv2.VideoCapture(video_path) + + while True: + ret, frame = cap.read() + if not ret: + break + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + faces = face_cascade.detectMultiScale(gray, 1.1, 4) + + for (x, y, w, h) in faces: + # 얼굴 영역을 30% 확장 + expansion_rate = 0.3 + new_width = int(w * (1 + expansion_rate)) + new_height = int(h * (1 + expansion_rate)) + new_x = x - int(w * expansion_rate / 2) + new_y = y - int(h * expansion_rate / 2) + + # 확장된 영역이 프레임을 벗어나지 않도록 조정 + new_x = max(0, new_x) + new_y = max(0, new_y) + new_width = min(new_width, frame.shape[1] - new_x) + new_height = min(new_height, frame.shape[0] - new_y) + + roi_color = frame[new_y:new_y+new_height, new_x:new_x+new_width] + eyes = eye_cascade.detectMultiScale(cv2.cvtColor(roi_color, cv2.COLOR_BGR2GRAY)) + if len(eyes) >= 2: # 두 눈이 검출되면 + face_img = cv2.resize(roi_color, (256, 256)) + face_img = remove(face_img, bgcolor=(255, 255, 255, 255)) + + video_name = "_".join(os.path.splitext(os.path.basename(video_path))[0].split("_")[:-2]) + origin_file_folder = os.path.join(save_folder,'data', video_name) + os.makedirs(origin_file_folder, exist_ok=True) + + cv2.imwrite(f'{os.path.join(origin_file_folder, video_name)}.png', face_img) + cap.release() + return + + print(os.path.basename(video_path)) + cap.release() + + +def main(video_folder: str, save_folder: str): + """ 비디오 폴더 경로에서 .mp4 파일 선택, + 정제 이후 파일 제거 + + Args: + video_folder (str): 탐색할 비디오가 있는 경로 + save_folder (str): 이미지 저장을 위한 파일 + """ + for root,_,files in os.walk(video_folder): + for file in files: + if file.endswith('.mp4'): + video_file = os.path.join(root, file) + process_video(video_file, save_folder) + os.remove(os.path.join(root,file)) + + +if __name__ == '__main__': + video_folder = '/home/carbox/Desktop/data/009.립리딩(입모양) 음성인식 데이터/01.데이터/2.Validation/원천데이터' + save_folder = "/home/carbox" + main(video_folder, save_folder) + + diff --git a/data/total_audio_video_image.py b/data/total/total_audio_video_image.py similarity index 100% rename from data/total_audio_video_image.py rename to data/total/total_audio_video_image.py diff --git a/data/total/total_origin_remove.py b/data/total/total_origin_remove.py new file mode 100644 index 0000000..68f66a0 --- /dev/null +++ b/data/total/total_origin_remove.py @@ -0,0 +1,60 @@ +import os +import re +import tarfile + +def extract_tar_if_needed(root_folder: str): + """ tar 파일을 추출하는 함수 + + Args: + root_folder (str): tar 파일이 들어있는 폴더 경로 + """ + for root, dirs, files in os.walk(root_folder): + for file in files: + if file.endswith('.tar'): + # .tar 파일과 같은 이름을 가진 폴더가 있는지 확인 + tar_path = os.path.join(root, file) + folder_name = os.path.splitext(tar_path)[0] + if not os.path.exists(folder_name): + # 동일한 이름의 폴더가 없으면 압축 해제 + print(f"Extracting {tar_path}") + with tarfile.open(tar_path) as tar: + tar.extractall(path=root) + print(f"Extracted to {folder_name}") + # 압축 해제 후 dirs 리스트 업데이트 + dirs.append(os.path.basename(folder_name)) + + # 추출 후 삭제 + os.remove(os.path.join(root, file)) + print(f"Deleted {file} ") + + + +def delete_files_except_extensions(root_folder: str, keep_extensions: list, pattern: str): + """ 정제에 필요한 파일을 제외한 다른 파일들 삭제 + + Args: + root_folder (str): 타겟 폴더 + keep_extensions (list): 유지할 확장자 wav, 혹은 끝나는 부분 (A_001.mp4) 확인 + pattern (str): 유지할 파일명 패턴 + """ + for root, dirs, files in os.walk(root_folder): + for file in files: + if not any(file.endswith(ext) for ext in keep_extensions): + if re.search(pattern, file): + continue + file_path = os.path.join(root, file) + os.remove(file_path) + print(f"Deleted {file}") + +def main(root_folder: str, keep_extensions: list, pattern: str): + # 먼저 .tar 파일이 있으면 압축을 해제 + extract_tar_if_needed(root_folder) + # 압축 해제 후 (해당되는 경우), 지정된 확장자 외의 파일 삭제 + delete_files_except_extensions(root_folder, keep_extensions, pattern) + print("End of processing") + +if __name__ == '__main__': + root_folder = '~/Desktop/GPU/009.립리딩(입모양) 음성인식 데이터/01.데이터/2.Validation/원천데이터' # 탐색을 시작할 폴더 경로 + keep_extensions = ['A_001.mp4', '.wav'] # 유지하고 싶은 파일 확장자 목록 + pattern = r'.*_A_.*\.json' + main(root_folder, keep_extensions, pattern) From 12fabe771abb2c6fc3acd64e35cb13943aa9d3d5 Mon Sep 17 00:00:00 2001 From: soyoonjeong <76814748+soyoonjeong@users.noreply.github.com> Date: Thu, 28 Mar 2024 11:12:46 +0900 Subject: [PATCH 2/9] [FEAT] Readme Code Merge (#9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Feat : First Commit * Update readme.md * Update readme.md * Feat : modify readme * Update readme.md * Update readme.md * Update README.md * Update readme.md * Update readme.md --------- Co-authored-by: jouhy Co-authored-by: Im._.SH <85490226+dlatjgus0612@users.noreply.github.com> Co-authored-by: 김태양_T6044 <52816769+taeyang916@users.noreply.github.com> --- modeling/README.md | 35 ++++++++++++++- readme.md | 109 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 readme.md diff --git a/modeling/README.md b/modeling/README.md index 9aff66e..1d7a598 100644 --- a/modeling/README.md +++ b/modeling/README.md @@ -1 +1,34 @@ -# voice2face-modeling- \ No newline at end of file +# Voice2Face-Modeling + +# File Tree + + modeling + ├─ pytorch_template + │ ├─ config + │ ├─ models + │ ├─ modules + │ ├─ predict.py + │ └─ train.py + ├─ sf2f + │ ├─ infer.py + │ ├─ inference_fuser.py + │ ├─ test.py + │ ├─ train.py + ├─ SimSwap + │ └─ inference_swap.py + └─ wcgan-gp + ├─ inference.py + └─ train.py + +# Getting Started + + + +## References +[Speech Fusion to Face](https://arxiv.org/pdf/2006.05888.pdf) + +[Conditional GAN](https://arxiv.org/pdf/1411.1784.pdf) + +[Sim Swap](https://github.com/neuralchen/SimSwap) + +[Pytorch Template](https://github.com/victoresque/pytorch-template) diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..51658db --- /dev/null +++ b/readme.md @@ -0,0 +1,109 @@ + + +# 🔊목소리로 가상 얼굴 생성 서비스 [너의목소리가보여] + + + + + + + + + + + + + + + + + +# ✅ Project Overview +

+ +사용자의 목소리를 입력 받아 얼굴을 생성하고, +생성된 얼굴을 다른 영상 속 얼굴에 합성하여 결과물 제공하는 서비스 제작 +### ✔️ 기획의도 + +

+ +- 사생활 보호와 사용자 경험을 향상 +- Multi-modal 기술에 대한 경험 +- 실제 서비스를 개발하고 개선하는 것 + +

+ +1. 요즘 얼굴을 드러내지 않고 활동하는 사람이 많아졌다는 점 +2. 사생활이나 목소리와 어울리지 않아 이질감을 주는 문제 + +이를 해결하기 위하여 **성대와 울림통에 의해 목소리가 결정되고, 사람의 목소리에서 추출한 특성으로 여러 생리학적 구조와 특성을 구별할 수 있음** 을 이용합니다. + +이런 ***목소리와 얼굴 간의 상관 관계*** 를 학습하도록 하였습니다. + +### ✔️ 기대효과 +

+ +### ✔️ 차별점 +⭐ **도파민(중독)** 개발 +- 최종 프로젝트를 구현하기 위해 `애자일하게 문제를 접근` 하여 **Bottom Up** 방식으로 개발할 부분을 정리하여 단계적으로 서비스를 고도화 해나갈 수 있도록 하였습니다. +- 모든 프로젝트에 사용했던 코드를 **`모듈화`** 을 통해 재사용 가능하도록 하였으며, 이를 활용하여 서비스 고도화 작업을 이뤄나갔습니다. +- `실 서비스`까지 프로젝트로 제공하겠다는 마음과, 순간 순간 집중하는 팀원들간의 `단합력`으로 도파민 풀충전 개발을 항상 함께 해나갔습니다. +### ➡️ 그 결과 **2일 만에 사용 횟수 🌟 100회** 달성 🌟 + +# ✅ 팀원 소개 +**우리는 `조화`와 `지속 가능한 성장`을 추구하는 `팀 MakeZenerator` 입니다.** + +**각자의 위치에서 `오너십`을 가지고 `적극적으로 참여`함으로써, 우리는 협업의 힘을 최대화합니다. `치열한 고민`과 `끊임없는 학습`으로, 자신의 역량을 키우고 새로운 아이디어를 탐구합니다.** **우리의 모토는 `함께 성장한다`입니다. 서로를 뒷받침하며 동료들과의 소통을 통해 더 나은 팀을 만들어갑니다.** + +***열정과 도전 정신으로, 우리는 항상 앞으로 나아가고 있습니다 !*** + +### 👥 팀원 +| [신호준] | [김태양]| [김혜지] | [정소윤] | [성주희] | [임서현] | +|--|--|--|--|--|--| +|

|

|

|

|

|

+|

[](https://github.com/internationalwe)

|

[](https://github.com/taeyang916)

|

[](https://github.com/carboxaminoo)

|

[](https://github.com/soyoonjeong)

|

[](https://github.com/jouhy)

|

[](https://github.com/dlatjgus0612)

| + +### 👥 역할 +

+ +# ✅ 타임라인 +팀 구성, 방향성을 설정하고 프로젝트를 설계하였습니다. 이후 `서비스 파이프라인`을 설계, `sprint 주기`에 맞춰 회의를 진행하고, `기능명세서`를 작성하여 `task`를 진행하였습니다. + +원활한 서비스 완성을 위해 `Version`을 나누었고, +서비스를 실습해보기 위해 간단한 v0.1, +이후 데이터 파이프라인을 구축하고, 시스템 아키텍처와 서비스 전반을 고도화하여 현재의 **`v1.0 최종 프로젝트 배포`** 가 완료된 상태입니다. + +✔️ 타임라인 표 +

+ +# ✅ 시스템 아키텍처 & 파이프라인 + +✔️ 아키텍처 사진 +

+ +✔️ 파이프라인 사진 +

+ +# ✅ Getting Started +> 아래 Readme를 통해 직접 프로젝트에 구현된 코드를 살펴볼 수 있습니다. + +### 💫 Model +- [Model](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/modeling) / [README.md](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/modeling/README.md) + +### 📊 Data +- [Data Pipeline](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/data) / [README.md](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/data/README.md) + +### 🖼️ Frontend +- [Frontend](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/frontend) / [README.md](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/frontend/README.md) + +### 💻 Backend +- [Backend](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/backend) / [README.md](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/backend/README.md) + +### 🌐 MLOps +- [MLOps](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/mlops) / [README.md](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/mlops/README.md) + +## Links +### [YOUTUBE 발표자료](https://youtu.be/VJL6UQUTKrY?si=ZEs1L4BqvAnHlwvh) +updated. 2024.04.02 +### [NOTION LINK](https://truealex.notion.site/CV-08-d7987f38c09f470aababdedd822e96ca?pvs=4) +updated. 2024.03.31 From 7d46b6166a62543d640c8e0f06bfb4bc23564bbd Mon Sep 17 00:00:00 2001 From: internationalwe <46400961+internationalwe@users.noreply.github.com> Date: Thu, 28 Mar 2024 11:22:00 +0900 Subject: [PATCH 3/9] Update readme.md --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 51658db..2bc7240 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ -# 🔊목소리로 가상 얼굴 생성 서비스 [너의목소리가보여] +# 🔊목소리로 가상 얼굴 생성 서비스 [너의 목소리가 보여] @@ -17,6 +17,7 @@ + # ✅ Project Overview

From fdfcdbea5f26d66335f6465a45aa0af1ad657ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=98=9C=EC=A7=80=5FT6046?= <149589697+carboxaminoo@users.noreply.github.com> Date: Sat, 30 Mar 2024 10:15:44 +0900 Subject: [PATCH 4/9] [Docs] Add Web-Frontend README code (#10) * Doc : Add Frontend README * Doc : Modify README title * Docs: Modify README --- frontend/README.md | 151 +++++++++++++++++++++++++++ frontend/static/resultlist/readme.md | 1 - 2 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 frontend/README.md delete mode 100644 frontend/static/resultlist/readme.md diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..ed49ea5 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,151 @@ +# 🔊목소리로 가상 얼굴 생성 서비스 [너의 목소리가 보여] + + + + +## Project Structure + +``` +frontend +┣ src +┃ ┣ components +┃ ┃ ┣ button +┃ ┃ ┃ ┣ basic_filled.svelte +┃ ┃ ┃ ┣ moving_filled.svelte +┃ ┃ ┃ ┣ request_filled.svelte +┃ ┃ ┃ ┗ result_save.svelte +┃ ┃ ┣ header +┃ ┃ ┃ ┣ header_login.svelte +┃ ┃ ┃ ┗ header_non.svelte +┃ ┃ ┣ image +┃ ┃ ┃ ┣ PlaceholderImage.svelte +┃ ┃ ┃ ┗ SocialProperty1Github.svelte +┃ ┃ ┣ modal +┃ ┃ ┃ ┗ basic_modal.svelte +┃ ┃ ┣ rating +┃ ┃ ┃ ┣ Star.svelte +┃ ┃ ┃ ┗ StarRating.svelte +┃ ┃ ┗ survey +┃ ┃ ┣ input_area.svelte +┃ ┃ ┗ survey.svelte +┃ ┣ routes +┃ ┃ ┣ aboutus +┃ ┃ ┃ ┗ +page.svelte +┃ ┃ ┣ home +┃ ┃ ┃ ┗ +page.svelte +┃ ┃ ┣ infogather +┃ ┃ ┃ ┣ +page.svelte +┃ ┃ ┃ ┗ VoiceButtonDefaultVariant3.svelte +┃ ┃ ┣ join +┃ ┃ ┃ ┣ +page.svelte +┃ ┃ ┃ ┣ ButtonStyleFilled.svelte +┃ ┃ ┃ ┣ ButtonStyleOutlined.svelte +┃ ┃ ┃ ┣ PlaceholderImage.svelte +┃ ┃ ┃ ┣ radio.svelte +┃ ┃ ┃ ┣ RadioBigDefault.svelte +┃ ┃ ┃ ┗ RadioSmallS.svelte +┃ ┃ ┣ loading +┃ ┃ ┃ ┗ +page.svelte +┃ ┃ ┣ login +┃ ┃ ┃ ┣ +page.svelte +┃ ┃ ┃ ┗ PlaceholderImage.svelte +┃ ┃ ┣ maintenance +┃ ┃ ┃ ┗ +page.svelte +┃ ┃ ┣ result +┃ ┃ ┃ ┣ +page.svelte +┃ ┃ ┃ ┗ PlaceholderImage.svelte +┃ ┃ ┗ resultlist +┃ ┃ ┃ ┣ +page.svelte +┃ ┃ ┃ ┗ ButtonStyleFilled.svelte +┃ ┃ ┣ +layout.svelte +┃ ┃ ┣ +page.js +┃ ┃ ┣ +page.svelte +┃ ┃ ┣ styles.css +┃ ┣ app.html +┃ ┣ app.pcss +┃ ┗ hooks.js +┣ static +┣ .gitignore +┣ .npmrc +┣ Dockerfile +┣ package.json +┣ package-lock.json +┣ postcss.config.cjs +┣ README.md +┣ svelte.config.js +┣ tailwind.config.cjs +┗ vite.config.js +``` +## Usage + + +### `src` +#### `components` +: 페이지 내부에 포함할 컴포넌트를 모듈화 하기 위해 보관해둔 폴더 + - `button`: 화면 변경이나, input event 등의 trigger로 사용하기 위한 버튼을 보관한 폴더 + - `header`: 웹사이트 header 보관 폴더 + - `image`: 웹에 사용되는 이미지 style을 지정할 폴더 + - `modal`: 주의사항을 표시할 modal을 보관한 폴더 + - `rating`: 별점 표시, 전송을 위한 컴포넌트를 보관한 폴더 + - `survey`: 설문조사 항목에 대한 컴포넌트를 보관한 폴더 + +#### `routes` +: 서비스에 사용된 페이지를 담아둔 폴더 + + - `aboutus`: 팀, 팀원 소개를 위한 페이지 + - `home`: 로그인 후 생성요청이나, 결과 확인으로 이동할 수 있는 화면 + - `infogather`: 사용자가 생성요청을 보낼 수 있는 페이지 + - `VoiceButtonDefaultVariant3.svelte`: 음성 녹음 및 Blob을 생성하기 위한 모듈 + - `join`: 회원가입을 위한 페이지 + - `loading`: 사용자가 이미지 생성 요청 후 넘어갈 수 있는 페이지로 결과나 `home`화면으로 이동할 수 있다. + - `login`: 로그인 페이지 + - `maintenance`: 서비스 점검 시 사용될 페이지 + - `result`: 결과를 확인할 수 있는 페이지 + - `resultlist`: 결과 목록 페이지 + +#### `hooks.js` +: 서비스 점검 시 모든 화면을 maintenance 화면으로 이동하는 event 를 발생시킬 훅을 추가하는 파일 +### `static` +: 서비스에 사용된 이미지를 보관해둔 폴더 + + +## Getting Started +This project was developed and tested on the following operating systems: +- **Linux**: Ubuntu 20.04 LTS +- **Windows**: Windows 11 Home + +### 1. Install Requirements + +To run this project, you'll need Node.js installed on your system. We recommend using NVM (Node Version Manager) to manage your Node.js versions. +``` +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash +source ~/.bashrc +nvm install 20.11.1 +``` + +This project uses Tailwind CSS, Flowbite, and Svelte routing for UI and navigation. +``` +# basic package +npm install +npx svelte-add@latest tailwindcss +npm install -D tailwindcss svelte-routing flowbite-svelte flowbite +``` +### 2. Developing + +To start the development server, run: + +```bash +npm run dev + +# or start the server and open the app in a new browser tab +npm run dev -- --open +``` + +### 3. Building + +To create a production build, use: + +``` +npm run build +``` + diff --git a/frontend/static/resultlist/readme.md b/frontend/static/resultlist/readme.md deleted file mode 100644 index 2dbf495..0000000 --- a/frontend/static/resultlist/readme.md +++ /dev/null @@ -1 +0,0 @@ -In this folder you can store your assets... \ No newline at end of file From c99e3444f51f39ae6e57049d02638d547bf236fd Mon Sep 17 00:00:00 2001 From: "Im._.SH" <85490226+dlatjgus0612@users.noreply.github.com> Date: Fri, 29 Mar 2024 01:37:27 +0900 Subject: [PATCH 5/9] Create README.md --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..238d61e --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Voice2Face-Data + src="https://img.shields.io/badge/github-181717?style=for-the-badge&logo=github&logoColor=white"> +# File Tree + + + +# Getting Started + + + +## References From 81f5f9983a8e7e6ad6102a907b94d1420b245e56 Mon Sep 17 00:00:00 2001 From: dlatjgus0612 Date: Fri, 29 Mar 2024 01:57:01 +0900 Subject: [PATCH 6/9] Docs : modify README --- README.md | 11 ----- data/README.md | 82 ++++++++++++++++++++++++++++++++++++ readme.md | 110 ------------------------------------------------- 3 files changed, 82 insertions(+), 121 deletions(-) delete mode 100644 README.md create mode 100644 data/README.md delete mode 100644 readme.md diff --git a/README.md b/README.md deleted file mode 100644 index 238d61e..0000000 --- a/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Voice2Face-Data - src="https://img.shields.io/badge/github-181717?style=for-the-badge&logo=github&logoColor=white"> -# File Tree - - - -# Getting Started - - - -## References diff --git a/data/README.md b/data/README.md new file mode 100644 index 0000000..890c364 --- /dev/null +++ b/data/README.md @@ -0,0 +1,82 @@ + +# 🔊 Voice2Face-Data + + + +## Project Structure +``` +data +┣ audio +┃ ┣ audio_check_dB.py +┃ ┣ audio_crop.py +┃ ┗ audio_wav_cropping.py +┣ crawling +┃ ┣ crawling_detect.py +┃ ┣ crawling_rename_video.py +┃ ┣ crawling_select_csv.py +┃ ┣ crawling_urlsave.py +┃ ┗ crawling_videosave.py +┣ image +┃ ┣ image_clipseg2.py +┃ ┗ image_face_frame.py +┣ relabel +┃ ┣ relabel_detect_getframe.py +┃ ┣ relabel_select_csv.py +┃ ┗ relabel_Vox_age.py +┣ total +┃ ┣ total_audio_video_image.py +┃ ┗ total_origin_remove.py +┣ video +┃ ┣ video_clipimage.py +┃ ┗ video_download.py +┗ README.md +┗ requirements.txt +``` + +## Getting Started + +### Setting up Vitual Enviornment + +1. Initialize and update the server + ``` + su - + source .bashrc + ``` + +2. Create and Activate a virtual environment in the project directory + + ``` + conda create -n env python=3.8 + conda activate env + ``` + +4. To deactivate and exit the virtual environment, simply run: + + ``` + deactivate + ``` + +### Install Requirements + +To Insall the necessary packages liksted in `requirements.txt`, run the following command while your virtual environment is activated: +``` +pip install -r requirements.txt +``` + +## Usage + +#### Training + +To train the model with your custom dataset, set the appropriate directories for the training images and model saving, then run the training script. + +``` +python train.py --data_dir /path/to/images --model_dir /path/to/model +``` + +#### Inference + +For generating predictions with a trained model, provide directories for evaluation data, the trained model, and output, then run the inference script. + +``` +python inference.py --data_dir /path/to/images --model_dir /path/to/model --output_dir /path/to/model +``` diff --git a/readme.md b/readme.md deleted file mode 100644 index 2bc7240..0000000 --- a/readme.md +++ /dev/null @@ -1,110 +0,0 @@ - - -# 🔊목소리로 가상 얼굴 생성 서비스 [너의 목소리가 보여] - - - - - - - - - - - - - - - - - - -# ✅ Project Overview -

- -사용자의 목소리를 입력 받아 얼굴을 생성하고, -생성된 얼굴을 다른 영상 속 얼굴에 합성하여 결과물 제공하는 서비스 제작 -### ✔️ 기획의도 - -

- -- 사생활 보호와 사용자 경험을 향상 -- Multi-modal 기술에 대한 경험 -- 실제 서비스를 개발하고 개선하는 것 - -

- -1. 요즘 얼굴을 드러내지 않고 활동하는 사람이 많아졌다는 점 -2. 사생활이나 목소리와 어울리지 않아 이질감을 주는 문제 - -이를 해결하기 위하여 **성대와 울림통에 의해 목소리가 결정되고, 사람의 목소리에서 추출한 특성으로 여러 생리학적 구조와 특성을 구별할 수 있음** 을 이용합니다. - -이런 ***목소리와 얼굴 간의 상관 관계*** 를 학습하도록 하였습니다. - -### ✔️ 기대효과 -

- -### ✔️ 차별점 -⭐ **도파민(중독)** 개발 -- 최종 프로젝트를 구현하기 위해 `애자일하게 문제를 접근` 하여 **Bottom Up** 방식으로 개발할 부분을 정리하여 단계적으로 서비스를 고도화 해나갈 수 있도록 하였습니다. -- 모든 프로젝트에 사용했던 코드를 **`모듈화`** 을 통해 재사용 가능하도록 하였으며, 이를 활용하여 서비스 고도화 작업을 이뤄나갔습니다. -- `실 서비스`까지 프로젝트로 제공하겠다는 마음과, 순간 순간 집중하는 팀원들간의 `단합력`으로 도파민 풀충전 개발을 항상 함께 해나갔습니다. -### ➡️ 그 결과 **2일 만에 사용 횟수 🌟 100회** 달성 🌟 - -# ✅ 팀원 소개 -**우리는 `조화`와 `지속 가능한 성장`을 추구하는 `팀 MakeZenerator` 입니다.** - -**각자의 위치에서 `오너십`을 가지고 `적극적으로 참여`함으로써, 우리는 협업의 힘을 최대화합니다. `치열한 고민`과 `끊임없는 학습`으로, 자신의 역량을 키우고 새로운 아이디어를 탐구합니다.** **우리의 모토는 `함께 성장한다`입니다. 서로를 뒷받침하며 동료들과의 소통을 통해 더 나은 팀을 만들어갑니다.** - -***열정과 도전 정신으로, 우리는 항상 앞으로 나아가고 있습니다 !*** - -### 👥 팀원 -| [신호준] | [김태양]| [김혜지] | [정소윤] | [성주희] | [임서현] | -|--|--|--|--|--|--| -|

|

|

|

|

|

-|

[](https://github.com/internationalwe)

|

[](https://github.com/taeyang916)

|

[](https://github.com/carboxaminoo)

|

[](https://github.com/soyoonjeong)

|

[](https://github.com/jouhy)

|

[](https://github.com/dlatjgus0612)

| - -### 👥 역할 -

- -# ✅ 타임라인 -팀 구성, 방향성을 설정하고 프로젝트를 설계하였습니다. 이후 `서비스 파이프라인`을 설계, `sprint 주기`에 맞춰 회의를 진행하고, `기능명세서`를 작성하여 `task`를 진행하였습니다. - -원활한 서비스 완성을 위해 `Version`을 나누었고, -서비스를 실습해보기 위해 간단한 v0.1, -이후 데이터 파이프라인을 구축하고, 시스템 아키텍처와 서비스 전반을 고도화하여 현재의 **`v1.0 최종 프로젝트 배포`** 가 완료된 상태입니다. - -✔️ 타임라인 표 -

- -# ✅ 시스템 아키텍처 & 파이프라인 - -✔️ 아키텍처 사진 -

- -✔️ 파이프라인 사진 -

- -# ✅ Getting Started -> 아래 Readme를 통해 직접 프로젝트에 구현된 코드를 살펴볼 수 있습니다. - -### 💫 Model -- [Model](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/modeling) / [README.md](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/modeling/README.md) - -### 📊 Data -- [Data Pipeline](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/data) / [README.md](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/data/README.md) - -### 🖼️ Frontend -- [Frontend](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/frontend) / [README.md](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/frontend/README.md) - -### 💻 Backend -- [Backend](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/backend) / [README.md](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/backend/README.md) - -### 🌐 MLOps -- [MLOps](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/mlops) / [README.md](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/main/mlops/README.md) - -## Links -### [YOUTUBE 발표자료](https://youtu.be/VJL6UQUTKrY?si=ZEs1L4BqvAnHlwvh) -updated. 2024.04.02 -### [NOTION LINK](https://truealex.notion.site/CV-08-d7987f38c09f470aababdedd822e96ca?pvs=4) -updated. 2024.03.31 From e399ea011ce4cf01c725e1ee1f06df18e395d613 Mon Sep 17 00:00:00 2001 From: dlatjgus0612 Date: Fri, 29 Mar 2024 03:46:49 +0900 Subject: [PATCH 7/9] Docs : Modify files & README --- data/README.md | 106 +++++++++++++----- .../audio/{audio_crop.py => audio_dB_crop.py} | 0 data/crawling/crawling_select_csv.py | 52 +++++++-- data/requirements.txt | 18 +++ data/video/video_clipimage.py | 66 ++++++----- data/video/video_download.py | 25 +++++ 6 files changed, 204 insertions(+), 63 deletions(-) rename data/audio/{audio_crop.py => audio_dB_crop.py} (100%) create mode 100644 data/requirements.txt diff --git a/data/README.md b/data/README.md index 890c364..360c808 100644 --- a/data/README.md +++ b/data/README.md @@ -1,14 +1,21 @@ + + # 🔊 Voice2Face-Data + + + + ## Project Structure + ``` data ┣ audio ┃ ┣ audio_check_dB.py -┃ ┣ audio_crop.py +┃ ┣ audio_dB_crop.py ┃ ┗ audio_wav_cropping.py ┣ crawling ┃ ┣ crawling_detect.py @@ -29,54 +36,103 @@ data ┣ video ┃ ┣ video_clipimage.py ┃ ┗ video_download.py -┗ README.md +┣ README.md ┗ requirements.txt ``` +## Usage + + + +#### audio + - `audio_check_dB.py`: 특정 dB 값을 확인하여 사람의 음성 여부를 판별하는 스크립트입니다. + - `audio_dB_crop.py`: 오디오 파일에서 인간의 목소리 세그먼트를 추출하고 감지된 음성 세그먼트를 포함하는 새로운 오디오 파일을 10초로 자르는 스크립트입니다. + - `audio_wav_cropping.py`: JSON POINT에 맞춰 오디오를 자르는 스크립트입니다. + +#### crawling + + - `crawling_detect.py`: 비디오 클립에서 얼굴과 오디오를 감지하고 세분화하는 스크립트입니다. + - `crawling_rename_video.py`: 'download' 폴더에서 비디오 이름과 CSV의 인덱스를 맞추는 스크립트입니다. + - `crawling_select_csv.py`: 주어진 CSV 파일에서 YouTube ID를 찾아 해당하는 파일 이름에서 정보를 추출하고, 이 정보를 새로운 CSV 파일에 저장하는 간단한 데이터 처리 작업을 수행하는 스크립트입니다. + - `crawling_urlsave.py`: Selenium을 사용하여 YouTube 크롤링을 수행하여 약 162개의 비디오에 대한 이름, 제목 및 URL 정보를 Youtube_search_df.csv에 저장하는 스크립트입니다. + - `crawling_videosave.py`: '`crawling_urlsave.py`'를 통해 얻은 URL에서 비디오를 다운로드하는 스크립트입니다. 비디오는 'download' 폴더에 저장됩니다. + +#### image + + - `image_clipseg2.py`: CLIPSeg 모델을 사용하여 텍스트 프롬프트를 기반으로 이미지 세분화를 수행하는 스크립트입니다. 이미지를 불러와 텍스트 프롬프트로 처리하고, 식별된 객체를 기반으로 세분화된 이미지를 생성합니다. + - `image_face_frame.py`: 비디오에서 사람의 얼굴이 정면이고, 눈을 뜨고 있을 때 캡쳐하고 배경을 제거하는 스크립트입니다. + +#### relabel + + - `relabel_detect_getframe.py`: 주어진 비디오에서 얼굴을 감지하고, 감지된 얼굴에 대해 성별과 연령을 추정하여 화면에 표시하고, 일정한 간격으로 프레임을 캡처하여 이미지 파일로 저장하는 기능을 수행합니다. + - `relabel_select_csv.py`: 데이터 경로에서 YouTube ID를 추출하고, 파일 이름에서 필요한 정보를 추출하여 새로운 CSV 파일에 저장하는 스크립트입니다. + - `relabel_Vox_age.py`: 이미지 폴더에서 이미지들을 읽어와 각 이미지의 나이를 예측하고, 가장 흔한 나이 그룹을 세서 출력하고, 그 결과를 CSV 파일에 저장하는 작업을 수행합니다. + +#### video + + - `video_clipimage.py`: 주어진 이미지에서 얼굴을 감지하고, 감지된 얼굴 영역을 사각형으로 표시한 후 해당 얼굴을 256x256 크기로 조정하여 저장하는 작업을 수행합니다. + - `video_download.py`: 주요 기능은 주어진 YouTube 비디오 링크에서 비디오를 다운로드하고, 다운로드한 비디오를 mp4 또는 mp3 형식으로 변환하는 스크립트입니다. + +#### total +- `total_audio_video_image.py`: 오디오, 비디오 및 이미지와 관련된 작업을 총 수행하는 스크립트입니다. +- `total_origin_remove.py`: 데이터 경로에서 원본 파일을 제거하는 스크립트입니다. + + + ## Getting Started + ### Setting up Vitual Enviornment + 1. Initialize and update the server - ``` - su - - source .bashrc - ``` -2. Create and Activate a virtual environment in the project directory +``` - ``` - conda create -n env python=3.8 - conda activate env - ``` +su - -4. To deactivate and exit the virtual environment, simply run: +source .bashrc - ``` - deactivate - ``` +``` -### Install Requirements + + +2. Create and Activate a virtual environment in the project directory + + -To Insall the necessary packages liksted in `requirements.txt`, run the following command while your virtual environment is activated: ``` -pip install -r requirements.txt + +conda create -n env python=3.8 + +conda activate env + ``` -## Usage + -#### Training +4. To deactivate and exit the virtual environment, simply run: -To train the model with your custom dataset, set the appropriate directories for the training images and model saving, then run the training script. + ``` -python train.py --data_dir /path/to/images --model_dir /path/to/model + +deactivate + ``` -#### Inference + + +### Install Requirements + + -For generating predictions with a trained model, provide directories for evaluation data, the trained model, and output, then run the inference script. +To Install the necessary packages liksted in `requirements.txt`, run the following command while your virtual environment is activated: ``` -python inference.py --data_dir /path/to/images --model_dir /path/to/model --output_dir /path/to/model + +pip install -r requirements.txt + ``` + + \ No newline at end of file diff --git a/data/audio/audio_crop.py b/data/audio/audio_dB_crop.py similarity index 100% rename from data/audio/audio_crop.py rename to data/audio/audio_dB_crop.py diff --git a/data/crawling/crawling_select_csv.py b/data/crawling/crawling_select_csv.py index 1bab567..64097a7 100644 --- a/data/crawling/crawling_select_csv.py +++ b/data/crawling/crawling_select_csv.py @@ -3,19 +3,34 @@ from argparse import ArgumentParser def parse_args(): + """ + Command-line arguments parser. + + Returns: + argparse.Namespace: Parsed arguments. + """ parser = ArgumentParser() - # Conventional args - parser.add_argument('--csv_file', type=str, default='output_test.csv') - parser.add_argument('--data_path', type=str, default='origin/video') - parser.add_argument('--save_csv', type=str, default='new_output.csv') + parser.add_argument('--csv_file', type=str, default='output_test.csv', + help="Path to the CSV file containing data.") + parser.add_argument('--data_path', type=str, default='origin/video', + help="Path to the directory containing files and folders.") + parser.add_argument('--save_csv', type=str, default='new_output.csv', + help="Path to save the new CSV file.") args = parser.parse_args() - return args - def list_files_and_folders(data_path): + """ + List files and folders in the given directory path. + + Args: + data_path (str): Path to the directory. + + Returns: + list or None: List of files and folders if directory exists, otherwise None. + """ if os.path.isdir(data_path): items = os.listdir(data_path) return items @@ -23,20 +38,37 @@ def list_files_and_folders(data_path): return None def main(csv_file, data_path, save_csv): + """ + Main function to process data. + Args: + csv_file (str): Path to the CSV file. + data_path (str): Path to the directory containing files and folders. + save_csv (str): Path to save the new CSV file. + """ + # Read CSV file csv_data = pd.read_csv(csv_file, header=None) + + # Get list of files and folders in the data path youtube_ids = list_files_and_folders(data_path) + # Process each YouTube ID for youtube_id in youtube_ids: + # Filter rows corresponding to the YouTube ID filtered_df = csv_data[csv_data[0].astype(str).str.contains(youtube_id)] first_row = filtered_df.iloc[0:1] + + # Extract information from file name file_name = list_files_and_folders(os.path.join(data_path, youtube_id))[0] file_name_list = file_name.split("_") - first_row[4] = file_name_list[0] - first_row[5] = file_name_list[1] + + # Add extracted information as new columns + first_row[4] = file_name_list[0] + first_row[5] = file_name_list[1] + + # Save to new CSV file first_row.to_csv(save_csv, mode="a", index=False, header=False) - if __name__ == '__main__': args = parse_args() - main(**args.__dict__) \ No newline at end of file + main(**args.__dict__) diff --git a/data/requirements.txt b/data/requirements.txt new file mode 100644 index 0000000..6a236ce --- /dev/null +++ b/data/requirements.txt @@ -0,0 +1,18 @@ +opencv-python +rembg +librosa +numpy +matplotlib +soundfile +pydub +pandas +moviepy +face_recognition +selenium +requests +beautifulsoup4 +pytube +transformers +Pillow +torch +facenet-pytorch diff --git a/data/video/video_clipimage.py b/data/video/video_clipimage.py index eb4e39c..e5c1bfb 100644 --- a/data/video/video_clipimage.py +++ b/data/video/video_clipimage.py @@ -1,31 +1,41 @@ import cv2 -face_cascade = cv2.CascadeClassifier('code/file/haarcascade_frontalface_default.xml') - -# 이미지 읽기 -img = cv2.imread('code/file/image.png') -gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - -# 얼굴 감지 -faces = face_cascade.detectMultiScale(gray, 1.3, 5) - -# 각 얼굴에 대해 반복 -for (x, y, w, h) in faces: - # 얼굴 영역에 사각형 그리기 - cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2) - - # 얼굴 영역을 256x256 크기로 조정 - face_crop = cv2.resize(img[y:y+h, x:x+w], (256, 256)) +def detect_and_save_faces(image_path, output_path): + """Detects faces in the input image and saves them as 256x256 pixel images. - # 얼굴 이미지 저장 - cv2.imwrite('code/file/face_detected_256x256.png', face_crop) - -# 이미지 보여주기 -cv2.imshow('Image view', img) - -# 'q' 키를 누를 때까지 대기 -while cv2.waitKey(0) & 0xFF != ord('q'): - pass - -cv2.destroyAllWindows() - + Args: + image_path (str): Path to the input image file. + output_path (str): Path to save the detected face images. + """ + # Load the pre-trained face cascade classifier + face_cascade = cv2.CascadeClassifier('code/file/haarcascade_frontalface_default.xml') + + # Read the input image + img = cv2.imread(image_path) + gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + + # Detect faces + faces = face_cascade.detectMultiScale(gray, 1.3, 5) + + # Iterate over each detected face + for (x, y, w, h) in faces: + # Draw rectangle around the face + cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2) + + # Resize the face region to 256x256 pixels + face_crop = cv2.resize(img[y:y+h, x:x+w], (256, 256)) + + # Save the face image + cv2.imwrite(output_path, face_crop) + + # Display the image + cv2.imshow('Image view', img) + + # Wait for 'q' key to be pressed + while cv2.waitKey(0) & 0xFF != ord('q'): + pass + + cv2.destroyAllWindows() + +# Example usage +detect_and_save_faces('code/file/image.png', 'code/file/face_detected_256x256.png') diff --git a/data/video/video_download.py b/data/video/video_download.py index faeeb96..5b156a0 100644 --- a/data/video/video_download.py +++ b/data/video/video_download.py @@ -7,7 +7,14 @@ class Download: ''' 파일을 변환하기 위해선 ffmpeg란 프로그램을 별도로 설치해 컴퓨터 환경변수 설정을 마쳐야 함. ''' + def __init__(self, link): + ''' + Download 클래스의 생성자입니다. + + Args: + link (str): 유튜브 영상의 링크. + ''' # link 인자는 GUI에서 입력된 값을 받을 때 사용 # 컴퓨터 이용자명을 받아서 다운로드 폴더를 기본 폴더로 지정 self.parent_dir = f"/Users/{getuser()}/Documents/voice2face-data/code/file" @@ -15,11 +22,23 @@ def __init__(self, link): def getVideoName(self): '''(GUI 버전) 비디오 이름을 내보내는 함수''' + ''' + 유튜브 비디오의 제목을 반환하는 함수입니다. + + Returns: + str: 비디오의 제목. + ''' name = self.yt.title return name def downloadMp3(self): '''mp3 파일로 다운로드하는 함수''' + ''' + mp3 형식으로 비디오를 다운로드하는 함수입니다. + + Returns: + str: 다운로드한 mp3 파일의 이름. + ''' # mp4 형태지만 영상 없이 소리만 있는 파일 다운로드 stream = self.yt.streams.filter(only_audio=True).first() stream.download(self.parent_dir) @@ -37,6 +56,12 @@ def downloadMp3(self): def downloadMp4(self): '''mp4 파일로 다운로드하는 함수''' + ''' + mp4 형식으로 비디오를 다운로드하는 함수입니다. + + Returns: + str: 다운로드한 mp4 파일의 이름. + ''' audio = self.downloadMp3() # mp3 파일 다운로드 video = self.yt.streams.filter(adaptive=True, file_extension='mp4').first() # 비디오 객체 가져오기 print(video) From 2181597ace546253776130a95c04bfbef7a265c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=83=9C=EC=96=91=5FT6044?= <52816769+taeyang916@users.noreply.github.com> Date: Sat, 30 Mar 2024 11:09:34 +0900 Subject: [PATCH 8/9] [Docs] Add modeling README code (#11) * Feat : Add gitignore * Feat : version 1 * feat : modify readme * feat : modiify readme - simswap * feat : modify readme * Feat : modify readme - simswap & sf2f of getting start * feat : modify readme - References * feat : modify README * feat : modify README * Update README.md * feat : modify readme - getting start --------- Co-authored-by: Jouhy Co-authored-by: soyoonjeong <76814748+soyoonjeong@users.noreply.github.com> --- modeling/README.md | 181 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 159 insertions(+), 22 deletions(-) diff --git a/modeling/README.md b/modeling/README.md index 1d7a598..1123b24 100644 --- a/modeling/README.md +++ b/modeling/README.md @@ -1,34 +1,171 @@ # Voice2Face-Modeling -# File Tree - - modeling - ├─ pytorch_template - │ ├─ config - │ ├─ models - │ ├─ modules - │ ├─ predict.py - │ └─ train.py - ├─ sf2f - │ ├─ infer.py - │ ├─ inference_fuser.py - │ ├─ test.py - │ ├─ train.py - ├─ SimSwap - │ └─ inference_swap.py - └─ wcgan-gp - ├─ inference.py - └─ train.py - -# Getting Started +## Project Structure +``` +modeling +┣ pytorch_template +┃ ┣ config +┃ ┣ models +┃ ┣ modules +┃ ┣ predict.py +┃ ┗ train.py +┣ sf2f +┃ ┣ datasets +┃ ┣ models +┃ ┣ options +┃ ┣ scripts +┃ ┣ utils +┃ ┣ infer.py +┃ ┣ inference_fuser.py +┃ ┣ test.py +┃ ┗ train.py +┣ SimSwap +┃ ┣ inference_swap.py +┃ ┗ test_*_swap*.py +┣ cgan-gp +┃ ┣ dataset.py +┃ ┣ inference_options.py +┃ ┣ inference.py +┃ ┣ model.py +┃ ┣ train_options.py +┃ ┣ train.py +┃ ┗ utils.py +┣ README.md +┗ requirements.txt +``` + +## Usage + +#### pytorch_template + + - `config`: 모델을 동작시킬 arguments를 모두 포함하는 config 파일들을 모아 놓은 폴더입니다. + - `models`: model을 정의하고 build하는 코드들을 저장하는 폴더입니다. + - `modules`: 모델을 학습시키는데 필요한 부가적인 파일들을 저장해 둔 폴더입니다. (dataloader, loss function, scaler, optimizer, metrics 등) + - `predict.py` : 학습한 모델을 통해 inference를 실행시키는 코드입니다. + - `train.py` : config 파일을 통해 build한 후 모델을 학습시키는 코드입니다. + +#### sf2f + + - `datasets` : dataset을 build하는 코드들을 모아둔 폴더입니다. + - `models` : voice encoder, embedding fuser, decoder, discriminator 등의 모델 전반적인 구조를 선언하고 build하는 파일들을 모아둔 폴더입니다. + - `options` : 사용할 모델의 구조와 데이터 셋, 하이퍼파라미터 등의 arguments를 정리해 둔 config 파일들을 모아 놓은 폴더입니다. + - `scripts` : mel spectrogram 변환, fid score 계산, inception score 계산 등의 기능들을 모아둔 폴더입니다. + - `utils` : loss, evalutation, metrics, training utils 등의 모델 학습과 평가지표를 구성한 파일들을 모아둔 폴더입니다. + - `infer.py`: voice를 spectrogram으로 변환시켜 입력하였을 때 encoder_decoder 구조만으로 결과를 생성하도록 하는 코드입니다. + - `inference_fuser.py`: voice를 spectrogram으로 변환시켜 입력하였을 때 encoder_decoder 구조와 embedding fuser를 통해 향상된 결과를 생성하도록 하는 코드입니다. + - `test.py`: 모델의 성능을 평가하기 위해 새로운 데이터셋으로 test를 진행하는 코드입니다. + - `train.py`: 모델을 학습시키기 위해 사용되는 코드로, stage-1과 stage-2로 변경해서 사용할 수 있도록 구성되어 있습니다. + +#### SimSwap + + - `inference_swap.py` : face image와 target video를 입력받고, frames 별로 얼굴을 합성한 후 최종 video의 frames과 fps를 출력하는 코드입니다. + - ` test_*_swap*.py ` : 다양한 얼굴 합성을 수행합니다. 이미지/영상의 얼굴 하나에만, 이미지/영상의 모든 얼굴, 이미지/영상의 특정 얼굴 등 파일에 따라 target을 바꿀 수 있습니다. + +#### cgan-gp + + - `dataset.py` : argument로 지정된 dataset을 불러오도록 선언해둔 코드입니다. + - `inference_options.py` : 학습된 모델에 inference를 위해 필요한 arguments를 parameter로 받는 코드입니다. + - `inference.py` : arguments를 통해 성별과 나이를 condition으로 주어 모델을 통해 64x64 face image를 생성하는 코드입니다. + - `model.py` : 모델을 (conditional GAN, Discriminator, convolutional block 등) 선언하여 build할 수 있도록 하는 코드입니다. + - `train_options.py` : 모델을 학습시킬 때 사용되는 arguments를 parameter로 받는 코드로, pre-train 혹은 finetuning을 진행할 수 있도록 제어할 수 있는 argument도 있습니다. + - `train.py` : arguments를 통해 모델을 선언하고 학습시키는 코드입니다. + - `utils.py` : Gradient Penalty Loss와 그 이외의 추가적인 optinal한 함수들을 모아둔 코드입니다. + +## Getting Started + + +### Setting up Vitual Enviornment + + +1. Initialize and update the server + +``` + +su - + +source .bashrc + +``` + + + +2. Create and Activate a virtual environment in the project directory + + + +``` + +conda create -n env python=3.8 + +conda activate env + +``` + + + +4. To deactivate and exit the virtual environment, simply run: + + + +``` + +deactivate + +``` + + + +### Install Requirements + + + +To Install the necessary packages liksted in `requirements.txt`, run the following command while your virtual environment is activated: + +``` + +pip install -r requirements.txt + +``` +### SF2F +[Prepare](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/blob/feat/modeling/modeling/sf2f/GETTING_STARTED.md#download-vggface2-resnet-checkpoint) \ +[Training](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/blob/feat/modeling/modeling/sf2f/GETTING_STARTED.md#launch-training) \ +Inference for a service that generates faces from voices : +``` +python sf2f/inference_swap.py --checkpoint_start_from CHEKPOINT_DIR/CHECKPOINT.pt --input_wav_file WAV_DIR/VOICE.wav +``` + + +### CGAN-GP +Training script for pre-train and finetuning model that generates faces from condition(gender, age) : +``` +# train shell +python wcgan-gp/main.py --gpu_ids 0 --use_gpu True --mode {train/finetune/inference} --train_continue {on/off} --checkpoint_path {./checkpoint} --checkpoint_name {epoch1.pth} --checkpoint_fine_tune_name {fine_tune/epoch1.pth} --dataset_path /workspace/data --dataset_name celeba --dataset_fine_tune_name VoxCeleb --output_path ./results --num_epoch 100 --num_freq_save 5 --batch_size 128 --lr_G 2e-4 --lr_D 2e-4 --lr_policy {linear/step/plateau/cosine} --lr_G_weight_decay 1e-5 --lr_D_weight_decay 1e-5 --nch_ker 64 --fine_tune True --fine_tune_nume_epoch 100 --fine_tune_num_freq_save 5 +``` + +Inference for a service that generates faces from condition(gender, age) : +``` +# inference shell +python wcgan/main.py --mode {inference} --fine_tune {True, HQ-VoxCeleb dataset에 fine tune 진행여부} --output_path {inference 결과 저장 위치} --checkpoint_name {경로/checkpoint를 불러올 주소와 이름} --input_gendere {m/man/male/f/female/woman} --input_age {0 - 100} +``` + + +### SimSwap +[Prepare](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/blob/feat/modeling/modeling/SimSwap/docs/guidance/preparation.md) \ +[Training](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/tree/feat/modeling/modeling/SimSwap#training) \ +[Inference for image or video face swapping](https://github.com/boostcampaitech6/level2-3-cv-finalproject-cv-08/blob/feat/modeling/modeling/SimSwap/docs/guidance/usage.md) \ +Inference for a service that swaps only one face within the video : +``` +python SimSwap/inference_swap.py --Arc_path SimSwap/arcface_model/arcface_checkpoint.tar --pic_a_path ./demo_file/hj.png --video_path ./demo_file/tae_24fps.mp4 +``` ## References [Speech Fusion to Face](https://arxiv.org/pdf/2006.05888.pdf) [Conditional GAN](https://arxiv.org/pdf/1411.1784.pdf) -[Sim Swap](https://github.com/neuralchen/SimSwap) +[Sim Swap](https://arxiv.org/pdf/2106.06340v1.pdf) [Pytorch Template](https://github.com/victoresque/pytorch-template) + From f4285e85f6574062904f7eed00898c6dd52684dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=98=9C=EC=A7=80=5FT6046?= <149589697+carboxaminoo@users.noreply.github.com> Date: Sat, 30 Mar 2024 11:11:39 +0900 Subject: [PATCH 9/9] [Docs] Adding Links in frontend README (#13) * Doc : Add Frontend README * Doc : Modify README title * Docs: Modify README * Docs: Adding figma links and origin github link --------- Co-authored-by: soyoonjeong <76814748+soyoonjeong@users.noreply.github.com> --- frontend/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontend/README.md b/frontend/README.md index ed49ea5..497f1ad 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,5 +1,6 @@ # 🔊목소리로 가상 얼굴 생성 서비스 [너의 목소리가 보여] + @@ -149,3 +150,8 @@ To create a production build, use: npm run build ``` +## Links +- [Wireframe](https://www.figma.com/file/MBWE1CthewJVCl0KH8xEcM/%5BV1%5D-%ED%99%94%EB%A9%B4-%EA%B5%AC%EC%84%B1?type=whiteboard&node-id=0:1&t=jPWmEIfP3RobQG6G-1) +- [Prototyping](https://www.figma.com/file/fN6DWRmoszsytULLaZ4cni/Voice2Face-V1?type=design&node-id=1603:2&mode=design&t=jPWmEIfP3RobQG6G-1) +- [Origin github](https://github.com/Make-Zenerator/voice2face-frontend.git) +