https://github.com/sweetkco/NIA2020AnnotationTools

Introduction

한국 정보화 진흥원 2020 인공지능 데이터셋 어노테이션 툴 입니다

본 툴에서 제공하는 기능

  • video 파일 업로드 및 프레임 단위 이미지 분할
  • 2D Human pose estimation을 위한 2D Keypoint dataset 구축
  • 3D Human pose estimation을 위한 3D Keyopint dataset 구축
  • Human shape recovery를 위한 rotation, shape params(SMPL), trans params(SMPL)

사용 방법은 아래와 같습니다.

1

2

3

4

5

6

7

 

8

9

 

10

AIHUB(피트니스 자세 이미지)데이터를 활용하고자 YOLOv8모델과 Media Pipe 모델의 키포인트를 비교하였습니다.

AI HUB<24> COCO(YOLO)<17> MediaPipe<32>
Nose(0) 코(0) 코(0)
Left Eye(1) 왼쪽 눈(2) 왼쪽 눈(5)
Right Eye(2) 오른쪽 눈(1) 오른쪽 눈(2)
Left Ear(3) 왼쪽 귀(4) 왼쪽 귀(8)
Right Ear(4) 오른쪽 귀(3) 오른쪽 귀(7)
Left Shoulder(5) 왼쪽 어깨(6) 왼쪽 어깨(12)
Right Shoulder(6) 오른쪽 어깨(5) 오른쪽 어깨(11)
Left Elbow(7) 왼쪽 팔꿈치(8) 왼쪽 팔꿈치(14)
Right Elbow(8) 오른쪽 팔꿈치(7) 오른쪽 팔꿈치(13)
Left Wrist(9) 왼쪽 손목(10) 왼쪽 손목(16)
Right Wrist(10) 오른쪽 손목(9) 오른쪽 손목(15)
Left Hip(11) 왼쪽 골반(12) 왼쪽 엉덩이(24)
Right Hip(12) 오른쪽 골반(11) 오른쪽 엉덩이(23)
Left Knee(13) 왼쪽 무릎(14) 왼쪽 무릎(26)
Right Knee(14) 오른쪽 무릎(13) 오른쪽 무릎(25)
Left Ankle(15)   왼쪽 발목(28)
Right Ankle(16)   오른쪽 발목(27)
Neck(17)    
Left Palm(18)    
Right Palm(19)    
Back(20)    
Waist(21)    
Left Foot(22) 왼쪽 발(16)  
Right Foot(23) 오른쪽 발(15)  
    오른쪽 눈 안쪽(1)
    오른쪽 눈 밖(3)
    왼쪽 눈 안쪽(4)
    왼쪽 눈 밖(6)
    입 오른쪽(9)
    입 왼쪽(10)
    오른쪽 새끼손가락 관절(17)
    왼쪽 새끼손가락 관절(18)
    오른쪽 검지손가락 관절(19)
    왼쪽 검지손가락 관절(20)
    오른쪽 발뒤꿈치(29)
    왼쪽 발뒤꿈치(30)
    오른쪽 발가락(31)
    왼쪽 발가락(32)

Keypoint detection 모델을 사용하기에 앞서, 키포인트를 비교함으로써, 적합한 키포인트 사용하여 성능을 높이고자 비교하였습니다.

AIHUB데이터는 키포인트가 24개로 이루어져있습니다.

YOLO(1-stage detector 방식)는 coco데이터셋으로 학습되었으며, 키포인트는 17개로 이루어져있습니다.

Media Pipe (2-stage detector 방식)는 키포인트가 32개로 이루어져있습니다.

 

pip install cv2

pip install Pyside6

사용중인 가상환경에 위 라이브러리를 설치합니다.

아래 코드를 실행합니다.

import sys
import cv2
import os
import PySide6.QtGui as QtGui
from PySide6.QtCore import Qt, QTimer
from PySide6.QtWidgets import QMainWindow, QPushButton, QVBoxLayout, QFileDialog, QLabel, QApplication, QSizePolicy, QWidget, QStatusBar

