opencv python 三帧差法实现运动目标区域检测与完整代码

三帧差法:连续三帧,12相减,23相减,结果做与运算。

相减公式:

其中阈值T需要手动调整。

结果得到一个二值图,对二值图做腐蚀,膨胀,在发现轮廓,其中所涉及到得函数有:

cv2.absdiff(img1,img2)#两图相减

cv2.threshold(img,thresh,255,cv2.THRESH_BINARY)#二值化注:此处没有转为1而是255,作用相同

cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))#结构花元素,腐蚀膨胀的kernel

cv2.erode(img,kernel)#腐蚀

cv2.dilate(img,kernel)#膨胀

cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#连通域分析,找轮廓边界

cv2.boundingRect(contour)#轮廓变方框。

import cv2
import numpy as np

def  three_frame_differencing(videopath):
    cap = cv2.VideoCapture(videopath)
    width =int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height =int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    one_frame = np.zeros((height,width),dtype=np.uint8)
    two_frame = np.zeros((height,width),dtype=np.uint8)
    three_frame = np.zeros((height,width),dtype=np.uint8)
    while cap.isOpened():
        ret,frame = cap.read()
        frame_gray =cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        if not ret:
            break
        one_frame,two_frame,three_frame = two_frame,three_frame,frame_gray
        abs1 = cv2.absdiff(one_frame,two_frame)#相减
        _,thresh1 = cv2.threshold(abs1,40,255,cv2.THRESH_BINARY)#二值,大于40的为255,小于0

        abs2 =cv2.absdiff(two_frame,three_frame)
        _,thresh2 =cv2.threshold(abs2,40,255,cv2.THRESH_BINARY)

        binary =cv2.bitwise_and(thresh1,thresh2)#与运算
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
        erode = cv2.erode(binary,kernel)#腐蚀
        dilate =cv2.dilate(erode,kernel)#膨胀
        dilate =cv2.dilate(dilate,kernel)#膨胀

        img,contours,hei = cv2.findContours(dilate.copy(),mode=cv2.RETR_EXTERNAL,method=cv2.CHAIN_APPROX_SIMPLE)#寻找轮廓
        for contour in contours:
            if 100<cv2.contourArea(contour)<40000:
                x,y,w,h =cv2.boundingRect(contour)#找方框
                cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255))
        cv2.namedWindow("binary",cv2.WINDOW_NORMAL)
        cv2.namedWindow("dilate",cv2.WINDOW_NORMAL)
        cv2.namedWindow("frame",cv2.WINDOW_NORMAL)
        cv2.imshow("binary",binary)
        cv2.imshow("dilate",dilate)
        cv2.imshow("frame",frame)
        if cv2.waitKey(50)&0xFF==ord("q"):
            break
    cap.release()
    cv2.destroyAllWindows()
if __name__ == '__main__':
    three_frame_differencing(0)

效果很不好,空洞太大了,准备改用KNN和高斯混合模型试试

涉及代码:

cv2.createBackgroundSubtractorMOG2()
cv2.createBackgroundSubtractorKNN()

高斯混合模型前景提取封装好了直接调用:

fgbg = cv2.createBackgroundSubtractorMOG2()#创建背景剪除

fgmask = fgbg.apply(frame)#获得二值轮廓图

接下了做形态学处理。

  cap = cv2.VideoCapture(r"C:\RecordDownload\NVR-THD_ch3_main_20190423120000_20190423120500.dav")
    kernel =cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
    fgbg =cv2.createBackgroundSubtractorMOG2()
    fourcc = cv2.VideoWriter_fourcc(*"XVID")
    frame1 = np.zeros((640,480))
    out = cv2.VideoWriter("test424.avi",fourcc,10,(640,480))
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
    while cap.isOpened():
        ret,frame =cap.read()
        if not ret:
            break
        cv2.imshow("1",frame)
        k = cv2.waitKey(30) & 0xff
        if k == 27:
            break

        fgmask =fgbg.apply(frame)
        mask = cv2.morphologyEx(fgmask,cv2.MORPH_OPEN,kernel)
        cv2.imshow("2",mask)
        k = cv2.waitKey(30) & 0xff
        if k == 27:
            break
        _,contours,_ = cv2.findContours(fgmask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
        for c in contours:
            if 100<cv2.contourArea(c)<40000:
                x,y,w,h = cv2.boundingRect(c)
                cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255))
            out.write(frame)
    out.release()
    cap.release()
    cv2.destoryAllWindows()

 

  • 13
    点赞
  • 141
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
差法是一种常用的运动目标检测算法,适用于在视频图像中发现移动物体。Python提供了丰富的计算机视觉库,如OpenCV,可以很方便地实现差法。 首先,要读取视频文件并提取帧。在Python中,使用OpenCV库可以通过`cv2.VideoCapture()`函数打开视频文件,然后通过循环读取每一帧。 接下来,通过将相邻两帧图像进行差分,可以得到帧差图像。差分得到的图像中,移动物体区域与静止背景区域的差异更大。可以使用`absdiff()`函数或其他方法来计算帧差图像。 然后,可以通过二值化处理将帧差图像转换为二值图像,以便于进一步的处理。可以使用`threshold()`函数将帧差图像中的像素值进行阈值化处理,得到二值图像。 之后,可以使用形态学操作(如腐蚀和膨胀)来去除二值图像中的噪声,以便更准确地检测移动目标物体。可以使用`erode()`和`dilate()`函数进行形态学操作。 最后,可以使用轮廓检测函数(如`findContours()`)来检测二值图像中的轮廓。可以使用`drawContours()`函数在原始帧图像上绘制检测到的轮廓,以标识运动目标。 通过以上步骤,就可以通过帧差法检测运动目标。在实际应用中,还可以进一步优化算法,如引入背景建模、运动方向判断等,以提高检测准确性和性能。 总之,使用PythonOpenCV库可以很方便地实现差法检测运动目标。通过读取视频帧、计算帧差图像、二值化处理、形态学操作和轮廓检测,可以准确地检测运动目标并标识出来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值