Modeling 수행
- colab으로 대용량 데이터 파일들을 옮기지도 못해서 local에서 진행
패키지 및 라이브러리 불러오기
# 패키지 및 라이브러리 불러오기
from ultralytics import YOLO
from PIL import Image
import cv2
import os
import urllib
import yaml
import json
디렉토리에 파일 개수 잘 들어갔는지 확인하는 코드
- 현재 사진,라벨링 데이터 각각 짝 맞춰서 2만개씩 다운로드 받았기에 모두 20000이 출력되어야 한다.
# 디렉토리 내의 파일 개수 확인
# folder_path = "Training/원천데이터" -> 다운로드 받은 사진데이터(jpg)들
# folder_path = "Training/라벨링데이터" -> 다운로드 받은 라벨링데이터(json)들
# folder_path = "Training/labels" -> json라벨링데이터들을 txt로 변환한 데이터들
folder_path = "Training/resizing_images" # -> (1920,1080)을 (640,360)으로 resize한 데이터들
file_list = os.listdir(folder_path)
file_count = len(file_list)
print(file_count)
resize한 결과이미지를 담을 디렉토리 생성
# resize할 이미지를 담을 디렉토리 생성
os.mkdir('Training/resizing_images')
이미지 resize 코드 (1920,1080) -> (640, 360)
- (640, 640)으로 변경하려 했지만 1920,1080 사진 기준으로 작성된 bbox의 위치가 이상하게 바뀔 수 있어서 비율을 맞춰 (640,360)으로 변경
-> Train할 때 image의 size를 정할 수 있어 resize할 필요가 없다. 코드 실행하지 않아도 됨
# 이미지 resize (1920, 1080) -> (640, 360) 나누기3한 비율만큼 줄이기
def resize_images(input_dir, output_dir, new_size):
os.makedirs(output_dir, exist_ok=True)
for filename in os.listdir(input_dir):
if filename.endswith(".jpg"):
input_path = os.path.join(input_dir, filename)
output_path = os.path.join(output_dir, filename)
# image resizing
image = Image.open(input_path)
resized_image = image.resize(new_size, Image.ANTIALIAS)
resized_image.save(output_path)
input_images_dir = 'Training/원천데이터'
output_images_dir = 'Training/resizing_images'
new_size = (640, 360)
resize_images(input_images_dir, output_images_dir, new_size)
image_files = [f for f in os.listdir(output_images_dir) if f.endswith('.jpg')]
print(f'Number of files in the RESIZING directory: image {len(image_files)}개')
json파일을 bbox및 class정보가 담겨져 있는 txt파일로 변환 코드
- (640,360)으로 고정
-> bbox의 좌표를 정규화된 숫자로 매핑해주기에 크기를 고정할 필요가 없다. 이 코드가 아닌 밑의 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 = 'C:\\Users\\Playdata\\Desktop\\지자체도로부속시설물 파손데이터\\Training'
dataset_dir = 'C:\\Users\\Playdata\\Desktop\\지자체도로부속시설물 파손데이터\\Training\\라벨링데이터'
# 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', encoding = 'UTF-8') 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 = 640 # data['images'][0]['width'] 640으로 고정
image_height = 360 #data['images'][0]['height'] 360으로 고정
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)
(1920,1080)을 (640,640)으로 resize하는 코드
- size를 640으로 설정하고 학습하는 reference가 많아 (640,640)으로 resize하는 코드
-> Train할 때 image의 size를 정할 수 있어 resize할 필요가 없다. 코드 실행하지 않아도 됨
# 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, target_width, target_height):
# 원본 이미지에서 bbox 좌표를 가져옴
x, y, w, h = bbox
# bbox 좌표를 (0, 1) 범위로 변환
x_center = (x + w / 2) / image_width
y_center = (y + h / 2) / image_height
width = w / image_width
height = h / image_height
# 새로운 크기에 맞게 bbox 좌표를 조정
x_center *= target_width
y_center *= target_height
width *= target_width
height *= target_height
return x_center, y_center, width, height
dst_dir = 'C:\\Users\\Playdata\\Desktop\\지자체도로부속시설물 파손데이터\\Training'
dataset_dir = 'C:\\Users\\Playdata\\Desktop\\지자체도로부속시설물 파손데이터\\Training\\라벨링데이터'
# Iterate through all JSON files in the dataset directory
image_width, image_height = 1920, 1080
target_width, target_height = 640, 640
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', encoding = 'UTF-8') 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 = 640 # data['images'][0]['width'] 640으로 고정
image_height = 360 #data['images'][0]['height'] 360으로 고정
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,
target_width=target_width,
target_height=target_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파일의 bbox를 정규화된 txt파일로 변환하는 코드
# 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 = 'Training'
dataset_dir = 'Training/라벨링데이터'
# 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', encoding='UTF-8') 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)

파이썬으로 yaml파일 작성
# write yaml file with python
data = {
"train" : 'Training',
"val" : 'Training',
# "test" : '/tld_sample/test/', optional
"names" : {1 : 'PE드럼 정상', 2 : 'PE드럼 파손', 3 : 'PE방호벽 정상', 4 : 'PE방호벽 파손', 5 : 'PE안내봉 정상', 6 : 'PE안내봉 파손',
7 : '라바콘 정상', 8 : '라바콘 파손', 9 : '시선유도봉 정상', 10 : '시선유도봉 파손', 11 : '제설함 정상', 12 : '제설함 파손',
13 : 'PE입간판 정상', 14 : 'PE입간판 파손', 15 : 'PE휀스 정상', 16 : 'PE휀스 파손'}}
with open('./customA.yaml', 'w', encoding = 'UTF-8') as f :
yaml.dump(data, f, allow_unicode=True) # allow_unicode -> 한글 깨지지 않도록
# check written file
with open('./customA.yaml', 'r', encoding = 'UTF-8') as f :
lines = yaml.safe_load(f)
print(lines)
학습
model = YOLO('yolov8n.pt')
model.train(data='./customA.yaml' , epochs=5)
-> error 발생

-> 0번 클래스를 없는 객체로 생각하여 etc로 설정하여 추가

그랬더니 ultralytics디렉토리에 있는 setting.yaml파일에서 경로 설정을 제대로 하라는데 아무리 찾아봐도 경로를 찾지못함
'프로젝트 > Data_Analysis_Track_33_FinalProject' 카테고리의 다른 글
| FinalProject_07(개별 Action 수행, AWS 학습) (0) | 2024.01.16 |
|---|---|
| FinalProject_06(개별 Action 수행, sequential img inference) (0) | 2024.01.12 |
| FinalProject_04(개별 Action 수행) (0) | 2024.01.10 |
| FinalProject_03(개별 Action 수행, 모델링 webcam FPS 측정 코드) (1) | 2024.01.08 |
| FinalProject_02(개별 Action 선정 및 수행, webcam inference code) (1) | 2024.01.03 |