Python is the best for machine learning. Despite not being a Python enthusiast I thought I might just check this out as an alternative. Especially since it runs well on Raspberry Pi type devices.
Pytorch is the most popular Machine Learning framework at the moment. As with the Android version of the Monkey Detector, we will be using a pre-trained model because somebody already made one which suits our purpose.
I used Pycharm as my IDE for Python programming here – mainly because it’s free, and made by Jetbrains so it’s almost the same interface as Android Studio; which although slow as hell on my system is still a great IDE.
I’m going to assume you are running Ubuntu Linux here. If you are using a raspberry pi with raspbian then that’s probably close enough, although I don’t have one to test this on…
Detection test – check if a monkey is contained in a static image:
First things first, full disclaimer! This is mostly not my code. In order to get started I followed an excellent tutorial here: https://www.learnopencv.com/pytorch-for-beginners-image-classification-using-pre-trained-models/
You should check it out, a lot is explained there, with the opportunity to delve deeper. Since I was only interested in hacking together a simple monkey detector I copy-pasted and tweaked until I got the below code, lets call it vision.py:
#!/usr/bin/env python from torchvision import models import torch dir(models) alexnet = models.alexnet(pretrained=True) # You will see a similar output as below # Downloading: "https://download.pytorch.org/models/alexnet-owt- 4df8aa71.pth" to /home/hp/.cache/torch/checkpoints/alexnet-owt-4df8aa71.pth from torchvision import transforms transform = transforms.Compose([ # transforms.Resize(256), # transforms.CenterCrop(224), # transforms.ToTensor(), # transforms.Normalize( # mean=[0.485, 0.456, 0.406], # std=[0.229, 0.224, 0.225] # )]) # Import Pillow from PIL import Image img = Image.open("/path/to/monkeyImage.jpg") img_t = transform(img) batch_t = torch.unsqueeze(img_t, 0) alexnet.eval() out = alexnet(batch_t) print(out.shape) # Load labels with open('/path/to/imagenet_classes.txt') as f: classes = [line.strip() for line in f.readlines()] _, indices = torch.sort(out, descending=True) percentage = torch.nn.functional.softmax(out, dim=1) * 100 [(classes[idx], percentage[idx].item()) for idx in indices[:5]] prediction = [(classes[idx], percentage[idx].item()) for idx in indices[:5]] print("Prediction ", prediction) #print output to file: with open('/path/to/f.txt', 'w') as f: print(prediction, file=f) # Python 3.x import os os.system('/path/to/checkIfResponseContainsMonkey.sh')
In addition to the code you will need to get imagenet_classes.txt from github as well as this bash script (called by os.system). I hacked this together to check if monkeys were indeed detected by Pytorch. Save this as checkIfResponseContainsMonkey.sh and change the path of f.txt to wherever the python script puts it. Don’t forget to mark it as executable:
!/bin/bash export DISPLAY=":0.0" # read output from python script f.txt: if grep -q "chimpanzee" /path/to/f.txt; then notify-send 'Monkey found' echo "MONKEEEEEYYYYYSSSS" else notify-send 'Not found…………..' echo "monkey not found" fi
*You may need to install notify-send for this to work.
sudo apt install inotify-tools
As you can see, I used grep to search for “chimpanzee”, since “monkey” was not available. The model still works great on vervets, however, obviously they are similar enough. Surprisingly it doesn’t trigger for humans, as far as I could see in a bit of testing. I tried a few images of feral looking wild humans, but no bites.
Oh and you need an image of a monkey. Here you go, take your pick.
Putting it together:
You have probably worked everything out by now, it’s just a matter of placing the checkIfResponseContainsMonkey.sh script and imagenet_classes.txt files somewhere, then linking them in the code along with your renamed monkeyImage.jpg and in Pycharm IDE at least you then just press PLAY.
Detecting monkeys in the garden:
As for pointing a camera out the window and getting Pytorch to recognize if there is a monkey out there, I hacked something together using Bash, Motion (a motion detection program for linux) and an inotify-wait while loop which monitors a folder for new images (produced by Motion) and then moves and renames them to monkeyImage.jpg in the right place for the Python script to do it’s magic.
! /bin/bash # the idea for this from https://askubuntu.com/questions/622971/how-i-can-monitor-new-files-in-a-directory-and-move-rename-them-into-another-dir folder=/var/lib/motion/ #default folder where motion puts it's captured images while inotifywait -e create --format '%w%f' $folder do notify-send 'removing that' mv ls -d /var/lib/motion/* | head -1 /path/to/monkeyTest.jpg echo ls -d /var/lib/motion/* | head -1 rm /var/lib/motion/*.jpg runuser -l tom -c 'python3 /path/to/vision.py' done
This whole hacked together system could probably be fully implemented in Python with OpenCV or something like that, however for now I am quite happy with the results from my system. Now on to the next part of this series, doing the same thing with an Android app, and making the sprinkler controller.