1. 이상행동 탐지 데이터 활용
◼ import
import os
import random
import shutil
import cv2
import glob
import xml.etree.ElementTree as ET
import csv
from tqdm import tqdm
|
◼ 경로설정
data_root = '/content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/8. Abnormal'
file_root = f'{data_root}/data'
|
◼ 동영상 데이터 세개만 넣어논 상태
file_list = os.listdir(f'{file_root}/images_id')
len(file_list)
|
3 ----------------------------------------------------------------------------------------------------------------------------------------------------- |
◼ 각 비디오 파일의 프레임을 이미지 파일로 저장하기
# mp4에서 이미지 추출하기
# 각 mp4이름으로 디렉토리 생성 후 저장
for file in tqdm(file_list):
name = file.split('.')[0]
if not os.path.isdir(f"{file_root}/images/{name}"):
os.mkdir(f"{file_root}/images/{name}")
video_path = f"{file_root}/images_id/{file}"
cap = cv2.VideoCapture(video_path)
num = 1
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
cv2.imwrite(f"{file_root}/images/{name}/{name}_{num:06d}.png", frame)
num += 1
else:
break
cap.release()
|
|
◼ 확인
# 프레임이 있는 파일 리스트만 추출
file_list = os.listdir(f'{file_root}/images_id')
real_file_list = []
for file in file_list:
temp = os.listdir(f"{file_root}/images/{file.split('.')[-2]}")
if len(temp) > 0:
real_file_list.append(file)
len(real_file_list)
|
3 |
◼ 파일 리스트를 학습, 검증, 테스트 세트로 나누기
random.seed(2024)
random.shuffle(real_file_list)
test_ratio = 0.1
num_file = len(real_file_list)
test_list = real_file_list[:int(num_file*test_ratio)]
valid_list = real_file_list[int(num_file*test_ratio):int(num_file*test_ratio)*2]
train_list = real_file_list[int(num_file*test_ratio)*2:]
|
◼ XML 파일에서 theft_start와 theft_end / 이벤트의 시작과 종료 프레임을 읽어오기
def read_one_xml(xml_path):
tree = ET.parse(xml_path)
root = tree.getroot()
event_dict = {
'event': None,
'start_frame': -1,
'end_frame': -1
}
for child in root.iter('track'):
if child.attrib['label'] == 'theft_start':
event_dict['event'] = child.attrib['label'].split('_')[0]
frame = child.find('box').attrib['frame']
event_dict['start_frame'] = int(frame)
elif child.attrib['label'] == 'theft_end':
event_dict['event'] = child.attrib['label'].split('_')[0]
try:
frame = child.find('box').attrib['frame']
except:
return {}, {}
event_dict['end_frame'] = int(frame)
return event_dict
|
◼ XML 파일에서 행동 정보를 추출하기
# XML 파일에서 행동 정보 추출하기
# {'event':'theft'}
file = real_file_list[0]
xml_path = f"{file_root}/labels_id/{file.replace('mp4', 'xml')}"
event_dict = read_one_xml(xml_path)
event_dict
|
{'event': 'theft', 'start_frame': 129, 'end_frame': 156} |
◼ 이벤트의 시작 프레임을 기준으로 이미지 파일의 경로와 해당 프레임에 대한 라벨을 재구성
# 라벨링 정보를 재구성
# 예) frame1, frame2, frame3, Label(정상:0 or 이상:1)
# [a1.png, a2.png, a3.png, 0]
# [a4.png, a5.png, a6.png, 0]
# ...
# [a75.png, a76.png, a77.png, 1]
name = file.split('.')[0]
frame_list = []
if event_dict is not None:
current_frame = 0
while(current_frame < event_dict['start_frame']+4):
tmp = []
if (current_frame+3) >= event_dict['start_frame']:
event_num = '1'
else:
event_num = '0'
tmp.append([
f'images/{name}/{name}_{(current_frame+1):06d}.png',
f'images/{name}/{name}_{(current_frame+2):06d}.png',
f'images/{name}/{name}_{(current_frame+3):06d}.png',
event_num
])
current_frame += 3
frame_list.append(tmp)
tmp = []
tmp.append([
f'images/{name}/{name}_{(current_frame+1):06d}.png',
f'images/{name}/{name}_{(current_frame+2):06d}.png',
f'images/{name}/{name}_{(current_frame+3):06d}.png',
event_num
])
frame_list.append(tmp)
|
|
- 주석
더보기
name = file.split('.')[0] # 비디오 파일 이름에서 확장자를 제거하여 이름만 추출
frame_list = [] # 프레임 및 라벨 정보를 저장할 빈 리스트 초기화
if event_dict is not None: # event_dict가 None이 아닌 경우에만 처리
current_frame = 0 # 현재 프레임을 0으로 초기화
# 현재 프레임이 이벤트 시작 프레임 + 4보다 작은 동안 반복
while current_frame < event_dict['start_frame'] + 4:
tmp = [] # 임시 리스트 초기화
# 현재 프레임이 이벤트 시작 프레임에 도달했거나 지나쳤다면 라벨을 '1'로 설정
if (current_frame + 3) >= event_dict['start_frame']:
event_num = '1'
else:
event_num = '0'
# 현재 프레임부터 3개의 이미지 파일 경로와 라벨을 tmp 리스트에 추가
tmp.append([
f'images/{name}/{name}_{(current_frame + 1):06d}.png', # 현재 프레임 이미지 경로
f'images/{name}/{name}_{(current_frame + 2):06d}.png', # 다음 프레임 이미지 경로
f'images/{name}/{name}_{(current_frame + 3):06d}.png', # 그 다음 프레임 이미지 경로
event_num # 해당 프레임 그룹의 라벨
])
# 현재 프레임을 3만큼 증가시켜 다음 프레임 그룹으로 이동
current_frame += 3
# tmp 리스트를 frame_list에 추가
frame_list.append(tmp)
# 마지막 그룹의 프레임 추가 (현재 프레임이 종료 프레임을 넘기지 않은 경우)
tmp = [] # 마지막 그룹을 위한 임시 리스트 초기화
tmp.append([
f'images/{name}/{name}_{(current_frame + 1):06d}.png', # 마지막 그룹의 현재 프레임 이미지 경로
f'images/{name}/{name}_{(current_frame + 2):06d}.png', # 마지막 그룹의 다음 프레임 이미지 경로
f'images/{name}/{name}_{(current_frame + 3):06d}.png', # 마지막 그룹의 그 다음 프레임 이미지 경로
event_num # 마지막 그룹의 라벨
])
frame_list.append(tmp) # 마지막 그룹을 frame_list에 추가
|
◼ frame_list의 길이와 첫 번째 항목의 첫 번째 요소를 출력
# frame_list[0]
# ['images/폴더명/파일명1.png','images/폴더명/파일명2.png, 'images/폴더명/파일명.png']
print(len(frame_list))
print(frame_list[0][0])
|
45 |
◼ frame_list의 데이터를 CSV 파일로 저장하기
name_list = f'{file_root}/ex.csv' f = open(name_list, 'w', newline='')
writer = csv.writer(f)
for i in frame_list:
writer.writerow(i[0])
f.close()
|
|
@. 과제
모델쓰기 : https://arxiv.org/pdf/1506.04214
참고: https://homepage.divms.uiowa.edu/~zhuoning/papers/p984-yuan.pdf
@. 다음 수업 데이터
'AI > 컴퓨터 비전' 카테고리의 다른 글
19. Mediapipe 활용(1) | 손 랜드마크 감지 (0) | 2025.01.03 |
---|---|
18. YOLO v8을 이용한 차량 파손 검사 (0) | 2024.08.13 |
16. YOLO v8를 활용한 안전모 탐지 (0) | 2024.08.08 |
15. YOLO v8을 이용한 폐질환 분류 (0) | 2024.08.07 |
14. YOLO | 객체탐지 (0) | 2024.08.06 |