Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬으로 만드는 웹캠 움직임 감지 프로그램

이 글에서는 웹캠으로 입력되는 영상을 실시간으로 분석해 움직임(모션)을 자동으로 감지하고, 움직임이 시작된 시각과 끝난 시각을 CSV 파일에 기록하는 파이썬 프로그램을 만들어 보겠습니다.

필요한 라이브러리

움직임 감지에는 OpenCV, 시간 데이터 저장에는 pandas 라이브러리를 사용합니다. 아직 설치하지 않았다면 pip 명령어로 간단히 설치할 수 있습니다.

$ pip install opencv-python pandas

동작 원리

프로그램은 다음과 같은 순서로 움직임을 판별합니다.

  1. 카메라에서 읽어 들인 첫 번째 프레임을 '기준 이미지'로 저장합니다.
  2. 이후 프레임들은 그레이스케일로 변환한 뒤 가우시안 블러(Gaussian Blur)로 노이즈를 제거합니다.
  3. 기준 이미지와 현재 프레임의 픽셀 차이(absdiff)를 계산합니다.
  4. 차이가 임계값(25)보다 큰 영역만 흰색으로 표시하는 이진화 처리를 수행합니다.
  5. 윤곽선(contour)을 검출해 면적이 충분히 크면 '움직임 있음'으로 판단하고 초록색 사각형을 그립니다.

전체 예제 코드

# 필요한 라이브러리 임포트
import cv2
import pandas as pd
from datetime import datetime

# 변수 초기화
stillImage = None
motionImage = [None, None]
time = []

# 시작/종료 시간을 담을 DataFrame 초기화
df = pd.DataFrame(columns=["start", "end"])

# 비디오 캡처 시작
video = cv2.VideoCapture(0)

while True:
    # 카메라에서 프레임 읽기
    check, frame = video.read()
    motion = 0

    # 컬러 이미지를 그레이스케일로 변환 후 블러 처리
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    gray = cv2.GaussianBlur(gray, (21, 21), 0)

    if stillImage is None:
        stillImage = gray
        continue

    # 기준 이미지와 현재 프레임의 차이 계산
    diff_frame = cv2.absdiff(stillImage, gray)

    # 정적 배경과 현재 프레임의 차이가 25보다 크면 흰색으로 표시
    thresh_frame = cv2.threshold(diff_frame, 25, 255, cv2.THRESH_BINARY)[1]
    thresh_frame = cv2.dilate(thresh_frame, None, iterations=2)

    # 움직이는 객체의 윤곽선 검출
    contours, hierarchy = cv2.findContours(thresh_frame.copy(),
                                           cv2.RETR_EXTERNAL,
                                           cv2.CHAIN_APPROX_SIMPLE)
    for contour in contours:
        if cv2.contourArea(contour) < 10000:
            continue
        motion = 1
        (x, y, w, h) = cv2.boundingRect(contour)
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)

    # 현재 모션 상태 기록
    motionImage.append(motion)
    motionImage = motionImage[-2:]

    # 모션 시작 시간 기록
    if motionImage[-1] == 1 and motionImage[-2] == 0:
        time.append(datetime.now())

    # 모션 종료 시간 기록
    if motionImage[-1] == 0 and motionImage[-2] == 1:
        time.append(datetime.now())

    # 그레이스케일 프레임 출력
    cv2.imshow("Gray_Frame", gray)

    # 흑백 프레임 출력 (픽셀 차이가 25보다 크면 흰색으로 표시)
    cv2.imshow("Threshold Frame", thresh_frame)

    # 컬러 프레임 출력
    cv2.imshow("Colored_Frame", frame)

    key = cv2.waitKey(1)
    # q 키를 누르면 프로세스 종료
    if key == ord('q'):
        if motion == 1:
            time.append(datetime.now())
        break

# 모션 시간을 DataFrame에 추가
for i in range(0, len(time), 2):
    df.loc[len(df)] = {"start": time[i], "end": time[i + 1]}

# 움직임 시간이 저장될 CSV 파일 생성
df.to_csv("FrameInMotion_time.csv")

video.release()

# 창 닫기
cv2.destroyAllWindows()

실행 결과

파이썬으로 만드는 웹캠 움직임 감지 프로그램

프로그램을 실행하면 세 개의 창이 열리고, 각각 그레이스케일·흑백(임계값)·컬러 모드로 웹캠 화면과 감지된 움직임을 보여 줍니다. 움직임이 있는 영역에는 초록색 사각형이 표시됩니다.

동시에 움직임이 감지된 시작 시각과 종료 시각이 CSV 파일에 기록됩니다. 생성된 CSV 파일의 내용은 아래와 같은 형태입니다.

FrameInMotion_time.csv (출력 예시)

   start                       end
0  2019-02-21 18:08:35.791487  2019-02-21 18:10:59.718005

프로그램을 종료하려면 아무 창이나 활성화한 상태에서 q 키를 누르면 됩니다. 종료 시점에 모션이 진행 중이었다면 그 시각도 자동으로 함께 기록됩니다.