From e399ea011ce4cf01c725e1ee1f06df18e395d613 Mon Sep 17 00:00:00 2001 From: dlatjgus0612 Date: Fri, 29 Mar 2024 03:46:49 +0900 Subject: [PATCH] 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)