概要
- 3画像で差分検出し変化した箇所を動体検出としている
- 画像は単に配列データとして扱う
- カラーの配列データをグレースケール画像の配列データに変換
- 差分箇所を論理積演算で特定する
- 差分箇所の外接を矩形で囲む
- 動体検知すると「Motion Detected」と表示
- 変化量を「Change Vol 数値」で表示
コメント
- サンプルコードを参考に一部カスタマイズしてトライしてみたけど、なんとなく動いてそう。
- 掲載したソースは「Mac」で動作確認済み(ラズパイでも動作するはず)
- FPS表示値は少し嘘っぽいなー
- 動画イメージを掲載したかったが方法がわからず断念
- 途中の画像のみ掲載しました
- 使ったツールバージョンは以下
- MacOS Mojave / python3.5.6 / Opencv3.4.2 / VS code1.38.1
イメージ画像(その1)
イメージ画像(その2)
ファイル構成
- motion_detect.py : 動体検知ソースファイル(下のソースコード)
import cv2
cap_camera = None
getimg1 = None
getimg2 = None
getimg3 = None
view_frame = None
before = None
cap_camera = cv2.VideoCapture(0)
cap_camera.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap_camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
def motion_check(img1,img2,img3):
gray1 = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_RGB2GRAY)
gray3 = cv2.cvtColor(img3, cv2.COLOR_RGB2GRAY)
diff_12 = cv2.absdiff(gray1, gray2)
diff_23 = cv2.absdiff(gray2, gray3)
bitwise_diff_and = cv2.bitwise_and(diff_12, diff_23)
ret, diff_thresholding = cv2.threshold(bitwise_diff_and, 30, 255, cv2.THRESH_BINARY)
diff = cv2.medianBlur(diff_thresholding, 5)
return diff
getimg1 = getimg2 = getimg3= cap_camera.read()[1]
while True:
tick = cv2.getTickCount()
diff = motion_check(getimg1, getimg2, getimg3)
cnt = cv2.countNonZero(diff)
gray = cv2.cvtColor(getimg3,cv2.COLOR_BGR2GRAY)
if before is None :
before = gray.copy().astype('float')
continue
if cnt > 500:
cv2.accumulateWeighted(gray,before,0.7)
diff_frame = cv2.absdiff(gray, cv2.convertScaleAbs(before))
thl = cv2.threshold(diff_frame,5,255,cv2.THRESH_BINARY)[1]
image, contours, hierarchy = cv2.findContours(thl.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
max_area = 0
target = None
for i in contours:
area = cv2.contourArea(i)
if max_area < area and area < 30000 and area > 3000:
max_area = area
target = i
if max_area >= 500:
x,y,w,h = cv2.boundingRect(target)
areaframe = cv2.rectangle(getimg3,(x,y),(x+w,y+h),(0,255,0),2)
cv2.putText(areaframe, "Motion Detected", (10,405), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1, cv2.LINE_AA)
view_frame = areaframe
else:
view_frame = getimg3
getimg1 = getimg2
getimg2 = getimg3
getimg3 = cap_camera.read()[1]
fps = cv2.getTickFrequency() / (cv2.getTickCount() - tick)
cv2.putText(view_frame, "FPS:{} ".format(int(fps)),(10, 430), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1, cv2.LINE_AA)
cv2.putText(view_frame, "Change Vol:{}".format(int(cnt)),(10,450), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1, cv2.LINE_AA)
cv2.imshow('Motion Detect Image', view_frame)
k = cv2.waitKey(1)
if k == 27:
break
cap_camera.release()
cv2.destroyAllWindows()