저번 포스팅까지는 이미지 데이터로부터 사람 인식 기술을 배웠다면,
이번 포스팅부터는 동영상 데이터로부터 사람을 인식하는 기술을 공부해봅니다.
사람 인식 기술은 앞의 포스팅에서 사용한 HOG 특징량을 사용하는 모델을 사용하며,
이번 포스팅을 통해 동영상에서 자동으로 몇 명의 사람이 있는지를 인식할 수 있고, 동영상의 중요 정보만 압축한 타임랩스 영상을 만들 수 있습니다.
✔Table of Contents
Tech 87. 중요한 정보만 압축한 타임랩스 영상을 만들어보자
장시간의 정보를 담은 긴 영상을 모두 눈으로 확인하는 것은 시간이 오래 걸립니다. 이 때 '타임랩스' 기능을 사용하면 좋습니다.
타임랩스란 일정 기간의 프레임 중에서, 1프레임만 꺼내는 '빠르게 재생하기' 기법입니다. 전반적인 경향을 빠르게 판단하기에 용이하겠죠?
새로운 타임랩스 영상을 만드는 데 필요한 메서드
- cv2.VideoWriter_fourcc(*params) : 동영상 데이터 포맷을 지정한다.
- .avi 형식의 경우, 파라미터로는 'X', 'V', 'I', 'D'를 지정한다. 또는 *XVID로 써도 된다.
- cv2.VideoWriter(filename, fourcc, fps, (width, height), isColor = None) : 동영상을 만든다.
- fourcc: 위에서 지정한 동영상 데이터 포맷
- fps: 초당 프레임 수
- isColor: True가 디폴트(컬러영상)
앞서 사용한 영상 mov01.avi를 불러와 압축한 타임랩스 영상을 만들어보겠습니다. 사실 이 영상의 길이는 12초로 원래 길이도 좀 짧은 편입니다. 전체 프레임은 401개가 있죠.
여기서 프레임 번호가 10의 배수인 경우만 저장하여 총 41개의 프레임으로만 구성된 짧은 타임랩스 영상을 만들어보겠습니다. 그럼 12초였던 영상 길이가 약 1초로 바뀌게 됩니다.
여기서 쓴 모델은 HOG 특징량을 사용하는 SVMDetector 모델입니다. 이 모델로 동영상 내의 사람을 인식합니다.
import cv2
print('타임랩스 생성 시작')
#동영상 읽어오기(앞에서 쓴 코드와 동일)
cap = cv2.VideoCapture('mov/mov01.avi')
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
#hog 모델 - 사람 인식(앞에서 쓴 코드와 동일)
hog = cv2.HOGDescriptor() #객체
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) #모델지정
hogParams = {'winStride': (8,8), 'padding': (32,32), 'scale': 1.05, 'hitThreshold': 0, 'finalThreshold': 5} #파라미터 설정
#타임랩스 작성
movie_name = 'timelapse2.avi'
fourcc = cv2.VideoWriter_fourcc(*'XVID') #'X', 'V', 'I', 'D'로 써도 됨
video = cv2.VideoWriter(movie_name, fourcc, 30, (width, height))
num = 0
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
#10으로 나누어 떨어지는 경우만(41개 프레임만)
if (num%10 == 0):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
human, r = hog.detectMultiScale(gray, **hogParams)
if (len(human) > 0):
for (x, y, w, h) in human:
cv2.rectangle(frame, (x,y), (x+w, y+h), (255,255,255), 3)
video.write(frame)
else: break
num += 1
#타임랩스 종료 및 발행
video.release()
cap.release()
cv2.destroyAllWindows()
print('타임랩스 생성 완료')
코드는 앞선 포스팅에서 한 것과 비슷하니 어렵지 않습니다.
이렇게 해서 만들어진 타임랩스 영상 'timelapse2.avi'를 불러옵니다.
지난 포스팅에서 봤던 원본 영상 mov01.avi는 12초였는 데 반해, 이렇게 만들어진 타임랩스 영상은 1초로 아주 짧아졌습니다!
이미지 인식 모델이 사람이라고 인식한 것에 흰색 네모박스가 씌워졌습니다. 사람이 아닌데 인식된 것도 있고 오차가 좀 있습니다.
그럼 이제부턴 모델이 잘 인식을 했는지, 동영상 내 프레임마다 인식된 사람의 수를 세어 그래프로 그려봅시다.
Tech 88 - 89. 동영상 내 사람의 수를 시계열 그래프로 나타내자.
영상이 흐름에 따라 사람으로 인식하는 숫자가 어떻게 바뀌는지 시계열 그래프를 만들어봅시다.
x축은 time(시간), y축은 사람 수로 보면 되겠죠?
코드는 앞에서 쓴 걸 그대로 가져오되, 불필요한 부분은 주석 처리했습니다.
그리고 프레임마다 인식된 사람 수의 합을 계산해 'list_df' 라는 데이터프레임에 넣어줍니다.
#위에서 한거랑 timelapse 부분 코드만 바꿈 (시간 오래 걸리니 주의)
import cv2
import pandas as pd
print('분석 시작')
#동영상 읽어오기
cap = cv2.VideoCapture('mov/mov01.avi')
fps = cap.get(cv2.CAP_PROP_FPS)
#hog 객체
hog = cv2.HOGDescriptor() #객체
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) #모델지정
hogParams = {'winStride': (8,8), 'padding': (32,32), 'scale': 1.05, 'hitThreshold': 0, 'finalThreshold': 5} #파라미터 설정
#그래프 작성
num = 0
list_df = pd.DataFrame(columns = ['time', 'people'])
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
#10으로 나누어 떨어지는 경우만(41개 프레임만)
if (num%10 == 0):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
human, r = hog.detectMultiScale(gray, **hogParams)
#그 뒤에 이어지는 사각형 표시는 여기선 필요없으므로 주석처리
# if (len(human) > 0):
# for (x, y, w, h) in human:
# cv2.rectangle(frame, (x,y), (x+w, y+h), (255,255,255), 3)
#새로 들어간 부분: 사람 수 인식하여 list_df에 추가
tmp = pd.Series([num/fps, len(human)], index = list_df.columns)
list_df = list_df.append(tmp, ignore_index = True)
#display(list_df)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else: break
num += 1
#종료
cap.release()
cv2.destroyAllWindows()
print('분석 종료')
어차피 'human' 이라는 객체가 사람의 위치정보가 들어 있으므로, 간단하게 len 을 사용하여 사람 수를 셀 수 있습니다.
그리고 전체 프레임이 아니라 41개 프레임만 뽑았었죠?
그러니 한 프레임이 원본 영상에서 몇초에 위치해있느냐는 num을 fps로 나눈 값으로 계산합니다.
이렇게 하여 list_df가 완성되었습니다. 이제 이걸 그대로 그래프로 그려봅니다.
#이제 list_df로 그래프 그려보자.
import matplotlib.pyplot as plt
plt.plot(list_df['time'], list_df['people'])
plt.xlabel('time(sec.)')
plt.ylabel('population')
plt.title('mov01 graph')
plt.ylim(0, 15)
plt.show()
이렇게 해서 mov01.avi 영상의 시계열 그래프가 완성되었습니다.
같은 방식으로 mov02.avi 영상에 대해서도 만들어봅시다. 코드는 똑같습니다.
######### 위에서 한거랑 동일 ############
import cv2
import pandas as pd
print('분석 시작')
#동영상 읽어오기
cap = cv2.VideoCapture('mov/mov02.avi') # ------> 얘만 바꿈
fps = cap.get(cv2.CAP_PROP_FPS)
#hog 객체
hog = cv2.HOGDescriptor() #객체
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) #모델지정
hogParams = {'winStride': (8,8), 'padding': (32,32), 'scale': 1.05, 'hitThreshold': 0, 'finalThreshold': 5} #파라미터 설정
#그래프 작성
num = 0
list_df2 = pd.DataFrame(columns = ['time', 'people'])
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
if (num%10 == 0):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
human, r = hog.detectMultiScale(gray, **hogParams)
# if (len(human) > 0):
# for (x, y, w, h) in human:
# cv2.rectangle(frame, (x,y), (x+w, y+h), (255,255,255), 3)
tmp = pd.Series([num/fps, len(human)], index = list_df2.columns)
list_df2 = list_df2.append(tmp, ignore_index = True)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else: break
num += 1
#종료
cap.release()
cv2.destroyAllWindows()
print('분석 종료')
이제 list_df2로 그래프를 그려보면
#이제 list_df2로 그래프 그려보자.
import matplotlib.pyplot as plt
plt.plot(list_df2['time'], list_df2['people'])
plt.xlabel('time(sec.)')
plt.ylabel('population')
plt.title('mov02 graph')
plt.ylim(0, 15)
plt.show()
이렇게 결과가 나옵니다. 두 그래프를 한 자리에 모아두고 비교를 해봅시다.
결과를 보면 mov01보다 mov02의 경우 사람 수가 조금 더 늘어난 것으로 보입니다.
실제로 두 영상 모두 같은 장소에서 촬영되었지만, 후자가 카메라 근처에 사람이 몰려있어서 이런 결과가 나오는 것이 타당한 결과입니다.
하지만 이 그래프는 HOG가 인식한 사람의 숫자입니다.
앞에서 HOG가 인식한 사람을 박스처리한 걸 봤을 때, 사람이 몰려있는 경우 표시가 잘 안되고, 열차를 사람으로 인식한 경우도 있었죠.
이렇게 HOG는 노이즈가 많고 오검출이 많습니다.
그래서 mov02 영상이 더 사람이 많지만, 그래프로만 보면 노이즈 때문에 mov01에 비해 값이 엄청 커 보이진 않습니다.
포스팅이 길어진 관계로, 다음 포스팅에선 이런 노이즈를 제거하여 더 정확한 사람 수를 세어 보도록 하겠습니다. :)
'Data Science > Analysis Study' 카테고리의 다른 글
파이썬 자연어 처리(NLP) - 텍스트 데이터 전처리 / 파이썬 데이터 분석 실무 테크닉 100 (0) | 2022.05.16 |
---|---|
Python OpenCV (5) - HOG 노이즈 제거하기 (이동평균 이용) (0) | 2022.05.14 |
Python OpenCV (3) - 이미지에서 사람 얼굴 & 방향 인식하기 (python dlib, 안면 인식 기술) (1) | 2022.05.13 |
Python OpenCV (2) - 이미지에서 사람 얼굴 인식하기 (0) | 2022.05.12 |
Python OpenCV (1) - 이미지, 동영상 데이터를 불러오고 저장하기 (0) | 2022.05.11 |