2016-11-09 2 views
7

내 목표는 IP 카메라 스트림의 특정 영역에서 움직임을 감지하는 것입니다. 필자는 작업 코드를 작성했지만 개인적인 이해를 기반으로합니다.OpenCV가 파이썬에서 움직임을 감지합니다.

이 코드는 작동
import cv2 
import numpy as np 
import os 
import time 
import datetime 
import urllib 
import pynotify 

stream=urllib.urlopen('http://user:[email protected]/video.mjpg') 
bytes='' 
fgbg = cv2.createBackgroundSubtractorMOG2() 

while True: 
    bytes+=stream.read(16384) 
    a = bytes.find('\xff\xd8') 
    b = bytes.find('\xff\xd9') 
    if a!=-1 and b!=-1: 
     jpg = bytes[a:b+2] 
     bytes= bytes[b+2:] 
     img = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.IMREAD_COLOR) 
     rows,cols,c = img.shape 
     mask = np.zeros(img.shape, dtype=np.uint8) 
     roi_corners = np.array([[(940,220),(1080,240), (1080,310), (940,290)]], dtype=np.int32) 
     channel_count = img.shape[2] 
     ignore_mask_color = (255,)*channel_count 
     cv2.fillPoly(mask, roi_corners, ignore_mask_color) 
     masked_image = cv2.bitwise_and(img, mask) 

     fgmask = fgbg.apply(masked_image) 
     iii = fgmask[220:310,940:1080] 

     hist,bins = np.histogram(iii.ravel(),256,[0,256]) 

     black, white, cnt1, cnt2 = 0,0,0,0 


     for i in range(0,127): 
      black += hist[i] 
      cnt1+=1 
     bl = float(black/cnt1) 

     for i in range(128,256): 
      white += hist[i] 
      cnt2+=1 
     wh = float(white/cnt2) 

     finalResult = ((bl+1)/(wh+1))/10 

    if finalResult < 1.0: 
     pynotify.init("cv2alert") 
      notice = pynotify.Notification('Alert', 'Alert text') 
      try: 
       notice.show() 
      except gio.Error: 
       print "Error" 

,하지만 이해가되지 않는 한 잘, 나는 오른쪽에 흰색이며, 직접 값을 얻을 수 있었다,하지만 히스토그램의 왼쪽과 같은 몇 가지 "해킹"으로 검은 색 않았다 히스토그램 및 black/white 내가 원하는 결과를 제공합니다. 나는 이것이 옳지 않다는 것을 알고 있지만 ROI가 없으면 4-9의 결과를, 누군가이 ROI를 입력하면 0.5-2.0의 결과를 얻습니다.

내 질문은 여기입니다 : 히스토그램을 읽고 데이터를 비교하는 다른 방법이 있습니까? 문서를 읽는 것이 도움이되지 않습니다.

+0

관심있는 지역은 미리 정의와 안정? 올바르게 이해하면 그레이 스케일 그림/비디오로 작업하면서 "픽셀 값의 급격한 변화"와 같은 모션을 감지하고 싶습니까? –

+0

예,이 지역은 사전 정의되었습니다. 히스토그램에서 값을 추출하려고했는데, 두 가지 색 (흑백) 만 있었기 때문에 행운이 없었기 때문입니다. 따라서 히스토그램의 전반부는 검은 색으로, 두 번째는 흰색으로 진행합니다. 내 질문은 이것을 달성하는 또 다른 방법이 존재 하는가? 내 주요 목표는 단순히 특정 지역의 움직임을 가능한 간단하게 감지하고 사용자에게 알리는 것입니다. – Aleksandar

+0

나는 거의 무수한 다른 방법이 있다고 생각한다. 예를 들어 마지막 x 프레임의 점수를 유지하고 차이 그림을 계산하는 데 사용하는 "평균"그림을 계산할 수 있습니다. n * m 패치와 같은 영역의 차이가 임계 값보다 높으면 이동이라고 부르거나보고 할 수 있습니다. ROI를 명시 적으로 정의 할 필요없이 이동 영역을 식별하는데도 사용할 수 있습니다. –

답변

1

