2016-11-09 8 views
7

私の目標は、IPカメラストリーム上の特定の領域の動きを検出することです。私は作業コードを書くことができましたが、私の個人的な理解に基づいています。OpenCVは動きをPythonで検出します

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

はい、この領域はあらかじめ定義されています。ヒストグラムから値を抽出しようとしました。なぜなら2色(黒と白)しかないからですが、運がないからです。だから、黒のヒストグラムの前半と白の二番目のヒストグラムを使ってみましょう。私の質問は、これを達成する別の方法が存在するかどうかです。私の主な目標は、特定の地域での動きをできるだけ単純に検出し、ユーザーに通知することです。 – Aleksandar

+0

私は、ほとんど無限の数の方法があると思います。たとえば、最後のxフレームのスコアを保持し、差分画像を計算するために使用する「平均」画像を計算することができます。 n * mパッチなどの任意の領域の差がしきい値より高い場合は、それを動きと呼んで報告することができます。 ROIを明示的に定義しなくても、これを使って動きの範囲を特定することもできます –

答えて

1

差分画像そこで差分画像は、2枚の画像の差分を示す二つの画像

の減算の結果です。これらの画像では、動きを見えるようにすることができます。

次のスクリプトでは、3つの連続した画像から計算された差分画像を使用します。これの利点は、興味のない背景が結果から削除されることです。

OpenCVでは、absdiff()を使用して、互いに2つの画像を引き算する可能性があります。 また、2つのイメージの論理演算はすでに が実装されています。 Bitwise_and()メソッドを使用して、最終的な差分画像を得る。 私たちがしなければならない最後のことは、私たちの前のスクリプトに差分画像機能をもたらしている

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

:Pythonで、それはこのようになります。 ループが始まる前に、最初の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

Adrianのコードを少し修正し、不要なものを削除した後、私はこの作業をすることができました。シンプルで効果的で、リソースへの影響が少ない(1%のCPUと30Mbのメモリ)。画面に画像を表示する代わりに、スクリプトの69行目の魅力のように動作します。ありがとう。私はこのコードは私の目的のために少し最適化することができると思うが、今はこの仕事。 – Aleksandar

4

動きを検出する1つの方法は、cv2.accumulateWeightedを使用してシーンの平均を維持することです。次に、新しいフレームをすべて平均と比較して、シーン内の変化を示す画像を得るためにcv2.absdiffを使用します。

私はa video processing projectの鉱山でこれを正確に行いました。ファイルdiffavg1.pyのメインループを調べて、アキュムレータを実行して差分を実行してください。

(プロジェクトの研究は、マルチコアCPUアーキテクチャを利用し、リアルタイムビデオ処理を達成することであったので、それ以降のバージョンがdiffavg2.pydiffavg3.pydiffavg4.pyは次第に高性能実装であるが、根本的な蓄積、差分アルゴリズムは同じです。)

+0

いいね。私はいくつかの価値を得ることができましたが、私の問題のためにほとんど仕事を必要としませんでした。 CPUとメモリの使用量が私のカスタムスクリプトよりも低いことに気付きました。 – Aleksandar

関連する問題