관리 메뉴

Nacho

(YOLOv8) 위성 영상데이터로 Cool_Roof 분류 - Object detection 본문

Python

(YOLOv8) 위성 영상데이터로 Cool_Roof 분류 - Object detection

Nacho_13 2024. 4. 13. 02:48
반응형

 

주제:   인공위성 데이터로 도시 환경 개선

 

도메인 이해.

Cool Roof
  • 건물지붕이나 옥상에 태양열 차단 효과가 있는 차열 페인트를 칠하여 건물에 열기가 축적되는 것을 줄이는 공법 
  • Cool Roof 사업 지원대상 선정을 위해 1차적으로 지원대상을 식별하는 방법 도출
  • 인공위성 영상 데이터를 이용하여 Cool Roof, Generic Roof 분류 

 

Datasets

 

Cool Roof 사업의 선정대상을 분류하는 문제이다. 따라서 Cool Roof : 0, Generic Roof : 1 로 지정.

 

접근 방식

  1. Cool Roof 의 특성상 태양열 반사를 목적으로 흰색 페인트를 이용한다.
    • 이미지를 Gray scale 로 변환하여 Cool Roof 를 분류하는 정확도를 높인다.
  2. 다른 건물에 의한 그림자가 Cool Roof 오분류를 야기한다.
    •  RGB 보다 그림자, 연속된 색상 표현에 유리한 HSV 포맷으로 이미지 변경.
  3. Genric Roof 의 경우 색상이 다양하고, 위성사진 영상을 확대한 이미지이기 때문에 지붕의 경계가 모호하다.
    • Sharpening Filter 를 적용하며 지붕의 외곽선 정보를 강조하였다.
  4. YOLO 모델 별 성능 차이를 비교, yolov8n, yolov8s, yolov8m ...

 

Code

파일 불러오기

# 라이브러리
import gdown, zipfile
import os, glob, shutil
from tqdm import tqdm
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import cv2
image_path = '/content/drive/MyDrive/KT_aivle/CNN/mini_4/cool_roof_images.zip'
label_path = "/content/drive/MyDrive/KT_aivle/CNN/mini_4/cool_roof_yolo_labels.zip"
test_path = "/content/drive/MyDrive/KT_aivle/CNN/mini_4/cool_roof_yolo_test.zip"
ex_train_path = '/content/drive/MyDrive/KT_aivle/CNN/mini_4/ex_train.zip' # 211개의 data를 수집, roboflow 증강을 통해 885 개의 train data
def dataset_extract(file_name) :
    with zipfile.ZipFile(file_name, 'r') as zip_ref :
        file_list = zip_ref.namelist()

        if os.path.exists(f'./{file_name[:-4]}/') :
            print(f'데이터셋 폴더가 이미 존재합니다.')
            return

        else :
            for f in tqdm(file_list, desc='Extracting', unit='files') :
                zip_ref.extract(member=f, path=f'./{file_name[-10:-4]}/')
dataset_extract(image_path)
dataset_extract(label_path)
dataset_extract(test_path)
dataset_extract(ex_train_path)

 

 

datasets file tree 구성

!mkdir /content/datasets
!mkdir /content/datasets/train; mkdir /content/datasets/valid;
!mkdir /content/datasets/train/images;mkdir /content/datasets/train/labels;
!mkdir /content/datasets/valid/images;mkdir /content/datasets/valid/labels;

 

costom dataset 구조는 yolov8 공식문서를 참조하자.

 

 

추가 데이터 불러오기

img_path = '/content/images/'
lab_path = '/content/labels/obj_train_data/'
ex_img_path = '/content/_train/train/images/'
ex_lab_path = '/content/_train/train/labels/'
ex_img_list = os.listdir(ex_img_path)
ex_lab_list = os.listdir(ex_lab_path)

for ex_tr_img, ex_tr_lab in zip(ex_img_list,ex_lab_list) :
    shutil.move(ex_img_path + ex_tr_img, img_path)
    shutil.move(ex_lab_path + ex_tr_lab, lab_path)

 

학습데이터 불러오기 

img_list = os.listdir(img_path)
img_list = sorted(img_list)
lab_list = os.listdir(lab_path)
lab_list = sorted(lab_list)


# 파일 담아오기
data_files = []
for img, lab in zip(img_list,lab_list):
    data_files.append([glob.glob(img_path+img), glob.glob(lab_path+lab)])

 

 

학습 데이터 'roof (1).jpg' ~ 'roof (200).jpg' 의 이미지 크기를 640 x 640 으로  변경

# Pillow 라이브러리 불러오기
from PIL import Image

