카테고리 없음

로보플로우 쓰지않고 이미지 학습시키기

chacha001 2024. 11. 19. 02:13

 

로보플로우는 오픈이라서 내 사진을 학습시키기가 애매할때가 있다.

 

내 얼굴 사진 2500 장을 학습시켜 나를 알아보는지? 모델링을 해보자

 

일단 웹캠으로 내 얼굴을 2500장 찍는 코드는 다음과 같다

###############################################################
## 해당 파일은 로컬 cam을 이용하여 본인의 이미지를 촬영하고 저장합니다.
###############################################################

import os
import cv2

## 이미지를 저장할 폴더 경로
folder_path = './my_face_temp'
## 이미지 저장 폴더가 없다면 폴더 생성
if not os.path.exists(folder_path) :
    os.makedirs(folder_path)
    print('my_face 폴더를 생성합니다.')

## 웹캠으로 얼굴 사진을 찍어 저장하는 함수
def capture_owner_images(num_images=2500) : ## num_images에 숫자를 입력한만큼 이미지 저장
    ## 0은 기본 웹캠
    cap = cv2.VideoCapture(0)
    ## haarcascade 알고리즘으로 얼굴 탐지
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

    ## 위에서 지정한 수만큼 촬영 및 저장하는 반복문
    count = 0
    while count < num_images :
        _, frame = cap.read()
        
        frame = cv2.flip(frame, 1)
        ## haarcascade 알고리즘은 흑백 이미지의 명암 차이로 탐지를 하는 것이기에 흑백으로 변환
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        ## 변환된 프레임에서 얼굴 탐지 시도
        faces = face_cascade.detectMultiScale(gray, 1.1, 4)

        ## 탐지된 얼굴에서 좌표를 가져오는 반복문
        for (x, y, w, h) in faces :
            ## 프레임에서 얼굴 영역만 가져온다
            face = frame[y:y+h, x:x+w]
            ## 탐지한 얼굴 영역 사이즈 변환 : 괄호를 채우면 됩니다.
            resized_face = cv2.resize(face, (512 , 512) )
            ## 파일 이름 설정 및 저장
            face_file = f"./my_face_temp/temp_{count}.jpg"
            cv2.imwrite(face_file, resized_face)
            count += 1
            ## 변환된 얼굴 이미지 출력하여 확인
            cv2.imshow('Captured Face', resized_face)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()
    
capture_owner_images()
print('저장 완료')

(혹시나 해서.. 윈도우 기준이다)

이코드를 돌리면 자동으로 사진이 찍히고 내가 설정한 경로에 저장된다.

 

2500장을 학습시킬때 로컬에서 돌리면 곤란하니깐 코랩에서 돌릴거다

구글 드라이브에 파일을 만들고 (내 코드에선 파일명: project) 내 사진과 다른사람들 사진 들을 zip파일로 올린다

코랩에서 실행시킬거기땨문에 꼭 zip으로 올리는게 좋다 아니면 내 컴퓨터에서 처리량이 많이지기 때문!!

추가로 다른사람들 사진은 2500장보다 많게 올렸다

 

#구글드라이브 연결
from google.colab import drive
drive.mount('/content/drive')
path = '/content/drive/MyDrive/project'

#라이브러리 로딩및 설치 (YOLO - cls 이용할거다)
!pip install ultralytics

 

기본준비를 마치고, 

내가 project 폴더에 넣어두었던 이미지 데이터셋을 불러온다

 

import os
import zipfile

data_myFace = os.path.join(path, 'my_face_temp.zip')
data_myFace

## Colab에서 생성할 본인 얼굴 이미지 데이터 폴더의 경로
extract_folder = '/content/my_face'

## 위의 경로에 폴더가 없을 때 폴더 생성
if not os.path.exists(extract_folder) :
    os.mkdir(extract_folder)

## 위의 경로에 압축 해제
## data_myFace 압축 파일을 읽기 모드로 사용할 건데, 그 이름은 zip_ref
with zipfile.ZipFile(data_myFace, 'r') as zip_ref :
    ## zip_ref에 있는 모든 파일을 리스트화
    file_list = zip_ref.namelist()
    # print(file_list)

    ## 모든 파일 리스트 반복문
    for f in file_list :
        ## 만약 파일명이 /로 끝나지 않으면서, .jpg로 끝난다면
        if not f.endswith('/') and f.lower().endswith('.jpg') :
            ## file_name이란 변수로 사용하겠다.
            file_name = os.path.basename(f)
            # print(file_name)

            ## 만약 파일명이 ._로 시작하지 않는다면 (Mac OS에서의 숨김 파일 방지용)
            if not file_name.startswith('._') :
                ## d_path 변수에 폴더명과 file_name을 합친 문자열을 사용하겠다.
                d_path = os.path.join(extract_folder, file_name)
                # print(d_path)

                ## 불러와서 쓰는 과정 : 이 과정에서 위의 폴더에 파일들이 생성됨.
                with zip_ref.open(f) as source, open(d_path, 'wb') as target :
                    target.write( source.read() )
                    
                    
                    
