From cafb1ed5d462126eb78b3cd4c621179b659ab019 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Thu, 25 Oct 2018 00:02:59 -0400 Subject: [PATCH 01/15] initial documentation for image_processing.tensorflow --- .../image_processing.tensorflow.markdown | 180 ++++++++++++++++++ source/images/supported_brands/tensorflow.png | Bin 0 -> 23652 bytes 2 files changed, 180 insertions(+) create mode 100644 source/_components/image_processing.tensorflow.markdown create mode 100644 source/images/supported_brands/tensorflow.png diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown new file mode 100644 index 000000000000..6c5c9f648433 --- /dev/null +++ b/source/_components/image_processing.tensorflow.markdown @@ -0,0 +1,180 @@ +--- +layout: page +title: "TensorFlow" +description: "Detect and recognize objects with TensorFlow." +date: 2018-10-24 00:00 +sidebar: true +comments: false +sharing: true +footer: true +logo: tensorflow.png +ha_category: Image Processing +featured: false +ha_release: 0.82 +--- + +The `tensorflow` image processing platform allows you to detect and recognize objects in a camera image using [TensorFlow](https://www.tensorflow.org/). The state of the entity is the number of objects detected, and recognized objects are listed in the `matches` attribute. The attribute provides the confidence `score` for recognition and the bounding `box` of the object for each detection category. + +## {% linkable_title Setup %} +TensorFlow is pre-configured in the [official home assistant docker image](https://hub.docker.com/r/homeassistant/home-assistant/). If you are using this image, you can skip this section. + +TensorFlow is special in that it can run on the CPU, or an Nvidia GPU using CUDA. Because of this, tensorflow is not listed in `REQUIREMENTS`. In your instance, you will need to pre-install either `tensorflow` or `tensorflow-gpu` via pip: + +```bash +# CPU +pip3 install tensorflow +# GPU +pip3 install tensorflow-gpu +``` + +Object detection also requires some dependancies outside of the core tensorflow package. These live in the [tensorflow/models](https://github.com/tensorflow/models/tree/master/research/object_detection) GitHub repository. The one we are interested in for this use case lives in `research/object_detection`. Since the repository is large, we will be cloning in `/tmp` and only moving the files this component needs. The rest can safely be deleted. Run the following, making sure to replace `/home/homeassistant/.homeassistant/` with the path to your config directory: + +```bash +cd /tmp + +# Clone the latest code from GitHub +git clone --depth 1 https://github.com/tensorflow/models.git tensorflow-models + +# download protobuf 3.4 +curl -OL https://github.com/google/protobuf/releases/download/v3.4.0/protoc-3.4.0-linux-x86_64.zip +unzip -a protoc-3.4.0-linux-x86_64.zip -d protobuf +mv protobuf/bin /tmp/tensorflow-models/research + +# Build the protobuf models +cd /tmp/tensorflow-models/research/ +./bin/protoc object_detection/protos/*.proto --python_out=. + +# Copy only necessary files +mkdir -p /home/homeassistant/.homeassistant/tensorflow/object_detection +touch /home/homeassistant/.homeassistant/tensorflow/object_detection/__init__.py +mv object_detection/data /home/homeassistant/.homeassistant/tensorflow/object_detection +mv object_detection/utils /home/homeassistant/.homeassistant/tensorflow/object_detection +mv object_detection/protos /home/homeassistant/.homeassistant/tensorflow/object_detection + +# Cleanup +rm -rf /tmp/* +``` + +Finally, you are ready to pick a model. Researchers have already built multiple TensorFlow object detection models using many open data sets like [COCO](http://cocodataset.org), [Kitti](http://www.cvlibs.net/datasets/kitti/), and [Open Images](https://github.com/openimages/dataset). + +This component can support all of them, and if you are feeling adventurous, you can even [roll your own](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/defining_your_own_model.md). + +For now, start with one of the COCO models available in the [Model Detection Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md). The trade-off here is accuracy vs speed. The `mAP` is an indication of the model's accuracy while the `ms` is inference speed (on an Nvidia Titan X). Most users won't see detection speeds close to what is listed. + +It is recommended to start with the `faster_rcnn_inception_v2_coco` model for users with a dedicated server with a decent CPU. If you are running on an ARM device like a Rasberry Pi, stick with a SSD MobileNet model like the `ssd_mobilenet_v2_coco` which was built for mobile devices. + +Whichever model you choose, download it and place the `frozen_inference_graph.pb` file somewhere accessible by Home Assistant like your config directory. + +## {% linkable_title Configuration %} + +To enable this platform in your installation, add the following to your `configuration.yaml` file: + +```yaml +# Example configuration.yaml entry +image_processing: + - platform: tensorflow + source: + - entity_id: camera.local_file + model: + graph: /home/homeassistant/.homeassistant/frozen_inference_graph.pb + labels: /home/homeassistant/.homeassistant/tensorflow/object_detection/data/mscoco_label_map.pbtxt + model_dir: /home/homeassistant/.homeassistant/tensorflow +``` + +{% configuration %} +source: + description: The list of image sources. + required: true + type: map + keys: + entity_id: + description: A camera entity id to get picture from. + required: true + type: string + name: + description: This parameter allows you to override the name of your `image_processing` entity. + required: false + type: string +file_out: + description: A [template](/docs/configuration/templating/#processing-incoming-data) for the component to save processed images including bounding boxes. `camera_entity` is available as the `entity_id` string of the triggered source camera. + required: false + type: list +model: + description: Information about the TensorFlow model. + required: true + type: map + keys: + graph: + description: Full path to `frozen_inference_graph.pb`. + required: true + type: file + labels: + description: Full path to a `*label_map.pbtext`. + required: false + type: file + default: /usr/src/app/tensorflow/object_detection/data/mscoco_label_map.pbtxt + model_dir: + description: Full path to tensorflow models directory. + required: false + type: directory + default: /usr/src/app/tensorflow + area: + description: Custom detection area. Only objects fully in this box will be reported. Top of image is 0, bottom is 1. Same left to right. + required: false + type: map + keys: + top: + description: Top line defined as % from top of image. + required: false + type: small_float + default: 0 + left: + description: Left line defined as % from left of image. + required: false + type: small_float + default: 0 + bottom: + description: Bottom line defined as % from top of image. + required: false + type: small_float + default: 1 + right: + description: Right line defined as % from left of image. + required: false + type: small_float + default: 1 + categories: + description: List of categories to include in object detection. Can be seen in the file provided to `labels`. + type: list + required: false +{% endconfiguration %} + +`categories` can also be defined as dictionary providing an `area` for each category as seen in the advanced configuration below: + +```yaml +# Example advanced configuration.yaml entry +image_processing: + - platform: tensorflow + source: + - entity_id: camera.local_file + file_out: + - "/tmp/{{ camera_entity.split('.')[1] }}_latest.jpg" + - "/tmp/{{ camera_entity.split('.')[1] }}_{{ now().strftime('%Y%m%d_%H%M%S') }}.jpg" + model: + graph: /home/homeassistant/.homeassistant/frozen_inference_graph.pb + labels: /home/homeassistant/.homeassistant/tensorflow/object_detection/data/mscoco_label_map.pbtxt + model_dir: /home/homeassistant/.homeassistant/tensorflow + categories: + - category: person + area: + # Exclude top 10% of image + top: 0.1 + # Exclude right 15% of image + right: 0.85 + - car + - truck +``` + +## {% linkable_title Optimising resources %} + +[Image processing components](https://www.home-assistant.io/components/image_processing/) process the image from a camera at a fixed period given by the `scan_interval`. This leads to excessive processing if the image on the camera hasn't changed, as the default `scan_interval` is 10 seconds. You can override this by adding to your config `scan_interval: 10000` (setting the interval to 10,000 seconds), and then call the `image_processing.scan` service when you actually want to perform processing. diff --git a/source/images/supported_brands/tensorflow.png b/source/images/supported_brands/tensorflow.png new file mode 100644 index 0000000000000000000000000000000000000000..e7208340a2c3ab68f163f407eb2f088f38a0dc9b GIT binary patch literal 23652 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 Hu0mjfx(@i{ literal 0 HcmV?d00001 From 02e9beccf20cad2697e70092f3e953643669389d Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Thu, 25 Oct 2018 15:34:36 -0400 Subject: [PATCH 02/15] add raw tag to fix template errors --- source/_components/image_processing.tensorflow.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 6c5c9f648433..81bddc24f65d 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -158,8 +158,8 @@ image_processing: source: - entity_id: camera.local_file file_out: - - "/tmp/{{ camera_entity.split('.')[1] }}_latest.jpg" - - "/tmp/{{ camera_entity.split('.')[1] }}_{{ now().strftime('%Y%m%d_%H%M%S') }}.jpg" + - "/tmp/{% raw %}{{ camera_entity.split('.')[1] }}{% endraw %}_latest.jpg" + - "/tmp/{% raw %}{{ camera_entity.split('.')[1] }}_{{ now().strftime('%Y%m%d_%H%M%S') }}{% endraw %}.jpg" model: graph: /home/homeassistant/.homeassistant/frozen_inference_graph.pb labels: /home/homeassistant/.homeassistant/tensorflow/object_detection/data/mscoco_label_map.pbtxt From 20ef1a5efeddd5438c1fdde29ff8c22f960d7046 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Thu, 25 Oct 2018 17:38:14 -0400 Subject: [PATCH 03/15] changes per review --- .../image_processing.tensorflow.markdown | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 81bddc24f65d..7449bea60941 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -16,9 +16,10 @@ ha_release: 0.82 The `tensorflow` image processing platform allows you to detect and recognize objects in a camera image using [TensorFlow](https://www.tensorflow.org/). The state of the entity is the number of objects detected, and recognized objects are listed in the `matches` attribute. The attribute provides the confidence `score` for recognition and the bounding `box` of the object for each detection category. ## {% linkable_title Setup %} -TensorFlow is pre-configured in the [official home assistant docker image](https://hub.docker.com/r/homeassistant/home-assistant/). If you are using this image, you can skip this section. -TensorFlow is special in that it can run on the CPU, or an Nvidia GPU using CUDA. Because of this, tensorflow is not listed in `REQUIREMENTS`. In your instance, you will need to pre-install either `tensorflow` or `tensorflow-gpu` via pip: +TensorFlow is pre-configured in the [official Home Assistant docker image](https://hub.docker.com/r/homeassistant/home-assistant/). If you are using this image, you can skip this section. + +TensorFlow is special in that it can run on the CPU, or a Nvidia GPU using CUDA. Because of this, tensorflow is not listed in `REQUIREMENTS`. In your instance, you will need to pre-install either `tensorflow` or `tensorflow-gpu` via pip: ```bash # CPU @@ -27,7 +28,7 @@ pip3 install tensorflow pip3 install tensorflow-gpu ``` -Object detection also requires some dependancies outside of the core tensorflow package. These live in the [tensorflow/models](https://github.com/tensorflow/models/tree/master/research/object_detection) GitHub repository. The one we are interested in for this use case lives in `research/object_detection`. Since the repository is large, we will be cloning in `/tmp` and only moving the files this component needs. The rest can safely be deleted. Run the following, making sure to replace `/home/homeassistant/.homeassistant/` with the path to your config directory: +Object detection also requires some dependencies outside of the core tensorflow package. These live in the [tensorflow/models](https://github.com/tensorflow/models/tree/master/research/object_detection) GitHub repository. The one we are interested in for this use case lives in `research/object_detection`. Since the repository is large, we will be cloning in `/tmp` and only moving the files this component needs. The rest can safely be deleted. Run the following, making sure to replace `/home/homeassistant/.homeassistant/` with the path to your config directory: ```bash cd /tmp @@ -55,13 +56,15 @@ mv object_detection/protos /home/homeassistant/.homeassistant/tensorflow/object_ rm -rf /tmp/* ``` +## {% linkable_title Model Selection %} + Finally, you are ready to pick a model. Researchers have already built multiple TensorFlow object detection models using many open data sets like [COCO](http://cocodataset.org), [Kitti](http://www.cvlibs.net/datasets/kitti/), and [Open Images](https://github.com/openimages/dataset). This component can support all of them, and if you are feeling adventurous, you can even [roll your own](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/defining_your_own_model.md). -For now, start with one of the COCO models available in the [Model Detection Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md). The trade-off here is accuracy vs speed. The `mAP` is an indication of the model's accuracy while the `ms` is inference speed (on an Nvidia Titan X). Most users won't see detection speeds close to what is listed. +For now, start with one of the COCO models available in the [Model Detection Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md). The trade-off here is accuracy vs speed. The `mAP` is an indication of the model's accuracy while the `ms` is inference speed (on a Nvidia Titan X). Most users won't see detection speeds close to what is listed. -It is recommended to start with the `faster_rcnn_inception_v2_coco` model for users with a dedicated server with a decent CPU. If you are running on an ARM device like a Rasberry Pi, stick with a SSD MobileNet model like the `ssd_mobilenet_v2_coco` which was built for mobile devices. +It is recommended to start with the `faster_rcnn_inception_v2_coco` model for users with a dedicated server with a decent CPU. If you are running on an ARM device like a Rasberry Pi, stick with an SSD MobileNet model like the `ssd_mobilenet_v2_coco` which was built for mobile devices. Whichever model you choose, download it and place the `frozen_inference_graph.pb` file somewhere accessible by Home Assistant like your config directory. @@ -107,44 +110,44 @@ model: graph: description: Full path to `frozen_inference_graph.pb`. required: true - type: file + type: string labels: description: Full path to a `*label_map.pbtext`. required: false - type: file + type: string default: /usr/src/app/tensorflow/object_detection/data/mscoco_label_map.pbtxt model_dir: description: Full path to tensorflow models directory. required: false - type: directory + type: string default: /usr/src/app/tensorflow area: - description: Custom detection area. Only objects fully in this box will be reported. Top of image is 0, bottom is 1. Same left to right. + description: Custom detection area. Only objects fully in this box will be reported. Top of image is 0, bottom is 1. Same left to right. required: false type: map keys: top: description: Top line defined as % from top of image. required: false - type: small_float + type: float default: 0 left: description: Left line defined as % from left of image. required: false - type: small_float + type: float default: 0 bottom: description: Bottom line defined as % from top of image. required: false - type: small_float + type: float default: 1 right: description: Right line defined as % from left of image. required: false - type: small_float + type: float default: 1 categories: - description: List of categories to include in object detection. Can be seen in the file provided to `labels`. + description: List of categories to include in object detection. Can be seen in the file provided to `labels`. type: list required: false {% endconfiguration %} From e078060a99b71ce212039ef581817324d7808949 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Fri, 2 Nov 2018 14:52:10 -0400 Subject: [PATCH 04/15] update documentation to reflect latest component changes and pull script out to gist --- .../image_processing.tensorflow.markdown | 59 ++++++------------- 1 file changed, 18 insertions(+), 41 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 7449bea60941..44da1106a192 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -13,48 +13,29 @@ featured: false ha_release: 0.82 --- -The `tensorflow` image processing platform allows you to detect and recognize objects in a camera image using [TensorFlow](https://www.tensorflow.org/). The state of the entity is the number of objects detected, and recognized objects are listed in the `matches` attribute. The attribute provides the confidence `score` for recognition and the bounding `box` of the object for each detection category. +The `tensorflow` image processing platform allows you to detect and recognize objects in a camera image using [TensorFlow](https://www.tensorflow.org/). The state of the entity is the number of objects detected, and recognized objects are listed in the `summary` attribute along with quantity. The `matches` attribute provides the confidence `score` for recognition and the bounding `box` of the object for each detection category. ## {% linkable_title Setup %} -TensorFlow is pre-configured in the [official Home Assistant docker image](https://hub.docker.com/r/homeassistant/home-assistant/). If you are using this image, you can skip this section. +TensorFlow object detection requires some dependencies outside of the core tensorflow package. These live in the [tensorflow/models](https://github.com/tensorflow/models/tree/master/research/object_detection) GitHub repository. The one we are interested in for this use case lives in `research/object_detection`. A general outline of the installation process is as follows: -TensorFlow is special in that it can run on the CPU, or a Nvidia GPU using CUDA. Because of this, tensorflow is not listed in `REQUIREMENTS`. In your instance, you will need to pre-install either `tensorflow` or `tensorflow-gpu` via pip: +- Clone [tensorflow/models](https://github.com/tensorflow/models/tree/master/research/object_detection) +- Compile protobuf models located in `research/object_detection/protos` with `protoc` +- Create the following directory structure inside your config directory: ```bash -# CPU -pip3 install tensorflow -# GPU -pip3 install tensorflow-gpu + |- deps + | - tensorflow + |- __init__.py + |- object_detection/ ``` -Object detection also requires some dependencies outside of the core tensorflow package. These live in the [tensorflow/models](https://github.com/tensorflow/models/tree/master/research/object_detection) GitHub repository. The one we are interested in for this use case lives in `research/object_detection`. Since the repository is large, we will be cloning in `/tmp` and only moving the files this component needs. The rest can safely be deleted. Run the following, making sure to replace `/home/homeassistant/.homeassistant/` with the path to your config directory: +- Copy required object_detection dependancies to the `object_detection` folder inside of the `tensorflow` folder: + - `research/object_detection/data` + - `research/object_detection/utils` + - `research/object_detection/protos` -```bash -cd /tmp - -# Clone the latest code from GitHub -git clone --depth 1 https://github.com/tensorflow/models.git tensorflow-models - -# download protobuf 3.4 -curl -OL https://github.com/google/protobuf/releases/download/v3.4.0/protoc-3.4.0-linux-x86_64.zip -unzip -a protoc-3.4.0-linux-x86_64.zip -d protobuf -mv protobuf/bin /tmp/tensorflow-models/research - -# Build the protobuf models -cd /tmp/tensorflow-models/research/ -./bin/protoc object_detection/protos/*.proto --python_out=. - -# Copy only necessary files -mkdir -p /home/homeassistant/.homeassistant/tensorflow/object_detection -touch /home/homeassistant/.homeassistant/tensorflow/object_detection/__init__.py -mv object_detection/data /home/homeassistant/.homeassistant/tensorflow/object_detection -mv object_detection/utils /home/homeassistant/.homeassistant/tensorflow/object_detection -mv object_detection/protos /home/homeassistant/.homeassistant/tensorflow/object_detection - -# Cleanup -rm -rf /tmp/* -``` +A sample script can be found at this gist: https://gist.github.com/hunterjm/6f9332f92b60c3d5e448ad936d7353c3 ## {% linkable_title Model Selection %} @@ -79,9 +60,7 @@ image_processing: source: - entity_id: camera.local_file model: - graph: /home/homeassistant/.homeassistant/frozen_inference_graph.pb - labels: /home/homeassistant/.homeassistant/tensorflow/object_detection/data/mscoco_label_map.pbtxt - model_dir: /home/homeassistant/.homeassistant/tensorflow + graph: /home/homeassistant/.homeassistant/deps/frozen_inference_graph.pb ``` {% configuration %} @@ -115,12 +94,12 @@ model: description: Full path to a `*label_map.pbtext`. required: false type: string - default: /usr/src/app/tensorflow/object_detection/data/mscoco_label_map.pbtxt + default: deps/tensorflow/object_detection/data/mscoco_label_map.pbtxt model_dir: description: Full path to tensorflow models directory. required: false type: string - default: /usr/src/app/tensorflow + default: deps/tensorflow inside config area: description: Custom detection area. Only objects fully in this box will be reported. Top of image is 0, bottom is 1. Same left to right. required: false @@ -164,9 +143,7 @@ image_processing: - "/tmp/{% raw %}{{ camera_entity.split('.')[1] }}{% endraw %}_latest.jpg" - "/tmp/{% raw %}{{ camera_entity.split('.')[1] }}_{{ now().strftime('%Y%m%d_%H%M%S') }}{% endraw %}.jpg" model: - graph: /home/homeassistant/.homeassistant/frozen_inference_graph.pb - labels: /home/homeassistant/.homeassistant/tensorflow/object_detection/data/mscoco_label_map.pbtxt - model_dir: /home/homeassistant/.homeassistant/tensorflow + graph: /home/homeassistant/.homeassistant/deps/frozen_inference_graph.pb categories: - category: person area: From 2f8da3648cf8bbca4342db83318fa4d9c6d62523 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Fri, 2 Nov 2018 15:24:31 -0400 Subject: [PATCH 05/15] do not use deps folder as default, as it should only be managed by HA. Update to have tensorflow in root config directory --- source/_components/image_processing.tensorflow.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 44da1106a192..adbfb6a787aa 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -24,7 +24,7 @@ TensorFlow object detection requires some dependencies outside of the core tenso - Create the following directory structure inside your config directory: ```bash - |- deps + |- {config_dir} | - tensorflow |- __init__.py |- object_detection/ From 07e6eb56bc650d385845e74e15f964ef23fd35a8 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Fri, 2 Nov 2018 15:42:41 -0400 Subject: [PATCH 06/15] make gist a link, remove additional deps references --- .../_components/image_processing.tensorflow.markdown | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index adbfb6a787aa..4c77e928e36d 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -35,7 +35,7 @@ TensorFlow object detection requires some dependencies outside of the core tenso - `research/object_detection/utils` - `research/object_detection/protos` -A sample script can be found at this gist: https://gist.github.com/hunterjm/6f9332f92b60c3d5e448ad936d7353c3 +A sample script can be found at [this gist](https://gist.github.com/hunterjm/6f9332f92b60c3d5e448ad936d7353c3). ## {% linkable_title Model Selection %} @@ -60,7 +60,7 @@ image_processing: source: - entity_id: camera.local_file model: - graph: /home/homeassistant/.homeassistant/deps/frozen_inference_graph.pb + graph: /home/homeassistant/.homeassistant/frozen_inference_graph.pb ``` {% configuration %} @@ -94,12 +94,12 @@ model: description: Full path to a `*label_map.pbtext`. required: false type: string - default: deps/tensorflow/object_detection/data/mscoco_label_map.pbtxt + default: tensorflow/object_detection/data/mscoco_label_map.pbtxt model_dir: description: Full path to tensorflow models directory. required: false type: string - default: deps/tensorflow inside config + default: /tensorflow inside config area: description: Custom detection area. Only objects fully in this box will be reported. Top of image is 0, bottom is 1. Same left to right. required: false @@ -143,7 +143,7 @@ image_processing: - "/tmp/{% raw %}{{ camera_entity.split('.')[1] }}{% endraw %}_latest.jpg" - "/tmp/{% raw %}{{ camera_entity.split('.')[1] }}_{{ now().strftime('%Y%m%d_%H%M%S') }}{% endraw %}.jpg" model: - graph: /home/homeassistant/.homeassistant/deps/frozen_inference_graph.pb + graph: /home/homeassistant/.homeassistant/frozen_inference_graph.pb categories: - category: person area: From 15d1f137fff33ee997e380b0dcb7062ec5c00669 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Sat, 3 Nov 2018 22:07:57 -0400 Subject: [PATCH 07/15] add additional cameras to example config, shorten model selection section, add warning at top for Hass.io --- .../image_processing.tensorflow.markdown | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 4c77e928e36d..d3b5ea0a5085 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -15,6 +15,10 @@ ha_release: 0.82 The `tensorflow` image processing platform allows you to detect and recognize objects in a camera image using [TensorFlow](https://www.tensorflow.org/). The state of the entity is the number of objects detected, and recognized objects are listed in the `summary` attribute along with quantity. The `matches` attribute provides the confidence `score` for recognition and the bounding `box` of the object for each detection category. +

+ This package will not yet work on Hass.io installations, but should work on Hassbian. [See here](https://www.tensorflow.org/install/pip) for system requirements. +

+ ## {% linkable_title Setup %} TensorFlow object detection requires some dependencies outside of the core tensorflow package. These live in the [tensorflow/models](https://github.com/tensorflow/models/tree/master/research/object_detection) GitHub repository. The one we are interested in for this use case lives in `research/object_detection`. A general outline of the installation process is as follows: @@ -39,15 +43,11 @@ A sample script can be found at [this gist](https://gist.github.com/hunterjm/6f9 ## {% linkable_title Model Selection %} -Finally, you are ready to pick a model. Researchers have already built multiple TensorFlow object detection models using many open data sets like [COCO](http://cocodataset.org), [Kitti](http://www.cvlibs.net/datasets/kitti/), and [Open Images](https://github.com/openimages/dataset). - -This component can support all of them, and if you are feeling adventurous, you can even [roll your own](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/defining_your_own_model.md). +Lastly, it is time to pick a model. It is recommended to start with one of the COCO models available in the [Model Detection Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md). -For now, start with one of the COCO models available in the [Model Detection Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md). The trade-off here is accuracy vs speed. The `mAP` is an indication of the model's accuracy while the `ms` is inference speed (on a Nvidia Titan X). Most users won't see detection speeds close to what is listed. +The trade-off between the different models is accuracy vs speed. Users with a decent CPU should start with the `faster_rcnn_inception_v2_coco` model. If you are running on an ARM device like a Rasberry Pi, start with the `ssd_mobilenet_v2_coco` model. -It is recommended to start with the `faster_rcnn_inception_v2_coco` model for users with a dedicated server with a decent CPU. If you are running on an ARM device like a Rasberry Pi, stick with an SSD MobileNet model like the `ssd_mobilenet_v2_coco` which was built for mobile devices. - -Whichever model you choose, download it and place the `frozen_inference_graph.pb` file somewhere accessible by Home Assistant like your config directory. +Whichever model you choose, download it and place the `frozen_inference_graph.pb` file somewhere in your config directory. ## {% linkable_title Configuration %} @@ -138,7 +138,8 @@ model: image_processing: - platform: tensorflow source: - - entity_id: camera.local_file + - entity_id: camera.driveway + - entity_id: camera.backyard file_out: - "/tmp/{% raw %}{{ camera_entity.split('.')[1] }}{% endraw %}_latest.jpg" - "/tmp/{% raw %}{{ camera_entity.split('.')[1] }}_{{ now().strftime('%Y%m%d_%H%M%S') }}{% endraw %}.jpg" From 0cd950e16cbbd387dc6d34317550183f24ff9fda Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Sun, 4 Nov 2018 01:06:25 -0400 Subject: [PATCH 08/15] Update warning adding further Hassbian instructions --- source/_components/image_processing.tensorflow.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index d3b5ea0a5085..4f658dfef87b 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -16,7 +16,9 @@ ha_release: 0.82 The `tensorflow` image processing platform allows you to detect and recognize objects in a camera image using [TensorFlow](https://www.tensorflow.org/). The state of the entity is the number of objects detected, and recognized objects are listed in the `summary` attribute along with quantity. The `matches` attribute provides the confidence `score` for recognition and the bounding `box` of the object for each detection category.

- This package will not yet work on Hass.io installations, but should work on Hassbian. [See here](https://www.tensorflow.org/install/pip) for system requirements. + This component will not yet work on Hass.io, but should work on Hassbian after following the setup and installing these packages: + + `sudo apt-get install libatlas-base-dev libopenjp2-7 libtiff5`

## {% linkable_title Setup %} From ae934080329db500b7f0beb2ac309959666dc2a6 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Sun, 4 Nov 2018 01:34:24 -0400 Subject: [PATCH 09/15] changes per PR review --- .../_components/image_processing.tensorflow.markdown | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 4f658dfef87b..83d036ab5b3c 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -23,7 +23,7 @@ The `tensorflow` image processing platform allows you to detect and recognize ob ## {% linkable_title Setup %} -TensorFlow object detection requires some dependencies outside of the core tensorflow package. These live in the [tensorflow/models](https://github.com/tensorflow/models/tree/master/research/object_detection) GitHub repository. The one we are interested in for this use case lives in `research/object_detection`. A general outline of the installation process is as follows: +This component requires files to be downloaded, compiled on your computer, and added to the Home Assistant configuration directory. These steps can be performed using the sample script at [this gist](https://gist.github.com/hunterjm/6f9332f92b60c3d5e448ad936d7353c3). Alternatively, if you wish to perform the process manually, the process is as follows: - Clone [tensorflow/models](https://github.com/tensorflow/models/tree/master/research/object_detection) - Compile protobuf models located in `research/object_detection/protos` with `protoc` @@ -41,15 +41,13 @@ TensorFlow object detection requires some dependencies outside of the core tenso - `research/object_detection/utils` - `research/object_detection/protos` -A sample script can be found at [this gist](https://gist.github.com/hunterjm/6f9332f92b60c3d5e448ad936d7353c3). - ## {% linkable_title Model Selection %} Lastly, it is time to pick a model. It is recommended to start with one of the COCO models available in the [Model Detection Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md). The trade-off between the different models is accuracy vs speed. Users with a decent CPU should start with the `faster_rcnn_inception_v2_coco` model. If you are running on an ARM device like a Rasberry Pi, start with the `ssd_mobilenet_v2_coco` model. -Whichever model you choose, download it and place the `frozen_inference_graph.pb` file somewhere in your config directory. +Whichever model you choose, download it and place the `frozen_inference_graph.pb` file in the `tensorflow` folder in your config directory. ## {% linkable_title Configuration %} @@ -62,7 +60,7 @@ image_processing: source: - entity_id: camera.local_file model: - graph: /home/homeassistant/.homeassistant/frozen_inference_graph.pb + graph: /home/homeassistant/.homeassistant/tensorflow/frozen_inference_graph.pb ``` {% configuration %} @@ -146,7 +144,7 @@ image_processing: - "/tmp/{% raw %}{{ camera_entity.split('.')[1] }}{% endraw %}_latest.jpg" - "/tmp/{% raw %}{{ camera_entity.split('.')[1] }}_{{ now().strftime('%Y%m%d_%H%M%S') }}{% endraw %}.jpg" model: - graph: /home/homeassistant/.homeassistant/frozen_inference_graph.pb + graph: /home/homeassistant/.homeassistant/tensorflow/frozen_inference_graph.pb categories: - category: person area: From ef9f84bc0156339f76762bacfc65690e43414d73 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Sun, 4 Nov 2018 01:40:45 -0400 Subject: [PATCH 10/15] fix init location in docs --- source/_components/image_processing.tensorflow.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 83d036ab5b3c..94b9ac1913d1 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -31,9 +31,9 @@ This component requires files to be downloaded, compiled on your computer, and a ```bash |- {config_dir} - | - tensorflow - |- __init__.py + | - tensorflow/ |- object_detection/ + |- __init__.py ``` - Copy required object_detection dependancies to the `object_detection` folder inside of the `tensorflow` folder: From 1c610db28fcdd3999c02df4d081406c9c6f8da03 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Sun, 4 Nov 2018 01:44:25 -0400 Subject: [PATCH 11/15] fix spelling of raspberry --- source/_components/image_processing.tensorflow.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 94b9ac1913d1..0b0fe910fecd 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -45,7 +45,7 @@ This component requires files to be downloaded, compiled on your computer, and a Lastly, it is time to pick a model. It is recommended to start with one of the COCO models available in the [Model Detection Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md). -The trade-off between the different models is accuracy vs speed. Users with a decent CPU should start with the `faster_rcnn_inception_v2_coco` model. If you are running on an ARM device like a Rasberry Pi, start with the `ssd_mobilenet_v2_coco` model. +The trade-off between the different models is accuracy vs speed. Users with a decent CPU should start with the `faster_rcnn_inception_v2_coco` model. If you are running on an ARM device like a Raspberry Pi, start with the `ssd_mobilenet_v2_coco` model. Whichever model you choose, download it and place the `frozen_inference_graph.pb` file in the `tensorflow` folder in your config directory. From 2d08c9b2773a1b85251ba2ab9ba81a8f31dc14d9 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 4 Nov 2018 13:56:39 +0100 Subject: [PATCH 12/15] Update image_processing.tensorflow.markdown --- source/_components/image_processing.tensorflow.markdown | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 0b0fe910fecd..3520b0c5a5fa 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -16,13 +16,14 @@ ha_release: 0.82 The `tensorflow` image processing platform allows you to detect and recognize objects in a camera image using [TensorFlow](https://www.tensorflow.org/). The state of the entity is the number of objects detected, and recognized objects are listed in the `summary` attribute along with quantity. The `matches` attribute provides the confidence `score` for recognition and the bounding `box` of the object for each detection category.

- This component will not yet work on Hass.io, but should work on Hassbian after following the setup and installing these packages: - + To work with Hassbian after following the setup and installing these packages: `sudo apt-get install libatlas-base-dev libopenjp2-7 libtiff5`

## {% linkable_title Setup %} +You need install tensorflow python packages with: `pip3 install tensorflow`. The wheel are not available for all platforms, it could be that you need compile it from source. Hass.io have this allready preinstalled. + This component requires files to be downloaded, compiled on your computer, and added to the Home Assistant configuration directory. These steps can be performed using the sample script at [this gist](https://gist.github.com/hunterjm/6f9332f92b60c3d5e448ad936d7353c3). Alternatively, if you wish to perform the process manually, the process is as follows: - Clone [tensorflow/models](https://github.com/tensorflow/models/tree/master/research/object_detection) From c1cd04c240e6b194b98a6edf8b04adbe841d4218 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 4 Nov 2018 14:24:31 +0100 Subject: [PATCH 13/15] Minor changes --- .../image_processing.tensorflow.markdown | 93 ++++++++++--------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 3520b0c5a5fa..8b97b0a81ff3 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -17,12 +17,12 @@ The `tensorflow` image processing platform allows you to detect and recognize ob

To work with Hassbian after following the setup and installing these packages: - `sudo apt-get install libatlas-base-dev libopenjp2-7 libtiff5` + `$ sudo apt-get install libatlas-base-dev libopenjp2-7 libtiff5`

## {% linkable_title Setup %} -You need install tensorflow python packages with: `pip3 install tensorflow`. The wheel are not available for all platforms, it could be that you need compile it from source. Hass.io have this allready preinstalled. +You need install `tensorflow` Python packages with: `$ pip3 install tensorflow`. The wheel are not available for all platforms, it could be that you need compile it from source. Hass.io have this already preinstalled. This component requires files to be downloaded, compiled on your computer, and added to the Home Assistant configuration directory. These steps can be performed using the sample script at [this gist](https://gist.github.com/hunterjm/6f9332f92b60c3d5e448ad936d7353c3). Alternatively, if you wish to perform the process manually, the process is as follows: @@ -38,17 +38,18 @@ This component requires files to be downloaded, compiled on your computer, and a ``` - Copy required object_detection dependancies to the `object_detection` folder inside of the `tensorflow` folder: - - `research/object_detection/data` - - `research/object_detection/utils` - - `research/object_detection/protos` + + - `research/object_detection/data` + - `research/object_detection/utils` + - `research/object_detection/protos` ## {% linkable_title Model Selection %} -Lastly, it is time to pick a model. It is recommended to start with one of the COCO models available in the [Model Detection Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md). +Lastly, it is time to pick a model. It is recommended to start with one of the COCO models available in the [Model Detection Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md). The trade-off between the different models is accuracy vs speed. Users with a decent CPU should start with the `faster_rcnn_inception_v2_coco` model. If you are running on an ARM device like a Raspberry Pi, start with the `ssd_mobilenet_v2_coco` model. -Whichever model you choose, download it and place the `frozen_inference_graph.pb` file in the `tensorflow` folder in your config directory. +Whichever model you choose, download it and place the `frozen_inference_graph.pb` file in the `tensorflow` folder in your configuration directory. ## {% linkable_title Configuration %} @@ -87,49 +88,49 @@ model: required: true type: map keys: - graph: - description: Full path to `frozen_inference_graph.pb`. - required: true - type: string - labels: - description: Full path to a `*label_map.pbtext`. + graph: + description: Full path to `frozen_inference_graph.pb`. + required: true + type: string + labels: + description: Full path to a `*label_map.pbtext`. + required: false + type: string + default: tensorflow/object_detection/data/mscoco_label_map.pbtxt + model_dir: + description: Full path to tensorflow models directory. + required: false + type: string + default: /tensorflow inside config + area: + description: Custom detection area. Only objects fully in this box will be reported. Top of image is 0, bottom is 1. Same left to right. + required: false + type: map + keys: + top: + description: Top line defined as % from top of image. required: false - type: string - default: tensorflow/object_detection/data/mscoco_label_map.pbtxt - model_dir: - description: Full path to tensorflow models directory. + type: float + default: 0 + left: + description: Left line defined as % from left of image. required: false - type: string - default: /tensorflow inside config - area: - description: Custom detection area. Only objects fully in this box will be reported. Top of image is 0, bottom is 1. Same left to right. + type: float + default: 0 + bottom: + description: Bottom line defined as % from top of image. required: false - type: map - keys: - top: - description: Top line defined as % from top of image. - required: false - type: float - default: 0 - left: - description: Left line defined as % from left of image. - required: false - type: float - default: 0 - bottom: - description: Bottom line defined as % from top of image. - required: false - type: float - default: 1 - right: - description: Right line defined as % from left of image. - required: false - type: float - default: 1 - categories: - description: List of categories to include in object detection. Can be seen in the file provided to `labels`. - type: list + type: float + default: 1 + right: + description: Right line defined as % from left of image. required: false + type: float + default: 1 + categories: + description: List of categories to include in object detection. Can be seen in the file provided to `labels`. + type: list + required: false {% endconfiguration %} `categories` can also be defined as dictionary providing an `area` for each category as seen in the advanced configuration below: From 460fbb250ceae583a7e67c02536da7eababdc638 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 4 Nov 2018 14:29:54 +0100 Subject: [PATCH 14/15] Add class --- source/_components/image_processing.tensorflow.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 8b97b0a81ff3..4171dac63776 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -9,7 +9,7 @@ sharing: true footer: true logo: tensorflow.png ha_category: Image Processing -featured: false +ha_iot_class: "Local Polling" ha_release: 0.82 --- @@ -47,7 +47,7 @@ This component requires files to be downloaded, compiled on your computer, and a Lastly, it is time to pick a model. It is recommended to start with one of the COCO models available in the [Model Detection Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md). -The trade-off between the different models is accuracy vs speed. Users with a decent CPU should start with the `faster_rcnn_inception_v2_coco` model. If you are running on an ARM device like a Raspberry Pi, start with the `ssd_mobilenet_v2_coco` model. +The trade-off between the different models is accuracy vs speed. Users with a decent CPU should start with the `faster_rcnn_inception_v2_coco` model. If you are running on an ARM device like a Raspberry Pi, start with the `ssd_mobilenet_v2_coco` model. Whichever model you choose, download it and place the `frozen_inference_graph.pb` file in the `tensorflow` folder in your configuration directory. From e3d2db7049c49e8b447df1cfd324065b8b5c09f4 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Sun, 4 Nov 2018 16:57:49 -0500 Subject: [PATCH 15/15] add link to tensorflow install site for additional installation options --- source/_components/image_processing.tensorflow.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/_components/image_processing.tensorflow.markdown b/source/_components/image_processing.tensorflow.markdown index 4171dac63776..81c9324007b9 100644 --- a/source/_components/image_processing.tensorflow.markdown +++ b/source/_components/image_processing.tensorflow.markdown @@ -16,13 +16,13 @@ ha_release: 0.82 The `tensorflow` image processing platform allows you to detect and recognize objects in a camera image using [TensorFlow](https://www.tensorflow.org/). The state of the entity is the number of objects detected, and recognized objects are listed in the `summary` attribute along with quantity. The `matches` attribute provides the confidence `score` for recognition and the bounding `box` of the object for each detection category.

- To work with Hassbian after following the setup and installing these packages: + The following packages must be installed on Hassbian after following the setup for the component to work: `$ sudo apt-get install libatlas-base-dev libopenjp2-7 libtiff5`

## {% linkable_title Setup %} -You need install `tensorflow` Python packages with: `$ pip3 install tensorflow`. The wheel are not available for all platforms, it could be that you need compile it from source. Hass.io have this already preinstalled. +You need to install the `tensorflow` Python packages with: `$ pip3 install tensorflow`. The wheel is not available for all platforms. See [the official install guide](https://www.tensorflow.org/install/) for other options. Hass.io has this package pre-installed. This component requires files to be downloaded, compiled on your computer, and added to the Home Assistant configuration directory. These steps can be performed using the sample script at [this gist](https://gist.github.com/hunterjm/6f9332f92b60c3d5e448ad936d7353c3). Alternatively, if you wish to perform the process manually, the process is as follows: