2021년 5월 13일부터 도로교통법 개정으로 인해 전동 킥보드를 이용할 때 안전모를 착용하지 않으면 범칙금 2만원을 내야합니다. 하지만 여전히 안전모를 착용하지 않고 전동 킥보드를 이용하지 않는 많은 사람들이 존재하며, 경찰분들이 일일이 모두 단속할 수는 없기 때문에 실시간 킥보드 단속 시스템을 구상하게 되었습니다.
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은 Make Sense를 이용하여 하였습니다. 라벨은 헬멧을 쓴 사람과 헬멧을 쓰지 않은 사람으로 2가지로 하였고 킥보드까지 전체 모습으로 하여야 전체 모습을 인식할 수 있기 때문에 전체 모습을 라벨링하였습니다.
다음 주소의 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=' '))