실시간 킥보드 헬멧 단속 시스템 - 프로젝트 배경과 Dataset 구성

프로젝트 배경

2021년 5월 13일부터 도로교통법 개정으로 인해 전동 킥보드를 이용할 때 안전모를 착용하지 않으면 범칙금 2만원을 내야합니다. 하지만 여전히 안전모를 착용하지 않고 전동 킥보드를 이용하지 않는 많은 사람들이 존재하며, 경찰분들이 일일이 모두 단속할 수는 없기 때문에 실시간 킥보드 단속 시스템을 구상하게 되었습니다.

Dataset 구성

  • 인터넷에서 수집한 사진 172장
  • 직접 촬영한 사진 598장

    - 비디오로 헬멧을 쓰고 전동킥보드를 이용하는 것과 헬멧을 쓰지 않고 전동 킥보드를 이용하는 모습을 촬영한 뒤 프레임 단위로 캡처되는 이미지로 변환하여 저장하였습니다.
import os
import cv2

def video2frame(video_name, invideofilename, save_path):
    vidcap = cv2.VideoCapture(invideofilename)
    count = 0
    while True:
      success,image = vidcap.read()
      if not success:
          break
      if(int(vidcap.get(1)) % 10 == 0):
        print ('Read a new frame: ', success)
        fname = "{}.jpg".format("{0:05d}".format(count))
        cv2.imwrite(save_path + video_name + '_' + fname, image) # save frame as JPEG file
        count += 1
    print("{} images are extracted in {}.". format(count, save_path))


video_list = os.listdir('./kickboard_video')

for video_name in video_list:
    name = video_name.split('.')[0]
    video2frame(name, './kickboard_video/' + video_name, './images/')

⭐ 원본 데이터 셋이 770장으로 적은 편이기 때문에 Data Augmentation을 통해 늘릴 것 입니다.

Data Labeling

Data Labeling은 Make Sense를 이용하여 하였습니다. 라벨은 헬멧을 쓴 사람과 헬멧을 쓰지 않은 사람으로 2가지로 하였고 킥보드까지 전체 모습으로 하여야 전체 모습을 인식할 수 있기 때문에 전체 모습을 라벨링하였습니다.

Data Augmentation

다음 주소의 Github를 참고하여 코드를 만들었습니다. 코드의 기능은 이미 라벨링 되어 있는 이미지를 augmentation하고 라벨링까지 augmentation된 이미지에 맞게 바꿔주기 때문에 추가적인 라벨링 과정이 필요없기 때문에 유용합니다.

from data_aug.data_aug import *
from data_aug.bbox_util import *
import numpy as np 
import cv2 
import matplotlib.pyplot as plt 
import pickle as pkl
%matplotlib inline

import os
from PIL import Image

def convert(size, box): 
    dw = 1./size[1] 
    dh = 1./size[0] 
    x = (box[0] + box[2])/2.0 
    y = (box[1] + box[3])/2.0 
    w = box[2] - box[0] 
    h = box[3] - box[1] 
    x = x*dw 
    w = w*dw 
    y = y*dh 
    h = h*dh 
    return (x,y,w,h)

img_path = '../images/' # 이미지 경로
label_path = '../labels/' # 라벨 경로
img_li = os.listdir(img_path)
label_li = os.listdir(label_path)

for i in range(len(img_li)):
    file_name = img_li[i].split('.')[0]
    image = '../images/' + img_li[i]
    print('이미지 경로', image)
    img = cv2.imread(image)[:,:,::-1]
    label_name = label_path + image.split('/')[-1].split('.')[0] + '.txt'
    print('라벨 경로', label_name)
    size = []
    size.append(img.shape[0]) 
    size.append(img.shape[1]) 
    print('이미지 크기', str(size))

    bboxes = np.loadtxt(label_name, delimiter=' ', skiprows=0, dtype=float)
    print('읽은 라벨 값 yolo', bboxes)

    if bboxes.ndim==1:
            rebboxes=np.zeros((1,bboxes.shape[0]))
    else:
        rebboxes=np.zeros(bboxes.shape)


    if bboxes.ndim==1:
        rebboxes[0][0]=bboxes[1]
        rebboxes[0][1]=bboxes[2]
        rebboxes[0][2]=bboxes[3]
        rebboxes[0][3]=bboxes[4]
        rebboxes[0][4]=bboxes[0]
        boundingbox=np.zeros(rebboxes.shape)
    else:
        rebboxes=bboxes[:,1:]
        rebboxes=np.hstack([rebboxes,bboxes[:,0:1]])
        boundingbox=np.zeros(bboxes.shape)

    print('순서 바꿈', rebboxes)

    #([0]=좌측상단 x, [1]=좌측상단 y, [2]=우측하단 x,[3]=우측하단 y)
    for i in range(boundingbox.shape[0]):
        boundingbox[i,0], boundingbox[i,1] = size[1] * (rebboxes[i,0] - rebboxes[i,2] / 2), size[0] * (rebboxes[i,1] - rebboxes[i,3] / 2)
        boundingbox[i,2], boundingbox[i,3] = size[1] * (rebboxes[i,0] + rebboxes[i,2] / 2), size[0] * (rebboxes[i,1] + rebboxes[i,3] / 2)
        boundingbox[i,4]=rebboxes[i,4]

    print('바운딩 박스', boundingbox)

    # augmentation 과정
    seq = Sequence([RandomHSV(40, 40, 30),RandomHorizontalFlip(), Scale(-0.7, -0.7),Translate(0.2, 0.2), RandomRotate(10), RandomShear()])
    img_, boundingbox_ = seq(img.copy(), boundingbox.copy())    

    plotted_img = draw_rect(img_, boundingbox_)
    plt.imshow(plotted_img)
    yolobox=np.zeros((boundingbox_.shape))
    plt.show()

    # 라벨을 YOLO 형식으로 바꿔주는 과정
    for i in range(0,boundingbox_.shape[0]):
        x,y,w,h=convert(size,boundingbox_[i])
        yolobox[i][0]=boundingbox_[i][4]
        yolobox[i][1]=x
        yolobox[i][2]=y
        yolobox[i][3]=w
        yolobox[i][4]=h

    new_img_ = Image.fromarray(img_)
    # augmentation한 이미지와 라벨 저장
    print(new_img_.save('../aug_images_3/'+ 'aug_3_'+ file_name + '.jpg'))
    print(np.savetxt('../aug_labels_3/' + 'aug_3_'+ file_name + '.txt',yolobox, fmt='%f',delimiter=' '))
    

Augmentation 결과

좋은 웹페이지 즐겨찾기