본문 바로가기

프로젝트/Data_Analysis_Track_33_FinalProject

FinalProject_02(개별 Action 선정 및 수행, webcam inference code)

개별 Action

  • detection 모델 선정과 webcam inference code, 학습 git 조사, 확보 -> 모델링 파트 2명 -> 내 파트
  • 학습 데이터 현황 정리 -> 1명
  • DB table 정리 -> 웹 파트 1명
    다음 멘토링 시 해당 내용 Review

 

- detection 모델 선정 및 webcam inference code reference(YOLOv8n)

 

transfer learning 의 종류 중 어떤 종류로 해야할지 정하기 (ex. Feature-based Transfer Learning (특징 기반 전이 학습), Fine-tuning (미세 조정) 등등 많다.) -> Fine-tuning (미세 조정)으로 결정

  • Transfer learning은 기계 학습의 한 방법으로, 한 작업에서 학습한 지식을 다른 관련 작업에 활용하는 것을 의미한다. 이 기술은 특히 데이터가 제한된 상황에서 유용하며, 미리 학습된 모델의 일부 또는 전체를 새로운 작업에 재사용하여 성능을 향상시킬 수 있다.

 

Fine-tuning이란?

  • Fine-tuning (미세 조정)
  • 미리 학습된 모델의 일부 또는 전체 가중치를 새로운 작업에 맞게 조정하는 방식이다.
  • 새로운 작업에 관련된 데이터로 모델을 조정하면서 기존의 지식을 보전한다.
  • 쉽게 말해서 기존에 학습되어져 있는 모델을 기반으로 아키텍쳐를 새로운 목적(나의 이미지 데이터에 맞게)변형하고 이미 학습된 모델 Weights로 부터 학습을 업데이트하는 방법이다.
Transfer learning 입력층에 가까운 부분의 결합 파라미터는 학습된 값으로 변화시키지 않음
Fine Tuning 출력층 및 출력층에 가까운 부분뿐만 아니라 모든 층의 파라미터 다시 학습

 

우리는 프로젝트에 맞는 데이터셋으로 새로운 학습을 할것이다. 정확성을 높이기 위해 Pretrained Model(사전학습된)인 YOLOv8모델에 Fine-tuning을 활용하여 도로부속시설물 파손 데이터셋으로 학습을 이어간다.

 

현 예상 Fine-tuning 절차

  • 데이터 수집 및 준비: 도로부속시설물 파손에 관련된 레이블이 달린 데이터셋을 수집하고 준비한다.
  • 미리 학습된 YOLOv8 모델 선택: Pre-Trained YOLOv8 모델을 가져온다. COCO 데이터셋 등으로 학습된 모델을 선택하고 이를 기반으로 Fine-tuning을 시작한다.
  • 모델 Fine-tuning: Pre-Trained 모델을 도로부속시설물 파손 데이터셋으로 Fine-tuning한다. 이 과정에서 모델이 새로운 도메인에 적응하도록 한다.
  • 하이퍼파라미터 조정: Fine-tuning 하면서 학습률, 배치 크기, 에폭 수 등의 하이퍼파라미터를 조정하여 모델의 성능을 향상시킨다.
  • 검증과 테스트: 학습된 모델을 검증 데이터셋과 테스트 데이터셋에 적용하여 성능을 평가한다. 모델이 도로부속시설물 파손 객체를 잘 탐지하는지 확인한다.
  • 모델 적용: 성능이 만족스러우면 웹캠에서 들어오는 영상에 모델을 적용하여 실시간으로 도로부속시설물 파손 객체를 탐지한다.

 

webcam inference code

import cv2
from ultralytics import YOLO

# 웹캠 연결
cap = cv2.VideoCapture(0)
#### YOLO 모델 생성
model = YOLO("models/yolov8n.pt")

