Broccoli's House

#5-(4) 훈련 데이터 수집 및 저장 본문

공부/캡스톤 디자인

#5-(4) 훈련 데이터 수집 및 저장

김콜리 2018. 3. 10. 16:02

5회차 - (4) 훈련 데이터 수집 및 저장



  • 훈련 데이터 수집
 - 딥러닝 모델을 만들어 학습시키기 위하여 앞서 작성했던 파이썬 코드들을 사용하여 훈련 데이터를 수집한다. 하나의 파이썬 파일 안에 스크린 이미지를 추출하는 코드와 로지텍 G27에서 조향, 엑셀, 브레이크 데이터를 추출하는 코드를 동시에 작성하는 경우, 전체 코드가 복잡해지고 깔끔하지 못하다. 따라서 두 개를 분리하여 다른 파이썬 파일 안에서 작성하고 훈련 데이터를 모으는 파이썬 파일을 새로 만들어, 모듈로써 각 기능을 하는 함수를 불러오도록 한다.




  • 이미지 추출 모듈 및 함수 작성

 - 컴퓨터 스크린을 촬영하고 이미지의 크기 조절 및 흑백 처리를 해주는 함수를 작성하고, 이미지를 저장해주는 함수를 따로 작성한다. 그 이유는 훈련 데이터를 다 모은 후에 딥러닝을 통한 학습이 완료되면, 이미지를 계속 추출은 해야하지만 저장할 필요는 없어지기 때문이다. 스크린 추출 방식은 전에 작성했던 것과 동일하다. 

 - 이미지를 저장하는데 중요한 점은, 이미지의 이름이 모두 달라야하고, 이미지가 촬영한 순서대로 나열되어야 한다는 점이다. 만약 이미지를 단순히 이름을 지정해서 저장한다면 단 하나의 이름을 지닌 이미지만 생성되고 그 내용만 바뀌기 때문에, 이미지의 이름이 계속 바뀌어야 할 필요가 있다. 이것을 위해 파이썬의 datetime 모듈을 사용하여 현재의 날짜 및 시간을 받아 그것을 이미지의 이름으로 사용한다. 

# getScreenImage.py

import numpy as np
from PIL import ImageGrab
from PIL import Image
import cv2
import datetime

def get_Screen() : # Get screen image

screen = np.array(ImageGrab.grab())
img_resize = cv2.resize(screen, (960,540), interpolation = cv2.INTER_AREA)
img = Image.fromarray(img_resize).convert('L')
pixel_array = np.array(img)
return img, pixel_array


def save_Image(img) : # Save screen image for training

now = datetime.datetime.now()
now_str = now.strftime("%H.%M.%S.%f")
img.save('D:/Capstone Design/Project/Training Data/{}.PNG'.format(now_str)) # The PNG format does not corrupt the data 


 - save() 함수를 통해 이미지를 저장할 수 있다.  이미지는 PNG 포맷을 사용한다. PNG는 용량이 크지만 비손실 압축 방식이라 이미지의 원본이 훼손되지 않는다. JPG는 손실 압축 방식이라 용량이 작지만 이미지의 원본이 훼손되기 때문에 PNG 포맷을 사용하는 것이다. 이미지의 이름은 앞서 말한대로 저장할 때의 날짜와 시간을 사용한다. 이렇게 하면 이미지를 시간
 순서대로 나열할 수 있고, 이미지의 이름이 매번 바뀌게 된다. 




  • G27 데이터 추출 모듈 및 함수 작성

 - 로지텍 G27에서 데이터를 모으는 전체 코드를 조이스틱을 초기화하는 함수, 데이터를 얻어오는 함수, 데이터를 저장하는 함수 크게 이 세 개로 분할하여 각각 따로 함수를 만들어준다. 조이스틱을 초기화하는 함수는 단 한번만 선언하면 되기에 반복문 안에 들어갈 필요가 없다. 따라서 전체 코드에서 분리하여 따로 함수를 만들어준 것이다. 데이터를 얻어오는 함수와 그것을 저장하는 함수는 스크린 이미지 추출 모듈과 마찬가지로 추후의 사용 여부가 달라지기 때문에 나눠서 함수를 작성해준 것이다.


