1

I have a Raspberry Pi which records videos on motion detections from a PIR sensor. Sometimes "random" heat variations will falsely trigger the sensor and record a video when there isn't any motion. If there isn't any motion in the picture I would like to filter out those videos with image processing using OpenCV 2.4.8

There are two criterias for a video to be saved: a heat varation triggering the PIR sensor and motion in the video. It works for most of the videos but I have noticed that illumination will sometimes vary a lot and mimic real motion in the video and trigger the filter falsely.

# -*- coding: utf-8 -*-
import os
import cv2
import numpy as np

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

kernel = np.ones((5,5),np.uint8)

for dirpath, dnames, fnames in os.walk("/path/to/videos"):
    for f in fnames:
        cap = cv2.VideoCapture(os.path.join(dirpath, f))

        total = 0
        count = 0

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

        while True:
            opening = cv2.morphologyEx(diffImg(t_minus, t, t_plus), cv2.MORPH_OPEN, kernel)
            total += cv2.countNonZero(opening)

            # Read next image
            t_minus = t
            t = t_plus
            ret, frame = cap.read()
            if ret == False:
              break
            t_plus = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
            count += 1

        if total/count < 800:
            print "file %s has no motion (%d)" % (os.path.join(dirpath, f), total/count)

My algorithm is very simple. It grabs three frames and calculates the difference and creates a binary image using cv2.bitwise_and. In order to remove noise it performs a morphological open on that differential image. Finally it uses cv2.countNonZero to determine the amount of motion in that frame. In the end i divide the total amount of motion by the number of frames (let's call this motion/frame) to get a number to work with. If this number is less than 800, the video is persumed to have no motion.

Here are two examples (one positive detection and one false positive detection)
Positive:
https://www.dropbox.com/s/ryvemvkoda6morn/2016-05-11_07-12-20.ts?dl=0 (motion/frame: 843) False positive:
https://www.dropbox.com/s/lqegj92jxhjjegv/2016-05-12_19-16-10.ts?dl=0 (motion/frame: 879)

As you can see from the latter, when the illumination varies a lot, it is falsely detected as motion. How can I remove these false positives from illumination changes?

Another thing worth mentioning is that this filter will be run as a post-process, i.e it won't be in realtime thus I am okay with a solution that is a somewhat heavier performance-wise than my current one.

(EDIT: I am running Linux so the solution needs to work on Linux)

Linus
  • 1,516
  • 17
  • 35

1 Answers1

2

Look into illumination invariant motion detection algorithms, namely go for something like contrast stretching or brightness equalization.

Have you looked into a physical/hardware solution to this, maybe covering the PIR sensor with something that might reduce glare effects?

EDIT:

I just found this result about removal of glare effects through masking. It might help you.

EDIT 2:

Couldn't remember this while posting the answer, but I came across this implementation long ago, its written in C++.

  • Thanks, I'll look into this some more and see if I can find a solution. – Linus May 15 '16 at 10:38
  • I am working in python and need my solution to work on Linux and because of that I am unable to use that specific implementation, but thanks for the link. – Linus May 15 '16 at 19:31