while cap.isOpened():
    # 한 frame(이미지)을 읽기
    succ, frame = cap.read()
    if not succ:
        print("웹캠 연결에 문제가 생겼습니다.")
        break
    # flip(대칭)
    frame = cv2.flip(frame, 1) # 양수: 좌우, 0: 상하, 음수: 상하좌우
    ###############################################
    # YOLO 모델을 이용한 추론 -> 결과 이미지 생성
    ###############################################
    img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # yolo는 rgb 이미지를 학습시킨다.
    
    # 추론. 추론대상이미지타입 - 문자열(경로), Image(ndarray, PIL.Image)
    result = model(img,
                   conf=0.5,  # 확률이 0.5 이상인 것만 결과로 리턴
                   verbose=False)[0] # 추론 결과 로그를 출력하지 않는다.
    
    # 결과에서 위치, 클래스 정보 추출
    ### (찾은 object 개수, shape)
    xyxy_list = result.boxes.xyxy.to("cpu").numpy().astype("int32")
    cls_list = result.boxes.cls.to("cpu").numpy().astype("int32")
    conf_list = result.boxes.conf.to("cpu").numpy()
    
    # for in 문을 이용해 찾은 object 별로 bbox 처리를 한다.
    for xyxy, cls, conf in zip(xyxy_list, cls_list, conf_list):
        pt1, pt2 = xyxy[:2], xyxy[2:]
        txt = f"{result.names[cls]} - {conf*100:.3f}%"
        # box
        cv2.rectangle(frame, pt1, pt2, color=(255, 0, 0), thickness=2)
        cv2.putText(frame, txt, org=pt1, fontFace=cv2.FONT_HERSHEY_COMPLEX, fontScale=1, color=(200,0,0), thickness=1, lineType=cv2.LINE_AA)
    
    # 영상 출력
    cv2.imshow("frame", frame)
    # 중단여부확인
    if cv2.waitKey(1) == 27: # ESC를 입력하면
        break
# 마무리
cap.release() # 웹캠연결 종료
cv2.destroyAllWindows() # 출력 윈도우 종료

- 위 코드는 jupyter 환경에서는 돌아가는데 colab에서는 웹캠이 뜨지 않는다 방안 찾아야함

  -> colab 환경에서는 동영상 display가 지원되지 않는다고 함. 그래서 colab에서 학습만 하고 pt파일을 local로 옮겨서 jupyter에서 inference 작업을 진행하려고 한다.

해결방안 reference 링크 : https://www.youtube.com/watch?v=QV85eYOb7gk

https://github.com/SkalskiP/yolov8-live?tab=readme-ov-file

 

 

- 학습 git 조사, 확보

fine-tuning train code 확보

 

reference들 링크 :

https://github.com/boostcampaitech4lv23cv3/final-project-level3-cv-19?tab=readme-ov-file

https://github.com/Spandan-Madan/Pytorch_fine_tuning_Tutorial/blob/master/main_fine_tuning.py

https://docs.ultralytics.com/ko/modes/train/#_1

https://www.youtube.com/watch?v=em_lOAp8DJE&t=186s

 

YOLOv8 학습 프로세스(커스텀 데이터)

  • Data Preparation: Custom Data 구축시 이미지 데이터와 정답 데이터는 확장자를 제외한 파일 이름은 동일해야 하며, YOLOv8에서 Annotation파일의 확장자는 반드시 .txt여야 한다.
  • Make YAML file: YOLOv8으로 Custom Data를 학습하기 위해서는 YAML 파일이 반드시 필요하며, 이 안에는 이미지와 정답이 저장되어 있는 디렉토리 정보(1)와 인식(Detection)하고 싶은 클래스 종류와 대응되는 각각의 이름(2)이 저장되어 있어야 한다.
  • Train model
  • Prediction

 

- Annotation파일 txt로 변환 코드

# json 파일을 txt파일로 변환
# categori_id, bbox(x,y,w,h)정규화 좌표

# bbox 좌표: 좌상단 x, 좌상단 y, bbox의 W, box의 H 
def convert_to_yolov8_format(bbox, image_width, image_height):
    x_center = (bbox[0] + bbox[2] / 2) / image_width
    y_center = (bbox[1] + bbox[3] / 2) / image_height
    width = bbox[2] / image_width
    height = bbox[3] / image_height
    return x_center, y_center, width, height