# getGearData.py

import pygame

def joystick_initialize() : # Initialize the Joystick (Logitech G27)

pygame.init()
pygame.joystick.init()
pad = pygame.joystick.Joystick(0)
pad.init()

print('Joystick Nmae : ' + pad.get_name())
print('Number of Axes in Joystick : ' + str(pad.get_numaxes()))
print('Steering Wheel Axis Index : 0')
print('Throttle Pedal Axis Index : 2')
print('Brake Pedal Axis Index : 3')
return pad


def get_Angle(joystick) : # Get angle data from the Joystick

pygame.event.pump()
angle = joystick.get_axis(0) * 100
return angle


def get_Throttle(joystick) : # Get Throttle data from the Joystick

pygame.event.pump()
throttle = joystick.get_axis(2)
return throttle


def get_Brake(joystick) : # Get Braking data from the Joystick

pygame.event.pump()
brake = joystick.get_axis(3)
return brake


def Save_Data(angle, throttle, brake) : # Write the steering angle to a text file

file_angle = open('D:/Capstone Design/Project/Training Data/Steering_Data.txt', 'a')
file_throttle = open('D:/Capstone Design/Project/Training Data/Throttle_Data.txt', 'a')
file_brake = open('D:/Capstone Design/Project/Training Data/Brake_Data.txt', 'a')

file_angle.write(str(angle) + '\n')
file_throttle.write(str(throttle) + '\n')
file_brake.write(str(brake) + '\n')

file_angle.close()
file_throttle.close()
file_brake.close()


 - 데이터를 저장하는 함수에서, 파일에 데이터를 쓸 때 계속 이어서 써야 하므로 설정을 'a'로 사용한다. 처음에 반복문 바깥에서 파일을 쓰기 설정으로 열고, 반복문 내부에서는 데이터를 쓰는 것만 하려했으나 코드를 실행했을 때 텍스트 파일에 아무것도 적히지 않았다. 정확한 이유를 모르나 훈련 데이터를 모으는 데는 코드를 실행하는 시간 지연이 그리 중요하지 않고, 시간 지연 자체도 길지 않기 때문에(1~2ms) 데이터 저장하려 할 때마다 파일을 열었다 닫아야 한다. 




  • 훈련 데이터 수집 코드 작성

 - 앞서 만들었던 두 개의 모듈을 불러와 차량 시뮬레이터의 영상 이미지와 그 때의 데이터를 추출 및 저장하는 훈련 데이터 수집 코드를 작성한다. 해당 코드를 실행하면, 인식한 조이스틱의 이름과 축의 개수, 인덱스를 출력해주고 해당 코드가 저장되있는 폴더에 이미지와 텍스트 파일이 생성된다. 


 - 현재 프로젝트의 기본 목표는 딥러닝을 통해 AI가 인간의 운전 방식을 모사하도록 스티어링 휠을 조작하는 것이다. 그러기 위해서는 사람이 직접 운전했을 때의 데이터가 딥러닝 모델에 훈련 데이터로 주어지는데, 데이터가 온전치 못한 경우(사람의 운전 조작 미숙) 잘못된 데이터로 학습이 이루어져 결과가 제대로 나오지 않을 수 있다. 따라서 부득이하게 잘못된 길을 들거나 조작이 잘못된 경우 이미지와 데이터를 저장하지 못하도록 G27의 특정 버튼을 누르면 반복문이 종료되도록 설정하였다.


# getTrainingData.py

import getGearData
import getScreenImage

pad = getGearData.joystick_initialize()

while(True) :

img, pixel_array = getScreenImage.get_Screen()
angle = getGearData.get_Angle(pad)
throttle = getGearData.get_Throttle(pad)
brake = getGearData.get_Brake(pad)

getScreenImage.save_Image(img)
getGearData.Save_Data(angle, throttle, brake)

if (pad.get_button(5) == 1) :
break



Comments