for i in tqdm(range(1,201)):
  img = Image.open(f'/content/images/roof ({i}).jpg')
  img = img.resize((640,640))
  img.save(f'/content/images/roof ({i}).jpg')


#test_img

test_path = "/content/o_test/test/images/"
for test_file in tqdm(os.listdir(test_path)):
  img = Image.open(test_path + test_file)
  img = img.resize((640,640))
  img.save(test_path + test_file)

 

HSV 변경

#HSV
import cv2
for i in tqdm(os.listdir(img_path)):
  rgbimg = cv2.imread(f'/content/images/roof ({i}).jpg')
  hsvimg = cv2.cvtColor(rgbimg, cv2.COLOR_RGB2HSV)
  cv2.imwrite(img_path + i, hsvimg)

for test_file in tqdm(os.listdir(test_path)):
  rgbimg = cv2.imread(test_path + test_file)
  hsvimg = cv2.cvtColor(rgbimg, cv2.COLOR_RGB2HSV)
  cv2.imwrite(test_path + test_file, hsvimg)

 

Gray scale 변경

#GRAY
import cv2
for i in tqdm(os.listdir(img_path)):
  rgbimg = cv2.imread(img_path + i)
  grayimg = cv2.cvtColor(rgbimg, cv2.COLOR_RGB2GRAY)
  cv2.imwrite(img_path + i, grayimg)

for test_file in tqdm(os.listdir(test_path)):
  rgbimg = cv2.imread(test_path + test_file)
  grayimg = cv2.cvtColor(rgbimg, cv2.COLOR_RGB2GRAY)
  cv2.imwrite(test_path + test_file, grayimg)

 

 

Sharpening Filter

def sharp(img):
    kernel_sharp = np.array((
        [-2, -2, -2],
        [-2, 17, -2],
        [-2, -2, -2]), dtype='int')
    return cv2.filter2D(img, -1, kernel_sharp)
for i in tqdm(os.listdir(img_path)):
  img = cv2.imread(img_path + i)
  sh_img = sharp(img)
  cv2.imwrite(img_path + i, sh_img)

for test_file in tqdm(os.listdir(test_path)):
  img = cv2.imread(test_path + test_file)
  sh_img = sharp(img)
  cv2.imwrite(test_path + test_file, sh_img)

 

 

Data split

from sklearn.model_selection import train_test_split

train, val = train_test_split(data_files, test_size=.2, random_state=2024)
train_path = '/content/datasets/train/'
valid_path = '/content/datasets/valid/'

for tr_img, tr_lab in train:
    shutil.move(tr_img[0], train_path +'images')
    shutil.move(tr_lab[0], train_path +'labels')

for va_img, va_lab in val:
    shutil.move(va_img[0], valid_path + 'images')
    shutil.move(va_lab[0], valid_path + 'labels')

 

 

Yaml 파일 생성

import yaml

data = {
    'train': '../train/images',
    'val': '../valid/images',
    'nc': 2,
    'names': ['cool roof', 'generic roof']
}

with open('/content/datasets/data.yaml', 'w') as outfile:
    yaml.dump(data, outfile, default_flow_style=False)

 

YOLO 모델 학습

!pip install ultralytics==8.0.196
model = YOLO(model='yolov8s.pt', task='detect')
settings['datasets_dir'] = '/content/'
settings.update()
model.train(data='/content/datasets/data.yaml',
            epochs=150,
            patience=7,
            pretrained=False,
            verbose=True,
            seed=2024,
            )
pred = model.predict(test_path,conf=.6,save=True, iou=0.2 )

 

 

 

 

결과

  • dataset 200개에 대한 yolov8s 모델 학습 결과

 

 

 

 

  • dataset 317개에 대한 yolov8n 모델 학습 결과

 

 

 

 

 

  • dataset 317개에 대한 yolov8s 모델 학습 결과

 

 

 

결론

  1. Sharping filter를 적용한 이미지의 예측 성승이 우수함.
    • generic roof를 판단하는데 건물의 외곽선 추출이 성능의 영향을 미침
  2. 그림자, 무지개 등 과 같은 명도를 표현하는데 RGB보다 유리한 HSV 포맷으로 변경하여 예측
    • 주변 건물에 의해서 그림자진 roof의 오분류를 줄이고자 하였으나 성능 개선은 이루어지지 않음
  3. cool roof 를 분류하는데 도움이 될 것이라는 가정으로 Gray scale 로 변환
    • cool roof 를 분류하는데 도움은 있은 것으로 보이나 generic roof 를 구분하는 것에서 성능이 저하된다.
  4. yolo model 크기별 비교
    • 시간이 부족해 nano, small 버전만 비교하였지만, 모델이 클수록 좋은 성능을 보인다.
반응형