I have a curious cat. And nothing can't happen without her participation in a flat. She adores to bite plants and destroys the Christmas tree.
Idea is to create a system that is scare away from a particular place. The first thought that came in my mind it is to scare her with a special whistle. However for cats, it doesn't work and some noise at night bad for my mind healthy. So, I need something soundless and something that might works at night. Bingo! IR camera + Raspberry Pi + Water pump.
My Supplies:
- Raspberry PI 3B
- Water Pump. I bought on AliExpress
- Pi NoIR Camera V2
- Current relay
- Lego
All works with the model in detector.py. Let's through the key points.
I've created the class Detector with only two methods check and is_detect.
The calling of the method check takes a picture and try to recognize objects, after that we should ask is there any detections i.e. is_detect.
It is a simple wrapper to work with gpiozero. One note that I want to emphasize there is OutputDevice(gpio_num, active_high=False) namely the parameter active_high. If it is left it in the default value (True) your relay will work unobvious. You will need to turn on a pin with method off and turn off vice versa.
This article isn't about how to train a model. I'm a programmer, but I'm interested in Data Science. Here I show how to use a model in a script.
I have the pre-trained model MobileNet V2 and I trained it with the dataset cats_vs_dogs. Here is a tutorial
After trainig I got .pb file and folder with some variables but I needed it to convert to .tflite.
I used a docker image with TensorFlow (I didn't want to install TF on my PC). Here is how easily you can convert your model:
tflite_convert --output_file=./model.tflite --saved_model_dir=/model
--output_file - Path where you want to save a converted model
--saved_model_dir - Path to folder which you've saved with tf.saved_model.save
We need to create an Interpreter and pass the path to our converted .tflite model. After that we can get the info about tensors by get_input_details(). However we need to know only about the first (input) tensor get_input_details()[0] - will return dict, where we need to get the key shape and there we have array like this: [ 1, 160, 160, 3].
- First element (1) it is how many images accepts our model
- Second and third elements (160, 160) are sizes of our image
- The last one (3) it is how many channels in the image (for RGB - 3, for gray - 1)
We need to get the size of an image to resize to it all input of images and we achieve it with slice [1:3]. Let's record the value to __img_input_size .
Let's analyze another key point self.__interpreter.tensor(tensor_index)()[0][:, :] = image
Here we self.__interpreter.tensor(tensor_index) retrieve a tensor by tensor_index (was retrieved from info like input size) this calling will return another function and we at once call it. Result will zero-matrix with shape (1, 160, 160, 3) like we got in get_input_details().
As we know the first element is a count of images that tensor accepts, so we need to get the first element self.__interpreter.tensor(tensor_index)()[0].
And further tricky moment [:, :] = image at right side (shape (160, 160, 3)) we get each element and rewrite it by each corresponded element from the left side. (image it is already converted and resized picture from camera). So, we "placed" the picture from the camera into a tensor.
After that we call self.__interpreter.invoke() it makes a magic calculation and we get a result self.__interpreter.get_output_details()[0]
In the result we have a number that can be < 0, it means that network detects the first class, and result can be > 0 - second class. And the more further from zero, the more confident result.
To run the script use this line:
GPIO_LED={number of GPIO for your LED} GPIO_GUN={number of GPIO for your pump} PATH_TO_MODEL={absolute path to your model .tflite file} THRESHOLD={number of threshold to detect object} {bin path to pythhon}/python3 {absolute path to folder with this project}/main.py
This script executes as daemon. To doesn't launch it every time I added it into /etc/rc.local
su pi -c 'GPIO_LED={number of GPIO for your LED} GPIO_GUN={number of GPIO for your pump} PATH_TO_MODEL={absolute path to your model .tflite file} THRESHOLD={number of threshold to detect object} {bin path to pythhon}/python3 {absolute path to folder with this project}/main.py'
From now, on each startup of raspberry it will start this script.
In my case, it isn't enough good quality of predictions. Sometimes my neural network detects me like a cat 😀.
And I should do something with water pressure in my water gun. For now, it is too low. Maybe narrow down a tube will be good enough.
P.S. During the development of this project, no one animal was injured.



