[Toy project] Deep Drowsiness Detection - 졸음 감지 part2

반응형

part1 에서 ultrastic yolo5 모델을 클로닝해서 학습된 모델이 잘 작동하는지 확인해봤습니다. 

이번 포스팅에서는 Real Time Detection 코드를 통해서 실시간으로 피드에 액세스하는 코드를 짜볼 것입니다.

랩탑에 탑재되어 있는 웹캠에 실시간으로 접속하여 저의 모습을 캡쳐하는 부분인데요.

 

프레임당 캡쳐를 하여 제가 깨어있는 모습과 졸고있는 모습을 각각 따로 수집을 해서 직접 라벨링을 해볼 것입니다. 

 


Real Time Detections 

# 단지 실시간으로 피드에 액세스하는 코드

cap = cv2.VideoCapture(0) # 웹캠에 액세스 하는 방법 , 자신의 기기에서 비디오 캡쳐 장치가 몇 번인지 확인.  

if not cap.isOpened():
  print("fail")

while cap.isOpened(): # 캠이 열려있는 동안 수행 
    ret, frame = cap.read() # 웹캠의 프레임이나 웹캠에서 이미지를 더한 부분 반환 
    
    # Make Detection
    results = model(frame) # 웹캠에서 얻은 프레임을 통과시킬 것이므로 cap.read를 실행할 때를 기억해야 한다. 
    
    cv2.imshow('YOLO', np.squeeze(results.render())) # 카메라 상단 팝업 바에 나타날 문장
    
    # np.squeeze(results.render()) -> 배열을 렌더링 함수에 넣기, cv2.imshow를 사용하여 이를 수행해야 하는데 
    # 나는 squeeze를 통해서 결과를 내야하므로 큰 배열에서 추출해야 합니다.
    
    if cv2.waitKey(10) & 0xff == ord('q'): # 여기서부터는 정상적으로 종료하는 것에 대한 코드. # q키를 누르고 있는지에 대한 여부 확인 
        break

cap.release() # 웹캠 해제
cv2.destroyAllWindows()

위의 코드를 작성하면 웹캠이 실행됩니다. 

위젯으로 실시간 웹캠이 작동되는 것을 확인할 수 있습니다. 

 

실시간 웹캠에 접속된 나의 모습 ㅋ

혹시 그냥 영상 파일을 업로드 해서 모델을 돌려보고 싶다면 

 

# 단지 실시간으로 피드에 액세스하는 코드

cap = cv2.VideoCapture('/Users/minyoungxi/DataScience/ai/CNN/IMG_9075.MOV') # 웹캠에 액세스 하는 방법 , 자신의 기기에서 비디오 캡쳐 장치가 몇 번인지 확인.  

while cap.isOpened(): # 캠이 열려있는 동안 수행 
    ret, frame = cap.read() # 웹캠의 프레임이나 웹캠에서 이미지를 더한 부분 반환 
    
    # Make Detection
    results = model(frame) # 웹캠에서 얻은 프레임을 통과시킬 것이므로 cap.read를 실행할 때를 기억해야 한다. 
    
    cv2.imshow('YOLO', np.squeeze(results.render())) # 카메라 상단 팝업 바에 나타날 문장
    
    # np.squeeze(results.render()) -> 배열을 렌더링 함수에 넣기, cv2.imshow를 사용하여 이를 수행해야 하는데 
    # 나는 squeeze를 통해서 결과를 내야하므로 큰 배열에서 추출해야 합니다.
    
    if cv2.waitKey(10) & 0xff == ord('q'): # 여기서부터는 정상적으로 종료하는 것에 대한 코드. # q키를 누르고 있는지에 대한 여부 확인 
        break

cap.release() # 웹캠 해제
cv2.destroyAllWindows()

cap 변수에 정의된 부분만 비디오 파일이 있는 경로로 설정해주면 바로 실행 가능합니다. 

 


이제 졸음 감지기를 훈련하는 일을 해야하므로 먼저 일부 이미지를 수집한 다음 레이블을 지정합니다. 

 

import uuid # unique identifier -> 고유 식별자 생성 , 이미지의 이름을 지정하는 데 사용될 것이므로 실제로 나 자신의 이미지를 실시간으로 수집하여 졸음 감지 수행
import os 
import time

uuid 라이브러리는 고유 식별자를 생성해주는 라이브러리입니다. 

 

cd 명령어를 통해 yolo 모델이 들어있는 디렉토리로 들어가줍니다. 

IMAGES_PATH = os.path.join('data', 'images') # data/images
labels = ['awake', 'drowsy'] 
number_imgs = 20

이미지가 들어있는 경로를 os 모듈을 활용해 data와 images의 이름을 join 해줍니다. 

그리고 label은 'awake' 와 'drowsy' 로 정합니다.

우리는 깨어있는 이미지와 졸고있는 이미지가 필요하기 때문에 레이블 이름을 저렇게 정해주도록 합니다. 

 


Real Time Detection collecting custome dataset 