## 생성된 본인 얼굴 이미지 데이터 폴더 안의 이미지 수
len(os.listdir(extract_folder) )

 

 

내 얼굴말고 다른얼굴 이미지도 불러온다

data_other = os.path.join(path, 'lfw-deepfunneled.zip')
data_other

## Colab에 생성할 다른 얼굴 폴더 경로
extract_folder = '/content/other_face'

## 위의 경로에 폴더가 없을 때 생성
if not os.path.exists(extract_folder) :
    os.makedirs(extract_folder)

## 위의 경로에 압축을 해제
with zipfile.ZipFile(data_other, 'r') as zip_ref :
    file_list = zip_ref.namelist()

    for f in file_list :
        if not f.endswith('/') and f.lower().endswith('.jpg') :
            file_name = os.path.basename(f)

            if not file_name.startswith('._') :
                d_path = os.path.join(extract_folder, file_name)

                with zip_ref.open(f) as source, open(d_path, 'wb') as target :
                    target.write(source.read())
                    
                    
                    
## 생성된 다른 사람 얼굴 이미지 데이터 폴더 안의 이미지 수
len(os.listdir(extract_folder) )

 

 

데이터 전처리

    • YOLO-cls 모델이 요구하는 폴더 구조를 만듭니다.
      1. Datasets라는 폴더를 생성합니다.
      2. Training set, Validation set이 들어갈 폴더를 생성합니다.
      3. 각 데이터셋 폴더에 분류할 클래스의 이름을 가진 폴더를 생성합니다.
    • 폴더 구조에 맞게 데이터를 분배합니다.

이 과정을 수행할거다

 

import os
import glob
import random
import shutil
import numpy as np

## 각 데이터셋 길이 비교
len(os.listdir('/content/my_face')) , len(os.listdir('/content/other_face'))

## 폴더 생성
datasets_path = '/content/Datasets'

## 원본 폴더 경로들
source_folders = {
    'my_face': '/content/my_face',
    'other_face': '/content/other_face'
}

## 타겟 폴더 경로들
target_folders = {
    'train': {'my_face': '/content/Datasets/train/my_face',
              'other_face': '/content/Datasets/train/other_face',
              },
    'val': {'my_face': '/content/Datasets/val/my_face',
            'other_face': '/content/Datasets/val/other_face',
            },
    }

## 폴더 생성
if not os.path.exists(datasets_path) :
    os.mkdir(datasets_path)

## 하위 폴더 생성
for folder in target_folders :
    temp1 = os.path.join(datasets_path , folder)
    if not os.path.exists( temp1 ) :
        os.mkdir( temp1 )

    for folder2 in source_folders.keys() :
        temp2 = os.path.join(temp1, folder2)
        if not os.path.exists( temp2 ) :
            os.mkdir( temp2 )

 

참고로 이번에 yaml 파일은 필요없다

각 폴더에 이미지 데이터 옮기기

 

# 스플릿 비율
split_size = 0.8

## 각 카테고리(my_face, other_face)에 대해 처리
for category, source_folder in source_folders.items():
    ## 원본 폴더에서 모든 파일 리스트 가져오기
    img_list = sorted(glob.glob(os.path.join(source_folder, '*')))

    ## 총 파일 개수 계산
    total_imgs = len(img_list)
    tr_val_split = int(total_imgs * split_size)

    ## train, validation로 나누기
    tr_img = img_list[ : tr_val_split]
    val_img = img_list[tr_val_split : ]

    ## 각각의 이미지들을 타겟 폴더로 이동
    for img_path in tr_img :
        dst_path = os.path.join(target_folders['train'][category], os.path.basename(img_path))
        shutil.move(img_path , dst_path)

    for img_path in val_img :
        dst_path = os.path.join(target_folders['val'][category], os.path.basename(img_path))
        shutil.move(img_path , dst_path)

    print(f'{category} images moved to train, validation sets')

 

 

사전 학습된 UltraLytics YOLO-cls 모델에 Transfer Learning하기

 

import os
os.environ['WANDB_MODE'] = 'disabled'

from ultralytics import YOLO, settings
#세부 모델로 n, s, m, l, x가 있습니다. n가 가장 빠르고, x가 가장 연산량이 많습니다.

settings['datasets_dir'] = '/content/'
settings

model = YOLO('yolo11n-cls.pt')

#학습
results_tr = model.train(model='/content/yolo11n-cls.pt',
                         data='/content/Datasets',
                         epochs=10,
                         patience=4,
                         )
                         

#추론
results = model.predict()

#모델저장
model_check = YOLO()
model_check

,pt 형태로 모델이 코랩에 저장이 되면, 로컬에 다운받아 사용하면 된다!!