class ViewVideo(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Video View")
        self.resize(800,600)

        # button
        self.view_file_button = QPushButton("video open")
        self.view_file_button.clicked.connect(self.open_video_file_dialog) #

        self.play_button = QPushButton("Play")
        self.play_button.clicked.connect(self.play_video)

        self.pause_button = QPushButton("Stop")
        self.pause_button.clicked.connect(self.pause_video) #

        self.capture_button = QPushButton("Capture")
        self.capture_button.clicked.connect(self.capture_frame) #
       
       
        # video view label
        self.video_view_label = QLabel()
        self.video_view_label.setAlignment(Qt.AlignCenter)
        self.video_view_label.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)

        # main layout
        main_layout = QVBoxLayout()
        main_layout.addWidget(self.view_file_button)
        main_layout.addWidget(self.play_button)
        main_layout.addWidget(self.pause_button)
        main_layout.addWidget(self.capture_button)
        main_layout.addWidget(self.video_view_label)

        central_widget = QWidget()
        central_widget.setLayout(main_layout)
        self.setCentralWidget(central_widget)


        self.video_path = ""
        self.video_width = 720
        self.video_height = 640
        self.video_capture = None
        self.video_timer = QTimer()
        self.video_timer.timeout.connect(self.display_next_frame) #

        self.paused = False
        self.current_frame = 0
        self.capture_count = 0

        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)

    def open_video_file_dialog(self):
        file_dialog = QFileDialog(self)
        # QF필터는 공백으로 형식을 구분해야한다!
        file_dialog.setNameFilter("Video Files (*.mp4 *.avi *.mov *.mkv)")

        if file_dialog.exec():
            selected_files = file_dialog.selectedFiles()
            if selected_files:
                self.video_path = selected_files[0]
                self.status_bar.showMessage(f"select video Path : {self.video_path}")

    def display_next_frame(self):
        if self.video_path :
            ret, frame = self.video_capture.read()

            if ret :
                frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                frame_resize = self.resize_frame(frame_rgb) # def resize_frame(image)
                h, w, _ = frame_resize.shape

                if w > 0 and h > 0:
                    frame_image = QtGui.QImage(frame_resize, w, h,
                                               QtGui.QImage.Format_RGB888)
                    pixmap = QtGui.QPixmap.fromImage(frame_image)
                    self.video_view_label.setPixmap(pixmap)
                    self.video_view_label.setScaledContents(True)

                self.current_frame +=1
           
            else :
                self.video_timer.stop()
    def play_video(self):
        if self.video_path:
            if self.paused:
                self.video_capture.set(cv2.CAP_PROP_POS_FRAMES, self.current_frame)
                self.paused = False

            else :
                self.video_capture = cv2.VideoCapture(self.video_path)
                self.current_frame = 0
           
            self.play_button.setEnabled(False)
            self.pause_button.setEnabled(True)
            self.capture_button.setEnabled(True)
            self.video_timer.start(30)

    def resize_frame(self, frame):
        height, width, _ = frame.shape

        if width > self.video_width or height > self.video_height:
            ratio_width = self.video_width / width
            ratio_height = self.video_height / height
            scale = min(ratio_width, ratio_height)

            new_width = int(width * scale)
            new_height = int(height * scale)

            frame = cv2.resize(frame, (new_width, new_height))

        return frame

    def pause_video(self):
        self.video_timer.stop()
        self.play_button.setEnabled(True)
        self.pause_button.setEnabled(False)
        self.capture_button.setEnabled(not self.paused)
        self.paused=True

    def capture_frame(self):
        ret, frame = self.video_capture.read()

        if ret:
            frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            frame_resize = self.resize_frame(frame_rgb)
            h, w, _ = frame_resize.shape

            if w > 0 and h > 0:
                folder_name = os.path.splitext(os.path.basename(self.video_path))[0]
                file_name = f"{folder_name}_{self.capture_count:04d}_image.png"
                os.makedirs("./capture_data", exist_ok=True)
                file_path = os.path.join("./capture_data", file_name)
                self.capture_count += 1
                cv2.imwrite(file_path, cv2.cvtColor(frame_resize, cv2.COLOR_RGB2BGR))
                self.status_bar.showMessage(f"capture ok {file_path}")
               
    def open_video_file_dialog(self):
        file_dialog = QFileDialog(self)
        file_dialog.setNameFilter("Video Files (*.mp4 *.avi *.mov *.mkv)")

        if file_dialog.exec():
            selected_files = file_dialog.selectedFiles()
            if selected_files:
                new_video_path = selected_files[0]
                if new_video_path != self.video_path:
                    self.video_path = new_video_path
                    self.status_bar.showMessage(f"Selected video path: {self.video_path}")
                    self.reset_video_player()

    def reset_video_player(self):
        self.video_timer.stop()
        if self.video_capture:
            self.video_capture.release()
        self.current_frame = 0
        self.capture_count = 0
        self.paused = False
        self.play_button.setEnabled(True)
        self.pause_button.setEnabled(False)
        self.capture_button.setEnabled(False)
        self.video_view_label.clear()
           
    def closeEvent(self, event):
        self.video_timer.stop()
        if self.video_capture:
            self.video_capture.release()
        event.accept()



if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = ViewVideo()
    window.show()
    app.exit(app.exec())
         

import random

def leap_year(year) :
    return int(((year & 3) == 0 and (year % 100 != 0)) or (year % 400 == 0))
# 비트 마스크와 나머지 연산자를 사용하여 (4의 배수 and 100의 배수X) or 400배수를 판단하여 윤년을 판단하였습니다.
# int로 전체를 묶어  True = 1 , False = 0 으로 변환시켰습니다.
for _ in range(20):
    year = random.randrange(1000, 3001)
    print(f"Year: {year}, Year: {leap_year(year)}")
# for 구문과 range를 사용하여 무작위로 년도를 20개를 뽑아 윤년을 검산하였습니다.

'코딩 연습 > 프로그래머스 코드' 카테고리의 다른 글

개인정보 수집 유효기간.py  (1) 2023.10.19
사분면 고르기.py  (0) 2023.10.19
양과늑대2023.py  (0) 2023.10.15
from datetime import datetime