dst_dir = '/content/drive/MyDrive/finalproject/도로부속시설물 파손데이터셋 샘플/03.라벨링 변환데이터'
dataset_dir = '/content/drive/MyDrive/finalproject/도로부속시설물 파손데이터셋 샘플/02.라벨링데이터'
# Iterate through all JSON files in the dataset directory
for json_file in os.listdir(dataset_dir):
    if json_file.endswith('.json'):
        json_path = os.path.join(dataset_dir, json_file)
        print(len(json_path))      # print
        with open(json_path, 'r') as f:
            data = json.load(f)
        # Process each annotation in the JSON file
        for annotation in data.get('annotations', []):
            label_path = os.path.join(dst_dir, "labels")
            if not os.path.exists(label_path):
                os.makedirs(label_path)
            image_name = data['images'][0]['file_name'].split('.')[0]
            print(f'image_name: {image_name}')
            image_width = data['images'][0]['width']
            image_height = data['images'][0]['height']
            print(f'image_width: {image_width}, image_height: {image_height}')
            label = annotation.get('category_id', None)
            bbox = annotation.get('bbox', None)
            print(f'label: {label}, bbox: {bbox}')
            if label is not None and bbox is not None:
                x_center, y_center, width, height = convert_to_yolov8_format(bbox=bbox, 
                                                                             image_width=image_width, 
                                                                             image_height=image_height)
                x_center = format(x_center, '.6f')
                y_center = format(y_center, '.6f')
                width = format(width, '.6f')
                height = format(height, '.6f')
                arr = list(map(str, [label, x_center, y_center, width, height]))
                data_line = ' '.join(arr) + '\n'
                # Save the data to a text file
                txt_filename = os.path.join(label_path, f"{image_name}.txt")
                with open(txt_filename, 'a', encoding='UTF-8') as txt_file:
                    txt_file.write(data_line)

 

이제 이 코드로 json파일을 txt파일로 형식에 맞춰 변환한 뒤, 모델링 진행할 예정이다.

 

이후 멘토링 회의 내용

  • 두 데이터셋의 xywh값 확인 필요
    데이터수량은 양적으로 충분하다.
    지도에 표시하는 부분은 데이터셋에서 구현할 수 없고 다른 부분에서 처리하면서 구현해야 할 듯 하다.
    두 데이터셋의 정합성은 적합하다.
    두 데이터셋의 클래스를 양쪽에 맞춰야 한다. 데이터 정제 작업이 필요하다. 데이터 정제로써 통일해야 한다.

    과제  
  • PM님 파트
    - 데이터셋의 라벨링되어있는 카테고리들을 정리
    - 현황파악
  • 모델링파트
            - time 라이브러리로 모델(n, m 등)의 FPS 측정할 수 있는 코드로 확인해보기(현재 가용할 수 있는 GPU 사양을 최대한 높여서 확인해보기)
    - CPU로밖에 진행을 못한다면 모델의 수준이 낮아질 수 밖에 없다. -> 확인해보기
    - 코드 부분의 result 위에 time before를 걸고 뒤에 time after를 걸어서 FPS확인하기
    - time을 활용한 FPS측정 강의 자료 레퍼런스 있는 걸로 앎 -> 찾아보기

    - AIhub 데이터셋 활용 AI 모델 확보할 수 있다면 확보, 모델을 돌릴 수 있는 환경 확보하기
    - 이후에 클래스 재정의할 것이다. 각각의 라벨 클래스를 더 살펴보고 어떤 걸 버리고 어떤 걸 채택할지 테이블 작성
  • 웹 파트
    - 지역 데이터 GPS 좌표(위도,경도)로 표현하는 방법을 강구(ex. 카카오 API)
    - 일반적으로 사진은 로컬 드라이브(d드라이브)에 저장한다.
    - 이미지-파일이름은 이미지 이름 그대로 저장하면 될 듯하다.
    - 어노테이션, bbox에 대한 테이블은 필요하지 않다.
    - DB파트에서는 지자체 회원이 탐지된 객체를 유지보수한 상태(처리)를 어떻게 표현할 것인지 고민해볼 필요가 있다.
    - UI: 메인페이지에 본인 자동차의 위치도 표시해야 한다. 일반 사용자 기준으로는 현재의 인터페이스가 필요하지 않다.
    사용자 메인페이지에 위험도 정렬, 범위 선택, 카테고리 선택과 같은 기능은 필요하지 않다. -> 네비게이션과 같은 UI가 필요하다.
    위의 세가지 기능은 개인 사용자에게 필요없는 인터페이스이다.
  • 공통
    - 사용자 시나리오에 대한 명확한 정의가 있다면 각각의 파트에 할 일이 수월해질 것이다.