Friday, 24 August 2018

Intelligent motion detection camera

So what Have I been doing with all this object detection? Simple, setting up a security camera!

It's quite simple, I started an age ago with building a camera from a pi-zero with a pi-cam (with the ir filter removed). Just find a dummy housing, like this one:

The install motion-eye (The instructions there are awesome) and you've got a security camera!

Next, wouldn't it be nice to alert you when it found something.. So I tried setting up motion-eye to trigger when it thought it saw something, but it was always giving me lots of false positives, for example when a cloud went overhead, a lot of pixels would change, then it would alert me.

Hmm not ideal, I wasn't that keen on having a cloud alerting function.

That's why I wrote the web service that you can find here on GitHub. So I set it up to email me when it detects. Even with that, I still got a lot of false object detections, so I modified the web service to have a filter and only filter if it spots one of the defined labels (- car     - person     - bicycle     - motorcycle     - cat     - dog)

How?
Well setup motion-pi like so:


download the source code from git
git clone https://github.com/stevegal/objectdetect_ws.git
cd objectdetect_ws

modify the application properties for your setup (in src/main/rescources) and build it and run it
mvn clean package
java -jar target/objectdetect4j-0.1-SNAPSHOT.jar

and now the detect script should look like:
#!/bin/bash

cd 
WORKING_DIR=$(ls -t | head -1)

cd $WORKING_DIR

for filename in *.jpg
do
 curl -m 5 -F "image=@$filename" http://:/detect/mailTo?mailTo=
 rm -f $filename
done

You now should have a security camera that sends you an email if it spots any of the objected you setup in the spring properties file. The email should look like this


with a nice box around the things it has spotted. Works for me!

Thursday, 23 August 2018

Tensorflow - The importance of session

Java Tensorflow


I've created a little web server that loads in a frozen graph and processes the images that are sent to it. It can be found here.

When I first set it up I was really disappointed at the performance, performance on the mobile phones were better than I was getting... 

My code was straight out of the example pages, e.g.
    try (Session session = new Session(this.graph)) {
      outputs = session
          .runner()
          .feed("image_tensor",tensor)
          .fetch("detection_scores")
          .fetch("detection_classes")
          .fetch("detection_boxes")
          .run();
    }

It was taking an age e.g. At first I thought it was down to the library not being compiled for my cpu as it was warning me on startup... so I recompiled (using the awesome documentation { basically
bazel build --config opt //tensorflow/java:tensorflow //tensorflow/java:libtensorflow_jni
} ), but it was still roughly the same. Not that then. But how bad was it?

2018-08-23 19:01:31.971  INFO 34476 --- [nio-9000-exec-8] u.c.s.t.c.TensorflowImageEvaluator       : session  time:0
2018-08-23 19:01:31.972  INFO 34476 --- [nio-9000-exec-8] u.c.s.t.c.TensorflowImageEvaluator       : runner setup  time:1
2018-08-23 19:01:36.050  INFO 34476 --- [nio-9000-exec-8] u.c.s.t.c.TensorflowImageEvaluator       : run time:4078
2018-08-23 19:01:36.051  INFO 34476 --- [nio-9000-exec-8] u.c.s.t.c.TensorflowImageEvaluator       : results time:0

That's right nearly 5 seconds... I though this was supposed to be quick... so what was I doing wrong? Basically not reusing the session. Once that is being reused... just look what happens on the same image. In this one I'm using a set of pre-pared sessions in a BlockingQueue to get the single thread use requirements for session
      Session session = this.sessions.take();
      Session.Runner runner = session
          .runner()
          .feed("image_tensor", tensor)
          .fetch("detection_scores")
          .fetch("detection_classes")
          .fetch("detection_boxes");
      start = logTimeDiff("runner setup  time:" ,start);
      outputs = runner.run();
      start = logTimeDiff("run time:" , start);
Just remember to pop the session back in at the end!

2018-08-23 19:01:57.739  INFO 34476 --- [io-9000-exec-10] u.c.s.t.c.TensorflowImageEvaluator       : session  time:0
2018-08-23 19:01:57.739  INFO 34476 --- [io-9000-exec-10] u.c.s.t.c.TensorflowImageEvaluator       : runner setup  time:0
2018-08-23 19:01:57.791  INFO 34476 --- [io-9000-exec-10] u.c.s.t.c.TensorflowImageEvaluator       : run time:51
2018-08-23 19:01:57.791  INFO 34476 --- [io-9000-exec-10] u.c.s.t.c.TensorflowImageEvaluator       : results time:0

Turns out it *is* fast after all!

My guess is its loading in the graph on first run so saving that... boom! fast runs!

Saturday, 18 August 2018

Setting up TensorFlow Object Detection on Mac OSX

This is more notes for me rather than anything considered.

Basically follow:
https://www.tensorflow.org/install/install_mac

but there are some caveats that I needed to do in order to get it working.

Basically `protoc` wasn't setup... how to install?


wget https://github.com/google/protobuf/releases/download/v3.6.1/protoc-3.6.1-osx-x86_64.zip
unzip protoc-3.6.1-osx-x86_64.zip
cp bin/protoc /usr/local/bin/protoc
Have a look at the readme:
Ensure you pip install the lot
pip install --user Cython
    pip install --user contextlib2
    pip install --user pillow
    pip install --user lxml
    pip install --user jupyter
    pip install --user matplotlib
Now download the object detection model
git clone https://github.com/tensorflow/models.git
cd models/research
protoc object_detection/protos/*.proto --pyhton_out=.
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
cd object_detection
jupyter notebook
Now you should be ready to follow the notebook instructions. Super fast and super easy