AI 탐구노트

카메라 영상을 이용한 침입감지 테스트 본문

DIY 테스트

카메라 영상을 이용한 침입감지 테스트

42morrow 2024. 11. 12. 15:50

1.카메라  영상 분석 

CCTV 카메라를 이용해 특정 금지구역이나 위험구역에 사람들이 들어가는 것을 신속하게 감지하고 경고를 주거나 알림 정보를 관리자에게 전달하는 솔루션이 최근 제조, 건설 현장 등에서 많이 활용되고 있습니다. 즉, 인공지능(AI) 기술이 접목된 지능형 CCTV 시스템, 혹은 영상분석(Video Surveillance)이 바로 그것인데요, 이번 글에서는 지능형 CCTV를 활용한 침입 감지를 하는 간단한 코드를 만들고 그것으로 테스트를 진행해 보겠습니다. 

 

참고로 아래 내용은 CCTV 보급과 발전과정을 시대 별로 정리해서 소개한 좋은 글입니다. 읽다가 링크를 가져와서 소개해야겠단 생각이 들어 가져와 소개합니다. 

2.테스트 및 결과 확인

2.1.환경구성

금지구역이나 위험구역에서는 무단 출입으로 인한 사고 발생 위험이 높습니다. 기존의 출입 통제 시스템은 수동적인 감시나 단순한 경고에 그쳐, 실시간 대응이 어렵고 침입을 완전히 방지하기에는 한계가 있습니다. 또한, 인력 중심의 감시는 비용이 많이 들고 효율성이 떨어질 수 있습니다.

# 가상환경 생성
$ conda create -n yolov10 python=3.11
$ conda activate yolov10

# 필요 패키지 설치
$ pip install ultralytics opencv-python

 

2.2.테스트 코드

적용한 사항은 다음과 같습니다. 

  • yolov10n 모델을 이용한 사람 감지
  • 카메라 영상 화면 상에서 감지구역을 마우스를 이용해서 그리고 저장
  • 기존 저장된 구역 정보가 있으면 불러오고 없으면 새로 작성
import cv2
import numpy as np
import time
import os
import json
from ultralytics import YOLO

# Load YOLOv10 model using ultralytics
model = YOLO('yolov10n.pt')

# Initialize webcam
# cap = cv2.VideoCapture(0)
cap = cv2.VideoCapture('test.mp4')

# To store points for polygon region
drawing = False
polygon_points = []
POLYGON_FILE = 'polygon_points.json'

# To manage detection state
warning_on = False
last_detection_time = 0
WARNING_DURATION = 3  # Duration of warning in seconds

def draw_polygon(event, x, y, flags, param):
    global drawing, polygon_points
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        polygon_points.append((x, y))
    elif event == cv2.EVENT_MOUSEMOVE and drawing:
        polygon_points[-1] = (x, y)
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        polygon_points[-1] = (x, y)

def save_polygon_points():
    with open(POLYGON_FILE, 'w') as f:
        json.dump(polygon_points, f)

def load_polygon_points():
    global polygon_points
    if os.path.exists(POLYGON_FILE):
        with open(POLYGON_FILE, 'r') as f:
            polygon_points = json.load(f)

# Load polygon points if the file exists
load_polygon_points()

# Set mouse callback
cv2.namedWindow('Webcam')
cv2.setMouseCallback('Webcam', draw_polygon)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # Draw polygon
    if len(polygon_points) > 0:
        pts = np.array(polygon_points, np.int32)
        pts = pts.reshape((-1, 1, 2))
        cv2.polylines(frame, [pts], isClosed=True, color=(0, 255, 0), thickness=2)

    # Perform YOLO detection
    results = model(frame)

    # Analyze YOLO outputs
    height, width, channels = frame.shape
    for result in results:
        for box in result.boxes:
            class_id = int(box.cls[0])
            confidence = box.conf[0]
            if confidence > 0.5 and class_id == 0:  # class_id 0 corresponds to 'person'
                # Get bounding box coordinates
                x, y, x2, y2 = map(int, box.xyxy[0])
                center_x = (x + x2) // 2
                center_y = (y + y2) // 2

                # Draw bounding box
                cv2.rectangle(frame, (x, y), (x2, y2), (255, 0, 0), 2)

                # Check if the person is inside the polygon
                if len(polygon_points) > 0 and cv2.pointPolygonTest(pts, (center_x, center_y), False) >= 0:
                    warning_on = True
                    last_detection_time = time.time()

    # Handle warning state
    if warning_on:
        if time.time() - last_detection_time < WARNING_DURATION:
            cv2.putText(frame, 'WARNING: Person Detected!', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            if int(time.time() * 10) % 2 == 0:  # Flash effect
                cv2.rectangle(frame, (0, 0), (width, height), (0, 0, 255), thickness=25)
        else:
            warning_on = False

    # Show the frame
    cv2.imshow('Webcam', frame)

    # Press 'q' to quit, 'w' to save polygon points
    key = cv2.waitKey(1)
    if key == ord('q'):
        break
    elif key == ord('w'):
        save_polygon_points()

# Release resources
cap.release()
cv2.destroyAllWindows()

 

2.3.테스트 결과 확인

 

아래 초록색 박스는 감지 영역입니다. CCTV라면 영역 지정을 이렇게 하진 않고 바닥면 기준으로 하고 사람도 bbox 전체를 가지고 평가하진 않겠지만 일단 테스트는 간단하게 해야 하므로 그대로 해 봤습니다. 그리고, 웹캠 카메라 대신 유튜브 영상을 이용했습니다. 그런데 생각보다 간단하게 잘 되네요. ^^

 

이용한 Youtube 영상은 다음과 같습니다. 

 

영상 출처 : Youtube 에 공개된 CCTV 영상

 

 

3.후기

금지구역에 들어가는 사람들의 복장 상태나 등록된 태그를 부착했는지 여부, 사람이 아닌 차량이나 물체에 대한 것 등도 원리는 크게 다르지 않을 것 같습니다. 게다가 가능한 가벼운 모델을 이용할 경우, 라즈베리파이 등의 싱글보드 컴퓨터에서도 동작하도록 만들 수 있을 것 같구요. 일상 생활에서 손쉽게 사용할 수 있는 기술로 '가성비'가 있어 보여 좋습니다.