def count_date(day):
    dt = datetime.strptime(day, "%Y.%m.%d")
    #strptime함수로 datetime 형식으로 변환하는 dt를 만듭니다.
    all_day = dt.year * 12 * 28 + (dt.month - 1) * 28 + dt.day
    # 총 며칠인지 계산합니다 (한달은 28일입니다.)
    # 월을 0부터 시작하는 인덱스로 사용하여 쉽게 계산하기 위함입니다.
    # 1월은 day로 계산하고 2월부터 계산하기 위해서 입니다.
    # 예를 들어, 1월은 인덱스 0, 2월은 인덱스 1, ..., 12월은 인덱스 11로 매핑됩니다.
    return all_day

def solution(today, terms, privacies):
    answer = []  # 결과를 저장할 리스트
    terms_dict = {}  # terms에 포함된 각 유효기간과 해당 기간을 저장할 딕셔너리입니다
    today = count_date(today)  # 오늘 날짜를 카운트하여 저장합니다


    for i in terms:
        name, days = i.split()
        terms_dict[name] = int(days) * 28
    # terms 리스트를 순회하며 약관의 종류(이름)과 기간을 terms_dict에 저장합니다
   
    for i, privacies in enumerate (privacies):
        # enumerate 함수는 파이썬에서 제공하는 내장 함수로, 순회 가능한(iterable)
        # (예: 리스트, 튜플, 문자열 등)를 인자로 받아 해당 객체의 각 요소와 인덱스를 순차적으로 반환하는 함수입니다.
        day, term = privacies.split(" ") # " "을 기준으로 "day", "term"을 구분합니다.
        day = count_date(day)  # 주어진 날짜를 카운트하여 저장합니다
        day += terms_dict[term]  # 개인정보가 수집된 유효기간을 더하여 적용된 날짜를 계산합니다

        if today >= day:  # 오늘 날짜와 개인정보가 수집된 요효기간 날짜를 비교하여 오늘보다 과거인 경우,
            answer.append(i + 1)  # 해당 용어의 인덱스에 1을 더하여 answer 리스트에 추가합니다.

    return answer  

'코딩 연습 > 프로그래머스 코드' 카테고리의 다른 글

윤년.py  (0) 2023.10.19
사분면 고르기.py  (0) 2023.10.19
양과늑대2023.py  (0) 2023.10.15
def A(x, y):
    if x > 0 and y > 0:
        return 1
    elif x < 0 and y > 0:
        return 2
    elif x < 0 and y < 0:
        return 3
    elif x > 0 and y < 0:
        return 4

 

'코딩 연습 > 프로그래머스 코드' 카테고리의 다른 글

윤년.py  (0) 2023.10.19
개인정보 수집 유효기간.py  (1) 2023.10.19
양과늑대2023.py  (0) 2023.10.15

https://www.oracle.com/java/technologies/downloads/#jdk20-windows

 

Download the Latest Java LTS Free

Subscribe to Java SE and get the most comprehensive Java support available, with 24/7 global access to the experts.

www.oracle.com

설치한 후에는 JDK가 설치된 경로를 찾아야 합니다.

예를 들어 저자의 경우에는 jdk가 아래의 경로에 설치되어 있습니다.

경로 : C:\Program Files\Java\jdk-20 11.0.1과 같이 버전에 대한 숫자는 어떤 버전을 설치했느냐에 따라 다를 수 있습니다.

2) JDK 환경 변수 설치 경로를 찾았다면 해당 경로를 복사합니다.

해당 경로를 윈도우 환경 변수에 추가해야하기 때문입니다. 윈도우 10기준) 제어판 > 시스템 및 보안 > 시스템 > 고급 시스템 설정 > 고급 > 환경 변수 새로 만들기(N)...를 누르고 JAVA_HOME이라는 환경 변수를 만듭니다. 환경 변수의 값은 앞서 찾 았던 jdk 설치 경로입니다.

검색에 시스템환경편집을 쳐서 시스템 환경 변수 편집을 클릭합니다.

 

 

'프로그램 설치하기' 카테고리의 다른 글

Node.js 설치하기  (0) 2023.10.19

https://quantum-leap-dep-2612.tistory.com/39 오라클-17 이후 버전을 설치 후, 실습이 가능합니다.

환경변수 설정 및 라이브러리 설치

