Skip to content

Commit

Permalink
feat: fall-detect initialization
Browse files Browse the repository at this point in the history
Merge pull request #14 from bhavikapanara/primary-fall-detect
  • Loading branch information
Ivelin Ivanov authored Jun 14, 2021
2 parents ce3a1d9 + fefece1 commit 6e439aa
Show file tree
Hide file tree
Showing 54 changed files with 2,301 additions and 5 deletions.
77 changes: 77 additions & 0 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Python package

on: [push, pull_request]

jobs:
build:
name: Build Job

runs-on: ubuntu-20.04
strategy:
max-parallel: 4
matrix:
python-version: [3.7, 3.8]

steps:
- uses: actions/checkout@v1
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install python package locally
run: |
python3 -m pip install --upgrade pip
pip3 install --editable src
- name: Lint with flake8
run: |
pip3 install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
env:
ARCH: "linux/amd64"
TAG_SUFFIX: "amd64"
run: |
pip3 install pytest
pwd
ls -al
echo GITHUB_WORKSPACE=${GITHUB_WORKSPACE}
echo "ARCH=${ARCH}"
${GITHUB_WORKSPACE}/install_requirements.sh
${GITHUB_WORKSPACE}/tests/run-tests.sh
release:
name: Release Job
needs: [build]
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Install Node.js 12
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: Install Python 3
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Install Semantic Release Tool
run: |
npm install --save-dev semantic-release
npm install --save-dev @semantic-release/commit-analyzer
npm install --save-dev @semantic-release/git
npm install --save-dev @semantic-release/release-notes-generator
npm install --save-dev @semantic-release/github
npm install --save-dev @semantic-release/changelog
npm install --save-dev @semantic-release/exec
- name: Run Semantic Release
run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Semantic release completed
run: echo Semantic release flow completed
28 changes: 28 additions & 0 deletions .github/workflows/pythonpublish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Upload Python Package

on:
release:
types: [created]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
cp README.md src/
cd src
python setup.py sdist bdist_wheel
twine upload dist/*
30 changes: 30 additions & 0 deletions .releaserc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"branch": "master",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
[
"@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md",
"changelogTitle": "# Semantic Versioning Changelog"
}
],
[
"@semantic-release/exec",
{
"prepareCmd": "./build/prepare-semantic-release.sh ${nextRelease.version}"
}
],
[
"@semantic-release/git",
{
"assets": [
"CHANGELOG.md",
"src/setup.cfg"
]
}
],
"@semantic-release/github",
]
}
200 changes: 200 additions & 0 deletions Demo.ipynb

Large diffs are not rendered by default.

Binary file added Images/background.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/fall_img_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/fall_img_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/fall_img_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/fall_img_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/fall_img_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/fall_img_6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/fall_img_7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/fall_img_8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/fall_img_9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 31 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ _This repo is the new home of the fall detection model used in Ambianic Edge. We

# TODO

- [ ] Standalone Python ML library for people fall detection based on Tensorflow and [PoseNet 2.0](https://github.com/tensorflow/tfjs-models/tree/master/posenet).
- [x] Standalone Python ML library for people fall detection based on Tensorflow and [PoseNet 2.0](https://github.com/tensorflow/tfjs-models/tree/master/posenet).
- [ ] Python source code and wheel package published on PyPi
- [ ] Jupyter Notebook to interactively test and experiement with the model
- [ ] CI & test suite
- [ ] Training and testing data sets
- [ ] Third party ML models used as building blocks
- [x] Jupyter Notebook to interactively test and experiement with the model
- [x] CI & test suite
- [x] Training and testing data sets
- [x] Third party ML models used as building blocks

# Project motivation

Expand All @@ -32,6 +32,32 @@ In the current design we use a combination of the [PoseNet 2.0](https://github.c

[![Fall Detection AI flow](https://user-images.githubusercontent.com/2234901/112545190-ea89d380-8d85-11eb-8e2c-7a6b104d159e.png)](https://drive.google.com/file/d/1sr2OcEWsGzoxJb4PwCIXOuEo7a5ubAxG/view?usp=sharing)

# Experiment

Experiment with the fall-detection module using simple script, jupyter-notebook or command line input(CLI) by feeding 2 or 3 images. The input images should be spaced about 1 second apart.

###### Run a Python Script

```
python3 demo-fall-detection.py
```

###### Run a `Demo.ipynb` jupyter-notebook for the experiment

###### Execute the below command for CLI usage

To test fall-detection using the CLI for 2 images:

```
python3 demo-fall-detection-cmd.py --image_1 Images/fall_img_1.png --image_2 Images/fall_img_2.png
```

To test fall-detection using the CLI for 3 images:

```
python3 demo-fall-detection-cmd.py --image_1 Images/fall_img_1.png --image_2 Images/fall_img_2.png --image_3 Images/fall_img_3.png
```

# Limitations

Based on testing and user feedback we are aware of the following limitations for the Fall Detection algorithm:
Expand Down
1 change: 1 addition & 0 deletions ai_models/pose_labels.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1 FALL
Binary file not shown.
Binary file not shown.
47 changes: 47 additions & 0 deletions demo-fall-detection-cmd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import argparse
from pathlib import Path
from PIL import Image
from fall_prediction import Fall_prediction
import numpy as np
import json
import time
import yaml

class JsonEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.integer):
return int(obj)
if isinstance(obj, np.floating):
return float(obj)
if isinstance(obj, np.ndarray):
return obj.tolist()

return super(JsonEncoder, self).default(obj)

parser = argparse.ArgumentParser()
parser.add_argument("--image_1", type=Path, help='Path to the First Image', required=True)
parser.add_argument("--image_2", type=Path, help='Path to the Second Image', required=True)
parser.add_argument("--image_3", type=Path, help='Path to the Third Image')

p = parser.parse_args()
img1 = Image.open(p.image_1)
img2 = Image.open(p.image_2)
img3 = Image.open(p.image_3) if p.image_3 else None

response = Fall_prediction(img1, img2, img3)

if response:

print("There is", response['category'])
print("Confidence :", response['confidence'])
print("Angle : ", response['angle'])
print("Keypoint_corr :", response['keypoint_corr'])

time_str = time.strftime("%Y%m%d-%H%M%S")
json_str = json.dumps(response, cls=JsonEncoder)

with open(f"tmp/{time_str}.yaml","w",) as file:
yaml.dump(json.loads(json_str), file)
else:
print("There is no fall detetcion...")

16 changes: 16 additions & 0 deletions demo-fall-detection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from PIL import Image
from fall_prediction import Fall_prediction

img1 = Image.open("Images/fall_img_1.png")
img2 = Image.open("Images/fall_img_2.png")
img3 = Image.open("Images/fall_img_3.png")

response = Fall_prediction(img1, img2, img3)

if response:
print("There is", response['category'])
print("Confidence :", response['confidence'])
print("Angle : ", response['angle'])
print("Keypoint_corr :", response['keypoint_corr'])
else:
print("There is no fall detetcion...")
83 changes: 83 additions & 0 deletions fall_prediction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import os
import time

from src.pipeline.fall_detect import FallDetector


def _fall_detect_config():

_dir = os.path.dirname(os.path.abspath(__file__))
_good_tflite_model = os.path.join(
_dir,
'ai_models/posenet_mobilenet_v1_100_257x257_multi_kpt_stripped.tflite'
)
_good_edgetpu_model = os.path.join(
_dir,
'ai_models/posenet_mobilenet_v1_075_721_1281_quant_decoder_edgetpu.tflite'
)
_good_labels = 'ai_models/pose_labels.txt'
config = {
'model': {
'tflite': _good_tflite_model,
'edgetpu': _good_edgetpu_model,
},
'labels': _good_labels,
'top_k': 3,
'confidence_threshold': 0.6,
}
return config


def Fall_prediction(img_1,img_2,img_3=None):

config = _fall_detect_config()
result = None

fall_detector = FallDetector(**config)

def process_response(response):
nonlocal result
for res in response:
result = res['inference_result']

process_response(fall_detector.process_sample(image=img_1))

time.sleep(fall_detector.min_time_between_frames)

process_response(fall_detector.process_sample(image=img_2))

if len(result) == 1:
category = result[0]['label']
confidence = result[0]['confidence']
angle = result[0]['leaning_angle']
keypoint_corr = result[0]['keypoint_corr']

dict_res = {}
dict_res["category"] = category
dict_res["confidence"] = confidence
dict_res["angle"] = angle
dict_res["keypoint_corr"] = keypoint_corr
return dict_res

else:

if img_3:

time.sleep(fall_detector.min_time_between_frames)
process_response(fall_detector.process_sample(image=img_3))

if len(result) == 1:

category = result[0]['label']
confidence = result[0]['confidence']
angle = result[0]['leaning_angle']
keypoint_corr = result[0]['keypoint_corr']

dict_res = {}
dict_res["category"] = category
dict_res["confidence"] = confidence
dict_res["angle"] = angle
dict_res["keypoint_corr"] = keypoint_corr
return dict_res

return None
56 changes: 56 additions & 0 deletions install_requirements.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash

echo "Installing Ambianic dependencies"

# exit bash script on error
set -e

# verbose mode
set -x

# update apt-get and install sudo
apt-get update -y && apt-get install -y sudo

# check if python3 is installed
if python3 --version
then
echo "python3 is already installed."
else
# install python3 and pip3 which are not available by default on slim buster
echo "python3 is not available from the parent image. Installing python3 now."
sudo apt-get install -y python3 && apt-get install -y python3-pip
fi

# install numpy native lib
sudo apt-get install -y python3-numpy
sudo apt-get install -y libjpeg-dev zlib1g-dev


# install python dependencies
python3 -m pip install --upgrade pip
pip3 --version
pip3 install -r requirements.txt



echo "Installing tflite for x86 CPU"
if python3 --version | grep -q 3.8
then
pip3 install --force-reinstall https://github.com/google-coral/pycoral/releases/download/v1.0.1/tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl
else
pip3 install https://dl.google.com/coral/python/tflite_runtime-1.14.0-cp37-cp37m-linux_x86_64.whl
fi

pip3 list
pip3 show tflite-runtime



# [Cleanup]
sudo apt-get -y autoremove

# remove apt-get cache
sudo rm -rf /var/lib/apt/lists/*

# This is run automatically on Debian and Ubuntu, but just in case
sudo apt-get clean
Loading

0 comments on commit 6e439aa

Please sign in to comment.