SimpleCV 로 움직임 감지하기

2014-11-08

tutorial python simplecv develop development raspberry-pi linux computer-vision motion

SimpleCV를 이용하면 어렴지 않게 카메라를 통해 움직임을 감지해 낼 수 있습니다. 복잡한 것은 SimpleCV가 거의 다 해주니 우리는 제공되는 API를 잘 활용하면, 금방 만들어 낼 수 있습니다. 이 글은 여러분들이 이미 SimpleCV를 설치 하셨다는 가정 하에 쓴 글 입니다. 아직 설치 하지 않으셨다면. 먼저 설치를 먼저 하신 다음, 이 글을 보시는 것이 좋습니다.

움직임을 감지하는 과정

먼저 움직임을 감지하는 과정을 생각 해 봅시다. 움직임을 감지하려면, 사진 두 장을 얻어 차이를 봐야 합니다. 같은 장소, 같은 카메라에서, 비슷한 시간에 초 또는 분 간격으로 시간차이를 두고 찍혔는대. 두 사진 사이 차이가 있다면, 사진에 찍힌 것들이 움직여서 차이가 있는 것 이겠죠? 그렇다면 아래와 같이 감지 방법을 생각해 볼 수 있습니다.

  1. 임계값을 정한다, 두 사진 사이 다른 정도를 비교해서, 움직임 감지 기준으로 사용할 값이다.
  2. 카메라에서 사진 하나 얻어서 기준 이미지로 정한다.
  3. 사진 하나를 더 얻는다.
  4. 기준 이미지와 추가로 얻은 이미지를 비교한다.
  5. 비교했을 때, 다른 정도가 정해진 것 보다 크다면, 움직임을 감지한 것으로 인식한다
  • 추가로 얻은 이미지를 새로운 기준 이미지로 정한다
  • “2.” 부터 다시 반복한다
  1. 비교했을 때, 다른 정도가 정해진 것 보다 작다면, “2.” 부터 다시 반복한다

코드로 작성해 보기

위 과정들을 한번 코드로 옮겨 봅시다.

먼저 필요한 모듈들을 임포트(import) 합시다. 여기서는 SimpleCV의 모듈들을 모두 임포트 합니다. 한글 입력이 필요한 경우 인코딩도 지정합시다.

#-*- coding: utf-8 -*-
from SimpleCV import *

그 다음, 움직임 감지 여부 기준으로 쓸, 임계값을 정합시다.

#임계값
threshold = 1.0

카메라를 초기화 하고, 이미지 하나를 얻어, 기준 이미지로 정합시다. 기준 이미지 이름은 “refImg” 로 정해봅시다.

#카메라 초기화
cam = Camera()

#카메라에서 이미지 얻어 기준 이미지로 정하기
print "기준 이미지 얻는중"
refImg = cam.getImage()