차동 이미지 그래서 차이 이미지는 두 이미지의 차이가 보여 두 이미지

의 뺄셈의 결과이다. 그 이미지로 당신은 움직임을 볼 수 있습니다.

다음 스크립트에서는 3 개의 연속 이미지에서 계산 된 차동 이미지를 사용합니다. 이 장점은 관심없는 배경이 결과에서 제거된다는 것입니다.

OpenCV는 absdiff()를 사용하여 두 이미지를 뺄 수있는 가능성을 제공합니다. 또한 두 이미지에 대한 논리 연산은 이미 으로 구현되었습니다. Bitwise_and() 메서드를 사용하여 최종 차분 이미지를 얻습니다. 파이썬에서 그것은 다음과 같습니다 : 우리는 우리의 기존 스크립트에 차동 이미지 기능을 가져오고있다해야 할

def diffImg(t0, t1, t2): 
    d1 = cv2.absdiff(t2, t1) 
    d2 = cv2.absdiff(t1, t0) 
    return cv2.bitwise_and(d1, d2) 

마지막 것은. 루프가 시작되기 전에 처음 3 개의 이미지 t_minus, t 및 t_plus를 읽고 색상 정보가 필요하지 않으므로 그레이 스케일 이미지로 변환합니다. 이러한 이미지를 사용하면 차동 이미지 계산을 시작할 수 있습니다. 차분 이미지를 보여준 후에는 가장 오래된 이미지를 제거하고 다음 이미지를 읽어야합니다. 마지막 스크립트는 다음과 같습니다

import cv2 

def diffImg(t0, t1, t2): 
    d1 = cv2.absdiff(t2, t1) 
    d2 = cv2.absdiff(t1, t0) 
    return cv2.bitwise_and(d1, d2) 

cam = cv2.VideoCapture(0) 

winName = "Movement Indicator" 
cv2.namedWindow(winName, cv2.CV_WINDOW_AUTOSIZE) 

# Read three images first: 
t_minus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY) 
t = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY) 
t_plus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY) 

while True: 
    cv2.imshow(winName, diffImg(t_minus, t, t_plus)) 

    # Read next image 
    t_minus = t 
    t = t_plus 
    t_plus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY) 

    key = cv2.waitKey(10) 
    if key == 27: 
    cv2.destroyWindow(winName) 
    break 

print "Goodbye" 

Here you will find more elaborative answer, for what you are looking for.

+0

애드리안 코드를 약간 수정하고 불필요한 것들을 제거한 후, 나는이 작업을 할 수있었습니다. 리소스에 대한 영향을 최소화하면서 간단하고 효율적입니다 (1 % CPU 및 30MB 메모리). 화면에 이미지를 표시하는 대신 스크립트의 69 행에있는 매력과 같이 작동합니다. 고마워. 나는이 코드가 내 목적을 위해 약간 최적화 될 수 있다고 생각하지만 지금은이 작업을한다. – Aleksandar

4

움직임을 감지하는 한 가지 방법은 cv2.accumulateWeighted을 사용하여 장면의 실행 평균을 유지하는 것입니다. 그런 다음 장면의 변경 사항을 나타내는 이미지를 얻으려면 cv2.absdiff을 사용하여 모든 새 프레임을 평균값과 비교하십시오.

정확히 내 a video processing project에서 이것을 수행했습니다. 파일 diffavg1.py에서 누산기를 실행하고 diff를 수행하는 기본 루프를 확인하십시오.

(프로젝트 연구는 멀티 코어 CPU 아키텍처를 이용하여 실시간 비디오 프로세싱을 달성하기 위해, 그래서 이후 버전 diffavg2.py, diffavg3.pydiffavg4.py 점진적으로 더 높은 성능 구현하지만 기본 누산-DIFF 알고리즘은 동일하다.)

+0

좋은 점. 나는 어떤 가치를 얻을 수 있었지만, 내 문제에 대해서는 거의 일할 필요가 없었다. CPU 및 메모리 사용량이 내 사용자 지정 스크립트보다 낮은 것으로 나타났습니다. – Aleksandar

관련 문제