kopora - 말뭉치 제공 라이브러리 / 코포라 사이트 (https://ko-nlp.github.io/Korpora/ko-docs/introduction/)

gesim - word2vec,fasttext,doc2vec 라이브러리 제공

Word2vec 실습

 

 

!pip install  korpora
!pip install  gensim
!apt-get install openjdk-20-jdk# JVM 설치

 
 

Word2vec(CBOW실습) 5~7분소요

 
from gensim.models import Word2Vec
from Korpora import Korpora

# "korean_petitions" 데이터셋 로드
corpus = Korpora.load("korean_petitions")

# 텍스트 전처리: 문장을 단어로 분할
sentences = [s for doc in corpus.get_all_texts() for s in doc.split('. ')]  # 문서를 문장으로 분할

# 단어로 분할된 문장 리스트
word_sentences = [sentence.split() for sentence in sentences]

# Word2Vec 모델 학습 (CBOW)
cbow_model = Word2Vec(word_sentences, vector_size=100, window=5, min_count=5, workers=4, sg=0)

# 단어 벡터 출력
word_vectors_cbow = cbow_model.wv

# 검색할 단어
target_word = "가상화폐"
print("CBOW - '{}'의 벡터:".format(target_word), word_vectors_cbow[target_word])
# 유사한 단어 찾기
similar_words = word_vectors_cbow.most_similar(target_word)

# 검색한 단어가 유사한 단어 목록에 포함되는 경우 제외한 유사한 단어 목록 생성
filtered_similar_words = [(word, score) for word, score in similar_words if word != target_word and target_word not in word]

print("검색한 단어:", target_word)
print("유사한 단어들:", filtered_similar_words)

 

 

Skip-gram 실습 20~24분소요

 

from gensim.models import Word2Vec
from Korpora import Korpora

# "korean_petitions" 데이터셋 로드
corpus = Korpora.load("korean_petitions")

# 텍스트 전처리: 문장을 단어로 분할
sentences = [s for doc in corpus.get_all_texts() for s in doc.split('. ')]  # 문서를 문장으로 분할

# 단어로 분할된 문장 리스트
word_sentences = [sentence.split() for sentence in sentences]

# Word2Vec 모델 학습 (Skip-Gram)
skipgram_model = Word2Vec(word_sentences, vector_size=100, window=5, min_count=5, workers=4, sg=1)

# 단어 벡터 출력
word_vectors_skipgram = skipgram_model.wv

# "국민"이라는 단어의 벡터 출력
target_word = "가상화폐"
print("Skip-Gram - '{}'의 벡터:".format(target_word), word_vectors_skipgram[target_word])

# 유사한 단어 찾기
similar_words = word_vectors_skipgram.most_similar(target_word)

# 검색한 단어가 유사한 단어 목록에 포함되는 경우 제외한 유사한 단어 목록 생성
filtered_similar_words = [(word, score) for word, score in similar_words if word != target_word and target_word not in word]

print("검색한 단어:", target_word)
print("유사한 단어들:", filtered_similar_words)


 
 

FastText 실습

 

Fasttext(CBOW)실습 15분소요

 

 

from gensim.models import FastText
from Korpora import Korpora
import re

# "korean_petitions" 데이터셋 로드
corpus = Korpora.load("korean_petitions")

# 텍스트 전처리: 문장을 단어로 분할
sentences = [s for doc in corpus.get_all_texts() for s in doc.split('. ')]  # 문서를 문장으로 분할

# 한글이 아닌 글자 제외하고 전처리
korean_sentences = [re.sub("[^가-힣a-zA-Z ]", "", sentence) for sentence in sentences]

# 단어로 분할된 문장 리스트
word_sentences = [sentence.split() for sentence in korean_sentences]

# FastText 모델 학습
fasttext_model = FastText(word_sentences, vector_size=100, window=5, min_count=5, workers=4, sg=0)

# 단어 벡터 출력
word_vectors_fasttext = fasttext_model.wv

# 검색할 단어
target_word = "가상화폐"

# 조사 제거를 위한 함수
def remove_josa(word):
    josa_list = ['은', '는', '이', '가', '을', '를', '와', '과']
    for josa in josa_list:
        if word.endswith(josa):
            return word[:-len(josa)]
    return word

# 검색할 단어에 조사 제거
target_word_no_josa = remove_josa(target_word)

print("FastText - '{}'의 벡터:".format(target_word_no_josa), word_vectors_fasttext[target_word_no_josa])

# 유사한 단어 찾기
similar_words = word_vectors_fasttext.most_similar(target_word_no_josa)

print("검색한 단어:", target_word)
print("유사한 단어들:", similar_words)
 
 

Fasttext(Skip-gram)실습 27~32분소요

from gensim.models import FastText
from Korpora import Korpora
import re

# "korean_petitions" 데이터셋 로드
corpus = Korpora.load("korean_petitions")

# 텍스트 전처리: 문장을 단어로 분할
sentences = [s for doc in corpus.get_all_texts() for s in doc.split('. ')]  # 문서를 문장으로 분할

# 한글이 아닌 글자 제외하고 전처리
korean_sentences = [re.sub("[^가-힣a-zA-Z ]", "", sentence) for sentence in sentences]

# 단어로 분할된 문장 리스트
word_sentences = [sentence.split() for sentence in korean_sentences]

# FastText 모델 학습
fasttext_model = FastText(word_sentences, vector_size=100, window=5, min_count=5, workers=4, sg=1)

# 검색할 단어
target_word = "가상화폐"

# 조사 제거를 위한 함수
def remove_josa(word):
    josa_list = ['은', '는', '이', '가', '을', '를', '와', '과']
    for josa in josa_list:
        if word.endswith(josa):
            return word[:-len(josa)]
    return word

# 검색할 단어에 조사 제거
target_word_no_josa = remove_josa(target_word)

print("FastText - '{}'의 벡터:".format(target_word_no_josa), fasttext_model.wv[target_word_no_josa])

# 유사한 단어 찾기
similar_words = fasttext_model.wv.most_similar(target_word_no_josa)

print("검색한 단어:", target_word)
print("유사한 단어들:", similar_words)

 
 

 

Doc2vec 실습

 
Doc2vec(DBOW)실습 25분소요
 

 

from gensim.models import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
from Korpora import Korpora
import re

# Korpora 라이브러리를 통해 한국어 청원 데이터를 불러옵니다
corpus = Korpora.load("korean_petitions")
petitions = corpus.get_all_texts()

# 전처리 함수 정의: 한글 아닌 글자 제거
def preprocess_text(text):
    text = re.sub("[^가-힣a-zA-Z ]", "", text)  # 한글 이외의 글자 제거
    text = text.strip()  # 문서 양 끝 공백 제거
    return text

# 전처리 적용한 데이터로 TaggedDocument 생성
tagged_data = [TaggedDocument(words=preprocess_text(petition).split(), tags=[str(i)]) for i, petition in enumerate(petitions)]

# DBOW 방식의 Doc2Vec 모델을 초기화하고 학습시킵니다
dbow_model = Doc2Vec(vector_size=100, window=5, min_count=1, workers=4, dm=0, epochs=20)
dbow_model.build_vocab(tagged_data)
dbow_model.train(tagged_data, total_examples=dbow_model.corpus_count, epochs=dbow_model.epochs)

# 특정 문서의 인덱스를 지정합니다
target_doc_index = 0

# DBOW 방식으로 얻은 특정 문서의 벡터 출력
doc_vector_dbow = dbow_model.dv[target_doc_index]
print("DBOW 방식으로 얻은 특정 문서의 벡터:", doc_vector_dbow)

# 특정 문서의 내용 출력
print("\n특정 문서 내용:")
print(petitions[target_doc_index])
print("\n")

# 특정 문서와 유사한 문서를 찾습니다
similar_documents_dbow = dbow_model.dv.most_similar(target_doc_index, topn=5)

print("특정 문서와 유사한 문서 (DBOW 방식):")
for doc_id, score in similar_documents_dbow:
    print(f"유사도 {score:.2f}, 문서 인덱스 {doc_id}:")
    print(petitions[int(doc_id)])
    print("\n")

 
 

Doc2vec(DM 실습) 35분 소요

from gensim.models import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
from Korpora import Korpora
import re

# Korpora 라이브러리를 통해 한국어 청원 데이터를 불러옵니다
corpus = Korpora.load("korean_petitions")
petitions = corpus.get_all_texts()

# 전처리 함수 정의: 한글 아닌 글자 제거
def preprocess_text(text):
    text = re.sub("[^가-힣a-zA-Z ]", "", text)  # 한글 이외의 글자 제거
    text = text.strip()  # 문서 양 끝 공백 제거
    return text

# 전처리 적용한 데이터로 TaggedDocument 생성
tagged_data = [TaggedDocument(words=preprocess_text(petition).split(), tags=[str(i)]) for i, petition in enumerate(petitions)]

# DM 방식의 Doc2Vec 모델을 초기화하고 학습시킵니다
dm_model = Doc2Vec(vector_size=100, window=5, min_count=1, workers=4, dm=1, epochs=20)
dm_model.build_vocab(tagged_data)
dm_model.train(tagged_data, total_examples=dm_model.corpus_count, epochs=dm_model.epochs)

# 특정 문서의 인덱스를 지정합니다
target_doc_index = 0

# DM 방식으로 얻은 특정 문서의 벡터 출력
doc_vector_dm = dm_model.dv[target_doc_index]
print("DM 방식으로 얻은 특정 문서의 벡터:", doc_vector_dm)

# 특정 문서의 내용 출력
print("\n특정 문서 내용:")
print(petitions[target_doc_index])
print("\n")

# 특정 문서와 유사한 문서를 찾습니다
similar_documents_dm = dm_model.dv.most_similar(target_doc_index, topn=5)

print("특정 문서와 유사한 문서 (DM 방식):")
for doc_id, score in similar_documents_dm:
    print(f"유사도 {score:.2f}, 문서 인덱스 {doc_id}:")
    print(petitions[int(doc_id)])
    print("\n")

 

 

음향데이터 이미지 저장하기 파일

목록

1 데이터 불러오기
2 waveshow 이미지 저장하기
2-1 원본이미지 저장하기
2-2 noise 또는 stretch 처리된 이미지 저장하기
3 STFT 이미지 저장하기3-1 원본이미지 저장하기
3-2 noise 또는 stretch 처리된 이미지 저장하기
4 MelSpectrogram 이미지 저장하기
4-1 원본이미지 저장하기
4-2 noise 또는 stretch 처리된 이미지 저장하기
5 이미지 리사이즈 하기데이터 불러오기 
* 원하는 이미지만 저장하여, image_extraction_data 폴더 안의 모든 이미지를 리사이즈 할 수 있게 만들었습니다.
 
원하시는 가상환경에 pip install librosa, pip install matplotlib, pip install numpy, pip install tqdm 해주세요.

1. 데이터 불러오기

 
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
import os
from tqdm import tqdm 

dir = []
input_dir = 'raw_data'

for root, dirs, files in os.walk(input_dir):
    current_dir = []
    
    for file in tqdm(files, desc=f"Scanning {root}"):
        if file.endswith(".wav"):
            file_path = os.path.join(root, file)
            current_dir.append(file_path)
    
    if current_dir:
        dir.append(current_dir)

for directory_files in dir:
    for wav in directory_files:
        print(wav)

# start와 end 값을 조절하여 wav데이터 시간을 슬라이싱 할 수 있습니다.
def skip_wav(input_dir, start=0, end=10, wav_data_list=None):
    if wav_data_list is None:
        wav_data_list = []

    for root, dirs, files in os.walk(input_dir):
        for file in tqdm(files, desc=f"Scanning {root}"):
            if file.endswith(".wav"):
                file_path = os.path.join(root, file)

                processed = any(file_path == item[2] for item in wav_data_list)

                if not processed:
                    try:
                        data, sr = librosa.load(file_path)
                    except Exception as e:
                        print(f"손상된 WAV 파일을 스킵합니다: {file_path}")
                        continue 

                    start_sample = int(start * sr)
                    end_sample = min(int(end * sr), len(data))
                    data = data[start_sample:end_sample]

                    wav_data_list.append((np.array(data), sr, file_path))

    return wav_data_list

2 Waveshow 이미지 저장하기

2 -1 원본이미지(waveshow) 저장하기
In [ ]:
input_dir = 'raw_data' 
output_dir = 'image_extraction_data/waveshow'

skipped_wav_data_list = []

wav_data_list = skip_wav(input_dir, wav_data_list=skipped_wav_data_list)

for data, sr, file_path in wav_data_list:
    subdir = os.path.relpath(os.path.dirname(file_path), input_dir)
    image_output_dir = os.path.join(output_dir, subdir)
    os.makedirs(image_output_dir, exist_ok=True)

    image_file_name = os.path.splitext(os.path.basename(file_path))[0] + ".png"
    image_file_path = os.path.join(image_output_dir, image_file_name)

    plt.figure(figsize=(12, 4))
    librosa.display.waveshow(data, sr=sr)
    plt.axis("off")

    plt.savefig(image_file_path, bbox_inches="tight", pad_inches=0)
    plt.close()

    print(f"이미지 저장: {image_file_path}")

print(f"이미지 저장 완료")
2-2 waveshow에 (noise 또는 stretch)가 적용된 이미지 저장하기
In [ ]:
input_dir = 'raw_data'
output_dir = 'image_extraction_data/waveshow'

skipped_wav_data_list = []

wav_data_list = skip_wav(input_dir, wav_data_list=skipped_wav_data_list)

for data, sr, file_path in wav_data_list:
    subdir = os.path.relpath(os.path.dirname(file_path), input_dir)
    image_output_dir = os.path.join(output_dir, subdir)
    os.makedirs(image_output_dir, exist_ok=True)

    ##############파라미터 조정#################
         
    noise_amp = np.amax(data) * 0.2 * np.random.uniform()
    noise = noise_amp * np.random.normal(size=data.shape)
    data_noise = data + noise

    image_file_name_noise = os.path.splitext(os.path.basename(file_path))[0] + "_noise.png"
    image_file_path_noise = os.path.join(image_output_dir, image_file_name_noise)

    plt.figure(figsize=(12, 4))
    librosa.display.waveshow(data_noise, sr=sr)
    plt.axis("off")

    plt.savefig(image_file_path_noise, bbox_inches="tight", pad_inches=0)
    plt.close()

    print(f"Noise 이미지 저장: {image_file_path_noise}")
    
    ##############파라미터 조정################

    rate = 0.8 + np.random.random() * 0.4  
    data_stretch = librosa.effects.time_stretch(data, rate=rate)

    image_file_name_stretch = os.path.splitext(os.path.basename(file_path))[0] + "_stretch.png"
    image_file_path_stretch = os.path.join(image_output_dir, image_file_name_stretch)

    plt.figure(figsize=(12, 4))
    librosa.display.waveshow(data_stretch, sr=sr)
    plt.axis("off")

    plt.savefig(image_file_path_stretch, bbox_inches="tight", pad_inches=0)
    plt.close()

    print(f"Stretch 이미지 저장: {image_file_path_stretch}")

print(f"이미지 저장 완료")

3 STFT 이미지 저장하기

3-1 원본이미지(STFT) 저장하기
In [ ]:
input_dir = 'raw_data'
output_dir = 'image_extraction_data/STFT'

skipped_wav_data_list = []

wav_data_list = skip_wav(input_dir, wav_data_list=skipped_wav_data_list)

for data, sr, file_path in wav_data_list:
    subdir = os.path.relpath(os.path.dirname(file_path), input_dir)
    image_output_dir = os.path.join(output_dir, subdir)
    os.makedirs(image_output_dir, exist_ok=True)

    stft = librosa.stft(data)
    stft_db = librosa.amplitude_to_db(abs(stft))

    image_file_name = os.path.splitext(os.path.basename(file_path))[0] + ".png"
    image_file_path = os.path.join(image_output_dir, image_file_name)

    plt.figure(figsize=(12, 4))
    librosa.display.specshow(stft_db, sr=sr, x_axis="time", y_axis="hz")
    plt.axis("off")

    plt.savefig(image_file_path, bbox_inches="tight", pad_inches=0)
    plt.close()

    print(f"STFT 이미지 저장: {image_file_path}")

print(f"이미지 저장 완료")
3-2 STFT에 (noise 또는 stretch)가 적용된 이미지 저장하기
In [ ]:
input_dir = 'raw_data'
output_dir = 'image_extraction_data/STFT'

skipped_wav_data_list = []

wav_data_list = skip_wav(input_dir, wav_data_list=skipped_wav_data_list)

for data, sr, file_path in wav_data_list:
    subdir = os.path.relpath(os.path.dirname(file_path), input_dir)
    image_output_dir = os.path.join(output_dir, subdir)
    os.makedirs(image_output_dir, exist_ok=True)

    ##############파라미터 조정################
    
    noise_amp = np.amax(np.abs(stft)) * 0.05 * np.random.uniform()
    noise = noise_amp * (2 * np.random.random(stft.shape) - 1) 
    stft_noisy = stft + noise
    stft_db_noisy = librosa.amplitude_to_db(S=abs(stft_noisy))

    image_file_name_noise = os.path.splitext(os.path.basename(file_path))[0] + "_stft_noise.png"
    image_file_path_noise = os.path.join(image_output_dir, image_file_name_noise)

    plt.figure(figsize=(12, 4))
    librosa.display.specshow(stft_db_noisy, sr=sr, x_axis="time", y_axis="hz")
    plt.axis("off")

    plt.savefig(image_file_path_noise, bbox_inches="tight", pad_inches=0)
    plt.close()

    print(f"STFT 이미지 (Noise) 저장: {image_file_path_noise}")

    ##############파라미터 조정################

    rate = 0.8 + np.random.random() * 0.4  
    data_stretched = librosa.effects.time_stretch(data, rate=rate)
    stft_stretched = librosa.stft(data_stretched)
    stft_db_stretched = librosa.amplitude_to_db(S=abs(stft_stretched))

    image_file_name_stretch = os.path.splitext(os.path.basename(file_path))[0] + "_stft_stretch.png"
    image_file_path_stretch = os.path.join(image_output_dir, image_file_name_stretch)

    plt.figure(figsize=(12, 4))
    librosa.display.specshow(stft_db_stretched, sr=sr, x_axis="time", y_axis="hz")
    plt.axis("off")

    plt.savefig(image_file_path_stretch, bbox_inches="tight", pad_inches=0)
    plt.close()

    print(f"STFT 이미지 (Stretch) 저장: {image_file_path_stretch}")

print(f"이미지 저장 완료")

4 MelSpectrogram 이미지 저장하기

4-1 원본이미지(MelSpectrogram) 저장하기
In [ ]:
input_dir = 'raw_data'
output_dir = 'image_extraction_data/mel_spectrogram'

skipped_wav_data_list = []

wav_data_list = skip_wav(input_dir, wav_data_list=skipped_wav_data_list)

for data, sr, file_path in wav_data_list:
    subdir = os.path.relpath(os.path.dirname(file_path), input_dir)
    image_output_dir = os.path.join(output_dir, subdir)
    os.makedirs(image_output_dir, exist_ok=True)
    
    stft = librosa.stft(data)

    mel_spec = librosa.feature.melspectrogram(S=abs(stft))
    mel_spec_db = librosa.amplitude_to_db(mel_spec, ref=np.max)

    image_file_name = os.path.splitext(os.path.basename(file_path))[0] + ".png"
    image_file_path = os.path.join(image_output_dir, image_file_name)

    plt.figure(figsize=(12, 4))
    librosa.display.specshow(mel_spec_db, sr=sr, x_axis="time", y_axis="mel")
    plt.axis("off")

    plt.savefig(image_file_path, bbox_inches="tight", pad_inches=0)
    plt.close()

    print(f"Mel Spectrogram 이미지 저장: {image_file_path}")

print(f"이미지 저장 완료")
4-2 MelSpectrogram에 (noise 또는 stretch)가 적용된 이미지 저장하기
In [ ]:
input_dir = 'raw_data'
output_dir = 'image_extraction_data/mel_spectrogram'

skipped_wav_data_list = []

wav_data_list = skip_wav(input_dir, wav_data_list=skipped_wav_data_list)

for data, sr, file_path in wav_data_list:
    subdir = os.path.relpath(os.path.dirname(file_path), input_dir)
    image_output_dir = os.path.join(output_dir, subdir)
    os.makedirs(image_output_dir, exist_ok=True)
    
    ##############파라미터 조정################

    noise_amp = np.amax(np.abs(data)) * 0.05 * np.random.uniform()
    noise = noise_amp * np.random.normal(size=data.shape)
    data_noise = data + noise

    mel_spec_noise = librosa.feature.melspectrogram(y=data_noise, sr=sr)
    mel_spec_db_noise = librosa.amplitude_to_db(mel_spec_noise, ref=np.max)

    image_file_name_noise = os.path.splitext(os.path.basename(file_path))[0] + "_MelSpec_noise.png"
    image_file_path_noise = os.path.join(image_output_dir, image_file_name_noise)

    plt.figure(figsize=(12, 4))
    librosa.display.specshow(mel_spec_db_noise, sr=sr, x_axis="time", y_axis="mel")
    plt.axis("off")

    plt.savefig(image_file_path_noise, bbox_inches="tight", pad_inches=0)
    plt.close()

    print(f"Mel Spectrogram 이미지 (Noise) 저장: {image_file_path_noise}")

    ##############파라미터 조정################

    rate = 0.8 + np.random.random() * 0.4 
    data_stretched = librosa.effects.time_stretch(data, rate=rate)
    
    mel_spec_stretched = librosa.feature.melspectrogram(y=data_stretched, sr=sr)
    mel_spec_db_stretched = librosa.amplitude_to_db(mel_spec_stretched, ref=np.max)

    image_file_name_stretch = os.path.splitext(os.path.basename(file_path))[0] + "_MelSpec_stretch.png"
    image_file_path_stretch = os.path.join(image_output_dir, image_file_name_stretch)

    plt.figure(figsize=(12, 4))
    librosa.display.specshow(mel_spec_db_stretched, sr=sr, x_axis="time", y_axis="mel")
    plt.axis("off")

    plt.savefig(image_file_path_stretch, bbox_inches="tight", pad_inches=0)
    plt.close()

    print(f"Mel Spectrogram 이미지 (Stretch) 저장: {image_file_path_stretch}")

print(f"이미지 저장 완료")

5 모든 이미지 리사이즈 후 정제 이미지 저장하기

In [ ]:
import cv2
import numpy as np
import os
from tqdm import tqdm

input_dir = 'image_extraction_data' 
output_dir = 'final_data' 

target_size = (255, 255)

def padding_to_square(img: np.ndarray, square_size: int) -> np.ndarray:
    h, w, c = img.shape

    if h == w:
        bg = img
    
    if h < w:
        padding_size = (w - h) // 2
        bg = np.zeros((w, w, c), dtype=np.uint8)
        bg[padding_size:padding_size + h, :] = img.copy()

    else: 
        padding_size = (h - w) // 2
        bg = np.zeros((h, h, c), dtype=np.uint8)
        bg[:, padding_size : padding_size + w] = img.copy()
    
    result = cv2.resize(bg, (square_size, square_size))
    return result

for root, dirs, files in os.walk(input_dir):
    for file in tqdm(files, desc=f"Scanning {root}"):
        if file.lower().endswith(('.png', '.jpg', '.jpeg')):

            subdir = os.path.relpath(root, input_dir)
            
            output_subdir = os.path.join(output_dir, subdir)
            os.makedirs(output_subdir, exist_ok=True)
            
            image_file_path = os.path.join(root, file)
            
            try:
                image = cv2.imread(image_file_path)
                if image is None:
                    print(f"이미지 읽기 실패: {image_file_path}")
                    continue
                
                image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
                
                padded_img = padding_to_square(image, 255)
                
                output_image_file_path = os.path.join(output_subdir, file)
                cv2.imwrite(output_image_file_path, cv2.cvtColor(padded_img, cv2.COLOR_RGB2BGR))
                
                print(f"변환된 이미지 저장: {output_image_file_path}")
            except Exception as e:
                print(f"이미지 처리 중 오류 발생: {e}")

print("이미지 변환 및 저장 완료")

Node.js는 Javascript로 작성된 프로그램을 운영체제상에서 일반 애플리케이션 프로그램처럼 실행시켜주는 런타임입니다. 특히, 서버 프로그램을 작성하는데 많이 사용되고 있는것 같습니다.

Node.js 한글 사이트는 다운로드 | Node.js (nodejs.org) 입니다. 설치 파일을 다운로드 받습니다. 현재 최신 버전은 21.0.0이네요.

 

다운로드 | Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

LTS버전을 추천합니다. 최신버전은 호환문제가 생길가능성이 높습니다. 나중에는 최신버전도 LTS버전으로 넘어 가겠지만, 그전까지는 LTS를 사용하는게 좋습니다. 

Node.js 다운로드 페이지

저는 이전 릴리스로 Node.js 16.20.2를 다운받겠습니다.

이전 릴리스 | Node.js (nodejs.org)

 

이전 릴리스 | Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org


다운받은 파일을 클릭하여 설치합니다.

설치 마법사 시작화면


라이센스에 동의합니다.

라이센스 동의 화면


설치 위치를 지정합니다. 기본 설치 위치는 C:\Program Files\nodejs\ 입니다.

설치위치 지정


사용자 설정화면 입니다. 모두 기본값을 사용하겠습니다.

- Node.js runtime : Node.js 런타임 본체입니다.
- corepack manager : 패키지 관리자입니다. npm, yarn등의 패키지 관리자의 여러 버전을 설치하고, 시용여부를 지정하는 것이 가능합니다. 서로 다른 개발 또는 배포 환경에서 상호간의 설치 호환성을 유지하기 위해서 사용되어질 수 있다고 합니다.
- npm package manager : 패키지 관리자 입니다.
- Online documentation shortcuts : 온라인 문서에 대한 바로가기 입니다.
- Add to PATH : PATH 환경변수에 등록합니다.

사용자 설정


Native 모듈들을 위한 툴을 설치할지 선택합니다. 선택하지 않겠습니다. npm 모듈중에 컴파일이 필요한 것이 있을때 필요한 도구(Python, Visual Studio Build Toos)를 자동으로 설치할지 물어 보는 것입니다.

선택적 툴 설치여부 선택

 


설치할 준비가 되었습니다. "Install"을 눌러 설치합니다.

설치준비 완료


설치중입니다.

설치중


설치가 완료되었습니다.

설치완료


설치확인을 위해서 명령창을 열고 "node -v" 명령으로 버전정보를 확인해 봅니다.

버전정보 확인

'프로그램 설치하기' 카테고리의 다른 글

오라클 설치하기  (0) 2023.10.19

+ Recent posts