실시간 웹캠을 활용하여 프레임별로 awake 와 drowsy한 이미지를 수집합니다. 

for 루프를 돌면서 깨어있는(awake) 나의 모습과 졸고있는(drowsy)모습을 저장합니다. ( 수집할 이미지는 20장입니다 )

 

cap = cv2.VideoCapture(0)

# loop through labels
for label in labels:
  print("Collecting images for {}".format(labels))
  time.sleep(5)

  # Loop through image range
  for img_num in range(number_imgs):
    print(f"Collecting images for {label}, image number {img_num}")

    # Webcam feed
    ret, frame = cap.read()

    # Naming out image path
    imgname = os.path.join(IMAGES_PATH, label+ '.' + str(uuid.uuid1())+'.jpg') # 파일 이름이 저장되는 방법
    
    # Writes out image to file
    cv2.imwrite(imgname, frame)

    # Render to the screen
    cv2.imshow('Image Collection', frame)

    # 2 second delat between captures 
    time.sleep(2)

    if cv2.waitKey(10) & 0xff == ord('q'): # 여기서부터는 정상적으로 종료하는 것에 대한 코드. # q키를 누르고 있는지에 대한 여부 확인 
        break

cap.release() # 웹캠 해제
cv2.destroyAllWindows()

이 코드를 실행하면 아래와 같이 결과가 나타납니다. 

이 루프가 돌아가는 것에 맞춰서 깨어있는 자신의 모습을 취해주시면 ( 예를 들어 눈을 뜨고 정면을 쳐다보는 모습 , 왼쪽 , 오른쪽 고개를 들고있는 모습 ) 자동으로 캡쳐가 되어 저장됩니다. ( data/images 디렉토리 ) 

 

저장된 이미지 파일이름 : awake.9b1ceefe-96fc-11ed-a4d0-ae2b5e9344e8.jpg

 

다음으로 필요한 클로닝을 해주고 이미지 레이블 파일에 효과적으로 시드하는데 필요한 라이브러리를 설치합니다.

 

!git clone https://github.com/heartexlabs/labelImg

!pip install pyqt5 lxml --upgrade

!cd labelImg && pyrcc5 -o libs/resources.py resources.qrc

 

 

GitHub - heartexlabs/labelImg: LabelImg is now part of the Label Studio community. The popular image annotation tool created by

LabelImg is now part of the Label Studio community. The popular image annotation tool created by Tzutalin is no longer actively being developed, but you can check out Label Studio, the open source ...

github.com

를 실행하여 labelImg 를 클로닝 해줍니다. 

 

labelImg를 클로닝하고 위의 링크 설명에 따라서 실행해주면 ( 터미널에서 python3 labelImg.py 실행 )

다음과 같은 화면이 나오는데요, 

여기에서 범위를 지정하고 레이블을 awake, drowsy로 설정해줍니다. 

그리고 눈을 뜬 이미지는 awake라는 레이블을 지정해주고 눈을 감거나 졸고있는 이미지는 drowsy라는 레이블로 지정하여 저장합니다. 

 

그 다음 

!cd yolov5 && python train.py --img 320 --batch 16 --epochs 500 --data dataset.yaml --weights yolov5s.pt

 

실행해주면 이미지에 대한 좌표를 제공해줍니다 ( YOLO format 으로 )


Load Custom model 

그러면 이제 커스텀한 모델과 데이터셋으로 학습을 진행해봅시다. 

 

model = torch.hub.load('ultralytics/yolov5', 
'custom', path='yolov5/runs/train/exp2/weights/last.pt', force_reload=True)

토치 허브에 이미 등록되어 있는 울트라스틱 yolo5 를 가져와서 model 을 설정합니다. 

잘 되는지 확인해볼건데요

img = os.path.join('data', 'images', 'drowsy.bea36394-96fc-11ed-a4d0-ae2b5e9344e8.jpg')
img

data/images 의 drowsy.bea36394-96fc-11ed-a4d0-ae2b5e9344e8.jpg 를 이미지로 지정합니다. 

 

results = model(img)
results.print()

%matplotlib inline

plt.imshow(np.squeeze(results.render()))
plt.show()

results 변수에 앞서 지정한 Img를 model에 적용하고 

matplotlib 를 사용하여 이미지를 띄워보면 

 

다음과 같이 졸고있는 이미지는 우리가 지정한 레이블인 drowsy로 object detection 되어 나타납니다! 

모델이 잘 적용하고 있으니 이걸 실시간 웹캠에 적용하는 코드를 실행시키면 실시간 웹캠에 바로 객체 탐지가 적용되어 나타납니다.

 

cap = cv2.VideoCapture(0)

while cap.isOpened():
    ret, frame = cap.read()
    
    results = model(frame)
    
    cv2.imshow('YOLO', np.squeeze(results.render()))
    
    if cv2.waitKey(10) & 0xFF == ord("q"):
        break
        
cap.release()
cv2.destroyAllWindows()
반응형