대형 폐기물 사진을 자동분류 해주는 AI 모델을 만듭니다. (송파구 기준)
- 대분류 모델 : 의자, TV, 자전거, 선풍기, 소파, 책상, 서랍장, 화분, 항아리, 목제침대, 돌침대 (11개 Class)
- 소분류 모델 : 의자 - 일반의자, 회전의자, 장의자 / 자전거 - 성인용, 아동2륜, 아동3륜
Site | URL |
---|---|
공공데이터포털 | https://data.seoul.go.kr/etc/aiEduData.do |
AI Hub | https://www.aihub.or.kr/unitysearch/list.do?kwd=%ED%8F%90%EA%B8%B0%EB%AC%BC |
의자 100장, TV 100장, 자전거 100장, 선풍기 100장 총 400장의 데이터로 모델 선정을 위해 간단한 실험 진행
YOLOv5, YOLOv8n, YOLOv8s,CNN 사용
-
YOLO Documents
-
Code
진행결과 가장 실질적으로 Detection이 뛰어난 YOLOv8n을 사용하기로 결정
데이터 수가 많고 질이 좋은 AI Hub 데이터를 사용
Json 파일 구조 확인을 위한 예시
for i in os.listdir(labels_folder_path):
file_name = i.replace('.Json','')
label_file_path = labels_folder_path + '/'+ i
image_file_path = images_folder_path + '/'+ i.replace('.Json','.jpg')
with open(label_file_path,'r', encoding='UTF8') as file:
data = json.load(file)
if data['BoundingCount']!='1':
print(file_name +'을 삭제합니다.')
file.close()
os.remove(label_file_path)
os.remove(image_file_path)
elif data['Bounding'][0]['Drawing'] == 'POLYGON':
x_point_list=[]
y_point_list=[]
for i in range(int(data['Bounding'][0]['PolygonCount'])):
x_point_list.append(int(list(data['Bounding'][0]['PolygonPoint'][i].values())[0].split(',')[0]))
y_point_list.append(int(list(data['Bounding'][0]['PolygonPoint'][i].values())[0].split(',')[1]))
x1 = min(x_point_list)
x2 = max(x_point_list)
y1 = min(y_point_list)
y2 = max(y_point_list)
# YOLO에 맞게 좌표 변환
x_center = ((x1 + x2) / 2) / img_width
y_center = ((y1 + y2) / 2) / img_height
width_norm = (x2 - x1) / img_width
height_norm = (y2 - y1) / img_height
if not os.path.exists(output_path): # if the path does not exist
os.makedirs(output_path) # create the path
# Determine the class based on the label
if '의자' == label:
class_id = '0'
#...
elif '항아리' in label:
class_id = '10'
else:
class_id = None
# If we have a valid class, write it to file
if class_id is not None:
with open(os.path.join(output_path, name+'.txt'), 'w') as file:
file.write(f"{class_id} {x_center:f} {y_center:f} {width_norm:f} {height_norm:f}\n")
label_dic = {0: chair, 1: tv, 2: bicycle, 3: fan, 4: sofa, 5: desk, 6: chiffonier, 7: pot, 8: jar, 9: bed, 10: ston_jade_bed}
with open('/content/drive/MyDrive/BIG_PROJECT/class.yaml', 'w') as f:
data = {
'path': '/content/drive/MyDrive/BIG_PROJECT',
'train':'images/train',
'val': 'images/val',
'nc': len(label_dic),
'names': label_dic,
}
yaml.safe_dump(data, f)
-
기존 데이터 서랍장 약 5400장, 선풍기 약 4000장, 소파 약 1600장, 의자 약 16200장, 책상 약 1600장, 티비 약 1700장, 항아리 약 1500장, 화분 약 11000장, 자전거 약 40000장
--> 데이터 불균형이 심각하고 데이터 용량이 너무 커서 모델 학습에 지장을 주므로 데이터 수를 줄이기로 결정
각 Class별로 train 1200장, val 300장으로 재정제
의자나 자전거의 경우 각 소분류 항목도 총 1500장 중에서 비율을 맞추어줌
의자 중 장의자의 이미지 경우 200장 미만으로 다른 의자(일반의자, 회전의자)와 데이터 수 차이가 큼
Image Augmentation을 활용해 데이터 증강 후 모델 성능 개선 된 것을 확인 가능
#ultralytics설치
!pip install --target=$my_path ultralytics
import ultralytics
ultralytics.checks()
from ultralytics import YOLO
#모델 yolov8n
model = YOLO('yolov8n.pt')
with open('/content/drive/MyDrive/BIG_PROJECT/class.yaml', 'w') as f:
data = {
'path': '/content/drive/MyDrive/BIG_PROJECT/',
'train':'/content/drive/MyDrive/BIG_PROJECT/images/train',
'val': '/content/drive/MyDrive/BIG_PROJECT/images/val',
'nc': len(label_dic),
'names': label_dic,
}
yaml.safe_dump(data, f)
#모델학습
model.train(data='/content/drive/MyDrive/BIG_PROJECT/class.yaml', epochs=100,patience=35,batch=32,imgsz=416)
with mlflow.start_run(experiment_id=exp_id, run_name=myname):
## 학습 전
# YOLO 모델 불러오기
model = YOLO('yolov8n.pt')
# 하이퍼파라미터 로깅
epochs = 100 #100
patience = 35 #30
batch_size = 32
imgsz = 416
data_path = '/content/drive/MyDrive/BIG_PROJECT/class.yaml'
mlflow.log_param("epochs", epochs)
mlflow.log_param("patience", patience)
mlflow.log_param("batch_size", batch_size)
mlflow.log_param("imgsz", imgsz)
mlflow.log_param("data_path", data_path)
model.add_callback("on_fit_epoch_end",on_fit_epoch_end)
## 모델 학습
results = model.train(data=data_path, epochs=epochs, patience=patience, batch=batch_size, imgsz=imgsz)
## 학습 후
# 모델 메트릭 로깅
mlflow.log_artifacts('/content/runs/detect/train')
# 베스트 모델 불러오기
checkpoint = torch.load('/content/runs/detect/train/weights/best.pt', map_location='cpu')
best_model = checkpoint.get('model') #, checkpoint)
# best.pt를 모델 폴더 안에 넣어줘야함!
mlflow.log_artifact('/content/runs/detect/train/weights/best.pt', artifact_path='best_model')
# MLflow에 모델 로깅 및 등록된 모델로 등록
mlflow.pytorch.log_model(best_model, "best_model", registered_model_name=model_name)
predict의 매개 변수 save_txt, save_conf을 이용하여 class 와 confidence scores을 text로 반환
result = model.predict(source = '/content/drive/MyDrive/BIG_PROJECT/images/test', save=True,save_txt=True,save_conf=True)