基於差值的運動物體檢測

 

'''
區域目標運動檢測
關鍵字:
    cv2: 攝像頭視頻讀取,運動物體框跟蹤, 基於與初始背景圖的差別得到二值圖
    os:window控制,執行exe
    configparser:配置文件寫入讀取
優點:
    佔用資源極小,調整檢測窗口至需要檢測的位置,當有物體運動則自動觸發設定好的exe(如瀏覽器),防背後有人居家必備√
'''
# coding=utf-8

import cv2
import os
import time
import numpy as np
import configparser


# config set
path = os.getcwd()
conf = configparser.ConfigParser()

# read and save config
while True:
    is_read = conf.read(filenames=path + r'\config_motion_detector')
    if is_read == []:
        # add section
        gadget_open_default = 'C:\Program Files\internet explorer\iexplore.exe'
        conf.add_section('detect_frame')
        conf.add_section('contours')
        conf.add_section('gadget_path')
        conf.add_section('binaryzation')
        conf.add_section('set')
        # set detect frame
        conf.set('detect_frame', 'detect_frame_vertical_1', '80')
        conf.set('detect_frame', 'detect_frame_vertical_2', '180')
        conf.set('detect_frame', 'detect_frame_horizon_1', '0')
        conf.set('detect_frame', 'detect_frame_horizon_2', '200')
        # for contours threshold
        conf.set('contours', 'contours_threshold', '1000')  # the size of contours covering motion object
        # for gadget path
        conf.set('gadget_path', 'gadget_path', gadget_open_default)
        conf.set('binaryzation', 'binaryzation_threshold', '8')
        conf.set('set','is_show_video','1')
        conf.write(open(path + r'\config_motion_detector', 'w+'))
        print("initialized config file")
    else:
        try:
            detect_frame_vertical_1 = int(conf.get('detect_frame','detect_frame_vertical_1'))
            detect_frame_vertical_2 = int(conf.get('detect_frame','detect_frame_vertical_2'))
            detect_frame_horizon_1 = int(conf.get('detect_frame','detect_frame_horizon_1'))
            detect_frame_horizon_2 = int(conf.get('detect_frame','detect_frame_horizon_2'))
            contours_threshold = int(conf.get('contours','contours_threshold'))
            binaryzation_threshold = int(conf.get('binaryzation','binaryzation_threshold'))
            is_show_video = int(conf.get('set','is_show_video'))
            gadget_open_default = conf.get('gadget_path','gadget_path')
            print("loaded config file")
            break
        except:
            pass

# gadget need opening
gadget_open = gadget_open_default

# capture video from camera
camera = cv2.VideoCapture(0) # 0:the first camera
time.sleep(0.5)
print("is camera opened:",camera.isOpened())

capture_size = (camera.get(cv2.CAP_PROP_FRAME_WIDTH),camera.get(cv2.CAP_PROP_FRAME_HEIGHT))
print("camera size:",capture_size)

#  for inflation
es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(9,4))

background = None
calc_n = 0
is_open_gadget = 0
time_start = time.time()
time_flag = time_start
while True:
    # read video (every frame)
    grabbed,frame_lwpCV = camera.read()
    frame_lwpCV = frame_lwpCV[detect_frame_vertical_1:detect_frame_vertical_2,detect_frame_horizon_1:detect_frame_horizon_2]
    # preprocess, to gray ,gauss filter(gauss blur:reduce noise)
    gray_lwpCV = cv2.cvtColor(frame_lwpCV,cv2.COLOR_RGB2GRAY)
    gray_lwpCV = cv2.GaussianBlur(gray_lwpCV,(21,21),0)

    # first frame as background
    if background is None:
        background = gray_lwpCV
        continue

    # calculate differ between each frame and background,got a different map
    different_map_1 = cv2.absdiff(background,gray_lwpCV)
    # binaryzation
    different_map_2 = cv2.threshold(different_map_1,binaryzation_threshold,255,cv2.THRESH_BINARY)[1]
    # inflation
    #different_map_2 = cv2.dilate(different_map_2,es,iterations=2)

    if np.max(different_map_2) != 0:
        calc_n += 1
        print("warring! ! ! x",calc_n )
    if np.max(different_map_2) != 0 and is_open_gadget == 0:
        try:
            os.startfile(gadget_open)
        except:
            print("warring:wrong open path")
        is_open_gadget = 1

    # calculation contours
    # find contours !
    image,contours,hierarchy = cv2.findContours(different_map_2.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    for c in contours:
        if cv2.contourArea(c) < contours_threshold:
            # only show contours over threshold(reduce noise influence)
            continue
        # calculation rectangle boundary frame(show the green rectangle cover object[moving])
        (x,y,w,h) = cv2.boundingRect(c)
        cv2.rectangle(frame_lwpCV,(x,y),(x+w,y+h),(0,255,0),2)

    # show
    if is_show_video == 1:
        cv2.imshow('contours:',frame_lwpCV)
        cv2.imshow('dis:',different_map_2) # show different map

    # exit judge
    if cv2.waitKey(1) == ord('q'):
        break

    # reset background , is_open_gadget
    if int(time.time() - time_start) % 5 == 0:
        background = gray_lwpCV

    if int(time.time() - time_start) % 10 == 0 and int(time.time()) - int(time_flag) > 1:
        is_open_gadget = 0
        time_flag = int(time.time())
    time.sleep(0.05)

camera.release()
cv2.destroyAllWindows()

'''

.配置文件中的gadget_path後的值,可以更改爲任意軟件或文件夾的地址,檢測到物體運動時會自動打開
.配置文件中的[detect_frame]爲檢測框位置,依次爲 長(上,下),寬(左,右)
.配置文件中的[binaryzation]爲二值化閾值,數值越低,在光線陰暗的地方可以提高識別率,同時也會增加誤判率
.配置文件中的[set]  1 = 顯示實時計算畫面,0 = 隱藏實時計算畫面
.配置文件中的[contours]爲標記框閾值,若物體大小小於該值則不會框中
.請勿刪除配置文件的值(可更改,不可刪除)
.若發生bug,請刪掉配置文件再重新執行exe,將會重新生成配置文件
.爲防止瘋狂打開設定的軟件,該程序設定爲10秒鐘內只會打開一次設定的軟件

 

'''

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章