아래는 기준 이미지 예시 입니다. (출처 : http://tutorial.simplecv.org/en/latest/examples/image-math.html#image-arithmetic)

기준 이미지와 비교할 이미지를 하나 더 얻습니다. 추가로 얻은 이미지를 “img” 라고 정합시다. 그리고 기준 이미지와의 차이를 얻어 봅시다. 단순히 5와 2의 차이를 “5 - 2"로 계산하듯, “기준이미지 - 새 이미지” 로 차이를 얻으면 됩니다. 그럼 여기선, “refImg - img” 로 하면 되죠. 두 이미지 사이에서 얻은 차이는 diff 로 정합시다.

#새 이미지 얻기
img = cam.getImage()
#두 이미지 사이 차이 얻기
diff = refImg - img

아래는 추가로 얻은 이미지 예시 입니다. (출처 : http://tutorial.simplecv.org/en/latest/examples/image-math.html#image-arithmetic)

기준 이미지에서, 추가로 얻은 이미지 사이 차이를 나타낸 이미지 예시 입니다. (출처 : http://tutorial.simplecv.org/en/latest/examples/image-math.html#image-arithmetic)

diff 이미지에는 차이가 있는 부분만 나타나는대, 그것을 수치상으로 표현해서. 처음에 정한 임계값과 비교해 봅시다. 임계값 보다 크면, 기준 이미지를 갱신하고, 그렇치 않으면 기준 이미지를 그대로 유지해 봅시다.

#getNumpy()는 이미지를 다차원 배열로 나타냄
#getNumpy().mean() 은 getNumpy()로 얻은 다차원 배열을 실수로 나타냄
if imgmath.getNumpy().mean() > threshold:
  #차이가 임계값 보다 크면
  print "움직임 감지됨"
  #기준 이미지 갱신
  refImg = img
  print "기준 이미지 갱신"
  print "갱신시각" + time.strftime("%H:%M:%S")
else:
  #그렇치 않다면
  print "기준 이미지와 큰 차이 없음 기준 이미지 유지"

대략적인 코드가 다 짜여 졌군요. 위 코드를 다 이으면 완전한 코드가 완성 되지만. 이미지를 지속적으로 얻어서 비교하지 못하는 코드가 됩니다. 한번만 비교하고 끝나기 때문입나다. 추가로 이미지를 얻는 부분부터 끝까지, 무한 반목을 감싸서 프로그램이 종료 될때까지 계속 움직임을 인식하도록 해 봅시다. 그리고 화면에 카메라에서 얻은 이미지도 계속 표시해 봅시다.

#무한 반복
while True:
    #새 이미지 얻기
    img = cam.getImage()
    # show()는 이미지를 화면상에 보여줍니다.
    img.show()

    #기준 이미지와 새 이미지 사이 차이 얻기
    imgmath = refImg - img
    #getNumpy()는 이미지를 다차원 배열로 나타냄
    #getNumpy().mean() 은 getNumpy()로 얻은 다차원 배열을 실수로 나타냄
    if imgmath.getNumpy().mean() > threshold:
        #차이가 임계값 보다 크면
        print "움직임 감지됨"
        #기준 이미지 갱신
        refImg = img
        print "기준 이미지 갱신"
        print "갱신시각" + time.strftime("%H:%M:%S")
    else:
        #그렇치 않다면
        print "기준 이미지와 큰 차이 없음 기준 이미지 유지"

이제 다 되었습니다. 완성된 코드는 아래와 같습니다. 저장 하신 후 한번 실행 해 보세요.

#-*- coding: utf-8 -*-
from SimpleCV import *

#임계값
threshold = 1.0

#카메라 초기화
cam = Camera()

#카메라에서 이미지 얻어 기준 이미지로 정하기
print "기준 이미지 얻는중"
refImg = cam.getImage()

while True:
    #새 이미지 얻기
    img = cam.getImage()
    # show()는 이미지를 화면상에 보여줍니다.
    img.show()

    #기준 이미지와 새 이미지 사이 차이 얻기
    imgmath = refImg - img
    #getNumpy()는 이미지를 다차원 배열로 나타냄
    #getNumpy().mean() 은 getNumpy()로 얻은 다차원 배열을 실수로 나타냄
    if imgmath.getNumpy().mean() > threshold:
        #차이가 임계값 보다 크면
        print "움직임 감지됨"
        #기준 이미지 갱신
        refImg = img
        print "기준 이미지 갱신"
        print "갱신시각" + time.strftime("%H:%M:%S")
    else:
        #그렇치 않다면
        print "기준 이미지와 큰 차이 없음 기준 이미지 유지"

광고 차단 소프트웨어를 사용하고 계신 것 같습니다. 혹시 글이 마음에 들었다면, 광고 차단을 해제해 주시거나 후원을 해 주시는 것은 어떤가요?

It seems like you're using ad block software, If you like the post, Would you like to disable that or donate me a bit?

SimpleCV 설치하고 테스트 해 보기.

2014-11-02

SimpleCV 는 파이썬 언어를 이용하여 컴퓨터 비전 앱을 쉽게 작성 할 수 있도록 도와주는 오픈소스 프레임워크 입니다. 이 프레임워크를 활용하면 고유값,다양하고 복잡한 얼굴인식 알고리즘, 행렬 대 비트맵 스토리지, 비트 깊이 등등의 복잡하고 어려운 것들을 사전에 공부하실 필요 없이 쉽게 컴퓨터 비전 앱을 작성 하실 수 있습니다. 이 글에서는 우분투 같은 데비안 계열 베포판에서 어떻게 SimpleCV를 설치하고 테스트 해 볼 수 있는지 이야기 해 보고자 합니다.

Raspberry Pi 원격접속 설정하기

2014-09-20

최근 동아리 프로젝트에 사용 겸 나중에 개인적으로 가지고 놀 용도로 Raspberry Pi Model B+ 를 구입했습니다. 그리고 남는 마이크로 SD 카드에 Raspbian 을 설치 했습니다. 그동안 hdmi 케이블이 없다보니 집에서 테스트 해보지 못했는대, 이번에 동아리 지원금을 이용해 하나 구했습니다. 구한 김에 원격 접속 설정을 했습니다. 언제까지 케이블이랑 키보드, 마우스 다 들고 다니면서 연결 할 순 없으니까요.

우분투 계열 리눅스 베포판에서 안드로이드 개발환경 구축하기.

2014-09-06

친구가 안드로이드 앱 개발을 시작해서, 글로 정리해 줄 겸 다른 분들도 보시라고 블로그에 올려봅니다. 우분투 리눅스 계열 배포판에서 안드로이드 개발환경을 구축하는 법을 말해보고자 합니다. 이 게시물은 여러분들께서 우분투 계열 리눅스를 사용하시고 계신다고 가정하고 작성하였습니다. 도움이 되셨스면 좋겠습니다^^ JDK 설치하기 먼저 안드로이드를 개발하려면, 안드로이드 앱을 Java로 작상하기에, JDK(Java Development Kit) 을 먼저 설치해야 합니다.