[KT 에이블스쿨] 3차 미니프로젝트

Choi·2023년 10월 10일
0

KT에이블스쿨

목록 보기
6/12
post-thumbnail

💲 3차 미니 프로젝트

미션: 저시력자들을 위한 원화 화폐 분류

활용 데이터셋

화폐정보 데이터(이미지, 메타정보)

활용 기술

Object Detection- YOLOv5

도메인 이해

리나라 국민 약 200명 중 1명은 시각장애

시각장애인 76%가 후천적 요인으로 시력을 잃음

시각장애인 90%가 점자 해독 불가능

📌 저시력자들은 빠르게 화폐를 구별할 수 있는 도구가 필요함!

데이터 전처리 및 구조 만들기

import os
import glob
import shutil
import random

# 데이터 분할 및 이동
def split_and_move_data(data_path, split_ratio=0.8):
    won_list = ['10', '50', '100', '500', '1000', '5000', '10000', '50000']

    for won in won_list:
        image_files = glob.glob(os.path.join(data_path, won, '*.jpg'))
        random.shuffle(image_files)  # 데이터 순서를 랜덤하게 섞음

        num_train = int(len(image_files) * split_ratio)

        for i, image_file in enumerate(image_files):
            if i < num_train:
                split = 'train'
            else:
                split = 'val'

            # 이미지 데이터 이동
            dest_image_path = os.path.join(data_path, 'images', split, os.path.basename(image_file))
            shutil.move(image_file, dest_image_path)

            # 레이블 데이터 파일명을 맞춰서 이동
            label_file = os.path.splitext(image_file)[0] + '.json'
            dest_label_path = os.path.join(data_path, 'labels', split, os.path.basename(label_file))
            shutil.move(label_file, dest_label_path)

if __name__ == '__main__':
    data_path = '/content/drive/MyDrive/Dataset/'

    split_and_move_data(data_path

JSON 파일 정보 추출 및 변경

import os
import json
won_dict = {0:'Ten', 1:'Fifty', 2:'Hundred', 3:'Five_Hundred', 4:'Thousand', 5:'Five_Thousand', 6:'Ten_Thousand', 7:'Fifty_Thousand'}
# JSON 파일에서 정보 추출 및 YOLO 형식으로 변환하는 함수
def convert_json_to_yolo(json_file_path):
    with open(json_file_path, 'r') as json_file:
        data = json.load(json_file)

        # 클래스 정보에서 앞뒷면 구분 없애기
        # label = data['shapes'][0]['label'].split('_')[0]
        label = data['shapes'][0]['label'].rsplit('_', 1)[0]

        # 클래스 이름을 매핑된 이름으로 변경
        label =list(won_dict.keys())[list(won_dict.values()).index(label)]
        # JSON 파일 내의 이미지 크기 가져오기
        original_image_width = data['imageWidth']
        original_image_height = data['imageHeight']

        # 이미지 크기 (원본 크기의 1/5)
        image_width = original_image_width / 5.0
        image_height = original_image_height / 5.0

        # 위치 정보 추출 및 YOLO 형식에 맞게 변환
        x1, y1 = data['shapes'][0]['points'][0]
        x2, y2 = data['shapes'][0]['points'][1]
        x1 = x1 / 5.0
        y1 = y1 / 5.0
        x2 = x2 / 5.0
        y2 = y2 / 5.0

        # YOLO 형식으로 변환
        x_center = (x1 + x2) / 2.0
        y_center = (y1 + y2) / 2.0
        width = x2 - x1
        height = y2 - y1

        # Normalize된 값으로 변환
        x_center_norm = x_center / image_width
        y_center_norm = y_center / image_height
        width_norm = width / image_width
        height_norm = height / image_height

        # YOLO 형식의 문자열 생성
        yolo_label = f"{label} {x_center_norm} {y_center_norm} {width_norm} {height_norm}"

        return yolo_label

# JSON 파일들이 있는 디렉토리 경로
base_json_dir = '/content/drive/MyDrive/Dataset/labels'
subdirs = ['train', 'val']

# JSON 파일을 YOLO 형식으로 변환하여 TXT 파일로 저장
for subdir in subdirs:
    json_dir = os.path.join(base_json_dir, subdir)
    for json_file in os.listdir(json_dir):
        if json_file.endswith('.json'):
            json_file_path = os.path.join(json_dir, json_file)
            yolo_label = convert_json_to_yolo(json_file_path)

            # TXT 파일로 저장
            txt_file_path = os.path.splitext(json_file_path)[0] + '.txt'
            with open(txt_file_path, 'w+') as txt_file:
                txt_file.write(yolo_label)

            # 변환된 레이블과 TXT 파일 경로 출력
            print(f'변환된 레이블: {yolo_label}')
            print(f'TXT 파일 경로: {txt_file_path}')

가중치 파일 다운로드 및 학습


#가중치 파일
!mkdir /content/drive/MyDrive/Dataset/weights  # 가중치 파일을 저장할 폴더 생성
!wget https://github.com/ultralytics/yolov5/releases/download/v5.0/yolov5s.pt -O /content/drive/MyDrive/Dataset/weights/yolov5s.pt

#학습
!python /content/yolov5/train.py --img-size 416 --batch-size 16 --epochs 50 --data /content/drive/MyDrive/Dataset/money.yaml --cfg yolov5/models/yolov5s.yaml --weights yolov5/weights/yolov5s.pt --name my_experiment

#탐지
!python yolov5/detect.py --weights /content/yolov5/runs/train/my_experiment/weights/best.pt --img-size 416 --conf 0.75 --iou-thres 0.25 --source  /content/drive/MyDrive/minipro_03/Dataset/test_money2.jpg

✔train.py를 통해 학습을 진행하기 위해 YOLOv5 데이터 구조 만들어주기

✔이미지 크기는 416, batch는 16, epochs는 50으로 설정

✔data에는 위에서 만든 yaml 파일 경로를 지정

✔weights와 cfg에는 위에서 다운한 yolov5s의 파일을 가져온다

✔마지막으로 결과를 저장할 이름을 설정하고 학습을 진행한다.

✔️학습을 마친 후에는 최적의 가중치가 담긴 best.pt가 생성되므로 학습 이 후에는 best.pt를 이용하여 detect를 진행한다.

화폐 분류 인식 결과 영상

🚩3차 미니 프로젝트를 마치며

일단 학습 데이터가 iconic했기에 여러 동전이 겹쳐있는 경우는 인식이 어려웠다. 하지만 화폐 전체가 잘 보인다면 인식률은 상당히 높았다!
YOLOv5는 캡스톤 디자인 때 많이 다뤄봤기에 에이블스쿨에서도 만나니 반가웠다. 이 얘기는 시각 지능을 얘기할 때 YOLO는 빠질 수 없는 기술이라는 것이다. 어떤 서비스를 기획할 때 카메라를 통한 연계 기술을 하고자 한다면 다시 찾을 YOLO.. 다음엔 YOLOv8을 사용해볼 것이다😊

profile
느려도 내 것으로 만드는게 좋잖아?

0개의 댓글