diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 47840bab..00000000
--- a/.coveragerc
+++ /dev/null
@@ -1,13 +0,0 @@
-[run]
-branch = True
-source = src
-
-[report]
-exclude_lines =
- if self.debug:
- pragma: no cover
- raise NotImplementedError
- if __name__ == .__main__.:
-ignore_errors = True
-omit =
- tests/*
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 481d6a68..fe4e5bd1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,9 @@ env
__pycache__
*.pyc
.DS_Store
+MANIFEST
+*.egg-info
+dist/
+.pypirc
+.remote-sync.json
+links.txt
diff --git a/.pylintrc b/.pylintrc
deleted file mode 100644
index 9eb3a1b5..00000000
--- a/.pylintrc
+++ /dev/null
@@ -1,424 +0,0 @@
-# This file was mostly generated with pylint --generate-rcfile. To see changes
-# from the default values, search for "DEFAULT" in this file.
-
-[MASTER]
-
-# Specify a configuration file.
-#rcfile=
-
-# Python code to execute, usually for sys.path manipulation such as
-# pygtk.require().
-#init-hook=
-
-# Add files or directories to the blacklist. They should be base names, not
-# paths.
-ignore=CVS
-
-# Add files or directories matching the regex patterns to the blacklist. The
-# regex matches against base names, not paths.
-ignore-patterns=
-
-# Pickle collected data for later comparisons.
-persistent=yes
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-# Use multiple processes to speed up Pylint.
-jobs=1
-
-# Allow loading of arbitrary C extensions. Extensions are imported into the
-# active Python interpreter and may run arbitrary code.
-unsafe-load-any-extension=no
-
-# A comma-separated list of package or module names from where C extensions may
-# be loaded. Extensions are loading into the active Python interpreter and may
-# run arbitrary code
-extension-pkg-whitelist=
-
-# Allow optimization of some AST trees. This will activate a peephole AST
-# optimizer, which will apply various small optimizations. For instance, it can
-# be used to obtain the result of joining multiple strings with the addition
-# operator. Joining a lot of strings can lead to a maximum recursion error in
-# Pylint and this flag can prevent that. It has one side effect, the resulting
-# AST will be different than the one from reality. This option is deprecated
-# and it will be removed in Pylint 2.0.
-optimize-ast=no
-
-
-[MESSAGES CONTROL]
-
-# Only show warnings with the listed confidence levels. Leave empty to show
-# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
-confidence=
-
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time (only on the command line, not in the configuration file where
-# it should appear only once). See also the "--disable" option for examples.
-#enable=
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifiers separated by comma (,) or put this
-# option multiple times (only on the command line, not in the configuration
-# file where it should appear only once).You can also use "--disable=all" to
-# disable everything first and then reenable specific checks. For example, if
-# you want to run only the similarities checker, you can use "--disable=all
-# --enable=similarities". If you want to run only the classes checker, but have
-# no Warning level messages displayed, use"--disable=all --enable=classes
-# --disable=W"
-# DEFAULT: without fixme,invalid-name,no-self-use
-# RATIONALE: (fixme) It generates warnings for TODOs.
-# RATIONALE: (invalid-name) It rejects class-level constants and short names.
-# RATIONALE: (no-self-use) @staticmethod is discouraged by Google style.
-disable=backtick,reduce-builtin,nonzero-method,long-suffix,file-builtin,indexing-exception,buffer-builtin,standarderror-builtin,apply-builtin,delslice-method,unicode-builtin,suppressed-message,zip-builtin-not-iterating,intern-builtin,old-octal-literal,old-division,range-builtin-not-iterating,useless-suppression,print-statement,filter-builtin-not-iterating,cmp-builtin,coerce-builtin,input-builtin,setslice-method,execfile-builtin,long-builtin,raising-string,getslice-method,cmp-method,coerce-method,next-method-called,raw_input-builtin,oct-method,import-star-module-level,unichr-builtin,round-builtin,parameter-unpacking,map-builtin-not-iterating,unpacking-in-except,dict-view-method,dict-iter-method,hex-method,old-raise-syntax,basestring-builtin,metaclass-assignment,using-cmp-argument,no-absolute-import,xrange-builtin,old-ne-operator,reload-builtin,fixme,invalid-name,no-self-use
-
-
-[REPORTS]
-
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html. You can also give a reporter class, eg
-# mypackage.mymodule.MyReporterClass.
-output-format=text
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]". This option is deprecated
-# and it will be removed in Pylint 2.0.
-files-output=no
-
-# Tells whether to display a full report or only the messages
-reports=yes
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Template used to display messages. This is a python new-style format string
-# used to format the message information. See doc for all details
-#msg-template=
-
-
-[SPELLING]
-
-# Spelling dictionary name. Available dictionaries: none. To make it working
-# install python-enchant package.
-spelling-dict=
-
-# List of comma separated words that should not be checked.
-spelling-ignore-words=
-
-# A path to a file that contains private dictionary; one word per line.
-spelling-private-dict-file=
-
-# Tells whether to store unknown words to indicated private dictionary in
-# --spelling-private-dict-file option instead of raising a message.
-spelling-store-unknown-words=no
-
-
-[FORMAT]
-
-# Maximum number of characters on a single line.
-max-line-length=100
-
-# Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=^\s*(# )??$
-
-# Allow the body of an if to be on the same line as the test if there is no
-# else.
-single-line-if-stmt=no
-
-# List of optional constructs for which whitespace checking is disabled. `dict-
-# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
-# `trailing-comma` allows a space between comma and closing bracket: (a, ).
-# `empty-line` allows space-only lines.
-no-space-check=trailing-comma,dict-separator
-
-# Maximum number of lines in a module
-max-module-lines=1000
-
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string=' '
-
-# Number of spaces of indent required inside a hanging or continued line.
-indent-after-paren=4
-
-# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
-expected-line-ending-format=
-
-
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
-
-
-[LOGGING]
-
-# Logging modules to check that the string format arguments are in logging
-# function parameter format
-logging-modules=logging
-
-
-[TYPECHECK]
-
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# List of module names for which member attributes should not be checked
-# (useful for modules/projects where namespaces are manipulated during runtime
-# and thus existing member attributes cannot be deduced by static analysis. It
-# supports qualified module names, as well as Unix pattern matching.
-ignored-modules=configargparse,google,grpc,numpy,oauth2client,RPi.GPIO,scipy,googlesamples
-
-# List of class names for which member attributes should not be checked (useful
-# for classes with dynamically set attributes). This supports the use of
-# qualified names.
-ignored-classes=optparse.Values,thread._local,_thread._local
-
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E1101 when accessed. Python regular
-# expressions are accepted.
-generated-members=.*Response.*
-
-# List of decorators that produce context managers, such as
-# contextlib.contextmanager. Add to this list to register other decorators that
-# produce valid context managers.
-contextmanager-decorators=contextlib.contextmanager
-
-
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-# Ignore imports when computing similarities.
-ignore-imports=no
-
-
-[BASIC]
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
-
-# Colon-delimited sets of names that determine each other's naming style when
-# the name regexes allow several styles.
-name-group=
-
-# Include a hint for the correct naming format with invalid-name
-include-naming-hint=no
-
-# List of decorators that produce properties, such as abc.abstractproperty. Add
-# to this list to register other decorators that produce valid properties.
-property-classes=abc.abstractproperty
-
-# Regular expression matching correct variable names
-variable-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Naming hint for variable names
-variable-name-hint=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression matching correct constant names
-const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Naming hint for constant names
-const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Regular expression matching correct class attribute names
-class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
-
-# Naming hint for class attribute names
-class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
-
-# Regular expression matching correct inline iteration names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
-
-# Naming hint for inline iteration names
-inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
-
-# Regular expression matching correct function names
-function-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Naming hint for function names
-function-name-hint=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression matching correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
-
-# Naming hint for class names
-class-name-hint=[A-Z_][a-zA-Z0-9]+$
-
-# Regular expression matching correct attribute names
-attr-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Naming hint for attribute names
-attr-name-hint=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression matching correct argument names
-argument-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Naming hint for argument names
-argument-name-hint=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression matching correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Naming hint for module names
-module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Regular expression matching correct method names
-method-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Naming hint for method names
-method-name-hint=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match function or class names that do
-# not require a docstring.
-# DEFAULT: ^_
-# RATIONALE: Docstring for main would duplicate file docstring.
-no-docstring-rgx=^_|^main$
-
-# Minimum line length for functions/classes that require docstrings, shorter
-# ones are exempt.
-# DEFAULT: -1
-# RATIONALE: Lots of short methods, where docstrings would be repetitive.
-docstring-min-length=10
-
-
-[ELIF]
-
-# Maximum number of nested blocks for function / method body
-max-nested-blocks=5
-
-
-[VARIABLES]
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching the name of dummy variables (i.e. expectedly
-# not used).
-dummy-variables-rgx=(_+[a-zA-Z0-9]*?$)|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-# DEFAULT: none
-# RATIONALE: Provided by gettext.
-additional-builtins=_
-
-# List of strings which can identify a callback function by name. A callback
-# name must start or end with one of those strings.
-callbacks=cb_,_cb
-
-# List of qualified module names which can have objects that can redefine
-# builtins.
-redefining-builtins-modules=six.moves,future.builtins
-
-
-[CLASSES]
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
-
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls
-
-# List of valid names for the first argument in a metaclass class method.
-valid-metaclass-classmethod-first-arg=mcs
-
-# List of member names, which should be excluded from the protected access
-# warning.
-exclude-protected=_asdict,_fields,_replace,_source,_make
-
-
-[DESIGN]
-
-# Maximum number of arguments for function / method
-# DEFAULT: 5
-# RATIONALE: Keyword arguments make this manageable.
-max-args=10
-
-# Argument names that match this expression will be ignored. Default to name
-# with leading underscore
-ignored-argument-names=_.*
-
-# Maximum number of locals for function / method body
-max-locals=15
-
-# Maximum number of return / yield for function / method body
-max-returns=6
-
-# Maximum number of branch for function / method body
-max-branches=12
-
-# Maximum number of statements in function / method body
-max-statements=50
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=7
-
-# Minimum number of public methods for a class (see R0903).
-# DEFAULT: 2
-# RATIONALE: Classes can have docstrings, namedtuples can't.
-min-public-methods=0
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
-
-# Maximum number of boolean expressions in a if statement
-max-bool-expr=5
-
-
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=optparse
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
-
-# Force import order to recognize a module as part of the standard
-# compatibility libraries.
-known-standard-library=audioop
-
-# Force import order to recognize a module as part of a third party library.
-known-third-party=enchant
-
-# Analyse import fallback blocks. This can be used to support both Python 2 and
-# 3 compatible code, which means that the block might have code that exists
-# only in one or another interpreter, leading to false positives when analysed.
-analyse-fallback-blocks=no
-
-
-[EXCEPTIONS]
-
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=Exception
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 373991c3..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-language: python
-python:
-- 3.4
-
-before_install:
-- sudo apt-get update -qq
-- sudo apt-get install -y python3-numpy python3-scipy
-
-install:
-- pip3 install pyflakes coverage pycodestyle
-- pip3 install -r requirements.txt
-
-script:
-- pycodestyle --max-line-length=100 --exclude=*_pb2.py .
-- nosetests --with-coverage
-
-after_success:
-- bash <(curl -s https://codecov.io/bash)
-
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 07603f52..00000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# How to contribute
-
-We'd love to accept your patches and contributions to this project. There are
-just a few small guidelines you need to follow.
-
-## Scope of contributions
-
-This project consists of the support libraries (audio, gRPC, etc) required for AIY Projects, as well as simple examples to experiment with and build upon.
-
-Please limit pull requests to bug fixes or improvements to code or documentation clarity.
-We're not accepting pull requests that add new commands to keep this project as simple as possible.
-If you've added new commands and you'd like to publish your fork for others to use, you can post on [hackster.io](https://www.hackster.io/) or other channels.
-
-## Contributor License Agreement
-
-Contributions to this project must be accompanied by a Contributor License
-Agreement. You (or your employer) retain the copyright to your contribution,
-this simply gives us permission to use and redistribute your contributions as
-part of the project. Head over to to see
-your current agreements on file or to sign a new one.
-
-You generally only need to submit a CLA once, so if you've already submitted one
-(even if it was for a different project), you probably don't need to do it
-again.
-
-## Code reviews
-
-All submissions, including submissions by project members, require review. We
-use GitHub pull requests for this purpose. Consult [GitHub Help] for more
-information on using pull requests.
-
-[GitHub Help]: https://help.github.com/articles/about-pull-requests/
-
diff --git a/HACKING.md b/HACKING.md
deleted file mode 100644
index aadfb96b..00000000
--- a/HACKING.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Setting up the image
-
-We recommend using [the images](https://aiyprojects.withgoogle.com/voice) we
-provide. Those images are based on [Raspbian](https://www.raspberrypi.org/downloads/raspbian/),
-with a few customizations and are tested on the Raspberry Pi 3. If you prefer
-to setup Raspbian yourself, there are some manual steps you need to take.
-
-## Installing the dependencies
-
-First, make sure you have `git` installed and clone this repository in
-`~/AIY-projects-python`:
-
-```shell
-sudo apt-get install git
-cd
-git clone https://github.com/google/aiyprojects-raspbian.git AIY-projects-python
-```
-
-Then, install the project dependencies and setup the services:
-
-``` shell
-cd ~/AIY-projects-python
-scripts/install-deps.sh
-sudo scripts/install-services.sh
-```
-
-## Configuring the Voice HAT driver
-
-To use the Voice HAT, your kernel needs to be 4.9 or later. This is available
-on Raspbian 2017-07-05 and later. You'll also need to configure ALSA:
-
-``` shell
-sudo scripts/configure-driver.sh
-sudo reboot
-```
-
-After your Pi has rebooted with the driver enabled, run:
-
-```
-cd ~/AIY-projects-python
-sudo scripts/install-alsa-config.sh
-env/bin/python checkpoints/check_audio.py
-sudo reboot
-```
-
-Don't skip running `check_audio.py` before rebooting, as it has an important
-effect on the state of ALSA, the sound architecture.
-
-## Get cloud credentials
-
-To access the cloud services you need to register a project and generate
-credentials for cloud APIs. This is documented in the
-[setup instructions](https://aiyprojects.withgoogle.com/voice#users-guide-1-1--connect-to-google-cloud-platform) on the
-webpage.
-
-## Making code changes
-
-If you edit the code on a different computer, you can deploy it to your
-Raspberry Pi by running:
-
-``` shell
-make deploy
-```
-
-## Running automatically
-
-You can find sample scripts in the `src` directory showing how to use the
-Assistant SDK.
-
-To execute any of these scripts on the Raspberry Pi, login to it and run
-(replacing the filename with the script you want to run):
-
-``` shell
-cd ~/AIY-projects-python
-source env/bin/activate
-python3 src/examples/voice/assistant_library_demo.py
-```
-
-If you want the voice recognizer service to run automatically when the Pi
-boots, you need to have a file in the `src` directory named `main.py`. You can
-make a copy of one of the example scripts and rename it. Then run this command:
-
-``` shell
-sudo systemctl enable voice-recognizer.service
-```
diff --git a/LICENSE b/LICENSE.txt
similarity index 100%
rename from LICENSE
rename to LICENSE.txt
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 5b72648c..00000000
--- a/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-PI ?= raspberrypi.local
-
-SHORTCUTS = $(wildcard shortcuts/*.desktop)
-
-check:
- PYTHONPATH=$$PWD/src python3 -m unittest discover tests
-
-deploy_scripts:
- git ls-files | rsync -avz --exclude=".*" --exclude="*.desktop" --files-from - . pi@$(PI):~/AIY-projects-python
-
-deploy_shortcuts:
- scp $(SHORTCUTS) pi@$(PI):~/Desktop
-
-deploy: deploy_scripts deploy_shortcuts
diff --git a/README.md b/README.md
index d272dbf4..4d69cbca 100644
--- a/README.md
+++ b/README.md
@@ -1,42 +1,239 @@
-
+# AIY Voice Only
-This repository contains an easy-to-use API for the AIY Vision Kit and
-AIY Voice Kit.
-You can use it for face detection and object recognition, or use it to create
-voice commands with simple while loops - have a look at the
-[demos](https://github.com/google/aiyprojects-raspbian/tree/aiyprojects/src/examples).
-Documentation is at the [AIY Projects site](https://aiyprojects.withgoogle.com).
+[Google AIY Voice Kit](https://aiyprojects.withgoogle.com/voice) is a cool
+project. But it locks you into its custom hardware. I have separated its
+software to work on Raspberry Pi (3B and 3B+) independently, just using a normal
+speaker and microphone.
-For guidelines on contributing, look at [CONTRIBUTING.md](CONTRIBUTING.md).
-If you're using Raspbian instead of Google's provided image, read
-[HACKING.md](HACKING.md) for information on getting started.
+The following instructions aim at:
-For returning users:
-The code for all AIY kits is in the `aiyprojects` branch, and is included in
-images starting with aiyprojects-2017-12-18.img. The previous `voicekit` branch
-contains code just for the Voice Kit, and the `master` branch contains the
-original, deprecated Voice Recognizer demo.
+**Raspberry Pi (3B, 3B+)**
+**Raspbian Stretch**
+**Python 3**
-# Support
+Additionally, you need:
-If you're having trouble assembling your kit or running the demos,
-try the [AIY Forums](https://www.raspberrypi.org/forums/viewforum.php?f=114).
+- a **Speaker** to plug into Raspberry Pi's headphone jack
+- a **USB Microphone**
-If you've found a bug in the AIY API or demos, you can look at the
-[known issues](https://github.com/google/aiyprojects-raspbian/issues) or create
-a new one, or even fix it yourself and send us a pull request.
+**Plug them in.** Let's go.
-If you've found a problem with the Assistant (for example, crashes in the
-library or incorrect responses), you can try
-[the G+ community](https://plus.google.com/communities/117537996116836200696),
-[Stack Overflow](https://stackoverflow.com/questions/tagged/google-assistant-sdk),
-or [the assistant-sdk-python repo](https://github.com/googlesamples/assistant-sdk-python/).
+## Find your speaker and mic
-If you've had a problem after updating the source code, try downloading the
-latest AIY image from the website, or alternatively run the following commands
-in the dev terminal:
+Locate your speaker in the list of playback hardware devices. Normally, it is at
+**card 0, device 0**, as indicated by the sample output below.
```
-rm -r env
-./scripts/install-deps.sh
+$ aplay -l
+
+**** List of PLAYBACK Hardware Devices ****
+card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
+ Subdevices: 8/8
+ Subdevice #0: subdevice #0
+ Subdevice #1: subdevice #1
+ Subdevice #2: subdevice #2
+ Subdevice #3: subdevice #3
+ Subdevice #4: subdevice #4
+ Subdevice #5: subdevice #5
+ Subdevice #6: subdevice #6
+ Subdevice #7: subdevice #7
+card 0: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI]
+ Subdevices: 1/1
+ Subdevice #0: subdevice #0
+```
+
+Locate your USB microphone in the list of capture hardware devices. Normally, it
+is at **card 1, device 0**, as indicated by the sample output below.
+
+```
+$ arecord -l
+
+**** List of CAPTURE Hardware Devices ****
+card 1: Device [USB PnP Audio Device], device 0: USB Audio [USB Audio]
+ Subdevices: 1/1
+ Subdevice #0: subdevice #0
+```
+
+*Your hardware's number might be different from mine. Adapt accordingly.*
+
+## Make them the defaults
+
+Create a new file named `.asoundrc` in the home directory (`/home/pi`). Put in
+the following contents. Adjust the `card,device` number if needed.
+
+```
+pcm.!default {
+ type asym
+ capture.pcm "mic"
+ playback.pcm "speaker"
+}
+pcm.mic {
+ type plug
+ slave {
+ pcm "hw:1,0" # card number, device number
+ }
+}
+pcm.speaker {
+ type plug
+ slave {
+ pcm "hw:0,0" # card number, device number
+ }
+}
+```
+
+## Make sure sound output to headphone jack
+
+Sound may be output via HDMI or headphone jack. We want to use the headphone
+jack.
+
+Enter `sudo raspi-config`. Select **Advanced Options**, then **Audio**. Choose
+**Force 3.5mm (headphone) jack**.
+
+## Turn up the volume
+
+A lot of times when sound applications seem to fail, it is because we forget to
+turn up the volume.
+
+Volume adjustment can be done with `alsamixer`. This program makes use of some
+function keys (`F1`, `F2`, etc). For function keys to function properly on
+PuTTY, we need to change some settings (click on the top-left corner of the
+PuTTY window, then select **Change Settings ...**):
+
+1. Go to **Terminal** / **Keyboard**
+2. Look for section **The Function keys and keypad**
+3. Select **Xterm R6**
+4. Press button **Apply**
+
+Now, we are ready to turn up the volume, for both the speaker and the mic:
+
+```
+$ alsamixer
+```
+`F6` to select between sound cards
+`F3` to select playback volume (for speaker)
+`F4` to select capture volume (for mic)
+`⬆` `⬇` arrow keys to adjust
+`Esc` to exit
+
+*If you unplug the USB microphone at any moment, all volume settings
+(including that of the speaker) may be reset. Make sure to check the volume
+again.*
+
+Hardware all set, let's test them.
+
+## Test the speaker
+
+```
+$ speaker-test -t wav
+```
+
+Press `Ctrl-C` when done.
+
+## Record a WAV file
+
```
+$ arecord --format=S16_LE --duration=5 --rate=16000 --file-type=wav out.wav
+```
+
+## Play a WAV file
+
+```
+$ aplay out.wav
+```
+
+## Register for Google Assistant or Google Cloud Speech
+
+Although we are not using Google's hardware, there is no escaping from its
+software. We still rely on Google Assistant or Google Cloud Speech API to
+perform voice recognition. To use these cloud services, you have to go through a
+series of registration steps:
+
+- [Configure Google Assistant API](https://developers.google.com/assistant/sdk/guides/library/python/embed/config-dev-project-and-account)
+- [Configure Google Cloud Speech API](https://aiyprojects.withgoogle.com/voice#makers-guide-3-1--change-to-the-cloud-speech-api)
+
+Which one to use depends on what you need. **Google Assistant** can recognize
+speech *and* talk back intelligently, but supports fewer languages. **Google
+Cloud Speech** only recognizes speech (no talk-back), but supports far more
+languages.
+
+Here is a summary of the steps for using **Google Assistant**, as of 2019-11-27.
+Always pay attention to the **Project ID** on top of the page to make sure you
+are in the right project.
+
+1. Create a Project
+
+2. Enable Google Assistant API
+
+3. Configure OAuth consent screen (must fill in **Support email**)
+
+4. Enable activity controls
+
+5. Register device model, Download credentials file (check `project_id`)
+
+6. Install system dependencies:
+ ```
+ $ sudo apt-get install portaudio19-dev libffi-dev libssl-dev
+ ```
+
+7. Install Python packages:
+ ```
+ $ sudo pip3 install --upgrade pip setuptools wheel
+ $ sudo pip3 install google-assistant-library==1.0.1 \
+ google-assistant-grpc==0.2.0 \
+ google-assistant-sdk[samples]==0.5.1 \
+ google-auth-oauthlib[tool] \
+ google-cloud-speech
+ ```
+ On Raspbian Buster, you likely have to downgrade to `google-assistant-library==1.0.0`
+ for it to work.
+
+8. Use `google-oauthlib-tool` to authenticate:
+ ```
+ $ google-oauthlib-tool --scope https://www.googleapis.com/auth/assistant-sdk-prototype \
+ --save --headless --client-secrets /path/to/client_secret_client-id.json
+ ```
+
+9. Use [`googlesamples-assistant-devicetool`](https://developers.google.com/assistant/sdk/reference/device-registration/device-tool)
+ to register your Raspberry Pi. A few useful commands may be:
+ ```
+ $ googlesamples-assistant-devicetool --project-id register-device \
+ --model \
+ --device \
+ --client-type LIBRARY
+
+ $ googlesamples-assistant-devicetool --project-id list --model
+
+ $ googlesamples-assistant-devicetool --project-id list --device
+ ```
+
+## How to use this library
+
+I used to have it uploaded to PYPI for easy installation. But Google Assistant
+is changing too rapidly. I find it more informing to download and try to
+integrate it manually:
+
+1. Download the `aiy` directory
+
+2. Set environment variable `PYTHONPATH` so Python can find the `aiy` package
+
+3. You may have to install the Pico text-to-speech engine, `libttspico-utils`,
+ to allow it to generate speech dynamically (If `apt-get install libttspico-utils`
+ doesn't work, manually download and install deb packages `libttspico-data`,
+ `libttspico0`, and `libttspico-utils` separately)
+
+The best way to experience the software is to try it.
+**[Let's go to the examples.](https://github.com/nickoala/aiy-voice-only/tree/aiyprojects/examples/voice)**
+
+## Changes to original library
+
+Here is an outline of the changes I have made to the original [AIY Voice
+Kit](https://github.com/google/aiyprojects-raspbian) source code:
+
+1. No Vision stuff: The AIY project actually includes the [Vision
+Kit](https://aiyprojects.withgoogle.com/vision) and associated software, which
+are of no concern to this project. I have removed those.
+
+2. No Voice Hat stuff: This project does not rely on the Voice Hat. The
+`aiy.board` module has been removed.
+
+3. The class `Led` and `Button` have been moved to the `aiy.util` module.
diff --git a/src/aiy/__init__.py b/aiy/__init__.py
similarity index 100%
rename from src/aiy/__init__.py
rename to aiy/__init__.py
diff --git a/src/aiy/_drivers/_buzzer.py b/aiy/_buzzer.py
similarity index 99%
rename from src/aiy/_drivers/_buzzer.py
rename to aiy/_buzzer.py
index 3f09c2c8..35b2e8d2 100644
--- a/src/aiy/_drivers/_buzzer.py
+++ b/aiy/_buzzer.py
@@ -30,7 +30,7 @@ def HzToPeriodUsec(freq_hz):
return USEC / freq_hz
-class PWMController(object):
+class PWMController:
"""Controller that simplifies the interface to pwm-soft Linux driver.
Simple usage:
diff --git a/src/aiy/_apis/__init__.py b/aiy/assistant/__init__.py
similarity index 100%
rename from src/aiy/_apis/__init__.py
rename to aiy/assistant/__init__.py
diff --git a/src/aiy/assistant/auth_helpers.py b/aiy/assistant/auth_helpers.py
similarity index 83%
rename from src/aiy/assistant/auth_helpers.py
rename to aiy/assistant/auth_helpers.py
index b1adac64..c0f2757f 100644
--- a/src/aiy/assistant/auth_helpers.py
+++ b/aiy/assistant/auth_helpers.py
@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Auth helpers for Google Assistant API."""
+"""Authentication helper for the Google Assistant API."""
import json
import logging
@@ -127,6 +127,25 @@ def _try_to_get_credentials(client_secrets):
def get_assistant_credentials(credentials_file=None):
+ """
+ Retreives the OAuth credentials required to access the Google Assistant API.
+
+ If you're using :mod:`aiy.assistant.library`, you must call this function and pass the result
+ to the :class:`~aiy.assistant.library.Assistant` constructor.
+
+ If you're using :mod:`aiy.assistant.grpc`, you do not need this function because the
+ :class:`~aiy.assistant.grpc.AssistantServiceClient` calls this during initialization (using the
+ credentials file at ``~/assistant.json``).
+
+ Args:
+ credentials_file: Absolute path to your JSON credentials file.
+ If None, it looks for the file at ``~/assistant.json``.
+ To get a credentials file, `follow these instructions
+ `_.
+
+ Returns:
+ The device OAuth credentials, as a ``google.oauth2.credentials.Credentials`` object.
+ """
if not credentials_file:
credentials_file = _ASSISTANT_CREDENTIALS_FILE
return _try_to_get_credentials(credentials_file)
diff --git a/src/aiy/assistant/device_helpers.py b/aiy/assistant/device_helpers.py
similarity index 100%
rename from src/aiy/assistant/device_helpers.py
rename to aiy/assistant/device_helpers.py
diff --git a/aiy/assistant/grpc.py b/aiy/assistant/grpc.py
new file mode 100644
index 00000000..b4574796
--- /dev/null
+++ b/aiy/assistant/grpc.py
@@ -0,0 +1,277 @@
+# Copyright 2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Enables a conversation with the Google Assistant, using the `Google Assistant Service`_, which
+connects to the Google Assistant using a streaming endpoint over gRPC.
+
+This gRPC service is typically more complicated to set up, compared to the Google Assistant
+Library, but this API takes care of all the complexity for you. So you simply create an instance
+of :class:`AssistantServiceClient`, then start the Google Assistant by calling
+:meth:`~AssistantServiceClient.conversation`.
+
+This API provides only an interface to initiate a conversation with the Google Assistant. It
+speaks and prints all responses for you—it does not allow you to handle the response events or
+create custom commands.
+For an example, see :github:`src/examples/voice/assistant_grpc_demo.py`.
+
+If you want to integrate custom device commands with the Google Assistant using the gRPC interface,
+instead use the `Google Assistant Service`_ directly. For an example, see `this gRPC sample
+`_.
+Or instead of interacting with the Google Assistant, you can use :mod:`aiy.cloudspeech`
+to convert your voice commands into text that triggers your actions.
+"""
+
+import array
+import logging
+import math
+import os
+import sys
+
+os.environ['GRPC_POLL_STRATEGY'] = 'epoll1'
+import google.auth.transport.grpc
+import google.auth.transport.requests
+import google.oauth2.credentials
+
+from google.assistant.embedded.v1alpha2 import embedded_assistant_pb2
+from google.assistant.embedded.v1alpha2 import embedded_assistant_pb2_grpc
+
+from aiy.assistant import auth_helpers, device_helpers
+from aiy.util import Led
+from aiy.voice.audio import AudioFormat, Recorder, BytesPlayer
+
+logger = logging.getLogger(__name__)
+
+ASSISTANT_API_ENDPOINT = 'embeddedassistant.googleapis.com'
+END_OF_UTTERANCE = embedded_assistant_pb2.AssistResponse.END_OF_UTTERANCE
+DIALOG_FOLLOW_ON = embedded_assistant_pb2.DialogStateOut.DIALOG_FOLLOW_ON
+CLOSE_MICROPHONE = embedded_assistant_pb2.DialogStateOut.CLOSE_MICROPHONE
+PLAYING = embedded_assistant_pb2.ScreenOutConfig.PLAYING
+DEFAULT_GRPC_DEADLINE = 60 * 3 + 5
+AUDIO_SAMPLE_RATE_HZ = 16000
+AUDIO_FORMAT=AudioFormat(sample_rate_hz=AUDIO_SAMPLE_RATE_HZ,
+ num_channels=1,
+ bytes_per_sample=2)
+
+def _normalize_audio_buffer(buf, volume_percentage, sample_width=2):
+ assert sample_width == 2
+ scale = math.pow(2, 1.0 * volume_percentage / 100) - 1
+ arr = array.array('h', buf)
+ for i in range(0, len(arr)):
+ arr[i] = int(arr[i] * scale)
+ return arr.tobytes()
+
+# https://developers.google.com/assistant/sdk/reference/rpc/
+class AssistantServiceClient:
+ """
+ Provides a simplified interface for the `EmbeddedAssistant
+ `_.
+
+ Args:
+ language_code: Language expected from the user, in IETF BCP 47 syntax (default is "en-US").
+ See the `list of supported languages
+ `_.
+ volume_percentage: Volume level of the audio output. Valid values are 1 to 100
+ (corresponding to 1% to 100%).
+ """
+ def __init__(self, language_code='en-US', volume_percentage=100):
+ self._volume_percentage = volume_percentage # Mutable state.
+ self._conversation_state = None # Mutable state.
+ self._language_code = language_code
+
+ ##
+ credentials = auth_helpers.get_assistant_credentials()
+ device_model_id, device_id = device_helpers.get_ids_for_service(credentials)
+
+ logger.info('device_model_id: %s', device_model_id)
+ logger.info('device_id: %s', device_id)
+
+ http_request = google.auth.transport.requests.Request()
+ try:
+ credentials.refresh(http_request)
+ except Exception as e:
+ raise RuntimeError('Error loading credentials: %s', e)
+
+ api_endpoint = ASSISTANT_API_ENDPOINT
+ grpc_channel = google.auth.transport.grpc.secure_authorized_channel(
+ credentials, http_request, api_endpoint)
+ logger.info('Connecting to %s', api_endpoint)
+ ##
+
+ self._assistant = embedded_assistant_pb2_grpc.EmbeddedAssistantStub(grpc_channel)
+ self._device_config = embedded_assistant_pb2.DeviceConfig(
+ device_model_id=device_model_id,
+ device_id=device_id)
+
+ @property
+ def volume_percentage(self):
+ """
+ Volume level of the audio output. Valid values are 1 to 100 (corresponding to 1% to 100%).
+ """
+ return self._volume_percentage
+
+ def _recording_started(self):
+ logger.info('Recording started.')
+
+ def _recording_stopped(self):
+ logger.info('Recording stopped.')
+
+ def _playing_started(self):
+ logger.info('Playing started.')
+
+ def _playing_stopped(self):
+ logger.info('Playing stopped.')
+
+ def _requests(self, recorder):
+ audio_in_config = embedded_assistant_pb2.AudioInConfig(
+ encoding='LINEAR16',
+ sample_rate_hertz=AUDIO_SAMPLE_RATE_HZ)
+
+ audio_out_config = embedded_assistant_pb2.AudioOutConfig(
+ encoding='LINEAR16',
+ sample_rate_hertz=AUDIO_SAMPLE_RATE_HZ,
+ volume_percentage=self._volume_percentage)
+
+ dialog_state_in = embedded_assistant_pb2.DialogStateIn(
+ conversation_state=self._conversation_state,
+ language_code=self._language_code)
+
+ config = embedded_assistant_pb2.AssistConfig(
+ audio_in_config=audio_in_config,
+ audio_out_config=audio_out_config,
+ device_config=self._device_config,
+ dialog_state_in=dialog_state_in)
+
+ yield embedded_assistant_pb2.AssistRequest(config=config)
+
+ for chunk in recorder.record(AUDIO_FORMAT,
+ chunk_duration_sec=0.1,
+ on_start=self._recording_started,
+ on_stop=self._recording_stopped):
+ yield embedded_assistant_pb2.AssistRequest(audio_in=chunk)
+
+
+ def _assist(self, recorder, play, deadline):
+ continue_conversation = False
+
+ for response in self._assistant.Assist(self._requests(recorder), deadline):
+ if response.event_type == END_OF_UTTERANCE:
+ logger.info('End of audio request detected.')
+ recorder.done()
+
+ # Process 'speech_results'.
+ if response.speech_results:
+ logger.info('You said: "%s".',
+ ' '.join(r.transcript for r in response.speech_results))
+ # Process 'audio_out'.
+ if response.audio_out.audio_data:
+ recorder.done() # Just in case.
+ play(_normalize_audio_buffer(response.audio_out.audio_data,
+ self._volume_percentage))
+
+ # Process 'dialog_state_out'.
+ if response.dialog_state_out.conversation_state:
+ conversation_state = response.dialog_state_out.conversation_state
+ logger.debug('Updating conversation state.')
+ self._conversation_state = conversation_state # Mutable state change.
+
+ volume_percentage = response.dialog_state_out.volume_percentage
+ if volume_percentage:
+ logger.info('Setting volume to %s%%', volume_percentage)
+ self._volume_percentage = volume_percentage # Mutable state change.
+
+ supplemental_display_text = response.dialog_state_out.supplemental_display_text
+ if supplemental_display_text:
+ logger.info('Assistant said: "%s"', supplemental_display_text)
+
+ microphone_mode = response.dialog_state_out.microphone_mode
+ if microphone_mode == DIALOG_FOLLOW_ON:
+ continue_conversation = True
+ logger.info('Expecting follow-on query from user.')
+ elif microphone_mode == CLOSE_MICROPHONE:
+ continue_conversation = False
+ logger.info('Not expecting follow-on query from user.')
+
+ return continue_conversation
+
+ def conversation(self, deadline=DEFAULT_GRPC_DEADLINE):
+ """
+ Starts a conversation with the Google Assistant.
+
+ The device begins listening for your query or command and will wait indefinitely.
+ Once it completes a query/command, it returns to listening for another.
+
+ Args:
+ deadline: The amount of time (in milliseconds) to wait for each gRPC request to
+ complete before terminating.
+ """
+ keep_talking = True
+ while keep_talking:
+ playing = False
+ with Recorder() as recorder, BytesPlayer() as player:
+ play = player.play(AUDIO_FORMAT)
+
+ def wrapped_play(data):
+ nonlocal playing
+ if not playing:
+ self._playing_started()
+ playing = True
+ play(data)
+
+ try:
+ keep_talking = self._assist(recorder, wrapped_play, deadline)
+ finally:
+ play(None) # Signal end of sound stream.
+ recorder.done() # Signal stop recording.
+
+ if playing:
+ self._playing_stopped()
+
+class AssistantServiceClientWithLed(AssistantServiceClient):
+ """
+ Same as :class:`AssistantServiceClient` but this also turns the
+ Voice Kit's button LED on and off in response to the conversation.
+
+ Args:
+ led: An instance of :class:`~aiy.util.Led`.
+ language_code: Language expected from the user, in IETF BCP 47 syntax (default is "en-US").
+ See the `list of supported languages`_.
+ volume_percentage: Volume level of the audio output. Valid values are 1 to 100
+ (corresponding to 1% to 100%).
+ """
+ def _update_led(self, state, brightness):
+ self._led.state = state
+ self._led.brightness = brightness
+
+ def __init__(self, led, language_code='en-US', volume_percentage=100):
+ super().__init__(language_code, volume_percentage)
+
+ self._led = led
+ self._update_led(Led.ON, 0.1)
+
+ def _recording_started(self):
+ super()._recording_started()
+ self._update_led(Led.ON, 1.0)
+
+ def _recording_stopped(self):
+ self._update_led(Led.ON, 0.1)
+ super()._recording_stopped()
+
+ def _playing_started(self):
+ super()._playing_started()
+ self._update_led(Led.PULSE_SLOW, 1.0)
+
+ def _playing_stopped(self):
+ self._update_led(Led.ON, 0.1)
+ super()._playing_stopped()
diff --git a/aiy/assistant/library.py b/aiy/assistant/library.py
new file mode 100644
index 00000000..056917ab
--- /dev/null
+++ b/aiy/assistant/library.py
@@ -0,0 +1,86 @@
+# Copyright 2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Facilitates access to the `Google Assistant Library`_, which provides APIs to initiate
+conversations with the Google Assistant and create custom device commands commands.
+
+This includes a wrapper for the ``Assistant`` class only. You must import all other Google
+Assistant classes directly from the |code| :assistant:`google.assistant.library<>`\ |endcode| module
+to handle each of the response events.
+
+.. note::
+
+ Hotword detection (such as "Okay Google") is not supported with the Raspberry Pi Zero
+ (only with Raspberry Pi 2/3). If you're using a Pi Zero, you must instead use the button or
+ another type of trigger to initiate a conversation with the Google Assistant.
+
+.. py:class:: Assistant(credentials)
+
+ Bases: |code| :assistant:`google.assistant.library.Assistant`\ |endcode|
+
+ A wrapper for the |code| :assistant:`Assistant`\ |endcode| class that handles
+ model and device registration based on the project name in your OAuth credentials
+ (``assistant.json``) file.
+
+ All the ``Assistant`` APIs are available through this class, such as
+ |code| :assistant:`start()`\ |endcode| to start the
+ Assistant, and |code| :assistant:`start_conversation()
+ `\ |endcode| to start
+ a conversation, but they are not documented here. Instead refer to the
+ `Google Assistant Library for Python documentation
+ `_.
+
+ To get started, you must call :meth:`~aiy.assistant.auth_helpers.get_assistant_credentials`
+ and pass the result to the ``Assistant`` constructor. For example::
+
+ from google.assistant.library.event import EventType
+ from aiy.assistant import auth_helpers
+ from aiy.assistant.library import Assistant
+
+ credentials = auth_helpers.get_assistant_credentials()
+ with Assistant(credentials) as assistant:
+ for event in assistant.start():
+ process_event(event)
+
+ For more example code, see :github:`src/examples/voice/assistant_library_demo.py`.
+
+ :param credentials: The Google OAuth2 credentials for the device. Get this from
+ :meth:`~aiy.assistant.auth_helpers.get_assistant_credentials`.
+"""
+
+import google.assistant.library
+
+from aiy.assistant import device_helpers
+
+class Assistant(google.assistant.library.Assistant):
+ """Client for the Google Assistant Library.
+
+ Similar to google.assistant.library.Assistant, but handles device
+ registration.
+ """
+
+ def __init__(self, credentials):
+ self._credentials = credentials
+ self._model_id = device_helpers.register_model_id(credentials)
+
+ super().__init__(credentials, self._model_id)
+
+ def start(self):
+ events = super().start()
+
+ device_helpers.register_device_id(
+ self._credentials, self._model_id, self.device_id, "SDK_LIBRARY")
+
+ return events
diff --git a/aiy/cloudspeech.py b/aiy/cloudspeech.py
new file mode 100644
index 00000000..d8bcd573
--- /dev/null
+++ b/aiy/cloudspeech.py
@@ -0,0 +1,166 @@
+# Copyright 2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+APIs that simplify interaction with the `Google Cloud Speech-to-Text service
+`_ so you can convert voice commands into actions.
+To use this service, you must have a Google Cloud account and a corresponding credentials file.
+For more information, see `these setup instructions
+`_.
+
+For an example, see :github:`src/examples/voice/cloudspeech_demo.py`.
+
+.. note::
+
+ These APIs are designed for the Voice Kit, but have no dependency on the Voice
+ HAT/Bonnet specifically. However, they do require some type of sound card
+ attached to the Raspberry Pi that can be detected by the ALSA subsystem.
+"""
+
+import os
+import logging
+
+os.environ['GRPC_POLL_STRATEGY'] = 'epoll1'
+from google.cloud import speech
+from google.oauth2 import service_account
+
+from aiy.voice.audio import AudioFormat, Recorder
+
+END_OF_SINGLE_UTTERANCE = speech.types.StreamingRecognizeResponse.END_OF_SINGLE_UTTERANCE
+AUDIO_SAMPLE_RATE_HZ = 16000
+AUDIO_FORMAT=AudioFormat(sample_rate_hz=AUDIO_SAMPLE_RATE_HZ,
+ num_channels=1,
+ bytes_per_sample=2)
+
+logger = logging.getLogger(__name__)
+
+# https://cloud.google.com/speech-to-text/docs/reference/rpc/google.cloud.speech.v1
+class CloudSpeechClient:
+ """
+ A simplified version of the Google Cloud ``SpeechClient`` class.
+
+ Args:
+ service_accout_file: Absolute path to your JSON account credentials file.
+ If None, it looks for the file at ``~/cloud_speech.json``.
+ To get a credentials file, `these setup instructions`_.
+ """
+ def __init__(self, service_accout_file=None):
+ if service_accout_file is None:
+ service_accout_file = os.path.expanduser('~/cloud_speech.json')
+
+ credentials = service_account.Credentials.from_service_account_file(service_accout_file)
+ self._client = speech.SpeechClient(credentials=credentials)
+
+ def _make_config(self, language_code, hint_phrases):
+ return speech.types.RecognitionConfig(
+ encoding=speech.types.RecognitionConfig.LINEAR16,
+ sample_rate_hertz=AUDIO_SAMPLE_RATE_HZ,
+ language_code=language_code,
+ speech_contexts=[speech.types.SpeechContext(phrases=hint_phrases)])
+
+ def recognize_bytes(self, data, language_code='en-US', hint_phrases=None):
+ """
+ Performs speech-to-text for a single utterance using the given data source.
+ Once it detects the user is done speaking, it stops listening and delivers the top
+ result as text.
+
+ Args:
+ data: The audio data source. Must be encoded with a sample rate of 16000Hz.
+ language_code: Language expected from the user, in IETF BCP 47 syntax (default is
+ "en-US"). See the `list of Cloud's supported languages
+ `_.
+ hint_phrase: A list of strings containing words and phrases that may be expected from
+ the user. These hints help the speech recognizer identify them in the dialog and
+ improve the accuracy of your results.
+
+ Returns:
+ The text transcription of the user's dialog.
+ """
+ streaming_config=speech.types.StreamingRecognitionConfig(
+ config=self._make_config(language_code, hint_phrases),
+ single_utterance=True)
+ responses = self._client.streaming_recognize(
+ config=streaming_config,
+ requests=[speech.types.StreamingRecognizeRequest(audio_content=data)])
+
+ for response in responses:
+ for result in response.results:
+ if result.is_final:
+ return result.alternatives[0].transcript
+
+ return None
+
+ def recognize(self, language_code='en-US', hint_phrases=None):
+ """
+ Performs speech-to-text for a single utterance using the default ALSA soundcard driver.
+ Once it detects the user is done speaking, it stops listening and delivers the top
+ result as text.
+
+ By default, this method calls :meth:`start_listening` and :meth:`stop_listening` as the
+ recording begins and ends, respectively.
+
+ Args:
+ language_code: Language expected from the user, in IETF BCP 47 syntax (default is
+ "en-US"). See the `list of Cloud's supported languages`_.
+ hint_phrase: A list of strings containing words and phrases that may be expected from
+ the user. These hints help the speech recognizer identify them in the dialog and
+ improve the accuracy of your results.
+
+ Returns:
+ The text transcription of the user's dialog.
+ """
+ streaming_config=speech.types.StreamingRecognitionConfig(
+ config=self._make_config(language_code, hint_phrases),
+ single_utterance=True)
+
+ with Recorder() as recorder:
+ chunks = recorder.record(AUDIO_FORMAT,
+ chunk_duration_sec=0.1,
+ on_start=self.start_listening,
+ on_stop=self.stop_listening)
+
+ requests = (speech.types.StreamingRecognizeRequest(audio_content=data) for data in chunks)
+ responses = self._client.streaming_recognize(config=streaming_config, requests=requests)
+
+ for response in responses:
+ if response.speech_event_type == END_OF_SINGLE_UTTERANCE:
+ recorder.done()
+
+ for result in response.results:
+ if result.is_final:
+ return result.alternatives[0].transcript
+
+ return None
+
+ def start_listening(self):
+ """
+ By default, this simply prints "Start listening" to the log.
+
+ This method is provided as a convenience method that you can override in a derived class to
+ do something else that indicates the status to the user, such as change the LED state.
+
+ Called by :meth:`recognize` when recording begins.
+ """
+ logger.info('Start listening.')
+
+ def stop_listening(self):
+ """
+ By default, this simply prints "Stop listening" to the log.
+
+ This method is provided as a convenience method that you can override in a derived class to
+ do something else that indicates the status to the user, such as change the LED state.
+
+ Called by :meth:`recognize` when recording ends.
+ """
+ logger.info('Stop listening.')
diff --git a/src/aiy/toneplayer.py b/aiy/toneplayer.py
similarity index 95%
rename from src/aiy/toneplayer.py
rename to aiy/toneplayer.py
index 0a1f2cdc..33902caa 100644
--- a/src/aiy/toneplayer.py
+++ b/aiy/toneplayer.py
@@ -12,16 +12,21 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Simple melodic music player for the piezo buzzer."""
+"""
+A simple melodic music player for the piezo buzzer.
+This API is designed for the Vision Kit, but has no dependency on the Vision
+Bonnet, so may be used without it. It only requires a piezo buzzer connected to
+:any:`aiy.pins.BUZZER_GPIO_PIN`.
+"""
-import time
import re
+import time
-from aiy._drivers._buzzer import PWMController
+from ._buzzer import PWMController
-class Rest(object):
+class Rest:
"""Simple internal class to represent a musical rest note.
Used in part with the TonePlayer class, this object represents a period of
@@ -84,7 +89,7 @@ def __str__(self):
return self.name + str(self.octave)
-class TonePlayer(object):
+class TonePlayer:
"""Class to play a simplified music notation via a PWMController.
This class makes use of a very simple music notation to play simple musical
@@ -100,7 +105,7 @@ class TonePlayer(object):
w: whole note
h: half note
q: quarter note (the default -- if you don't specify the length, we
- assume quarter)
+ assume quarter)
e: eighth note
s: sixteenth note
diff --git a/src/aiy/trackplayer.py b/aiy/trackplayer.py
similarity index 98%
rename from src/aiy/trackplayer.py
rename to aiy/trackplayer.py
index 0ea588d6..4e544407 100644
--- a/src/aiy/trackplayer.py
+++ b/aiy/trackplayer.py
@@ -12,18 +12,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Tracker-based music player for the piezo buzzer."""
+"""
+A tracker-based music player for the piezo buzzer.
+
+This API is designed for the Vision Kit, but has no dependency on the Vision
+Bonnet, so may be used without it. It only requires a piezo buzzer connected to
+:any:`aiy.pins.BUZZER_GPIO_PIN`.
+"""
import math
import re
import time
-from aiy._drivers._buzzer import PWMController
-from aiy.toneplayer import Note
+from .toneplayer import Note
+from ._buzzer import PWMController
-class Command(object):
+class Command:
"""Base class for all commands."""
def apply(self, player, controller, note, tick_delta):
@@ -244,7 +250,7 @@ def parse(klass, *args):
return klass(), 0
-class TrackPlayer(object):
+class TrackPlayer:
"""Plays a tracker-like song."""
def __init__(self, gpio, speed=3, debug=False):
@@ -359,7 +365,7 @@ def play(self):
controller.set_frequency(0)
-class TrackLoader(object):
+class TrackLoader:
"""Simple track module loader.
This class, given a filename and a gpio will load and parse in the given
diff --git a/aiy/util.py b/aiy/util.py
new file mode 100644
index 00000000..61540da7
--- /dev/null
+++ b/aiy/util.py
@@ -0,0 +1,203 @@
+# Copyright 2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import itertools
+import queue
+import threading
+import time
+
+from collections import namedtuple
+
+from RPi import GPIO
+
+class Button:
+ """ An interface for the button connected to the AIY board's
+ button connector."""
+ @staticmethod
+ def _trigger(event_queue, callback):
+ try:
+ while True:
+ event_queue.get_nowait().set()
+ except queue.Empty:
+ pass
+
+ if callback:
+ callback()
+
+ def _run(self):
+ when_pressed = 0.0
+ pressed = False
+ while not self._done.is_set():
+ now = time.monotonic()
+ if now - when_pressed > self._debounce_time:
+ if GPIO.input(self._channel) == self._expected:
+ if not pressed:
+ pressed = True
+ when_pressed = now
+ self._trigger(self._pressed_queue, self._pressed_callback)
+ else:
+ if pressed:
+ pressed = False
+ self._trigger(self._released_queue, self._released_callback)
+ self._done.wait(0.05)
+
+ def __init__(self, channel, edge='falling', pull_up_down='up',
+ debounce_time=0.08):
+ if pull_up_down not in ('up', 'down'):
+ raise ValueError('Must be "up" or "down"')
+
+ if edge not in ('falling', 'rising'):
+ raise ValueError('Must be "falling" or "rising"')
+
+ self._channel = channel
+ GPIO.setmode(GPIO.BCM)
+ GPIO.setup(channel, GPIO.IN,
+ pull_up_down={'up': GPIO.PUD_UP, 'down': GPIO.PUD_DOWN}[pull_up_down])
+
+ self._pressed_callback = None
+ self._released_callback = None
+
+ self._debounce_time = debounce_time
+ self._expected = True if edge == 'rising' else False
+
+ self._pressed_queue = queue.Queue()
+ self._released_queue = queue.Queue()
+
+ self._done = threading.Event()
+ self._thread = threading.Thread(target=self._run)
+ self._thread.start()
+
+ def close(self):
+ """Internal method to clean up the object when done."""
+ self._done.set()
+ self._thread.join()
+ GPIO.cleanup(self._channel)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, exc_tb):
+ self.close()
+
+ def _when_pressed(self, callback):
+ self._pressed_callback = callback
+ when_pressed = property(None, _when_pressed)
+ """A function to run when the button is pressed."""
+
+ def _when_released(self, callback):
+ self._released_callback = callback
+ when_released = property(None, _when_released)
+ """A function to run when the button is released."""
+
+ def wait_for_press(self, timeout=None):
+ """Pauses the script until the button is pressed or the timeout is reached.
+
+ Args:
+ timeout: Seconds to wait before proceeding. By default, this is ``None``,
+ which means wait indefinitely."""
+ event = threading.Event()
+ self._pressed_queue.put(event)
+ return event.wait(timeout)
+
+ def wait_for_release(self, timeout=None):
+ """Pauses the script until the button is released or the timeout is reached.
+
+ Args:
+ timeout: Seconds to wait before proceeding. By default, this is ``None``,
+ which means wait indefinitely."""
+ event = threading.Event()
+ self._released_queue.put(event)
+ return event.wait(timeout)
+
+
+class Led:
+ Config = namedtuple('Config', ['duty_cycles', 'pause'])
+
+ OFF = Config(duty_cycles=lambda: [0], pause=1.0)
+ ON = Config(duty_cycles=lambda: [100], pause=1.0)
+ BLINK = Config(duty_cycles=lambda: [0, 100], pause=0.5)
+ BLINK_3 = Config(duty_cycles=lambda: [0, 100] * 3 + [0, 0],
+ pause=0.25)
+ BEACON = Config(duty_cycles=lambda: itertools.chain([30] * 100,
+ [100] * 8,
+ range(100, 30, -5)),
+ pause=0.05)
+ BEACON_DARK = Config(duty_cycles=lambda: itertools.chain([0] * 100,
+ range(0, 30, 3),
+ range(30, 0, -3)),
+ pause=0.05)
+ DECAY = Config(duty_cycles=lambda: range(100, 0, -2),
+ pause=0.05)
+ PULSE_SLOW = Config(duty_cycles=lambda: itertools.chain(range(0, 100, 2),
+ range(100, 0, -2)),
+ pause=0.1)
+ PULSE_QUICK = Config(duty_cycles=lambda: itertools.chain(range(0, 100, 5),
+ range(100, 0, -5)),
+ pause=0.05)
+
+ def _run(self):
+ while True:
+ try:
+ state = self._queue.get_nowait()
+ if state is None:
+ break
+ it = itertools.cycle(state.duty_cycles())
+ except queue.Empty:
+ pass
+
+ self._pwm.ChangeDutyCycle(int(self._brightness * next(it)))
+ self._updated.wait(state.pause)
+ self._updated.clear()
+
+ def __init__(self, channel):
+ self._brightness = 1.0 # Read and written atomically.
+ self._channel = channel
+ self._queue = queue.Queue(maxsize=1)
+ self._queue.put(self.OFF)
+ self._updated = threading.Event()
+
+ GPIO.setmode(GPIO.BCM)
+ GPIO.setup(channel, GPIO.OUT)
+ self._pwm = GPIO.PWM(channel, 100)
+ self._pwm.start(0)
+
+ self._thread = threading.Thread(target=self._run)
+ self._thread.start()
+
+ def close(self):
+ self._queue.put(None)
+ self._thread.join()
+ self._pwm.stop()
+ GPIO.cleanup(self._channel)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, exc_tb):
+ self.close()
+
+ @property
+ def brightness(self):
+ return self._brightness
+
+ @brightness.setter
+ def brightness(self, value):
+ if value < 0.0 or value > 1.0:
+ raise ValueError('Brightness must be between 0.0 and 1.0.')
+ self._brightness = value
+
+ def _set_state(self, state):
+ self._queue.put(state)
+ self._updated.set()
+ state = property(None, _set_state)
diff --git a/src/aiy/_drivers/__init__.py b/aiy/voice/__init__.py
similarity index 100%
rename from src/aiy/_drivers/__init__.py
rename to aiy/voice/__init__.py
diff --git a/aiy/voice/audio.py b/aiy/voice/audio.py
new file mode 100644
index 00000000..0b46b3cd
--- /dev/null
+++ b/aiy/voice/audio.py
@@ -0,0 +1,425 @@
+"""
+APIs to record and play audio files.
+
+.. note::
+
+ These APIs are designed for the Voice Kit, but have no dependency on the Voice
+ HAT/Bonnet specifically. However, many of the APIs require some type of sound card
+ attached to the Raspberry Pi that can be detected by the ALSA subsystem.
+
+.. module:: aiy.voice.audio
+
+Recording
+---------
+
+.. autofunction:: arecord
+
+.. autofunction:: record_file
+
+.. autofunction:: record_file_async
+
+.. autoclass:: Recorder
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Playback
+--------
+
+.. autofunction:: aplay
+
+.. autofunction:: play_raw
+
+.. autofunction:: play_raw_async
+
+.. autofunction:: play_wav
+
+.. autofunction:: play_wav_async
+
+.. autoclass:: BytesPlayer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+ :inherited-members:
+
+.. autoclass:: FilePlayer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+ :inherited-members:
+
+
+Audio format
+------------
+
+.. autofunction:: wave_set_format
+
+.. autofunction:: wave_get_format
+
+.. autoclass:: AudioFormat
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+"""
+
+import contextlib
+import subprocess
+import threading
+import itertools
+import wave
+
+from collections import namedtuple
+
+SUPPORTED_FILETYPES = ('wav', 'raw', 'voc', 'au')
+
+
+class AudioFormat(namedtuple('AudioFormat',
+ ['sample_rate_hz', 'num_channels', 'bytes_per_sample'])):
+ @property
+ def bytes_per_second(self):
+ return self.sample_rate_hz * self.num_channels * self.bytes_per_sample
+
+AudioFormat.CD = AudioFormat(sample_rate_hz=44100, num_channels=2, bytes_per_sample=2)
+
+
+def wave_set_format(wav_file, fmt):
+ """
+ Sets the format for the given WAV file, using the given :class:`AudioFormat`.
+
+ Args:
+ wav_file: A :class:`wave.Wave_write` object.
+ fmt: A :class:`AudioFormat` object.
+ """
+ wav_file.setnchannels(fmt.num_channels)
+ wav_file.setsampwidth(fmt.bytes_per_sample)
+ wav_file.setframerate(fmt.sample_rate_hz)
+
+
+def wave_get_format(wav_file):
+ """
+ Returns the :class:`AudioFormat` corresponding to the WAV file provided.
+
+ Args:
+ wav_file: A :class:`wave.Wave_read` object.
+ """
+ return AudioFormat(sample_rate_hz=wav_file.getframerate(),
+ num_channels=wav_file.getnchannels(),
+ bytes_per_sample=wav_file.getsampwidth())
+
+
+def arecord(fmt, filetype='raw', filename=None, device='default'):
+ """Returns an ``arecord`` command-line command.
+
+ Args:
+ fmt: The audio format; an instance of :class:`AudioFormat`.
+ filetype: The type of file. Must be either 'wav', 'raw', 'voc', or 'au'.
+ filename: The audio file to play.
+ device: The PCM device name. Leave as ``default`` to use the default ALSA soundcard.
+ """
+ if fmt is None:
+ raise ValueError('Format must be specified for recording.')
+
+ if filetype not in SUPPORTED_FILETYPES:
+ raise ValueError('File type must be %s.' % ', '.join(SUPPORTED_FILETYPES))
+
+ cmd = ['arecord', '-q',
+ '-D', device,
+ '-t', filetype,
+ '-c', str(fmt.num_channels),
+ '-f', 's%d' % (8 * fmt.bytes_per_sample),
+ '-r', str(fmt.sample_rate_hz)]
+
+ if filename is not None:
+ cmd.append(filename)
+
+ return cmd
+
+
+def aplay(fmt, filetype='raw', filename=None, device='default'):
+ """Returns an ``aplay`` command-line command.
+
+ Args:
+ fmt: The audio format; an instance of :class:`AudioFormat`.
+ filetype: The type of file. Must be either 'wav', 'raw', 'voc', or 'au'.
+ filename: The audio file to play.
+ device: The PCM device name. Leave as ``default`` to use the default ALSA soundcard.
+ """
+ if filetype == 'raw' and fmt is None:
+ raise ValueError('Format must be specified for raw data.')
+
+ cmd = ['aplay', '-q',
+ '-D', device,
+ '-t', filetype]
+
+ if fmt is not None:
+ cmd.extend(['-c', str(fmt.num_channels),
+ '-f', 's%d' % (8 * fmt.bytes_per_sample),
+ '-r', str(fmt.sample_rate_hz)])
+
+ if filename is not None:
+ cmd.append(filename)
+
+ return cmd
+
+def record_file_async(fmt, filename, filetype, device='default'):
+ """
+ Records an audio file, asynchronously. To stop the recording, terminate the returned
+ :class:`~subprocess.Popen` object.
+
+ Args:
+ fmt: The audio format; an instance of :class:`AudioFormat`.
+ filename: The file where the recording should be saved.
+ filetype: The type of file. Must be either 'wav', 'raw', 'voc', or 'au'.
+ device: The PCM device name. Leave as ``default`` to use the default ALSA soundcard.
+
+ Returns:
+ The :class:`~subprocess.Popen` object for the subprocess in which audio is recording.
+ """
+ if filename is None:
+ raise ValueError('Filename must be specified.')
+
+ if filetype is None:
+ raise ValueError('Filetype must be specified.')
+
+ cmd = arecord(fmt, filetype=filetype, filename=filename, device=device)
+ return subprocess.Popen(cmd)
+
+
+def record_file(fmt, filename, filetype, wait, device='default'):
+ """
+ Records an audio file (blocking). The length of the recording is determined by a
+ blocking ``wait`` function that you provide. When your ``wait`` function finishes,
+ so does this function and the recording.
+
+ For an example, see :github:`src/examples/voice/voice_recorder.py`.
+
+ Args:
+ fmt: The audio format; an instance of :class:`AudioFormat`.
+ filename: The file where the recording should be saved.
+ filetype: The type of file. Must be either 'wav', 'raw', 'voc', or 'au'.
+ wait: A blocking function that determines the length of the recording (and thus the
+ length of time that this function is blocking).
+ device: The PCM device name. Leave as ``default`` to use the default ALSA soundcard.
+ """
+ if wait is None:
+ raise ValueError('Wait callback must be specified.')
+
+ process = record_file_async(fmt, filename, filetype, device)
+ try:
+ wait()
+ finally:
+ process.terminate()
+ process.wait()
+
+
+def play_wav_async(filename_or_data):
+ """
+ Plays a WAV file or data asynchronously.
+
+ Args:
+ filename_or_data: The WAV file or bytes to play.
+
+ Returns:
+ The :class:`~subprocess.Popen` object for the subprocess in which audio is playing.
+ """
+ if isinstance(filename_or_data, (bytes, bytearray)):
+ cmd = aplay(fmt=None, filetype='wav', filename=None)
+ process = subprocess.Popen(cmd, stdin=subprocess.PIPE)
+ process.stdin.write(filename_or_data)
+ return process
+
+ if isinstance(filename_or_data, str):
+ cmd = aplay(fmt=None, filetype='wav', filename=filename_or_data)
+ return subprocess.Popen(cmd)
+
+ raise ValueError('Must be filename or byte-like object')
+
+
+def play_wav(filename_or_data):
+ """
+ Plays a WAV file or data (blocking).
+
+ Args:
+ filename_or_data: The WAV file or bytes to play.
+ """
+ play_wav_async(filename_or_data).wait()
+
+
+def play_raw_async(fmt, filename_or_data):
+ """
+ Plays raw audio data asynchronously.
+
+ Args:
+ fmt: The audio format; an instance of :class:`AudioFormat`.
+ filename_or_data: The file or bytes to play.
+
+ Returns:
+ The :class:`~subprocess.Popen` object for the subprocess in which audio is playing.
+ """
+ if isinstance(filename_or_data, (bytes, bytearray)):
+ cmd = aplay(fmt=fmt, filetype='raw')
+ process = subprocess.Popen(cmd, stdin=subprocess.PIPE)
+ process.stdin.write(filename_or_data)
+ return process
+
+ if isinstance(filename_or_data, str):
+ cmd = aplay(fmt=fmt, filetype='raw', filename=filename_or_data)
+ return subprocess.Popen(cmd)
+
+ raise ValueError('Must be filename or byte-like object')
+
+
+def play_raw(fmt, filename_or_data):
+ """
+ Plays raw audio data (blocking).
+
+ Args:
+ fmt: The audio format; an instance of :class:`AudioFormat`.
+ filename_or_data: The file or bytes to play.
+ """
+ play_raw_async(fmt, filename_or_data).wait()
+
+
+class Recorder:
+
+ def __init__(self, ):
+ self._process = None
+ self._done = threading.Event()
+ self._started = threading.Event()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, exc_tb):
+ self.join()
+
+ def record(self, fmt, chunk_duration_sec, device='default',
+ num_chunks=None,
+ on_start=None, on_stop=None, filename=None):
+ """
+ Records audio with the ALSA soundcard driver, via ``arecord``.
+
+ Args:
+ fmt: The audio format; an instance of :class:`AudioFormat`.
+ chunk_duration_sec: The duration of each audio chunk, in seconds (may be float).
+ device: The PCM device name. Leave as ``default`` to use the default ALSA soundcard.
+ num_chunks: The number of chunks to record. Leave as ``None`` to instead record
+ indefinitely, until you call :meth:`~Recorder.done`.
+ on_start: A function callback to call when recording starts.
+ on_stop: A function callback to call when recording stops.
+ filename: A filename to use if you want to save the recording as a WAV file.
+ Yields:
+ A chunk of audio data. Each chunk size = ``chunk_duraction_sec * fmt.bytes_per_second``
+ """
+
+ chunk_size = int(chunk_duration_sec * fmt.bytes_per_second)
+ cmd = arecord(fmt=fmt, device=device)
+
+ wav_file = None
+ if filename:
+ wav_file = wave.open(filename, 'wb')
+ wave_set_format(wav_file, fmt)
+
+ self._process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ self._started.set()
+ if on_start:
+ on_start()
+ try:
+ for _ in (range(num_chunks) if num_chunks else itertools.count()):
+ if self._done.is_set():
+ break
+ data = self._process.stdout.read(chunk_size)
+ if not data:
+ break
+ if wav_file:
+ wav_file.writeframes(data)
+ yield data
+ finally:
+ self._process.stdout.close()
+ if on_stop:
+ on_stop()
+ if wav_file:
+ wav_file.close()
+
+ def done(self):
+ """
+ Stops the recording that started via :meth:`~Recorder.record`.
+ """
+ self._done.set()
+
+ def join(self):
+ self._started.wait()
+ self._process.wait()
+
+
+
+class Player:
+ def __init__(self):
+ self._process = None
+ self._started = threading.Event()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, exc_tb):
+ self.join()
+
+ def _popen(self, cmd, **kwargs):
+ self._process = subprocess.Popen(cmd, **kwargs)
+ self._started.set()
+ return self._process
+
+ def join(self):
+ self._started.wait()
+ self._process.wait()
+
+
+class FilePlayer(Player):
+ """
+ Plays audio from a file.
+ """
+ def play_raw(self, fmt, filename, device='default'):
+ """
+ Plays a raw audio file.
+
+ Args:
+ fmt: The audio format; an instance of :class:`AudioFormat`.
+ filename: The audio file to play.
+ device: The PCM device name. Leave as ``default`` to use the default ALSA soundcard.
+ """
+ self._popen(aplay(fmt=fmt, filetype='raw', filename=filename, device=device))
+
+
+ def play_wav(self, filename, device='default'):
+ """
+ Plays a WAV file.
+
+ Args:
+ filename: The WAV file to play.
+ device: The PCM device name. Leave as ``default`` to use the default ALSA soundcard.
+ """
+ self._popen(aplay(fmt=None, filetype='wav', filename=filename, device=device))
+
+class BytesPlayer(Player):
+ """
+ Plays audio from a given byte data source.
+ """
+ def play(self, fmt, device='default'):
+ """
+ Args:
+ fmt: The audio format; an instance of :class:`AudioFormat`.
+ device: The PCM device name. Leave as ``default`` to use the default ALSA soundcard.
+
+ Returns:
+ A closure with an inner function ``push()`` that accepts the byte data.
+ """
+ process = self._popen(aplay(fmt=fmt, filetype='raw', device=device), stdin=subprocess.PIPE)
+
+ def push(data):
+ if data:
+ process.stdin.write(data)
+ else:
+ process.stdin.close()
+ return push
diff --git a/aiy/voice/tts.py b/aiy/voice/tts.py
new file mode 100644
index 00000000..458a0fef
--- /dev/null
+++ b/aiy/voice/tts.py
@@ -0,0 +1,72 @@
+# Copyright 2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+An API that performs text-to-speech.
+
+You can also use this to perform text-to-speech from the command line::
+
+ python ~/AIY-projects-python/src/aiy/voice/tts.py "hello world"
+
+"""
+
+import argparse
+import os
+import subprocess
+import tempfile
+
+RUN_DIR = '/run/user/%d' % os.getuid()
+
+def say(text, lang='en-US', volume=60, pitch=130, speed=100, device='default'):
+ """
+ Speaks the provided text.
+
+ Args:
+ text: The text you want to speak.
+ lang: The language to use. Supported languages are:
+ en-US, en-GB, de-DE, es-ES, fr-FR, it-IT.
+ volume: Volume level for the converted audio. The normal volume level is
+ 100. Valid volume levels are between 0 (no audible output) and 500 (increasing the
+ volume by a factor of 5). Values higher than 100 might result in degraded signal
+ quality due to saturation effects (clipping) and is not recommended. To instead adjust
+ the volume output of your device, enter ``alsamixer`` at the command line.
+ pitch: The pitch level for the voice. The normal pitch level is 100, the allowed values lie
+ between 50 (one octave lower) and 200 (one octave higher).
+ speed: The speed of the voice. The normal speed level is 100, the allowed values lie
+ between 20 (slowing down by a factor of 5) and 500 (speeding up by a factor of 5).
+ device: The PCM device name. Leave as ``default`` to use the default ALSA soundcard.
+ """
+ data = "%s" % \
+ (volume, pitch, speed, text)
+ with tempfile.NamedTemporaryFile(suffix='.wav', dir=RUN_DIR) as f:
+ cmd = 'pico2wave --wave %s --lang %s "%s" && aplay -q -D %s %s' % \
+ (f.name, lang, data, device, f.name)
+ subprocess.check_call(cmd, shell=True)
+
+
+def _main():
+ parser = argparse.ArgumentParser(description='Text To Speech (pico2wave)')
+ parser.add_argument('--lang', default='en-US')
+ parser.add_argument('--volume', type=int, default=60)
+ parser.add_argument('--pitch', type=int, default=130)
+ parser.add_argument('--speed', type=int, default=100)
+ parser.add_argument('--device', default='default')
+ parser.add_argument('text', help='path to disk image file ')
+ args = parser.parse_args()
+ say(args.text, lang=args.lang, volume=args.volume, pitch=args.pitch, speed=args.speed,
+ device=args.device)
+
+
+if __name__ == '__main__':
+ _main()
diff --git a/checkpoints/check_audio.py b/checkpoints/check_audio.py
deleted file mode 100755
index 8f677a23..00000000
--- a/checkpoints/check_audio.py
+++ /dev/null
@@ -1,184 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Check that the voiceHAT audio input and output are both working."""
-
-
-import fileinput
-import os
-import re
-import subprocess
-import sys
-import tempfile
-import textwrap
-import traceback
-
-import aiy.audio # noqa
-from aiy._drivers._hat import get_aiy_device_name
-
-AIY_PROJECTS_DIR = os.path.dirname(os.path.dirname(__file__))
-
-CARDS_PATH = '/proc/asound/cards'
-CARDS_ID = {
- "Voice Hat": "googlevoicehat",
- "Voice Bonnet": "aiy-voicebonnet",
-}
-
-STOP_DELAY = 1.0
-
-TEST_SOUND_PATH = '/usr/share/sounds/alsa/Front_Center.wav'
-
-RECORD_DURATION_SECONDS = 3
-
-
-def get_sound_cards():
- """Read a dictionary of ALSA cards from /proc, indexed by number."""
- cards = {}
-
- with open(CARDS_PATH) as f: # pylint: disable=invalid-name
- for line in f.read().splitlines():
- try:
- index = int(line.strip().split()[0])
- except (IndexError, ValueError):
- continue
-
- cards[index] = line
-
- return cards
-
-
-def ask(prompt):
- """Get a yes or no answer from the user."""
- ans = input(prompt + ' (y/n) ')
-
- while not ans or ans[0].lower() not in 'yn':
- ans = input('Please enter y or n: ')
-
- return ans[0].lower() == 'y'
-
-
-def check_voicehat_present():
- """Check that the voiceHAT audio driver is present."""
- card_id = CARDS_ID[get_aiy_device_name()]
- return any(card_id in card for card in get_sound_cards().values())
-
-
-def check_voicehat_is_first_card():
- """Check that the voiceHAT is the first card on the system."""
- cards = get_sound_cards()
- card_id = CARDS_ID[get_aiy_device_name()]
- return 0 in cards and card_id in cards[0]
-
-
-def check_asoundrc_is_not_bad():
- """Check that ~/.asoundrc is absent or has the AIY config."""
- asoundrc = os.path.expanduser('~/.asoundrc')
- if not os.path.exists(asoundrc):
- return True
-
- with open(os.path.join(AIY_PROJECTS_DIR, 'scripts', 'asound.conf')) as f:
- wanted_contents = f.read()
- with open(asoundrc) as f:
- contents = f.read()
-
- return contents == wanted_contents
-
-
-def check_speaker_works():
- """Check the speaker makes a sound."""
- print('Playing a test sound...')
- aiy.audio.play_wave(TEST_SOUND_PATH)
-
- return ask('Did you hear the test sound?')
-
-
-def check_mic_works():
- """Check the microphone records correctly."""
- temp_file, temp_path = tempfile.mkstemp(suffix='.wav')
- os.close(temp_file)
-
- try:
- input("When you're ready, press enter and say 'Testing, 1 2 3'...")
- print('Recording...')
- aiy.audio.record_to_wave(temp_path, RECORD_DURATION_SECONDS)
- print('Playing back recorded audio...')
- aiy.audio.play_wave(temp_path)
- finally:
- try:
- os.unlink(temp_path)
- except FileNotFoundError:
- pass
-
- return ask('Did you hear your own voice?')
-
-
-def do_checks():
- """Run all audio checks and print status."""
- if not check_voicehat_present():
- print(textwrap.fill(
- """Failed to find the voiceHAT soundcard. Refer to HACKING.md for
-how to setup the voiceHAT driver: https://git.io/v99yK"""))
- return
-
- if not check_voicehat_is_first_card():
- print(textwrap.fill(
- """The voiceHAT not the first sound device, so the voice recognizer
-may be unable to find it. Please try removing other sound drivers."""))
- return
-
- try:
- if not check_speaker_works():
- print(textwrap.fill(
- """There may be a problem with your speaker. Check that it's
-connected properly."""))
- return
- except BrokenPipeError:
- # aplay crashed - check if ~/.asoundrc is the culprit
- if not check_asoundrc_is_not_bad():
- print(textwrap.fill(
- """~/.asoundrc exists, and it doesn't have the expected
-contents. Try deleting it with `rm ~/.asoundrc`."""))
- else:
- print("aplay crashed - try checking your ALSA config.")
- return
-
- if not check_mic_works():
- print(textwrap.fill(
- """There may be a problem with your microphone. Check that it's
-connected properly."""))
- return
-
- print('The audio seems to be working.')
-
-
-def enable_audio_driver():
- print("Enabling audio driver for VoiceKit.")
- configure_driver = os.path.join(AIY_PROJECTS_DIR, 'scripts', 'configure-driver.sh')
- subprocess.check_call(['sudo', configure_driver])
-
-
-def main():
- if get_aiy_device_name() == 'Voice Hat':
- enable_audio_driver()
- do_checks()
-
-
-if __name__ == '__main__':
- try:
- main()
- input('Press Enter to close...')
- except Exception: # pylint: disable=W0703
- traceback.print_exc()
- input('Press Enter to close...')
diff --git a/checkpoints/check_cloud.py b/checkpoints/check_cloud.py
deleted file mode 100755
index 6e301e96..00000000
--- a/checkpoints/check_cloud.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Check that the Cloud Speech API can be used."""
-
-import json
-import os
-import os.path
-import sys
-import traceback
-
-sys.path.append(os.path.realpath(os.path.join(__file__, '..', '..')) + '/src/')
-
-import aiy._apis._speech # noqa
-
-OLD_CREDENTIALS_FILE = os.path.expanduser('~/credentials.json')
-NEW_CREDENTIALS_FILE = os.path.expanduser('~/cloud_speech.json')
-if os.path.exists(OLD_CREDENTIALS_FILE):
- # Legacy fallback: old location of credentials.
- CREDENTIALS_PATH = OLD_CREDENTIALS_FILE
-else:
- CREDENTIALS_PATH = NEW_CREDENTIALS_FILE
-
-ROOT_PATH = os.path.realpath(os.path.join(__file__, '..', '..'))
-PYTHON3 = ROOT_PATH + '/env/bin/python3'
-SPEECH_PY = ROOT_PATH + '/src/aiy/_apis/_speech.py'
-SPEECH_PY_ENV = {
- 'VIRTUAL_ENV': ROOT_PATH + '/env',
- 'PATH': ROOT_PATH + '/env/bin:' + os.getenv('PATH'),
-}
-TEST_AUDIO = ROOT_PATH + '/checkpoints/test_hello.raw'
-RECOGNIZED_TEXT = 'hello'
-
-
-def check_credentials_valid():
- """Check the credentials are JSON service credentials."""
- try:
- obj = json.load(open(CREDENTIALS_PATH))
- except ValueError:
- return False
-
- return 'type' in obj and obj['type'] == 'service_account'
-
-
-def check_speech_reco():
- """Try to test the speech recognition code from AIY APIs."""
- print('Testing the Google Cloud Speech API...')
- req = aiy._apis._speech.CloudSpeechRequest(CREDENTIALS_PATH)
- with open(TEST_AUDIO, 'rb') as f:
- while True:
- chunk = f.read(64000)
- if not chunk:
- break
- req.add_data(chunk)
- req.end_audio()
- output = req.do_request()
-
- if RECOGNIZED_TEXT in output:
- return True
-
- print('Speech recognition failed or output not as expected:')
- print(output)
- print('Expected:', RECOGNIZED_TEXT)
- return False
-
-
-def main():
- """Run all checks and print status."""
- if not os.path.exists(CREDENTIALS_PATH):
- print(
- """Please follow these instructions to get Google Cloud credentials:
-https://cloud.google.com/speech/docs/getting-started#set_up_your_project
-and save them to""", CREDENTIALS_PATH)
- return
-
- if not check_credentials_valid():
- print(
- CREDENTIALS_PATH, """is not valid, please check that you have downloaded JSON
-service credentials.""")
- return
-
- if not check_speech_reco():
- print('Failed to test the Cloud Speech API. Please see error above.')
- return
-
- print("Everything's set up to use the Google Cloud.")
-
-
-if __name__ == '__main__':
- try:
- main()
- input('Press Enter to close...')
- except Exception:
- traceback.print_exc()
- input('Press Enter to close...')
diff --git a/checkpoints/check_wifi.py b/checkpoints/check_wifi.py
deleted file mode 100755
index 3ec89702..00000000
--- a/checkpoints/check_wifi.py
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Check that the WiFi is working."""
-
-import socket
-import subprocess
-import traceback
-
-WPA_CONF_PATH = '/etc/wpa_supplicant/wpa_supplicant.conf'
-GOOGLE_SERVER_ADDRESS = ('speech.googleapis.com', 443)
-
-
-def check_wifi_is_configured():
- """Check wpa_supplicant.conf has at least one network configured."""
- output = subprocess.check_output(['sudo', 'cat', WPA_CONF_PATH]).decode('utf-8')
-
- return 'network=' in output
-
-
-def check_wifi_is_connected():
- """Check wlan0 has an IP address."""
- output = subprocess.check_output(['ifconfig', 'wlan0']).decode('utf-8')
-
- return 'inet ' in output
-
-
-def check_can_reach_google_server():
- """Check the API server is reachable on port 443."""
- print("Trying to contact Google's servers...")
- try:
- sock = socket.create_connection(GOOGLE_SERVER_ADDRESS, timeout=10)
- sock.close()
- return True
- except Exception: # pylint: disable=W0703
- return False
-
-
-def main():
- """Run all checks and print status."""
- print('Checking the WiFi connection...')
-
- if not check_wifi_is_configured():
- print('Please click the WiFi icon at the top right to set up a WiFi network.')
- return
-
- if not check_wifi_is_connected():
- print(
- """You are not connected to WiFi. Please click the WiFi icon at the top right
-to check your settings.""")
- return
-
- if not check_can_reach_google_server():
- print(
- """Failed to reach Google servers. Please check that your WiFi network is
-connected to the internet.""")
- return
-
- print('The WiFi connection seems to be working.')
-
-
-if __name__ == '__main__':
- try:
- main()
- input('Press Enter to close...')
- except Exception:
- traceback.print_exc()
- input('Press Enter to close...')
diff --git a/checkpoints/test_hello.raw b/checkpoints/test_hello.raw
deleted file mode 100644
index 42538f81..00000000
Binary files a/checkpoints/test_hello.raw and /dev/null differ
diff --git a/examples/button_led.py b/examples/button_led.py
new file mode 100644
index 00000000..b22df6f7
--- /dev/null
+++ b/examples/button_led.py
@@ -0,0 +1,16 @@
+from aiy.util import Led, Button
+
+def main():
+ print('LED is ON while button is pressed (Ctrl-C for exit).')
+ with Led(channel=17) as led, Button(channel=27) as button:
+ while True:
+ button.wait_for_press()
+ print('ON')
+ led.state = Led.ON
+ button.wait_for_release()
+ print('OFF')
+ led.state = Led.OFF
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/examples/vision/buzzer/buzzer_demo.py b/examples/buzzer/buzzer_demo.py
old mode 100755
new mode 100644
similarity index 100%
rename from src/examples/vision/buzzer/buzzer_demo.py
rename to examples/buzzer/buzzer_demo.py
diff --git a/src/examples/vision/buzzer/buzzer_tracker_demo.py b/examples/buzzer/buzzer_tracker_demo.py
old mode 100755
new mode 100644
similarity index 100%
rename from src/examples/vision/buzzer/buzzer_tracker_demo.py
rename to examples/buzzer/buzzer_tracker_demo.py
diff --git a/src/examples/vision/buzzer/congratulations.track b/examples/buzzer/congratulations.track
similarity index 100%
rename from src/examples/vision/buzzer/congratulations.track
rename to examples/buzzer/congratulations.track
diff --git a/src/examples/vision/buzzer/dramatic.track b/examples/buzzer/dramatic.track
similarity index 100%
rename from src/examples/vision/buzzer/dramatic.track
rename to examples/buzzer/dramatic.track
diff --git a/src/examples/vision/buzzer/laughing.track b/examples/buzzer/laughing.track
similarity index 100%
rename from src/examples/vision/buzzer/laughing.track
rename to examples/buzzer/laughing.track
diff --git a/src/examples/vision/buzzer/sadtrombone.track b/examples/buzzer/sadtrombone.track
similarity index 100%
rename from src/examples/vision/buzzer/sadtrombone.track
rename to examples/buzzer/sadtrombone.track
diff --git a/src/examples/vision/buzzer/tetris.track b/examples/buzzer/tetris.track
similarity index 100%
rename from src/examples/vision/buzzer/tetris.track
rename to examples/buzzer/tetris.track
diff --git a/examples/voice/README.md b/examples/voice/README.md
new file mode 100644
index 00000000..79451845
--- /dev/null
+++ b/examples/voice/README.md
@@ -0,0 +1,84 @@
+# Google Assistant and Cloud Speech Examples
+
+To fully experience the interactions, you need an **LED** (+resistor) and a
+**button**. The LED is for conveying the machine's "state of mind". The button
+is to trigger the machine to listen, for cases where you don't want it to be
+bothered by noises. Not all examples require a button.
+
+I suggest you try the examples in the following order:
+
+1. **assistant_library_demo.py**
+
+ **Required credential file:** `/home/pi/assistant.json`
+
+ **LED:** short end to ground, long end to GPIO 17
+
+ **Run:** `python3 assistant_library_demo.py`
+
+ **Usage:** Say "OK, Google", ask it a question, then listen to its responses.
+ Notice how the LED changes.
+
+2. **assistant_library_with_local_commands_demo.py**
+
+ **Required credential file:** `/home/pi/assistant.json`
+
+ **LED:** short end to ground, long end to GPIO 17
+
+ **Run:** `python3 assistant_library_with_local_commands_demo.py`
+
+ **Usage:** Say "OK, Google", converse as before, or say one of these commands:
+
+ - "Power off": supposed to shutdown the pi, but I have commented out the
+ actual shutdown system call
+
+ - "Reboot": supposed to reboot the pi, but I have commented out the actual
+ reboot system call
+
+ - "IP address": tells the internal IP address
+
+ These commands use the `aiy.voice.tts` module (which in turn uses the Pico
+ text-to-speech engine) to generate verbal responses. You can obviously hear
+ the difference.
+
+ `sudo apt-get install libttspico-utils` to install Pico if you haven't done
+ so already.
+
+3. **assistant_grpc_demo.py**
+
+ **Required credential file:** `/home/pi/assistant.json`
+
+ **LED:** short end to ground, long end to GPIO 17
+
+ **Button:** one end to ground, one end to GPIO 27
+
+ **Run:** `python3 assistant_grpc_demo.py --language en-US`. If you don't
+ supply the language, it assumes the Pi's default language, which may not be
+ supported.
+
+ **Usage:** Press the button before speaking. Ask some questions.
+
+4. **cloudspeech_demo.py**
+
+ This one uses Google Cloud Speech, only able to recognize speech, but
+ provide no verbal response.
+
+ **Required credential file:** `/home/pi/cloud_speech.json`
+
+ **LED:** short end to ground, long end to GPIO 17
+
+ **Run:** `python3 cloudspeech_demo.py`
+
+ **Usage:** Say something to see it translate, or say one of the commands and
+ notice how the LED changes:
+
+ - "Turn on the light"
+
+ - "Turn off the light"
+
+ - "Blink the light"
+
+ Say "Goodbye" to exit.
+
+ **Cantonese**: `python3 cloudspeech_demo.py --language yue-Hant-HK` and try
+ to modify the code to make it respond to 開燈, 熄燈, 關燈, 閃燈, 眨燈, 拜拜,
+ 再見.
diff --git a/examples/voice/assistant_grpc_demo.py b/examples/voice/assistant_grpc_demo.py
new file mode 100644
index 00000000..d4e29970
--- /dev/null
+++ b/examples/voice/assistant_grpc_demo.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+# Copyright 2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""A demo of the Google Assistant GRPC recognizer."""
+
+import argparse
+import locale
+import logging
+import signal
+import sys
+
+from aiy.assistant.grpc import AssistantServiceClientWithLed
+from aiy.util import Led, Button
+
+def volume(string):
+ value = int(string)
+ if value < 0 or value > 100:
+ raise argparse.ArgumentTypeError('Volume must be in [0...100] range.')
+ return value
+
+def locale_language():
+ language, _ = locale.getdefaultlocale()
+ return language
+
+def main():
+ logging.basicConfig(level=logging.DEBUG)
+ signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(0))
+
+ parser = argparse.ArgumentParser(description='Assistant service example.')
+ parser.add_argument('--language', default=locale_language())
+ parser.add_argument('--volume', type=volume, default=100)
+ args = parser.parse_args()
+
+ with Led(channel=17) as led, Button(channel=27) as button:
+ assistant = AssistantServiceClientWithLed(led=led,
+ volume_percentage=args.volume,
+ language_code=args.language)
+ while True:
+ logging.info('Press button to start conversation...')
+ button.wait_for_press()
+ logging.info('Conversation started!')
+ assistant.conversation()
+
+if __name__ == '__main__':
+ main()
diff --git a/src/examples/voice/assistant_library_demo.py b/examples/voice/assistant_library_demo.py
old mode 100755
new mode 100644
similarity index 57%
rename from src/examples/voice/assistant_library_demo.py
rename to examples/voice/assistant_library_demo.py
index 1d079b62..46f1af76
--- a/src/examples/voice/assistant_library_demo.py
+++ b/examples/voice/assistant_library_demo.py
@@ -13,60 +13,58 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Run a recognizer using the Google Assistant Library.
+"""Activates the Google Assistant with hotword detection, using the Google Assistant Library.
The Google Assistant Library has direct access to the audio API, so this Python
-code doesn't need to record audio. Hot word detection "OK, Google" is supported.
+code doesn't need to record audio.
-It is available for Raspberry Pi 2/3 only; Pi Zero is not supported.
+.. note:
+
+ This example depends on hotword detection (such as "Okay Google") to activate the Google
+ Assistant, which is supported only with Raspberry Pi 2/3. If you're using a Pi Zero, this
+ code won't work. Instead, you must use the button or another type of trigger, as shown
+ in assistant_library_with_button_demo.py.
"""
import logging
import platform
import sys
-import aiy.assistant.auth_helpers
-from aiy.assistant.library import Assistant
-import aiy.voicehat
from google.assistant.library.event import EventType
-logging.basicConfig(
- level=logging.INFO,
- format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s"
-)
+from aiy.assistant import auth_helpers
+from aiy.assistant.library import Assistant
+from aiy.util import Led
+def process_event(led, event):
+ logging.info(event)
-def process_event(event):
- status_ui = aiy.voicehat.get_status_ui()
if event.type == EventType.ON_START_FINISHED:
- status_ui.status('ready')
- if sys.stdout.isatty():
- print('Say "OK, Google" then speak, or press Ctrl+C to quit...')
+ led.state = Led.BEACON_DARK # Ready.
+ logging.info('Say "OK, Google" then speak, or press Ctrl+C to quit...')
elif event.type == EventType.ON_CONVERSATION_TURN_STARTED:
- status_ui.status('listening')
+ led.state = Led.ON # Listening.
elif event.type == EventType.ON_END_OF_UTTERANCE:
- status_ui.status('thinking')
+ led.state = Led.PULSE_QUICK # Thinking.
elif (event.type == EventType.ON_CONVERSATION_TURN_FINISHED
or event.type == EventType.ON_CONVERSATION_TURN_TIMEOUT
or event.type == EventType.ON_NO_RESPONSE):
- status_ui.status('ready')
+ led.state = Led.BEACON_DARK
elif event.type == EventType.ON_ASSISTANT_ERROR and event.args and event.args['is_fatal']:
sys.exit(1)
def main():
- if platform.machine() == 'armv6l':
- print('Cannot run hotword demo on Pi Zero!')
- exit(-1)
+ logging.basicConfig(level=logging.INFO)
- credentials = aiy.assistant.auth_helpers.get_assistant_credentials()
- with Assistant(credentials) as assistant:
+ credentials = auth_helpers.get_assistant_credentials()
+ with Led(channel=17) as led, Assistant(credentials) as assistant:
for event in assistant.start():
- process_event(event)
+ process_event(led, event)
if __name__ == '__main__':
diff --git a/src/examples/voice/assistant_library_with_local_commands_demo.py b/examples/voice/assistant_library_with_local_commands_demo.py
old mode 100755
new mode 100644
similarity index 68%
rename from src/examples/voice/assistant_library_with_local_commands_demo.py
rename to examples/voice/assistant_library_with_local_commands_demo.py
index 837f7a8a..f40c1afd
--- a/src/examples/voice/assistant_library_with_local_commands_demo.py
+++ b/examples/voice/assistant_library_with_local_commands_demo.py
@@ -26,43 +26,35 @@
import subprocess
import sys
-import aiy.assistant.auth_helpers
-from aiy.assistant.library import Assistant
-import aiy.audio
-import aiy.voicehat
from google.assistant.library.event import EventType
-logging.basicConfig(
- level=logging.INFO,
- format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s"
-)
-
+from aiy.assistant import auth_helpers
+from aiy.assistant.library import Assistant
+from aiy.util import Led
+from aiy.voice import tts
def power_off_pi():
- aiy.audio.say('Good bye!')
- subprocess.call('sudo shutdown now', shell=True)
+ tts.say('Good bye!')
+ # subprocess.call('sudo shutdown now', shell=True)
def reboot_pi():
- aiy.audio.say('See you in a bit!')
- subprocess.call('sudo reboot', shell=True)
+ tts.say('See you in a bit!')
+ # subprocess.call('sudo reboot', shell=True)
def say_ip():
ip_address = subprocess.check_output("hostname -I | cut -d' ' -f1", shell=True)
- aiy.audio.say('My IP address is %s' % ip_address.decode('utf-8'))
+ tts.say('My IP address is %s' % ip_address.decode('utf-8'))
-def process_event(assistant, event):
- status_ui = aiy.voicehat.get_status_ui()
+def process_event(assistant, led, event):
+ logging.info(event)
if event.type == EventType.ON_START_FINISHED:
- status_ui.status('ready')
- if sys.stdout.isatty():
- print('Say "OK, Google" then speak, or press Ctrl+C to quit...')
-
+ led.state = Led.BEACON_DARK # Ready.
+ print('Say "OK, Google" then speak, or press Ctrl+C to quit...')
elif event.type == EventType.ON_CONVERSATION_TURN_STARTED:
- status_ui.status('listening')
-
+ led.state = Led.ON # Listening.
elif event.type == EventType.ON_RECOGNIZING_SPEECH_FINISHED and event.args:
print('You said:', event.args['text'])
text = event.args['text'].lower()
@@ -75,28 +67,23 @@ def process_event(assistant, event):
elif text == 'ip address':
assistant.stop_conversation()
say_ip()
-
elif event.type == EventType.ON_END_OF_UTTERANCE:
- status_ui.status('thinking')
-
+ led.state = Led.PULSE_QUICK # Thinking.
elif (event.type == EventType.ON_CONVERSATION_TURN_FINISHED
or event.type == EventType.ON_CONVERSATION_TURN_TIMEOUT
or event.type == EventType.ON_NO_RESPONSE):
- status_ui.status('ready')
-
+ led.state = Led.BEACON_DARK # Ready.
elif event.type == EventType.ON_ASSISTANT_ERROR and event.args and event.args['is_fatal']:
sys.exit(1)
def main():
- if platform.machine() == 'armv6l':
- print('Cannot run hotword demo on Pi Zero!')
- exit(-1)
+ logging.basicConfig(level=logging.INFO)
- credentials = aiy.assistant.auth_helpers.get_assistant_credentials()
- with Assistant(credentials) as assistant:
+ credentials = auth_helpers.get_assistant_credentials()
+ with Led(channel=17) as led, Assistant(credentials) as assistant:
for event in assistant.start():
- process_event(assistant, event)
+ process_event(assistant, led, event)
if __name__ == '__main__':
diff --git a/examples/voice/cloudspeech_demo.py b/examples/voice/cloudspeech_demo.py
new file mode 100644
index 00000000..8e941f91
--- /dev/null
+++ b/examples/voice/cloudspeech_demo.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+# Copyright 2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""A demo of the Google CloudSpeech recognizer."""
+import argparse
+import locale
+import logging
+
+from aiy.util import Led
+from aiy.cloudspeech import CloudSpeechClient
+
+
+def get_hints(language_code):
+ if language_code.startswith('en_'):
+ return ('turn on the light',
+ 'turn off the light',
+ 'blink the light',
+ 'goodbye')
+ return None
+
+def locale_language():
+ language, _ = locale.getdefaultlocale()
+ return language
+
+def main():
+ logging.basicConfig(level=logging.DEBUG)
+
+ parser = argparse.ArgumentParser(description='Assistant service example.')
+ parser.add_argument('--language', default=locale_language())
+ args = parser.parse_args()
+
+ logging.info('Initializing for language %s...', args.language)
+ hints = get_hints(args.language)
+ client = CloudSpeechClient()
+ with Led(channel=17) as led:
+ while True:
+ if hints:
+ logging.info('Say something, e.g. %s.' % ', '.join(hints))
+ else:
+ logging.info('Say something.')
+ text = client.recognize(language_code=args.language,
+ hint_phrases=hints)
+ if text is None:
+ logging.info('You said nothing.')
+ continue
+
+ logging.info('You said: "%s"' % text)
+ text = text.lower()
+ if 'turn on the light' in text:
+ led.state = Led.ON
+ elif 'turn off the light' in text:
+ led.state = Led.OFF
+ elif 'blink the light' in text:
+ led.state = Led.BLINK
+ elif 'goodbye' in text:
+ break
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/voice/voice_recorder.py b/examples/voice/voice_recorder.py
new file mode 100644
index 00000000..ef564a7c
--- /dev/null
+++ b/examples/voice/voice_recorder.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+# Copyright 2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+import time
+import threading
+
+from aiy.util import Button
+from aiy.voice.audio import AudioFormat, play_wav, record_file, Recorder
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--filename', '-f', default='recording.wav')
+ args = parser.parse_args()
+
+ with Button(channel=27) as button:
+ print('Press button to start recording.')
+ button.wait_for_press()
+
+ done = threading.Event()
+ button.when_pressed = done.set
+
+ def wait():
+ start = time.monotonic()
+ while not done.is_set():
+ duration = time.monotonic() - start
+ print('Recording: %.02f seconds [Press button to stop]' % duration)
+ time.sleep(0.5)
+
+ record_file(AudioFormat.CD, filename=args.filename, wait=wait, filetype='wav')
+ print('Press button to play recorded sound.')
+ button.wait_for_press()
+
+ print('Playing...')
+ play_wav(args.filename)
+ print('Done.')
+
+if __name__ == '__main__':
+ main()
diff --git a/make_dpkg.sh b/make_dpkg.sh
deleted file mode 100755
index 0a8f07da..00000000
--- a/make_dpkg.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/bash
-
-# set -x
-set -e
-
-SCRIPT_DIR=$(dirname $(readlink -f $0))
-WORK_DIR=$(mktemp -d)
-
-
-mkdir -p ${WORK_DIR}/aiy-projects-python-0.1/opt/aiy/
-git worktree add --detach ${WORK_DIR}/aiy-projects-python-0.1/debian origin/debian
-git worktree add --detach ${WORK_DIR}/aiy-projects-python-0.1/projects-python origin/aiyprojects
-
-# Copy aiyprojects and set remote to github.
-AIY_PYTHON_DIR=${WORK_DIR}/aiy-projects-python-0.1/projects-python
-rm -f ${AIY_PYTHON_DIR}/.git
-if [ -d ${AIY_PYTHON_DIR}/.git ]; then
- rsync -rL --exclude=.git/shallow ${SCRIPT_DIR}/.git ${AIY_PYTHON_DIR}
-else
- cp -r ${SCRIPT_DIR}/../.git/modules/aiy-projects-python ${AIY_PYTHON_DIR}/.git
-fi
-ls -la ${AIY_PYTHON_DIR}/.git/
-sed -i '/\tworktree =/d' ${AIY_PYTHON_DIR}/.git/config
-git -C ${AIY_PYTHON_DIR} checkout aiyprojects
-for BRANCH in $(git -C ${AIY_PYTHON_DIR} branch | sed 's/\*//'); do
- if [[ "$BRANCH" != "aiyprojects" ]]; then
- git -C ${AIY_PYTHON_DIR} branch -D ${BRANCH}
- fi
-done
-git -C ${AIY_PYTHON_DIR} remote remove origin | true
-git -C ${AIY_PYTHON_DIR} remote add origin \
- https://github.com/google/aiyprojects-raspbian
-
-pushd ${WORK_DIR}/aiy-projects-python-0.1
-tar cf ${WORK_DIR}/aiy-projects-python_0.1.orig.tar.xz projects-python
-# tar tf ${WORK_DIR}/aiy-projects-python_0.1.orig.tar.xz
-find .
-
-debuild --no-lintian -us -uc
-
-cp ${WORK_DIR}/aiy-projects-python_0.1-0_all.deb ${SCRIPT_DIR}
-rm -rf ${WORK_DIR}
-popd
-git worktree prune
diff --git a/po/de.po b/po/de.po
deleted file mode 100644
index db130ddf..00000000
--- a/po/de.po
+++ /dev/null
@@ -1,127 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: voice-recognizer-1.0\n"
-"POT-Creation-Date: 2017-04-21 14:33+CEST\n"
-"PO-Revision-Date: 2017-02-16 09:26+0100\n"
-"Last-Translator: Stefan Sauer \n"
-"Language-Team: \n"
-"Language: de\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-"X-Generator: Poedit 1.5.4\n"
-
-#: src/action.py:172
-msgid "Volume at %d %%."
-msgstr "Lautstärke auf %d %%."
-
-#: src/action.py:202
-msgid "ip address"
-msgstr "IP Adresse"
-
-#: src/action.py:204
-msgid "I do not have an ip address assigned to me."
-msgstr "Ich habe keine IP Adresse zugewiesen bekommen."
-
-#: src/action.py:206
-msgid "volume up"
-msgstr "Lautstärke hoch"
-
-#: src/action.py:207
-msgid "volume down"
-msgstr "Lautstärke runter"
-
-#: src/action.py:208
-msgid "max volume"
-msgstr "volle Lautstärke"
-
-#: src/action.py:210 src/action.py:211
-msgid "repeat after me"
-msgstr "sprich mir nach"
-
-#: src/action.py:225
-msgid "We've been friends since we were both starter projects"
-msgstr "Da wir beide ganz neu sind, verstehen wir uns prima."
-
-#: src/action.py:229
-msgid "clap"
-msgstr "klatsche"
-
-#: src/action.py:229
-msgid "clap clap"
-msgstr "klatsch klatsch"
-
-#: src/action.py:230
-msgid "She taught me everything I know."
-msgstr "Sie hat mir alles im Leben beigebracht."
-
-#: src/action.py:231
-msgid "hello"
-msgstr "Hallo"
-
-#: src/action.py:231
-msgid "hello to you too"
-msgstr "Hallo auch zu dir"
-
-#: src/action.py:232
-msgid "tell me a joke"
-msgstr "Erzähl mir einen Witz"
-
-#: src/action.py:233
-msgid "What do you call an alligator in a vest? An investigator."
-msgstr "Was hat vier Beine und kann fliegen? Zwei Vögel."
-
-#: src/action.py:234
-msgid "three laws of robotics"
-msgstr ""
-
-#: src/action.py:235
-msgid ""
-"The laws of robotics are\n"
-"0: A robot may not injure a human being or, through inaction, allow a human\n"
-"being to come to harm.\n"
-"1: A robot must obey orders given it by human beings except where such "
-"orders\n"
-"would conflict with the First Law.\n"
-"2: A robot must protect its own existence as long as such protection does "
-"not\n"
-"conflict with the First or Second Law."
-msgstr ""
-
-#: src/action.py:242
-msgid "A galaxy far, far, just kidding. I'm from Seattle."
-msgstr ""
-"Aus einer weit, weit entfernten Galaxie, Ach Quatsch ich komm aus Seattle."
-
-#: src/action.py:242
-msgid "where are you from"
-msgstr "Woher kommst du"
-
-#: src/action.py:243
-msgid "A machine has no name"
-msgstr "Eine Maschine hat keinen Namen."
-
-#: src/action.py:243
-msgid "your name"
-msgstr "dein Name"
-
-#: src/action.py:245
-msgid "time"
-msgstr "Zeit"
-
-#: src/main.py:279
-msgid "Unexpected error. Try again or check the logs."
-msgstr "Unerwarteter Fehler. Probiere nocheinmal oder kontrolliere die Logs."
-
-#: src/main.py:292
-msgid "I don’t know how to answer that."
-msgstr "Das weis ich nicht."
-
-#: src/main.py:295
-msgid "Could you try that again?"
-msgstr "Bitte probiere es nocheinmal."
diff --git a/po/de/LC_MESSAGES/voice-recognizer.mo b/po/de/LC_MESSAGES/voice-recognizer.mo
deleted file mode 100644
index 0226877a..00000000
Binary files a/po/de/LC_MESSAGES/voice-recognizer.mo and /dev/null differ
diff --git a/po/voice-recognizer.pot b/po/voice-recognizer.pot
deleted file mode 100644
index 2bce8ab8..00000000
--- a/po/voice-recognizer.pot
+++ /dev/null
@@ -1,124 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2017-04-21 14:33+CEST\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-#: src/action.py:172
-msgid "Volume at %d %%."
-msgstr ""
-
-#: src/action.py:202
-msgid "ip address"
-msgstr ""
-
-#: src/action.py:204
-msgid "I do not have an ip address assigned to me."
-msgstr ""
-
-#: src/action.py:206
-msgid "volume up"
-msgstr ""
-
-#: src/action.py:207
-msgid "volume down"
-msgstr ""
-
-#: src/action.py:208
-msgid "max volume"
-msgstr ""
-
-#: src/action.py:210 src/action.py:211
-msgid "repeat after me"
-msgstr ""
-
-#: src/action.py:225
-msgid "We've been friends since we were both starter projects"
-msgstr ""
-
-#: src/action.py:229
-msgid "clap"
-msgstr ""
-
-#: src/action.py:229
-msgid "clap clap"
-msgstr ""
-
-#: src/action.py:230
-msgid "She taught me everything I know."
-msgstr ""
-
-#: src/action.py:231
-msgid "hello"
-msgstr ""
-
-#: src/action.py:231
-msgid "hello to you too"
-msgstr ""
-
-#: src/action.py:232
-msgid "tell me a joke"
-msgstr ""
-
-#: src/action.py:233
-msgid "What do you call an alligator in a vest? An investigator."
-msgstr ""
-
-#: src/action.py:234
-msgid "three laws of robotics"
-msgstr ""
-
-#: src/action.py:235
-msgid ""
-"The laws of robotics are\n"
-"0: A robot may not injure a human being or, through inaction, allow a human\n"
-"being to come to harm.\n"
-"1: A robot must obey orders given it by human beings except where such orders\n"
-"would conflict with the First Law.\n"
-"2: A robot must protect its own existence as long as such protection does not\n"
-"conflict with the First or Second Law."
-msgstr ""
-
-#: src/action.py:242
-msgid "A galaxy far, far, just kidding. I'm from Seattle."
-msgstr ""
-
-#: src/action.py:242
-msgid "where are you from"
-msgstr ""
-
-#: src/action.py:243
-msgid "A machine has no name"
-msgstr ""
-
-#: src/action.py:243
-msgid "your name"
-msgstr ""
-
-#: src/action.py:245
-msgid "time"
-msgstr ""
-
-#: src/main.py:279
-msgid "Unexpected error. Try again or check the logs."
-msgstr ""
-
-#: src/main.py:292
-msgid "I don’t know how to answer that."
-msgstr ""
-
-#: src/main.py:295
-msgid "Could you try that again?"
-msgstr ""
-
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 01d7d1d8..00000000
--- a/requirements.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-google-assistant-grpc==0.1.0
-google-cloud-speech==0.30.0
-google-auth-oauthlib==0.2.0
-pyasn1==0.4.2
-grpcio==1.7.0
diff --git a/scripts/asound.conf b/scripts/asound.conf
deleted file mode 100755
index 951ddade..00000000
--- a/scripts/asound.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-options snd_rpi_googlevoicehat_soundcard index=0
-
-pcm.softvol {
- type softvol
- slave.pcm dmix
- control {
- name Master
- card 0
- }
-}
-
-pcm.micboost {
- type route
- slave.pcm dsnoop
- ttable {
- 0.0 30.0
- 1.1 30.0
- }
-}
-
-pcm.!default {
- type asym
- playback.pcm "plug:softvol"
- capture.pcm "plug:micboost"
-}
-
-ctl.!default {
- type hw
- card 0
-}
diff --git a/scripts/configure-driver.sh b/scripts/configure-driver.sh
deleted file mode 100755
index ee3a0710..00000000
--- a/scripts/configure-driver.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -o errexit
-
-if [[ $EUID -ne 0 ]]; then
- echo "This script must be run as root (use sudo)" 1>&2
- exit 1
-fi
-
-set -e
-
-sed -i \
- -e "s/^dtparam=audio=on/#\0/" \
- -e "s/^#\s*\(dtparam=i2s=on\)/\1/" \
- -e "s/^#\s*\(dtoverlay=i2s-mmap\)/\1/" \
- -e "s/^#\s*\(dtoverlay=googlevoicehat-soundcard\)/\1/" \
- /boot/config.txt
-grep -q "dtoverlay=i2s-mmap" /boot/config.txt || \
- echo "dtoverlay=i2s-mmap" >> /boot/config.txt
-grep -q "dtoverlay=googlevoicehat-soundcard" /boot/config.txt || \
- echo "dtoverlay=googlevoicehat-soundcard" >> /boot/config.txt
-grep -q "dtparam=i2s=on" /boot/config.txt || \
- echo "dtparam=i2s=on" >> /boot/config.txt
-
-dtoverlay googlevoicehat-soundcard
diff --git a/scripts/install-alsa-config.sh b/scripts/install-alsa-config.sh
deleted file mode 100755
index e81b71dc..00000000
--- a/scripts/install-alsa-config.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/bash
-#
-# Replace the Raspberry Pi's default ALSA config with one for the voiceHAT.
-#
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -o errexit
-
-if [[ $EUID -ne 0 ]]; then
- echo "This script must be run as root (use sudo)" 1>&2
- exit 1
-fi
-
-cd "$(dirname "${BASH_SOURCE[0]}")/.."
-
-asoundrc=/home/pi/.asoundrc
-global_asoundrc=/etc/asound.conf
-
-for rcfile in "$asoundrc" "$global_asoundrc"; do
- if [[ -f "$rcfile" ]] ; then
- echo "Renaming $rcfile to $rcfile.bak..."
- sudo mv "$rcfile" "$rcfile.bak"
- fi
-done
-
-sudo cp scripts/asound.conf "$global_asoundrc"
-echo "Installed voiceHAT ALSA config at $global_asoundrc"
-
-# TODO(rodrigoq): it shouldn't be necessary to install at both locations, but
-# if we don't install to $HOME then the volume widget (volumealsa) has a
-# tendency to create an incompatible ~/.asoundrc and break the Voice Kit audio.
-sudo cp scripts/asound.conf "$asoundrc"
-echo "Installed voiceHAT ALSA config at $asoundrc"
diff --git a/scripts/install-deps.sh b/scripts/install-deps.sh
deleted file mode 100755
index 3242b61e..00000000
--- a/scripts/install-deps.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -o errexit
-
-scripts_dir="$(dirname "${BASH_SOURCE[0]}")"
-
-# make sure we're running as the owner of the checkout directory
-RUN_AS="$(ls -ld "$scripts_dir" | awk 'NR==1 {print $3}')"
-if [ "$USER" != "$RUN_AS" ]
-then
- echo "This script must run as $RUN_AS, trying to change user..."
- exec sudo -u $RUN_AS $0
-fi
-
-# The google-assistant-library is only available on some platforms.
-if [[ "$(uname -m)" == "armv7l" || "$(uname -m)" == "x86_64" || "$(uname -m)" == "armv6l" ]] ; then
- pip3 install google-assistant-library==0.1.0
-fi
diff --git a/scripts/install-services.sh b/scripts/install-services.sh
deleted file mode 100755
index e06a084f..00000000
--- a/scripts/install-services.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-#
-# Install systemd service files for running on startup.
-#
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -o errexit
-
-if [[ $EUID -ne 0 ]]; then
- echo "This script must be run as root (use sudo)" 1>&2
- exit 1
-fi
-
-cd "$(dirname "${BASH_SOURCE[0]}")/.."
-repo_path="$PWD"
-
-for service in systemd/*.service; do
- sed "s:/home/pi/AIY-projects-python:${repo_path}:g" "$service" \
- > "/lib/systemd/system/$(basename "$service")"
-done
-
-# voice-recognizer is not enabled by default, as it doesn't work until
-# credentials are set up, so we explicitly enable the other services.
-systemctl enable alsa-init.service
-systemctl enable ntpdate.service
diff --git a/scripts/pre-commit b/scripts/pre-commit
deleted file mode 100755
index abdee0b1..00000000
--- a/scripts/pre-commit
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-# git hook to ensure code style
-# ln ../../scripts/pre-commit .git/hooks/
-
-which >/dev/null autopep8 || { echo "please install autopep8"; exit 1; }
-files=$(git diff --name-only --staged --diff-filter=ACMRTUXB | egrep "*.py$")
-
-if test -n "$files"; then
- diff=$(autopep8 --max-line-length=100 --diff $files)
- if [[ -n "${diff}" ]]; then
- echo
- autopep8 --max-line-length=100 --diff $files
- echo
- echo "To fix run: autopep8 --max-line-length=100 -i $files"
- exit 1
- fi
-fi
diff --git a/shortcuts/check_audio.desktop b/shortcuts/check_audio.desktop
deleted file mode 100644
index 8c961fc1..00000000
--- a/shortcuts/check_audio.desktop
+++ /dev/null
@@ -1,7 +0,0 @@
-[Desktop Entry]
-Encoding=UTF-8
-Type=Application
-Name=Check audio
-Comment=Check that the voiceHAT audio input and output are both working.
-Exec=/home/pi/AIY-projects-python/checkpoints/check_audio.py
-Terminal=true
diff --git a/shortcuts/check_cloud.desktop b/shortcuts/check_cloud.desktop
deleted file mode 100644
index dd9b91d5..00000000
--- a/shortcuts/check_cloud.desktop
+++ /dev/null
@@ -1,7 +0,0 @@
-[Desktop Entry]
-Encoding=UTF-8
-Type=Application
-Name=Check Cloud
-Comment=Check that the Cloud Speech API can be used.
-Exec=/home/pi/AIY-projects-python/checkpoints/check_cloud.py
-Terminal=true
diff --git a/shortcuts/check_wifi.desktop b/shortcuts/check_wifi.desktop
deleted file mode 100644
index 059aaee5..00000000
--- a/shortcuts/check_wifi.desktop
+++ /dev/null
@@ -1,7 +0,0 @@
-[Desktop Entry]
-Encoding=UTF-8
-Type=Application
-Name=Check WiFi
-Comment=Check that the WiFi is working.
-Exec=/home/pi/AIY-projects-python/checkpoints/check_wifi.py
-Terminal=true
diff --git a/src/.gitignore b/src/.gitignore
deleted file mode 100644
index e5547674..00000000
--- a/src/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-MANIFEST
-*.egg-info
-dist/
diff --git a/src/README.md b/src/README.md
deleted file mode 100644
index d272dbf4..00000000
--- a/src/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-This repository contains an easy-to-use API for the AIY Vision Kit and
-AIY Voice Kit.
-You can use it for face detection and object recognition, or use it to create
-voice commands with simple while loops - have a look at the
-[demos](https://github.com/google/aiyprojects-raspbian/tree/aiyprojects/src/examples).
-Documentation is at the [AIY Projects site](https://aiyprojects.withgoogle.com).
-
-For guidelines on contributing, look at [CONTRIBUTING.md](CONTRIBUTING.md).
-If you're using Raspbian instead of Google's provided image, read
-[HACKING.md](HACKING.md) for information on getting started.
-
-For returning users:
-The code for all AIY kits is in the `aiyprojects` branch, and is included in
-images starting with aiyprojects-2017-12-18.img. The previous `voicekit` branch
-contains code just for the Voice Kit, and the `master` branch contains the
-original, deprecated Voice Recognizer demo.
-
-# Support
-
-If you're having trouble assembling your kit or running the demos,
-try the [AIY Forums](https://www.raspberrypi.org/forums/viewforum.php?f=114).
-
-If you've found a bug in the AIY API or demos, you can look at the
-[known issues](https://github.com/google/aiyprojects-raspbian/issues) or create
-a new one, or even fix it yourself and send us a pull request.
-
-If you've found a problem with the Assistant (for example, crashes in the
-library or incorrect responses), you can try
-[the G+ community](https://plus.google.com/communities/117537996116836200696),
-[Stack Overflow](https://stackoverflow.com/questions/tagged/google-assistant-sdk),
-or [the assistant-sdk-python repo](https://github.com/googlesamples/assistant-sdk-python/).
-
-If you've had a problem after updating the source code, try downloading the
-latest AIY image from the website, or alternatively run the following commands
-in the dev terminal:
-
-```
-rm -r env
-./scripts/install-deps.sh
-```
diff --git a/src/aiy/_apis/_speech.py b/src/aiy/_apis/_speech.py
deleted file mode 100644
index 2a59d5a5..00000000
--- a/src/aiy/_apis/_speech.py
+++ /dev/null
@@ -1,477 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Classes for speech interaction."""
-
-from abc import abstractmethod
-import collections
-import logging
-import os
-import sys
-import tempfile
-import wave
-
-import google.auth
-import google.auth.exceptions
-import google.auth.transport.grpc
-import google.auth.transport.requests
-try:
- from google.cloud import speech
- from google.cloud.speech import enums
- from google.cloud.speech import types
-except ImportError:
- print("Failed to import google.cloud.speech. Try:")
- print(" env/bin/pip install -r requirements.txt")
- sys.exit(1)
-
-from google.rpc import code_pb2 as error_code
-from google.assistant.embedded.v1alpha2 import (
- embedded_assistant_pb2,
- embedded_assistant_pb2_grpc,
-)
-import grpc
-from six.moves import queue
-
-import aiy.i18n
-
-logger = logging.getLogger('speech')
-
-AUDIO_SAMPLE_SIZE = 2 # bytes per sample
-AUDIO_SAMPLE_RATE_HZ = 16000
-
-# Expected location of the service credentials file:
-SERVICE_CREDENTIALS = os.path.expanduser('~/cloud_speech.json')
-
-
-_Result = collections.namedtuple('_Result', ['transcript', 'response_audio'])
-
-
-class Error(Exception):
- pass
-
-
-class _ChannelFactory(object):
-
- """Creates gRPC channels with a given configuration."""
-
- def __init__(self, api_host, credentials):
- self._api_host = api_host
- self._credentials = credentials
-
- self._checked = False
-
- def make_channel(self):
- """Creates a secure channel."""
-
- request = google.auth.transport.requests.Request()
- target = self._api_host + ':443'
-
- if not self._checked:
- # Refresh now, to catch any errors early. Otherwise, they'll be
- # raised and swallowed somewhere inside gRPC.
- self._credentials.refresh(request)
- self._checked = True
-
- return google.auth.transport.grpc.secure_authorized_channel(
- self._credentials, request, target)
-
-
-class GenericSpeechRequest(object):
-
- """Common base class for Cloud Speech and Assistant APIs."""
-
- # TODO(rodrigoq): Refactor audio logging.
- # pylint: disable=attribute-defined-outside-init,too-many-instance-attributes
-
- DEADLINE_SECS = 185
-
- def __init__(self, api_host, credentials):
- self.dialog_follow_on = False
- self._audio_queue = queue.Queue()
- self._phrases = []
- self._channel_factory = _ChannelFactory(api_host, credentials)
- self._endpointer_cb = None
- self._audio_logging_enabled = False
- self._request_log_wav = None
-
- def add_phrases(self, phrases):
- """Makes the recognition more likely to recognize the given phrase(s).
- phrases: an object with a method get_phrases() that returns a list of
- phrases.
- """
-
- self._phrases.extend(phrases.get_phrases())
-
- def add_phrase(self, phrase):
- """Makes the recognition more likely to recognize the given phrase."""
- self._phrases.append(phrase)
-
- def set_endpointer_cb(self, cb):
- """Callback to invoke on end of speech."""
- self._endpointer_cb = cb
-
- def set_audio_logging_enabled(self, audio_logging_enabled=True):
- self._audio_logging_enabled = audio_logging_enabled
-
- if audio_logging_enabled:
- self._audio_log_dir = tempfile.mkdtemp()
- self._audio_log_ix = 0
-
- def reset(self):
- while True:
- try:
- self._audio_queue.get(False)
- except queue.Empty:
- return
-
- self.dialog_follow_on = False
-
- def add_data(self, data):
- self._audio_queue.put(data)
-
- def end_audio(self):
- self.add_data(None)
-
- def _get_speech_context(self):
- """Return a SpeechContext instance to bias recognition towards certain
- phrases.
- """
- return types.SpeechContext(
- phrases=self._phrases,
- )
-
- @abstractmethod
- def _make_service(self, channel):
- """Create a service stub.
- """
- return
-
- @abstractmethod
- def _create_config_request(self):
- """Create a config request for the given endpoint.
-
- This is sent first to the server to configure the speech recognition.
- """
- return
-
- @abstractmethod
- def _create_audio_request(self, data):
- """Create an audio request for the given endpoint.
-
- This is sent to the server with audio to be recognized.
- """
- return
-
- def _request_stream(self):
- """Yields a config request followed by requests constructed from the
- audio queue.
- """
- yield self._create_config_request()
-
- while True:
- data = self._audio_queue.get()
-
- if not data:
- return
-
- if self._request_log_wav:
- self._request_log_wav.writeframes(data)
-
- yield self._create_audio_request(data)
-
- @abstractmethod
- def _create_response_stream(self, service, request_stream, deadline):
- """Given a request stream, start the gRPC call to get the response
- stream.
- """
- return
-
- @abstractmethod
- def _stop_sending_audio(self, resp):
- """Return true if this response says user has stopped speaking.
-
- This stops the request from sending further audio.
- """
- return
-
- @abstractmethod
- def _handle_response(self, resp):
- """Handle a response from the remote API.
-
- Args:
- resp: StreamingRecognizeResponse instance
- """
- return
-
- def _end_audio_request(self):
- self.end_audio()
- if self._endpointer_cb:
- self._endpointer_cb()
-
- def _handle_response_stream(self, response_stream):
- for resp in response_stream:
- if self._stop_sending_audio(resp):
- self._end_audio_request()
-
- self._handle_response(resp)
-
- # Server has closed the connection
- return self._finish_request() or ''
-
- def _start_logging_request(self):
- """Open a WAV file to log the request audio."""
- self._audio_log_ix += 1
- request_filename = '%s/request.%03d.wav' % (
- self._audio_log_dir, self._audio_log_ix)
- logger.info('Writing request to %s', request_filename)
-
- self._request_log_wav = wave.open(request_filename, 'w')
-
- self._request_log_wav.setnchannels(1)
- self._request_log_wav.setsampwidth(AUDIO_SAMPLE_SIZE)
- self._request_log_wav.setframerate(AUDIO_SAMPLE_RATE_HZ)
-
- def _finish_request(self):
- """Called after the final response is received."""
-
- if self._request_log_wav:
- self._request_log_wav.close()
-
- return _Result(None, None)
-
- def do_request(self):
- """Establishes a connection and starts sending audio to the cloud
- endpoint. Responses are handled by the subclass until one returns a
- result.
-
- Returns:
- namedtuple with the following fields:
- transcript: string with transcript of user query
- response_audio: optionally, an audio response from the server
-
- Raises speech.Error on error.
- """
- try:
- service = self._make_service(self._channel_factory.make_channel())
-
- response_stream = self._create_response_stream(
- service, self._request_stream(), self.DEADLINE_SECS)
-
- if self._audio_logging_enabled:
- self._start_logging_request()
-
- return self._handle_response_stream(response_stream)
- except (
- google.auth.exceptions.GoogleAuthError,
- grpc.RpcError,
- ) as exc:
- raise Error('Exception in speech request') from exc
-
-
-class CloudSpeechRequest(GenericSpeechRequest):
-
- """A transcription request to the Cloud Speech API.
-
- Args:
- credentials_file: path to service account credentials JSON file
- """
-
- SCOPE = 'https://www.googleapis.com/auth/cloud-platform'
-
- def __init__(self, credentials_file):
- os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = credentials_file
- credentials, _ = google.auth.default(scopes=[self.SCOPE])
-
- super().__init__('speech.googleapis.com', credentials)
-
- self._transcript = None
-
- def reset(self):
- super().reset()
- self._transcript = None
-
- def _make_service(self, channel):
- return speech.SpeechClient()
-
- def _create_config_request(self):
- recognition_config = types.RecognitionConfig(
- encoding=enums.RecognitionConfig.AudioEncoding.LINEAR16,
- sample_rate_hertz=AUDIO_SAMPLE_RATE_HZ,
- language_code=aiy.i18n.get_language_code(),
- speech_contexts=[self._get_speech_context()],
- )
- streaming_config = types.StreamingRecognitionConfig(
- config=recognition_config,
- single_utterance=True,
- )
-
- # TODO(rodrigoq): we're actually returning a Config, not a Request, as
- # the v1 API takes the Config and wraps it up in a Request, but we still
- # want to share code with the Assistant API. Can we clean this up?
- return streaming_config
-
- def _create_audio_request(self, data):
- return types.StreamingRecognizeRequest(audio_content=data)
-
- def _create_response_stream(self, client, request_stream, deadline):
- config = next(request_stream)
- return client.streaming_recognize(config, request_stream)
-
- def _stop_sending_audio(self, resp):
- """Check the endpointer type to see if an utterance has ended."""
-
- if resp.speech_event_type:
- speech_event_type = types.StreamingRecognizeResponse.SpeechEventType.Name(
- resp.speech_event_type)
- logger.info('endpointer_type: %s', speech_event_type)
-
- END_OF_SINGLE_UTTERANCE = types.StreamingRecognizeResponse.SpeechEventType.Value(
- 'END_OF_SINGLE_UTTERANCE')
- return resp.speech_event_type == END_OF_SINGLE_UTTERANCE
-
- def _handle_response(self, resp):
- """Store the last transcript we received."""
- if resp.results:
- self._transcript = ' '.join(
- result.alternatives[0].transcript for result in resp.results)
- logger.info('transcript: %s', self._transcript)
-
- def _finish_request(self):
- super()._finish_request()
- return _Result(self._transcript, None)
-
-
-class AssistantSpeechRequest(GenericSpeechRequest):
-
- """A request to the Assistant API, which returns audio and text."""
-
- def __init__(self, credentials, model_id, device_id):
-
- super().__init__('embeddedassistant.googleapis.com', credentials)
-
- self.model_id = model_id
- self.device_id = device_id
-
- self._conversation_state = None
- self._response_audio = b''
- self._transcript = None
-
- def reset(self):
- super().reset()
- self._response_audio = b''
- self._transcript = None
-
- def _make_service(self, channel):
- return embedded_assistant_pb2_grpc.EmbeddedAssistantStub(channel)
-
- def _create_config_request(self):
- audio_in_config = embedded_assistant_pb2.AudioInConfig(
- encoding='LINEAR16',
- sample_rate_hertz=AUDIO_SAMPLE_RATE_HZ,
- )
- audio_out_config = embedded_assistant_pb2.AudioOutConfig(
- encoding='LINEAR16',
- sample_rate_hertz=AUDIO_SAMPLE_RATE_HZ,
- volume_percentage=50,
- )
- device_config = embedded_assistant_pb2.DeviceConfig(
- device_id=self.device_id,
- device_model_id=self.model_id,
- )
- dialog_state_in = embedded_assistant_pb2.DialogStateIn(
- conversation_state=self._conversation_state,
- language_code=aiy.i18n.get_language_code(),
- )
- assist_config = embedded_assistant_pb2.AssistConfig(
- audio_in_config=audio_in_config,
- audio_out_config=audio_out_config,
- device_config=device_config,
- dialog_state_in=dialog_state_in,
- )
-
- return embedded_assistant_pb2.AssistRequest(config=assist_config)
-
- def _create_audio_request(self, data):
- return embedded_assistant_pb2.AssistRequest(audio_in=data)
-
- def _create_response_stream(self, service, request_stream, deadline):
- return service.Assist(request_stream, deadline)
-
- def _stop_sending_audio(self, resp):
- if resp.event_type:
- logger.info('event_type: %s', resp.event_type)
-
- return (resp.event_type ==
- embedded_assistant_pb2.AssistResponse.END_OF_UTTERANCE)
-
- def _handle_response(self, resp):
- """Accumulate audio and text from the remote end. It will be handled
- in _finish_request().
- """
-
- if resp.speech_results:
- self._transcript = ' '.join(r.transcript for r in resp.speech_results)
- logger.info('transcript: %s', self._transcript)
-
- self._response_audio += resp.audio_out.audio_data
-
- if resp.dialog_state_out.conversation_state:
- self._conversation_state = resp.dialog_state_out.conversation_state
-
- if resp.dialog_state_out.microphone_mode:
- self.dialog_follow_on = (
- resp.dialog_state_out.microphone_mode ==
- embedded_assistant_pb2.DialogStateOut.DIALOG_FOLLOW_ON)
-
- def _finish_request(self):
- super()._finish_request()
-
- if self._response_audio and self._audio_logging_enabled:
- self._log_audio_out(self._response_audio)
-
- return _Result(self._transcript, self._response_audio)
-
- def _log_audio_out(self, frames):
- response_filename = '%s/response.%03d.wav' % (
- self._audio_log_dir, self._audio_log_ix)
- logger.info('Writing response to %s', response_filename)
-
- response_wav = wave.open(response_filename, 'w')
- response_wav.setnchannels(1)
- response_wav.setsampwidth(AUDIO_SAMPLE_SIZE)
- response_wav.setframerate(AUDIO_SAMPLE_RATE_HZ)
- response_wav.writeframes(frames)
- response_wav.close()
-
-
-if __name__ == '__main__':
- logging.basicConfig(level=logging.INFO)
-
- # for testing: use audio from a file
- import argparse
- parser = argparse.ArgumentParser()
- parser.add_argument('file', nargs='?', default='test_speech.raw')
- args = parser.parse_args()
-
- req = CloudSpeechRequest(SERVICE_CREDENTIALS)
-
- with open(args.file, 'rb') as f:
- while True:
- chunk = f.read(64000)
- if not chunk:
- break
- req.add_data(chunk)
- req.end_audio()
-
- print('down response:', req.do_request())
diff --git a/src/aiy/_drivers/_alsa.py b/src/aiy/_drivers/_alsa.py
deleted file mode 100644
index 58c466cc..00000000
--- a/src/aiy/_drivers/_alsa.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Helpers for ALSA tools, including aplay and arecord."""
-
-
-def sample_width_to_string(sample_width):
- """Convert sample width (bytes) to ALSA format string."""
- return {1: 's8', 2: 's16', 4: 's32'}.get(sample_width, None)
diff --git a/src/aiy/_drivers/_button.py b/src/aiy/_drivers/_button.py
deleted file mode 100644
index 7c133c69..00000000
--- a/src/aiy/_drivers/_button.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Button driver for the VoiceHat."""
-
-import time
-import RPi.GPIO as GPIO
-
-
-class Button(object):
- """Detect edges on the given GPIO channel."""
-
- def __init__(self,
- channel,
- polarity=GPIO.FALLING,
- pull_up_down=GPIO.PUD_UP,
- debounce_time=0.08):
- """A simple GPIO-based button driver.
-
- This driver supports a simple GPIO-based button. It works by detecting
- edges on the given GPIO channel. Debouncing is automatic.
-
- Args:
- channel: the GPIO pin number to use (BCM mode)
- polarity: the GPIO polarity to detect; either GPIO.FALLING or
- GPIO.RISING.
- pull_up_down: whether the port should be pulled up or down; defaults to
- GPIO.PUD_UP.
- debounce_time: the time used in debouncing the button in seconds.
- """
- if polarity not in [GPIO.FALLING, GPIO.RISING]:
- raise ValueError(
- 'polarity must be one of: GPIO.FALLING or GPIO.RISING')
-
- self.channel = int(channel)
- self.polarity = polarity
- self.expected_value = polarity == GPIO.RISING
- self.debounce_time = debounce_time
-
- GPIO.setmode(GPIO.BCM)
- GPIO.setup(channel, GPIO.IN, pull_up_down=pull_up_down)
-
- self.callback = None
-
- def __del__(self):
- GPIO.cleanup(self.channel)
-
- def wait_for_press(self):
- """Wait for the button to be pressed.
-
- This method blocks until the button is pressed.
- """
- GPIO.add_event_detect(self.channel, self.polarity)
- while True:
- if GPIO.event_detected(self.channel) and self._debounce():
- GPIO.remove_event_detect(self.channel)
- return
- time.sleep(0.02)
-
- def on_press(self, callback):
- """Call the callback whenever the button is pressed.
-
- Args:
- callback: a function to call whenever the button is pressed. It should
- take a single channel number. If the callback is None, the previously
- registered callback, if any, is canceled.
-
- Example:
- def MyButtonPressHandler(channel):
- print "button pressed: channel = %d" % channel
- my_button.on_press(MyButtonPressHandler)
- """
- GPIO.remove_event_detect(self.channel)
- if callback:
- self.callback = callback
- GPIO.add_event_detect(
- self.channel, self.polarity, callback=self._debounce_and_callback)
-
- def _debounce_and_callback(self, _):
- if self._debounce():
- self.callback()
-
- def _debounce(self):
- """Debounce the GPIO signal.
-
- Check that the input holds the expected value for the debounce
- period, to avoid false trigger on short pulses.
- """
- start = time.time()
- while time.time() < start + self.debounce_time:
- if GPIO.input(self.channel) != self.expected_value:
- return False
- time.sleep(0.01)
- return True
diff --git a/src/aiy/_drivers/_hat.py b/src/aiy/_drivers/_hat.py
deleted file mode 100644
index 26868e44..00000000
--- a/src/aiy/_drivers/_hat.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Utilities to identify the currently installed AIY device (if any)."""
-
-import re
-import os
-
-HAT_PATH = '/proc/device-tree/hat/'
-HAT_PRODUCT_ID_RE = re.compile('0x[0-9A-Fa-f]+')
-AIY_HATS = {
- 1: 'Voice Hat',
- 2: 'Vision Bonnet',
- 3: 'Voice Bonnet',
-}
-
-
-def _is_hat_attached():
- return os.path.exists(HAT_PATH)
-
-
-def _get_hat_product():
- with open(os.path.join(HAT_PATH, 'product')) as f:
- return f.readline().strip()
-
-
-def _get_hat_product_id():
- with open(os.path.join(HAT_PATH, 'product_id')) as f:
- matches = HAT_PRODUCT_ID_RE.match(f.readline().strip())
- if matches:
- return int(matches.group(0), 16)
-
-
-def get_aiy_device_name():
- if not _is_hat_attached():
- # Early Voice HATs don't have correctly programmed EEPROM, so no entry
- # shows up in /proc/device-tree.
- return 'Voice Hat'
- product = _get_hat_product()
- if 'AIY' not in product:
- return None
- product_id = _get_hat_product_id()
- if not product_id:
- return None
- if product_id not in AIY_HATS:
- return None
- return AIY_HATS[product_id]
diff --git a/src/aiy/_drivers/_led.py b/src/aiy/_drivers/_led.py
deleted file mode 100644
index f99b1912..00000000
--- a/src/aiy/_drivers/_led.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""LED driver for the VoiceHat."""
-
-import itertools
-import threading
-import time
-import RPi.GPIO as GPIO
-
-
-class LED:
- """Starts a background thread to show patterns with the LED.
-
- Simple usage:
- my_led = LED(channel = 25)
- my_led.start()
- my_led.set_state(LED.BEACON)
- my_led.stop()
- """
-
- OFF = 0
- ON = 1
- BLINK = 2
- BLINK_3 = 3
- BEACON = 4
- BEACON_DARK = 5
- DECAY = 6
- PULSE_SLOW = 7
- PULSE_QUICK = 8
-
- def __init__(self, channel):
- self.animator = threading.Thread(target=self._animate, daemon=True)
- self.channel = channel
- self.iterator = None
- self.running = False
- self.state = None
- self.sleep = 0
- GPIO.setmode(GPIO.BCM)
- GPIO.setup(channel, GPIO.OUT)
- self.pwm = GPIO.PWM(channel, 100)
- self.lock = threading.Lock()
-
- def __del__(self):
- self.stop()
- GPIO.cleanup(self.channel)
-
- def start(self):
- """Start the LED driver."""
- with self.lock: # pylint: disable=E1129
- if not self.running:
- self.running = True
- self.pwm.start(0) # off by default
- self.animator.start()
-
- def stop(self):
- """Stop the LED driver and sets the LED to off."""
- with self.lock: # pylint: disable=E1129
- if self.running:
- self.running = False
-
- try:
- self.animator.join()
- except RuntimeError:
- # Edge case where this is stopped before it starts.
- pass
-
- self.pwm.stop()
-
- def set_state(self, state):
- """Set the LED driver's new state.
-
- Note the LED driver must be started for this to have any effect.
- """
- with self.lock: # pylint: disable=E1129
- self.state = state
-
- def _animate(self):
- while True:
- state = None
- running = False
- with self.lock: # pylint: disable=E1129
- state = self.state
- self.state = None
- running = self.running
- if not running:
- return
- if state is not None:
- if not self._parse_state(state):
- raise ValueError('unsupported state: %d' % state)
- if self.iterator:
- self.pwm.ChangeDutyCycle(next(self.iterator))
- time.sleep(self.sleep)
- else:
- # We can also wait for a state change here with a Condition.
- time.sleep(1)
-
- def _parse_state(self, state):
- self.iterator = None
- self.sleep = 0.0
- handled = False
-
- if state == self.OFF:
- self.pwm.ChangeDutyCycle(0)
- handled = True
- elif state == self.ON:
- self.pwm.ChangeDutyCycle(100)
- handled = True
- elif state == self.BLINK:
- self.iterator = itertools.cycle([0, 100])
- self.sleep = 0.5
- handled = True
- elif state == self.BLINK_3:
- self.iterator = itertools.cycle([0, 100] * 3 + [0, 0])
- self.sleep = 0.25
- handled = True
- elif state == self.BEACON:
- self.iterator = itertools.cycle(
- itertools.chain([30] * 100, [100] * 8, range(100, 30, -5)))
- self.sleep = 0.05
- handled = True
- elif state == self.BEACON_DARK:
- self.iterator = itertools.cycle(
- itertools.chain([0] * 100, range(0, 30, 3), range(30, 0, -3)))
- self.sleep = 0.05
- handled = True
- elif state == self.DECAY:
- self.iterator = itertools.cycle(range(100, 0, -2))
- self.sleep = 0.05
- handled = True
- elif state == self.PULSE_SLOW:
- self.iterator = itertools.cycle(
- itertools.chain(range(0, 100, 2), range(100, 0, -2)))
- self.sleep = 0.1
- handled = True
- elif state == self.PULSE_QUICK:
- self.iterator = itertools.cycle(
- itertools.chain(range(0, 100, 5), range(100, 0, -5)))
- self.sleep = 0.05
- handled = True
-
- return handled
diff --git a/src/aiy/_drivers/_player.py b/src/aiy/_drivers/_player.py
deleted file mode 100644
index cc1dc623..00000000
--- a/src/aiy/_drivers/_player.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""A driver for audio playback."""
-
-import logging
-import subprocess
-import wave
-
-import aiy._drivers._alsa
-
-logger = logging.getLogger('audio')
-
-
-class Player(object):
- """Plays short audio clips from a buffer or file."""
-
- def __init__(self, output_device='default'):
- self._output_device = output_device
-
- def play_bytes(self, audio_bytes, sample_rate, sample_width=2):
- """Play audio from the given bytes-like object.
-
- Args:
- audio_bytes: audio data (mono)
- sample_rate: sample rate in Hertz (24 kHz by default)
- sample_width: sample width in bytes (eg 2 for 16-bit audio)
- """
- cmd = [
- 'aplay',
- '-q',
- '-t', 'raw',
- '-D', self._output_device,
- '-c', '1',
- # pylint: disable=W0212
- '-f', aiy._drivers._alsa.sample_width_to_string(sample_width),
- '-r', str(sample_rate),
- ]
-
- aplay = subprocess.Popen(cmd, stdin=subprocess.PIPE)
- aplay.stdin.write(audio_bytes)
- aplay.stdin.close()
- retcode = aplay.wait()
-
- if retcode:
- logger.error('aplay failed with %d', retcode)
-
- def play_wav(self, wav_path):
- """Play audio from the given WAV file.
-
- The file should be mono and small enough to load into memory.
- Args:
- wav_path: path to the wav file
- """
- with wave.open(wav_path, 'r') as wav:
- if wav.getnchannels() != 1:
- raise ValueError(wav_path + ' is not a mono file')
-
- frames = wav.readframes(wav.getnframes())
- self.play_bytes(frames, wav.getframerate(), wav.getsampwidth())
diff --git a/src/aiy/_drivers/_recorder.py b/src/aiy/_drivers/_recorder.py
deleted file mode 100644
index 6e69a837..00000000
--- a/src/aiy/_drivers/_recorder.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""A recorder driver capable of recording voice samples from the VoiceHat microphones."""
-
-import logging
-import os
-import subprocess
-import threading
-
-import aiy._drivers._alsa
-
-logger = logging.getLogger('recorder')
-
-
-class Recorder(threading.Thread):
- """A driver to record audio from the VoiceHat microphones.
-
- Stream audio from microphone in a background thread and run processing
- callbacks. It reads audio in a configurable format from the microphone,
- then converts it to a known format before passing it to the processors.
-
- This driver accumulates input (audio samples) in a local buffer. Once the
- buffer contains more than CHUNK_S seconds, it passes the chunk to all
- processors. An audio processor defines a 'add_data' method that receives
- the chunk of audio samples to process.
- """
-
- CHUNK_S = 0.1
-
- def __init__(self, input_device='default',
- channels=1, bytes_per_sample=2, sample_rate_hz=16000):
- """Create a Recorder with the given audio format.
-
- The Recorder will not start until start() is called. start() is called
- automatically if the Recorder is used in a `with`-statement.
-
- - input_device: name of ALSA device (for a list, run `arecord -L`)
- - channels: number of channels in audio read from the mic
- - bytes_per_sample: sample width in bytes (eg 2 for 16-bit audio)
- - sample_rate_hz: sample rate in hertz
- """
-
- super().__init__(daemon=True)
- self._record_event = threading.Event()
- self._processors = []
-
- self._chunk_bytes = int(self.CHUNK_S * sample_rate_hz) * channels * bytes_per_sample
-
- self._cmd = [
- 'arecord',
- '-q',
- '-t', 'raw',
- '-D', input_device,
- '-c', str(channels),
- # pylint: disable=W0212
- '-f', aiy._drivers._alsa.sample_width_to_string(bytes_per_sample),
- '-r', str(sample_rate_hz),
- ]
- self._arecord = None
- self._closed = False
-
- def add_processor(self, processor):
- """Add an audio processor.
-
- An audio processor is an object that has an 'add_data' method with the
- following signature:
- class MyProcessor(object):
- def __init__(self):
- ...
-
- def add_data(self, data):
- # processes the chunk of data here.
-
- The added processor may be called multiple times with chunks of audio data.
- """
- self._record_event.set()
- self._processors.append(processor)
-
- def remove_processor(self, processor):
- """Remove an added audio processor."""
- try:
- self._processors.remove(processor)
- except ValueError:
- logger.warn("processor was not found in the list")
- self._record_event.clear()
-
- def run(self):
- """Reads data from arecord and passes to processors."""
-
- logger.info("started recording")
-
- # Check for race-condition when __exit__ is called at the same time as
- # the process is started by the background thread
- if self._closed:
- self._arecord.kill()
- return
-
- this_chunk = b''
- while True:
- if not self._record_event.is_set() and self._arecord:
- self._arecord.kill()
- self._arecord = None
- self._record_event.wait()
- if not self._arecord:
- self._arecord = subprocess.Popen(self._cmd, stdout=subprocess.PIPE)
- input_data = self._arecord.stdout.read(self._chunk_bytes)
- if not input_data:
- break
-
- this_chunk += input_data
- if len(this_chunk) >= self._chunk_bytes:
- self._handle_chunk(this_chunk[:self._chunk_bytes])
- this_chunk = this_chunk[self._chunk_bytes:]
-
- if not self._closed:
- logger.error('Microphone recorder died unexpectedly, aborting...')
- # sys.exit doesn't work from background threads, so use os._exit as
- # an emergency measure.
- logging.shutdown()
- os._exit(1) # pylint: disable=protected-access
-
- def stop(self):
- """Stops the recorder and cleans up all resources."""
- self._closed = True
- if self._arecord:
- self._arecord.kill()
-
- def _handle_chunk(self, chunk):
- """Send audio chunk to all processors."""
- for p in self._processors:
- p.add_data(chunk)
-
- def __enter__(self):
- self.start()
- return self
-
- def __exit__(self, *args):
- self.stop()
diff --git a/src/aiy/_drivers/_spicomm.py b/src/aiy/_drivers/_spicomm.py
deleted file mode 100644
index 38557d8a..00000000
--- a/src/aiy/_drivers/_spicomm.py
+++ /dev/null
@@ -1,143 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Python wrapper around the VisionBonnet Spicomm device node."""
-
-import array
-import fcntl
-import struct
-import sys
-
-SPICOMM_DEV = '/dev/vision_spicomm'
-
-SPICOMM_IOCTL_BASE = 0x8900
-# TODO: 0xc0100000 should be calculated properly base on structure size.
-SPICOMM_IOCTL_TRANSACT = 0xc0100000 + SPICOMM_IOCTL_BASE + 3
-
-HEADER_SIZE = 16
-PAYLOAD_SIZE = 12 * 1024 * 1024 # 12 M
-
-FLAG_ERROR = 1 << 0
-FLAG_TIMEOUT = 1 << 1
-FLAG_OVERFLOW = 1 << 2
-
-
-class SpicommError(IOError):
- """Base class for Spicomm errors."""
- pass
-
-
-class SpicommDevNotFoundError(SpicommError):
- """A usable Spicomm device node not found."""
- pass
-
-
-class SpicommOverflowError(SpicommError):
- """Transaction buffer too small for response.
-
- Attributes:
- size: Number of bytes needed for the response.
- """
-
- def __init__(self, size):
- self.size = size
- super(SpicommOverflowError, self).__init__()
-
-
-class SpicommTimeoutError(SpicommError):
- """Transaction timed out."""
- pass
-
-
-class SpicommInternalError(SpicommError):
- """Internal unexpected error."""
- pass
-
-
-class Spicomm(object):
- """VisionBonnet Spicomm wrapper.
-
- Provides the ability to send and receive data as a transaction.
- This means that every call to transact consists of a combined
- send and receive step that's atomic from the calling application's
- point of view. Multiple threads and processes can access the device
- node concurrently using one Spicomm instance per thread.
- Transactions are serialized in the underlying kernel driver.
- """
-
- def __init__(self):
- try:
- self._dev = open(SPICOMM_DEV, 'r+b', 0)
- except (IOError, OSError):
- raise SpicommDevNotFoundError
- self._tbuf = bytearray(HEADER_SIZE + PAYLOAD_SIZE)
-
- def __enter__(self):
- return self
-
- def __exit__(self, exc_type, exc_value, exc_tb):
- self.close()
-
- def close(self):
- if self._dev:
- self._dev.close()
-
- def transact(self, request, timeout=15):
- """Execute a Spicomm transaction.
-
- The bytes in request are sent, a response is waited for and returned.
- If the request or response is too large SpicommOverflowError is raised.
-
- Args:
- request: Request bytes to send.
- timeout: How long a response will be waited for, in seconds.
-
- Returns:
- Bytes-like object with response data.
-
- Raises:
- SpicommOverflowError: Transaction buffer was too small for response.
- The 'size' attribute contains the required size.
- SpicommTimeoutError : Transaction timed out.
- SpicommInternalError: Unexpected error interacting with kernel driver.
- """
-
- payload_len = len(request)
- if payload_len > PAYLOAD_SIZE:
- raise SpicommOverflowError(PAYLOAD_SIZE)
-
- # Fill in transaction buffer.
- self._tbuf[0:4] = struct.pack('I', 0) # flags, not currently used.
- self._tbuf[4:8] = struct.pack('I', int(timeout * 1000)) # timeout, ms.
- self._tbuf[8:12] = struct.pack('I', len(self._tbuf)) # total buffer size.
- self._tbuf[12:16] = struct.pack('I', payload_len) # filled range of buffer.
- self._tbuf[16:16 + payload_len] = request
-
- try:
- # Send transaction to kernel driver.
- fcntl.ioctl(self._dev, SPICOMM_IOCTL_TRANSACT, self._tbuf)
-
- # No exception means errno 0 and self._tbuf is now mutated.
- _, _, _, payload_len = struct.unpack('IIII', self._tbuf[0:16])
- return self._tbuf[16:16 + payload_len]
- except (IOError, OSError):
- # FLAG_ERROR is set if we actually talked to the kernel.
- flags, _, _, payload_len = struct.unpack('IIII', self._tbuf[0:16])
- if flags & FLAG_ERROR:
- if flags & FLAG_TIMEOUT:
- raise SpicommTimeoutError
- elif flags & FLAG_OVERFLOW:
- raise SpicommOverflowError(payload_len)
-
- # This is unexpected.
- raise SpicommInternalError
diff --git a/src/aiy/_drivers/_status_ui.py b/src/aiy/_drivers/_status_ui.py
deleted file mode 100644
index 64556729..00000000
--- a/src/aiy/_drivers/_status_ui.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""A status UI powered by the LED on the VoiceHat."""
-
-import logging
-import os.path
-
-import aiy.audio
-import aiy.voicehat
-
-logger = logging.getLogger('status_ui')
-
-
-class _StatusUi(object):
- """Gives the user status feedback.
-
- The LED and optionally a trigger sound tell the user when the box is
- ready, listening or thinking.
- """
-
- def __init__(self):
- self._trigger_sound_wave = None
- self._state_map = {
- "starting": aiy.voicehat.LED.PULSE_QUICK,
- "ready": aiy.voicehat.LED.BEACON_DARK,
- "listening": aiy.voicehat.LED.ON,
- "thinking": aiy.voicehat.LED.PULSE_QUICK,
- "stopping": aiy.voicehat.LED.PULSE_QUICK,
- "power-off": aiy.voicehat.LED.OFF,
- "error": aiy.voicehat.LED.BLINK_3,
- }
- aiy.voicehat.get_led().set_state(aiy.voicehat.LED.OFF)
-
- def set_trigger_sound_wave(self, trigger_sound_wave):
- """Set the trigger sound.
-
- A trigger sound is played when the status is 'listening' to indicate
- that the assistant is actively listening to the user.
- The trigger_sound_wave argument should be the path to a valid wave file.
- If it is None, the trigger sound is disabled.
- """
- if not trigger_sound_wave:
- self._trigger_sound_wave = None
- return
- expanded_path = os.path.expanduser(trigger_sound_wave)
- if os.path.exists(expanded_path):
- self._trigger_sound_wave = expanded_path
- else:
- logger.warning(
- 'File %s specified as trigger sound does not exist.',
- trigger_sound_wave)
- self._trigger_sound_wave = None
-
- def status(self, status):
- """Activate the status.
-
- This method updates the LED animation. Returns True if the status is
- valid and has been updated.
- """
- if status not in self._state_map:
- logger.warning("unsupported state: %s, must be one of %s",
- status, ",".join(self._state_map.keys()))
- return False
- aiy.voicehat.get_led().set_state(self._state_map[status])
- if status == 'listening' and self._trigger_sound_wave:
- aiy.audio.play_wave(self._trigger_sound_wave)
- return True
diff --git a/src/aiy/_drivers/_transport.py b/src/aiy/_drivers/_transport.py
deleted file mode 100644
index a0251da4..00000000
--- a/src/aiy/_drivers/_transport.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Transport to communicate with VisionBonnet board."""
-
-import logging
-import os
-import socket
-import struct
-
-from aiy._drivers import _spicomm
-
-
-class _SpiTransport(object):
- """Communicate with VisionBonnet over SPI bus."""
-
- def __init__(self):
- self._spicomm = _spicomm.Spicomm()
-
- # TODO(dkovalev): add timeout when implemented in Spicomm
- def send(self, request):
- return self._spicomm.transact(request)
-
- def close(self):
- self._spicomm.close()
-
-
-def _socket_recvall(s, size):
- buf = b''
- while size:
- newbuf = s.recv(size)
- if not newbuf:
- return None
- buf += newbuf
- size -= len(newbuf)
- return buf
-
-
-def _socket_receive_message(s):
- buf = _socket_recvall(s, 4) # 4 bytes
- if not buf:
- return None
- size = struct.unpack('!I', buf)[0]
- return _socket_recvall(s, size)
-
-
-def _socket_send_message(s, msg):
- s.sendall(struct.pack('!I', len(msg))) # 4 bytes
- s.sendall(msg) # len(msg) bytes
-
-
-class _SocketTransport(object):
- """Communicate with VisionBonnet over socket."""
-
- def __init__(self):
- """Open connection to the bonnet."""
- self._client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
- host = os.environ.get('VISION_BONNET_HOST', '172.28.28.10')
- port = int(os.environ.get('VISION_BONNET_PORT', '35000'))
- self._client.connect((host, port))
-
- # TODO(dkovalev,weiranzhao): add timeout parameter
- def send(self, request):
- _socket_send_message(self._client, request)
- return _socket_receive_message(self._client)
-
- def close(self):
- self._client.close()
-
-
-def _is_arm():
- return os.uname()[4].startswith('arm')
-
-
-def make_transport():
- if _is_arm():
- return _SpiTransport()
- else:
- return _SocketTransport()
diff --git a/src/aiy/_drivers/_tts.py b/src/aiy/_drivers/_tts.py
deleted file mode 100644
index c223479b..00000000
--- a/src/aiy/_drivers/_tts.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Wrapper around a TTS system."""
-
-import functools
-import logging
-import os
-import subprocess
-import tempfile
-from aiy import i18n
-
-# Path to a tmpfs directory to avoid SD card wear
-TMP_DIR = '/run/user/%d' % os.getuid()
-
-logger = logging.getLogger('tts')
-
-
-def create_say(player):
- """Return a function say(words) for the given player."""
- lang = i18n.get_language_code()
- return functools.partial(say, player, lang=lang)
-
-
-def say(player, words, lang='en-US', volume=60, pitch=130):
- """Say the given words with TTS.
-
- Args:
- player: To play the text-to-speech audio.
- words: string to say aloud.
- lang: language for the text-to-speech engine.
- volume: volume for the text-to-speech engine.
- pitch: pitch for the text-to-speech engine.
- """
- try:
- (fd, tts_wav) = tempfile.mkstemp(suffix='.wav', dir=TMP_DIR)
- except IOError:
- logger.exception('Using fallback directory for TTS output')
- (fd, tts_wav) = tempfile.mkstemp(suffix='.wav')
- os.close(fd)
- words = '' + words + ''
- try:
- subprocess.call(['pico2wave', '--lang', lang, '-w', tts_wav, words])
- player.play_wav(tts_wav)
- finally:
- os.unlink(tts_wav)
-
-
-def _main():
- import argparse
- from aiy import audio
-
- logging.basicConfig(level=logging.INFO)
-
- parser = argparse.ArgumentParser(description='Test TTS wrapper')
- parser.add_argument('words', nargs='*', help='Words to say')
- args = parser.parse_args()
-
- if args.words:
- words = ' '.join(args.words)
- player = audio.get_player()
- create_say(player)(words)
-
-
-if __name__ == '__main__':
- _main()
diff --git a/src/aiy/assistant/__init__.py b/src/aiy/assistant/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/aiy/assistant/grpc.py b/src/aiy/assistant/grpc.py
deleted file mode 100644
index 0f85413b..00000000
--- a/src/aiy/assistant/grpc.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""An API to access the Google Assistant."""
-
-import aiy._apis._speech
-import aiy.assistant.auth_helpers
-import aiy.assistant.device_helpers
-import aiy.audio
-import aiy.voicehat
-
-# Global variables. They are lazily initialized.
-_assistant_recognizer = None
-
-
-class _AssistantRecognizer(object):
- """Your personal Google Assistant."""
-
- def __init__(self, credentials):
- model_id, device_id = aiy.assistant.device_helpers.get_ids_for_service(credentials)
- self._request = aiy._apis._speech.AssistantSpeechRequest(credentials, model_id, device_id)
- self._recorder = aiy.audio.get_recorder()
-
- def recognize(self):
- """Recognizes the user's speech and gets answers from Google Assistant.
-
- This function listens to the user's speech via the VoiceHat speaker and
- sends the audio to the Google Assistant Library. The response is returned in
- both text and audio.
-
- Usage:
- transcript, audio = my_recognizer.recognize()
- if transcript is not None:
- print('You said ', transcript)
- aiy.audio.play_audio(audio)
- """
- self._request.reset()
- self._request.set_endpointer_cb(self._endpointer_callback)
- self._recorder.add_processor(self._request)
- response = self._request.do_request()
- return response.transcript, response.response_audio
-
- def _endpointer_callback(self):
- self._recorder.remove_processor(self._request)
-
-
-def get_assistant():
- """Returns a recognizer that uses Google Assistant APIs.
-
- Sample usage:
- button = aiy.voicehat.get_button()
- recognizer = aiy.assistant.grpc.get_recognizer()
- print('Your Google Assistant is ready.')
- while True:
- print('Press the button and speak')
- button.wait_for_press()
- print('Listening...')
- transcript, audio = recognizer.recognize()
- if transcript is not None:
- print('Assistant said ', transcript)
- if audio is not None:
- aiy.audio.play_audio(audio)
- """
- global _assistant_recognizer
- if not _assistant_recognizer:
- credentials = aiy.assistant.auth_helpers.get_assistant_credentials()
- _assistant_recognizer = _AssistantRecognizer(credentials)
- return _assistant_recognizer
diff --git a/src/aiy/assistant/library.py b/src/aiy/assistant/library.py
deleted file mode 100644
index 3af3b162..00000000
--- a/src/aiy/assistant/library.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Wrapper around google.assistant.library.
-
-Handles model and device registration."""
-
-import google.assistant.library
-
-import aiy.assistant.device_helpers as device_helpers
-
-
-class Assistant(google.assistant.library.Assistant):
- """Client for the Google Assistant Library.
-
- Similar to google.assistant.library.Assistant, but handles device
- registration.
- """
-
- def __init__(self, credentials):
- self._credentials = credentials
- self._model_id = device_helpers.register_model_id(credentials)
-
- super().__init__(credentials, self._model_id)
-
- def start(self):
- events = super().start()
-
- device_helpers.register_device_id(
- self._credentials, self._model_id, self.device_id, "SDK_LIBRARY")
-
- return events
diff --git a/src/aiy/audio.py b/src/aiy/audio.py
deleted file mode 100644
index 7f766bbd..00000000
--- a/src/aiy/audio.py
+++ /dev/null
@@ -1,162 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Drivers for audio functionality provided by the VoiceHat."""
-
-import time
-import wave
-
-import aiy._drivers._player
-import aiy._drivers._recorder
-import aiy._drivers._tts
-
-AUDIO_SAMPLE_SIZE = 2 # bytes per sample
-AUDIO_SAMPLE_RATE_HZ = 16000
-
-# Global variables. They are lazily initialized.
-_voicehat_recorder = None
-_voicehat_player = None
-_status_ui = None
-_tts_volume = 60
-_tts_pitch = 130
-
-
-class _WaveDump(object):
- """A processor that saves recorded audio to a wave file."""
-
- def __init__(self, filepath, duration):
- self._wave = wave.open(filepath, 'wb')
- self._wave.setnchannels(1)
- self._wave.setsampwidth(2)
- self._wave.setframerate(16000)
- self._bytes = 0
- self._bytes_limit = int(duration * 16000) * 1 * 2
-
- def add_data(self, data):
- max_bytes = self._bytes_limit - self._bytes
- data = data[:max_bytes]
- self._bytes += len(data)
- if data:
- self._wave.writeframes(data)
-
- def is_done(self):
- return self._bytes >= self._bytes_limit
-
- def __enter__(self):
- return self
-
- def __exit__(self, *args):
- self._wave.close()
-
-
-def get_player():
- """Returns a driver to control the VoiceHat speaker.
-
- The aiy modules automatically use this player. So usually you do not need to
- use this. Instead, use 'aiy.audio.play_wave' if you would like to play some
- audio.
- """
- global _voicehat_player
- if not _voicehat_player:
- _voicehat_player = aiy._drivers._player.Player()
- return _voicehat_player
-
-
-def get_recorder():
- """Returns a driver to control the VoiceHat microphones.
-
- The aiy modules automatically use this recorder. So usually you do not need to
- use this.
- """
- global _voicehat_recorder
- if not _voicehat_recorder:
- _voicehat_recorder = aiy._drivers._recorder.Recorder()
- return _voicehat_recorder
-
-
-def record_to_wave(filepath, duration):
- """Records an audio for the given duration to a wave file."""
- recorder = get_recorder()
- dumper = _WaveDump(filepath, duration)
- with recorder, dumper:
- recorder.add_processor(dumper)
- while not dumper.is_done():
- time.sleep(0.1)
-
-
-def play_wave(wave_file):
- """Plays the given wave file.
-
- The wave file has to be mono and small enough to be loaded in memory.
- """
- player = get_player()
- player.play_wav(wave_file)
-
-
-def play_audio(audio_data):
- """Plays the given audio data."""
- player = get_player()
- player.play_bytes(audio_data, sample_width=AUDIO_SAMPLE_SIZE, sample_rate=AUDIO_SAMPLE_RATE_HZ)
-
-
-def say(words, lang=None, volume=None, pitch=None):
- """Says the given words in the given language with Google TTS engine.
-
- If lang is specified, e.g. "en-US", it will be used to say the given words.
- Otherwise, the language from aiy.i18n will be used.
- volume (optional) volume used to say the given words.
- pitch (optional) pitch to say the given words.
- Example: aiy.audio.say('This is an example', lang="en-US", volume=75, pitch=135)
- Any of the optional variables can be left out.
- """
-
- if not lang:
- lang = aiy.i18n.get_language_code()
- if not volume:
- volume = aiy.audio.get_tts_volume()
- if not pitch:
- pitch = aiy.audio.get_tts_pitch()
- aiy._drivers._tts.say(aiy.audio.get_player(), words, lang=lang, volume=volume, pitch=pitch)
-
-
-def get_status_ui():
- """Returns a driver to access the StatusUI daemon.
-
- The StatusUI daemon controls the LEDs in the background. It supports a list
- of statuses it is able to communicate with the LED on the Voicehat.
- """
- global _status_ui
- if not _status_ui:
- _status_ui = aiy._drivers._StatusUi()
- return _status_ui
-
-
-def set_tts_volume(volume):
- global _tts_volume
- _tts_volume = volume
-
-
-def get_tts_volume():
- global _tts_volume
- return _tts_volume
-
-
-def set_tts_pitch(pitch):
- global _tts_pitch
- _tts_pitch = pitch
-
-
-def get_tts_pitch():
- global _tts_pitch
- return _tts_pitch
diff --git a/src/aiy/cloudspeech.py b/src/aiy/cloudspeech.py
deleted file mode 100644
index 160fa63f..00000000
--- a/src/aiy/cloudspeech.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""An API to access Google Speech recognition service."""
-
-import os.path
-
-import aiy._apis._speech
-import aiy.audio
-import aiy.voicehat
-
-# Global variables. They are lazily initialized.
-_cloudspeech_recognizer = None
-
-# Expected location of the CloudSpeech credentials file:
-CLOUDSPEECH_CREDENTIALS_FILE = os.path.expanduser('~/cloud_speech.json')
-
-
-class _CloudSpeechRecognizer(object):
- """A speech recognizer backed by the Google CloudSpeech APIs.
- """
-
- def __init__(self, credentials_file):
- self._request = aiy._apis._speech.CloudSpeechRequest(credentials_file)
- self._recorder = aiy.audio.get_recorder()
- self._hotwords = []
-
- def recognize(self, immediate=False):
- """Recognizes the user's speech and transcript it into text.
-
- This function listens to the user's speech via the VoiceHat speaker. Then it
- contacts Google CloudSpeech APIs and returns a textual transcript if possible.
- If hotword list is populated this method will only respond if hotword is said.
-
- Args:
- immediate: ignore the hotword list, even if it has been populated
- may be used to create a conversational experience, for example:
-
- text = recognizer.recognize()
- if 'call a friend' in text:
- aiy.audio.say('OK, which one?')
- friend = recognizer.recognize(immediate=True)
- make_a_call(friend)
- """
- self._request.reset()
- self._request.set_endpointer_cb(self._endpointer_callback)
- self._recorder.add_processor(self._request)
- text = self._request.do_request().transcript
- if immediate:
- return text
- elif self._hotwords and text:
- text = text.lower()
- loc_min = len(text)
- hotword_found = ''
- for hotword in self._hotwords:
- loc_temp = text.find(hotword)
- if loc_temp > -1 and loc_min > loc_temp:
- loc_min = loc_temp
- hotword_found = hotword
- if hotword_found:
- parse_text = text.split(hotword_found)[1]
- return parse_text.strip()
- else:
- return ''
- else:
- return '' if self._hotwords else text
-
- def expect_hotword(self, hotword_list):
- """Enables hotword detection for a selected list
- This method is optional and populates the list of hotwords
- to be used for hotword activation.
-
- For example, to create a recognizer for Google:
-
- recognizer.expect_hotword('Google')
- recognizer.expect_hotword(['Google','Raspberry Pi'])
- """
- if isinstance(hotword_list, list):
- for hotword in hotword_list:
- self._hotwords.append(hotword.lower())
- else:
- self._hotwords.append(hotword_list.lower())
-
- def expect_phrase(self, phrase):
- """Explicitly tells the engine that the phrase is more likely to appear.
-
- This method is optional and makes speech recognition more accurate
- especially when certain commands are expected.
-
- For example, a light control system may want to add the following commands:
-
- recognizer.expect_phrase('light on')
- recognizer.expect_phrase('light off')
- """
- self._request.add_phrase(phrase)
-
- def _endpointer_callback(self):
- self._recorder.remove_processor(self._request)
-
-
-def get_recognizer():
- """Returns a recognizer that uses Google CloudSpeech APIs.
-
- Sample usage:
- button = aiy.voicehat.get_button()
- recognizer = aiy.cloudspeech.get_recognizer()
- while True:
- print('Press the button and speak')
- button.wait_for_press()
- text = recognizer.recognize()
- if 'light on' in text:
- turn_on_light()
- elif 'light off' in text:
- turn_off_light()
- """
- global _cloudspeech_recognizer
- if not _cloudspeech_recognizer:
- _cloudspeech_recognizer = _CloudSpeechRecognizer(CLOUDSPEECH_CREDENTIALS_FILE)
- return _cloudspeech_recognizer
diff --git a/src/aiy/i18n.py b/src/aiy/i18n.py
deleted file mode 100644
index 4afae431..00000000
--- a/src/aiy/i18n.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Internationalization helpers."""
-
-import gettext
-
-_DEFAULT_LANGUAGE_CODE = 'en-US'
-_LOCALE_DOMAIN = 'voice-recognizer'
-
-_language_code = _DEFAULT_LANGUAGE_CODE
-
-_locale_dir = None
-
-
-def set_locale_dir(locale_dir):
- """Sets the directory that contains the language bundles.
-
- This is only required if you call set_language_code with gettext_install=True.
- """
- global _locale_dir
- if not locale_dir:
- raise ValueError('locale_dir must be valid')
- _locale_dir = locale_dir
-
-
-def set_language_code(code, gettext_install=False):
- """Set the BCP-47 language code that the speech systems should use.
-
- Args:
- gettext_install: if True, gettext's _() will be installed in as a builtin.
- As this has global effect, it should only be done by applications.
- """
- global _language_code
- _language_code = code.replace('_', '-')
-
- if gettext_install:
- if not _locale_dir:
- raise ValueError('locale_dir is not set. Please call set_locale_dir().')
- language_id = code.replace('-', '_')
- t = gettext.translation(_LOCALE_DOMAIN, _locale_dir, [language_id], fallback=True)
- t.install()
-
-
-def get_language_code():
- """Returns the BCP-47 language code that the speech systems should use.
-
- We don't use the system locale because the Assistant API only supports
- en-US at launch, so that should be used by default in all environments.
- """
- return _language_code
diff --git a/src/aiy/test/__init__.py b/src/aiy/test/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/aiy/vision/__init__.py b/src/aiy/vision/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/aiy/vision/inference.py b/src/aiy/vision/inference.py
deleted file mode 100644
index 6b7a08c5..00000000
--- a/src/aiy/vision/inference.py
+++ /dev/null
@@ -1,317 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""VisionBonnet InferenceEngine API.
-
-Python API to communicate with the VisionBonnet from the Raspberry Pi side.
-
-It can be used to load a model, analyze local image or image from camera
-shot. It automatically unload the model once the associated object is
-deleted. See image_classification.py and object_recognition.py as examples on
-how to use this API.
-"""
-
-import logging
-from aiy._drivers._transport import make_transport
-from aiy.vision.proto import protocol_pb2
-
-
-_SUPPORTED_FIRMWARE_VERSION = (1, 0) # major, minor
-
-
-class FirmwareVersionException(Exception):
-
- def __init__(self, *args, **kwargs):
- Exception.__init__(self, *args, **kwargs)
-
-
-def _check_firmware_info(info):
- firmware_version = '%d.%d' % info
- supported_version = '%d.%d' % _SUPPORTED_FIRMWARE_VERSION
- if info[0] > _SUPPORTED_FIRMWARE_VERSION[0]:
- raise FirmwareVersionException(
- 'AIY library supports firmware version %s, current firmware '
- 'version is %s. You should upgrade AIY library.' %
- (supported_version, firmware_version))
- if info[0] < _SUPPORTED_FIRMWARE_VERSION[0]:
- raise FirmwareVersionException(
- 'AIY library supports firmware version %s, current firmware '
- 'version is %s. You should upgrade firmware.' %
- (supported_version, firmware_version))
- if info[1] > _SUPPORTED_FIRMWARE_VERSION[1]:
- logging.warn(
- 'AIY library supports firmware version %s, current firmware '
- 'version is %s. Consider upgrading AIY library.',
- supported_version, firmware_version)
- if info[1] < _SUPPORTED_FIRMWARE_VERSION[1]:
- logging.warn(
- 'AIY library supports firmware version %s, current firmware '
- 'version is %s. Consider upgrading firmware.',
- supported_version, firmware_version)
-
-
-class CameraInference(object):
- """Helper class to run camera inference."""
-
- def __init__(self, descriptor, params=None):
- self._engine = InferenceEngine()
- self._key = self._engine.load_model(descriptor)
- self._engine.start_camera_inference(self._key, params)
-
- def camera_state(self):
- return self._engine.get_camera_state()
-
- def run(self):
- while True:
- yield self._engine.camera_inference()
-
- def close(self):
- self._engine.stop_camera_inference()
- self._engine.unload_model(self._key)
- self._engine.close()
-
- def __enter__(self):
- return self
-
- def __exit__(self, exc_type, exc_value, exc_tb):
- self.close()
-
-
-class ImageInference(object):
- """Helper class to run image inference."""
-
- def __init__(self, descriptor):
- self._engine = InferenceEngine()
- self._key = self._engine.load_model(descriptor)
-
- def run(self, image, params=None):
- return self._engine.image_inference(self._key, image, params)
-
- def close(self):
- self._engine.unload_model(self._key)
- self._engine.close()
-
- def __enter__(self):
- return self
-
- def __exit__(self, exc_type, exc_value, exc_tb):
- self.close()
-
-
-class ModelDescriptor(object):
- """Info used by VisionBonnet to load model."""
-
- def __init__(self, name, input_shape, input_normalizer, compute_graph):
- """Initialzes ModelDescriptor.
-
- Args:
- name: string, a name used to refer the model, should not conflict
- with existing model names.
- input_shape: (batch, height, width, depth). For now, only batch=1 and
- depth=3 are supported.
- input_normalizer: (mean, stddev) to convert input image (for analysis) to
- the same range model is
- trained. For example, if the model is trained with [-1, 1] input. To
- analyze an RGB image (input range [0, 255]), one needs to specify the
- input normalizer as (128.0, 128.0).
- compute_graph: string, converted model proto
- """
- self.name = name
- self.input_shape = input_shape
- self.input_normalizer = input_normalizer
- self.compute_graph = compute_graph
-
-
-class InferenceException(Exception):
-
- def __init__(self, *args, **kwargs):
- Exception.__init__(self, *args, **kwargs)
-
-
-class InferenceEngine(object):
- """Class to access InferenceEngine on VisionBonnet board.
-
- Inference result has the following format:
-
- message InferenceResult {
- string model_name; // Name of the model to run inference on.
- int32 width; // Input image/frame width.
- int32 height; // Input image/frame height.
- Rectangle window; // Window inside width x height image/frame.
- int32 duration_ms; // Inference duration.
- map tensors; // Output tensors.
-
- message Frame {
- int32 index; // Frame number.
- int64 timestamp_us; // Frame timestamp.
- }
-
- Frame frame; // Frame-specific inference data.
- }
- """
-
- def __init__(self):
- self._transport = make_transport()
- logging.info('InferenceEngine transport: %s',
- self._transport.__class__.__name__)
-
- def close(self):
- self._transport.close()
-
- def __enter__(self):
- return self
-
- def __exit__(self, exc_type, exc_value, exc_tb):
- self.close()
-
- def _communicate(self, request):
- """Gets response and logs messages if need to.
-
- Args:
- request: protocol_pb2.Request
-
- Returns:
- protocol_pb2.Response
- """
- response = protocol_pb2.Response()
- response.ParseFromString(self._transport.send(request.SerializeToString()))
- if response.status.code != protocol_pb2.Response.Status.OK:
- raise InferenceException(response.status.message)
- return response
-
- def load_model(self, descriptor):
- """Loads model on VisionBonnet.
-
- Args:
- descriptor: ModelDescriptor, meta info that defines model name,
- where to get the model and etc.
- Returns:
- Model identifier.
- """
- _check_firmware_info(self.get_firmware_info())
-
- logging.info('Loading model "%s"...', descriptor.name)
-
- batch, height, width, depth = descriptor.input_shape
- mean, stddev = descriptor.input_normalizer
- if batch != 1:
- raise ValueError('Unsupported batch value: %d. Must be 1.')
-
- if depth != 3:
- raise ValueError('Unsupported depth value: %d. Must be 3.')
-
- request = protocol_pb2.Request()
- request.load_model.model_name = descriptor.name
- request.load_model.input_shape.batch = batch
- request.load_model.input_shape.height = height
- request.load_model.input_shape.width = width
- request.load_model.input_shape.depth = depth
- request.load_model.input_normalizer.mean = mean
- request.load_model.input_normalizer.stddev = stddev
- if descriptor.compute_graph:
- request.load_model.compute_graph = descriptor.compute_graph
-
- try:
- self._communicate(request)
- except InferenceException as e:
- logging.warning(str(e))
-
- return descriptor.name
-
- def unload_model(self, model_name):
- """Deletes model on VisionBonnet.
-
- Args:
- model_name: string, unique identifier used to refer a model.
- """
- logging.info('Unloading model "%s"...', model_name)
-
- request = protocol_pb2.Request()
- request.unload_model.model_name = model_name
- self._communicate(request)
-
- def start_camera_inference(self, model_name, params=None):
- """Starts inference running on VisionBonnet."""
- request = protocol_pb2.Request()
- request.start_camera_inference.model_name = model_name
-
- for key, value in (params or {}).items():
- request.start_camera_inference.params[key] = str(value)
-
- self._communicate(request)
-
- def camera_inference(self):
- """Returns the latest inference result from VisionBonnet."""
- request = protocol_pb2.Request()
- request.camera_inference.SetInParent()
- return self._communicate(request).inference_result
-
- def stop_camera_inference(self):
- """Stops inference running on VisionBonnet."""
- request = protocol_pb2.Request()
- request.stop_camera_inference.SetInParent()
- self._communicate(request)
-
- def get_camera_state(self):
- request = protocol_pb2.Request()
- request.get_camera_state.SetInParent()
- return self._communicate(request).camera_state
-
- def get_firmware_info(self):
- """Returns firmware version as (major, minor) tuple."""
- request = protocol_pb2.Request()
- request.get_firmware_info.SetInParent()
- try:
- info = self._communicate(request).firmware_info
- return (info.major_version, info.minor_version)
- except InferenceException:
- # Request is not supported by firmware, default to 1.0
- return (1, 0)
-
- def image_inference(self, model_name, image, params=None):
- """Runs inference on image using model (identified by model_name).
-
- Args:
- model_name: string, unique identifier used to refer a model.
- image: PIL.Image,
- params: dict, additional parameters to run inference
-
- Returns:
- protocol_pb2.Response
- """
- if not model_name:
- raise ValueError('Model name must not be empty.')
-
- logging.info('Image inference with model "%s"...', model_name)
-
- width, height = image.size
-
- request = protocol_pb2.Request()
- request.image_inference.model_name = model_name
- request.image_inference.tensor.shape.height = height
- request.image_inference.tensor.shape.width = width
-
- if image.mode == 'RGB':
- r, g, b = image.split()
- request.image_inference.tensor.shape.depth = 3
- request.image_inference.tensor.data = r.tobytes() + g.tobytes() + b.tobytes()
- elif image.mode == 'L':
- request.image_inference.tensor.shape.depth = 1
- request.image_inference.tensor.data = image.tobytes()
- else:
- raise InferenceException('Unsupported image format: %s. Must be L or RGB.' % image.mode)
-
- for key, value in (params or {}).items():
- request.image_inference.params[key] = str(value)
-
- return self._communicate(request).inference_result
diff --git a/src/aiy/vision/leds.py b/src/aiy/vision/leds.py
deleted file mode 100644
index 2ad77ee1..00000000
--- a/src/aiy/vision/leds.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# Copyright 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-def _tflash_reg(duration_ms):
- if duration_ms <= 128:
- return 0
- elif duration_ms <= 384:
- return 1
- else:
- return min((int(round(duration_ms / 128))) - 2, 126)
-
-
-def _pwm1_reg(percent):
- return int(round(256.0 * percent))
-
-
-def _trise_tfall_reg(duration_ms):
- if duration_ms <= 1.5:
- return 0
- else:
- return min(int(round(duration_ms / 96)), 15)
-
-
-def _write(path, data):
- with open(path, 'w') as file:
- file.write(str(data))
-
-
-def _device_file(prop):
- return '/sys/class/leds/ktd202x:led1/device/%s' % prop
-
-
-class Pattern(object):
- """Class to define blinking pattern."""
-
- def __init__(self, period_ms, on_percent=0.5, rise_ms=0, fall_ms=0):
- if on_percent < 0 or on_percent > 0.996:
- raise ValueError('on_percent must be in the range [0..0.996]')
-
- if period_ms < 0 or rise_ms < 0 or fall_ms < 0:
- raise ValueError('durations must be non-negative')
-
- self.period_ms = period_ms
- self.on_percent = on_percent
- self.rise_ms = rise_ms
- self.fall_ms = fall_ms
-
- @staticmethod
- def blink(period_ms):
- return Pattern(period_ms, 0.5)
-
- @staticmethod
- def breathe(period_ms):
- return Pattern(period_ms, 0.3, period_ms * 0.3, period_ms * 0.3)
-
-
-class Leds(object):
- """Class to control KTD LED driver chip."""
- class Channel(object):
- """Configuration of each channel on KTD LED driver."""
- OFF = 0
- ON = 1
- PATTERN = 2
-
- def __init__(self, state, brightness):
- if state not in (self.ON, self.OFF, self.PATTERN):
- raise ValueError('state must be OFF, ON, or PATTERN')
-
- if brightness < 0 or brightness > 255:
- raise ValueError('brightness must be in the range [0..255]')
-
- self.state = state
- self.brightness = brightness
-
- @staticmethod
- def rgb(state, rgb):
- """Returns configuration for channels: 1 (red), 2 (green), 3 (blue)."""
- return {
- 1: Leds.Channel(state, rgb[0]),
- 2: Leds.Channel(state, rgb[1]),
- 3: Leds.Channel(state, rgb[2]),
- }
-
- @staticmethod
- def rgb_off():
- return Leds.rgb(Leds.Channel.OFF, (0, 0, 0))
-
- @staticmethod
- def rgb_on(rgb):
- return Leds.rgb(Leds.Channel.ON, rgb)
-
- @staticmethod
- def rgb_pattern(rgb):
- return Leds.rgb(Leds.Channel.PATTERN, rgb)
-
- @staticmethod
- def privacy(enabled, brightness=255):
- """Returns configuration for channel 4 (privacy)."""
- if enabled:
- return {4: Leds.Channel(Leds.Channel.ON, brightness)}
- else:
- return {4: Leds.Channel(Leds.Channel.OFF, 0)}
-
- @staticmethod
- def privacy_on(brightness=255):
- return Leds.privacy(True, brightness)
-
- @staticmethod
- def privacy_off():
- return Leds.privacy(False, 0)
-
- def __init__(self, reset=True):
- if reset:
- self.reset()
-
- def reset(self):
- _write(_device_file('reset'), 1)
-
- @property
- def pattern(self):
- return self._pattern
-
- @pattern.setter
- def pattern(self, value):
- self._pattern = value
- command = 'tflash=%d;pwm1=%d;trise=%d;tfall=%d;' % (
- _tflash_reg(value.period_ms),
- _pwm1_reg(value.on_percent),
- _trise_tfall_reg(value.rise_ms),
- _trise_tfall_reg(value.fall_ms))
- _write(_device_file('registers'), command)
-
- def update(self, channels):
- command = ''
- for index, channel in channels.items():
- if channel.brightness is not None:
- command += 'led%d=%d;' % (index, channel.brightness)
- if channel.state is not None:
- command += 'ch%d_enable=%d;' % (index, channel.state)
- if command:
- _write(_device_file('registers'), command)
-
-
-class PrivacyLed(object):
- """Helper class to turn Privacy LED off automatically."""
-
- def __init__(self, leds, brightness=32):
- self._leds = leds
- self._brightness = brightness
-
- def __enter__(self):
- self._leds.update(Leds.privacy_on(self._brightness))
-
- def __exit__(self, exc_type, exc_value, exc_tb):
- self._leds.update(Leds.privacy_off())
-
-
-class RgbLeds(object):
- """Helper class to turn RGB LEDs off automatically."""
-
- def __init__(self, leds, channels):
- self._leds = leds
- self._channels = channels
-
- def __enter__(self):
- self._leds.update(self._channels)
-
- def __exit__(self, exc_type, exc_value, exc_tb):
- self._leds.update(Leds.rgb_off())
diff --git a/src/aiy/vision/models/__init__.py b/src/aiy/vision/models/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/aiy/vision/models/dish_classifier.py b/src/aiy/vision/models/dish_classifier.py
deleted file mode 100644
index 0be5c53c..00000000
--- a/src/aiy/vision/models/dish_classifier.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""API for Dish Classifier."""
-
-from aiy.vision.inference import ModelDescriptor
-from aiy.vision.models import utils
-from aiy.vision.models.dish_classifier_classes import CLASSES
-
-_COMPUTE_GRAPH_NAME = 'mobilenet_v1_192res_1.0_seefood.binaryproto'
-
-
-def model():
- return ModelDescriptor(
- name='dish_classifier',
- input_shape=(1, 192, 192, 3),
- input_normalizer=(128.0, 128.0),
- compute_graph=utils.load_compute_graph(_COMPUTE_GRAPH_NAME))
-
-
-def get_classes(result, max_num_objects=None, object_prob_threshold=0.0):
- """Converts dish classifier model output to list of detected objects.
-
- Args:
- result: output tensor from dish classifier model.
- max_num_objects: int; max number of objects to return.
- object_prob_threshold: float; min probability of each returned object.
-
- Returns:
- A list of (class_name: string, probability: float) pairs ordered by
- probability from highest to lowest. The number of pairs is not greater than
- max_num_objects. Each probability is greater than object_prob_threshold. For
- example:
-
- [('Ramen', 0.981934)
- ('Yaka mein, 0.005497)]
- """
- assert len(result.tensors) == 1
- tensor = result.tensors['MobilenetV1/Predictions/Softmax']
- probs, shape = tensor.data, tensor.shape
- assert (shape.batch, shape.height, shape.width, shape.depth) == (1, 1, 1,
- 2024)
-
- pairs = [pair for pair in enumerate(probs) if pair[1] > object_prob_threshold]
- pairs = sorted(pairs, key=lambda pair: pair[1], reverse=True)
- pairs = pairs[0:max_num_objects]
- return [('/'.join(CLASSES[index]), prob) for index, prob in pairs]
diff --git a/src/aiy/vision/models/dish_classifier_classes.py b/src/aiy/vision/models/dish_classifier_classes.py
deleted file mode 100644
index 70c711ea..00000000
--- a/src/aiy/vision/models/dish_classifier_classes.py
+++ /dev/null
@@ -1,2042 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Predefined dish classes for dish classifier model."""
-
-CLASSES = (
- ('background',), # index=0
- ('Chaudin',), # index=1
- ('Bambalouni',), # index=2
- ('Ghoriba',), # index=3
- ('Mango sticky rice',), # index=4
- ('Jianbing',), # index=5
- ('Aguachile',), # index=6
- ('Carrozza',), # index=7
- ('Miyan kuka',), # index=8
- ('Efo riro',), # index=9
- ('Ayam masak merah',), # index=10
- ('Chiffon pie',), # index=11
- ('Instant noodle',), # index=12
- ('Riso patate e cozze',), # index=13
- ('Bazin',), # index=14
- ('Black bottom pie',), # index=15
- ('Pal\xc3\xb3c soup',), # index=16
- ('Sailor sandwich',), # index=17
- ('Tuwo shinkafa',), # index=18
- ('Carne a la tampique\xc3\xb1a',), # index=19
- ('Pastel azteca',), # index=20
- ('Fujian red wine chicken',), # index=21
- ('Boeber',), # index=22
- ('Lady Baltimore cake',), # index=23
- ('Yam khai dao',), # index=24
- ('Texas Tommy',), # index=25
- ('Har cheong gai',), # index=26
- ('Kolokythopita',), # index=27
- ('Karydopita',), # index=28
- ('Rinflaj\xc5\xa1',), # index=29
- ('Hainanese curry rice',), # index=30
- ('Sonoran hot dog',), # index=31
- ('Kamounia',), # index=32
- ('Afghani burger',), # index=33
- ('Teochew porridge',), # index=34
- ('Minestra di ceci',), # index=35
- ('Pastrami on rye',), # index=36
- ('Roast beef sandwich',), # index=37
- ('Chahan',), # index=38
- ('Ekuru',), # index=39
- ('Sciusceddu',), # index=40
- ('Breakfast burrito',), # index=41
- ('\xc3\x84ggost',), # index=42
- ('Sausage Stroganoff',), # index=43
- ('Roti jala',), # index=44
- ('Pirao',), # index=45
- ('Casatiello',), # index=46
- ('Khanom tan',), # index=47
- ('Muamba chicken',), # index=48
- ('Dobradinha',), # index=49
- ('Bruckfleisch',), # index=50
- ('Molote',), # index=51
- ('Spongata',), # index=52
- ('Funge',), # index=53
- ('\xc3\x84lplermagronen',), # index=54
- ('K\xc3\xb6ttbullar',), # index=55
- ("Ka'ak",), # index=56
- ('Papet vaudois',), # index=57
- ('Broodpap',), # index=58
- ('Prosciutto di Norcia',), # index=59
- ('Malloreddus',), # index=60
- ('Farcidure',), # index=61
- ('Pannekoek',), # index=62
- ('\xc5\xa0porki makaruli',), # index=63
- ('Bolo Rei',), # index=64
- ('Camarones al mojo de ajo',), # index=65
- ('Fricasse',), # index=66
- ('Stracciatella',), # index=67
- ('Fondu creusois',), # index=68
- ('Sart\xc3\xb9',), # index=69
- ('Matelote',), # index=70
- ('Baodu',), # index=71
- ('Tarte au maton',), # index=72
- ('Cartellate',), # index=73
- ('Gyeran-ppang',), # index=74
- ('Torta pasqualina',), # index=75
- ('Caltabo\xc8\x99',), # index=76
- ('Khanom mo kaeng',), # index=77
- ('Suimono',), # index=78
- ('Dimlama',), # index=79
- ('Tav\xc3\xab kosi',), # index=80
- ('Salade li\xc3\xa9geoise',), # index=81
- ('Salame di Fabriano',), # index=82
- ('Kalach',), # index=83
- ('Jambon persill\xc3\xa9',), # index=84
- ('Tonkotsu ramen',), # index=85
- ('Pozharsky cutlet',), # index=86
- ('Roccoc\xc3\xb2',), # index=87
- ('Feij\xc3\xa3o com \xc3\xb3leo de palma',), # index=88
- ('Calulu',), # index=89
- ('Begova \xc4\x8dorba',), # index=90
- ('Cuzzupa',), # index=91
- ('Th\xe1\xbb\x8bt kho t\xc3\xa0u',), # index=92
- ('Bon bon chicken',), # index=93
- ('Zoque',), # index=94
- ('Bint al-sahn',), # index=95
- ('Tempoyak',), # index=96
- ('Puran poli',), # index=97
- ('Enfrijoladas',), # index=98
- ('Chueo-tang',), # index=99
- ('Naem',), # index=100
- ('Sate kikil',), # index=101
- ('Pinzimonio',), # index=102
- ('Pizokels',), # index=103
- ('Schiacciatina',), # index=104
- ('Schiacciata',), # index=105
- ('Daheen',), # index=106
- ('Chapssal-tteok',), # index=107
- ('Ojja',), # index=108
- ('Tigella',), # index=109
- ('Pansotti',), # index=110
- ('Fried eggplant',), # index=111
- ('Portuguese seafood rice',), # index=112
- ('Tripes \xc3\xa0 la mode de Caen',), # index=113
- ('Arraksbulle',), # index=114
- ('Brenebon',), # index=115
- ('Gnocco fritto',), # index=116
- ('Pan di ramerino',), # index=117
- ('Tahu tek-tek',), # index=118
- ('Bibikkan',), # index=119
- ('Tongseng cumi',), # index=120
- ('Nakl\xc3\xa1dan\xc3\xbd hermel\xc3\xadn',), # index=121
- ('Bundevara',), # index=122
- ('Sop saudara',), # index=123
- ('Mian cha',), # index=124
- ('Erbazzone',), # index=125
- ('Kisra',), # index=126
- ('Carne di t\xc3\xacblizze del Me\xc4\x91imurje',), # index=127
- ('Kagape kambing',), # index=128
- ('Markook',), # index=129
- ('Pisarei e fa\xc5\x9b\xc3\xb6',), # index=130
- ('Lontong Krubyuk',), # index=131
- ('Pampushka',), # index=132
- ('Makowiec',), # index=133
- ('Saleeg',), # index=134
- ('Scaccia',), # index=135
- ('J\xc3\xb3kai bean soup',), # index=136
- ('Bookbinder soup',), # index=137
- ('Selat solo',), # index=138
- ('Kutsinta',), # index=139
- ('Sago soup',), # index=140
- ('Vinegret',), # index=141
- ('Shrimp and grits',), # index=142
- ('Sirop de Li\xc3\xa8ge',), # index=143
- ('Woku',), # index=144
- ('Muhallebi',), # index=145
- ('Empal gepuk',), # index=146
- ('Fou\xc3\xa9e',), # index=147
- ('Octopus as food',), # index=148
- ('Koba',), # index=149
- ('B\xc3\xb2 l\xc3\xbac l\xe1\xba\xafc',), # index=150
- ("Squid l\xc5\xab'au",), # index=151
- ('Shrimp Louie',), # index=152
- ('Black pudding',), # index=153
- ('Cherry kebab',), # index=154
- ('Pitsi-pits\xc3\xae',), # index=155
- ('Sabich salad',), # index=156
- ('Mie kocok',), # index=157
- ('Maraca pie',), # index=158
- ('Banga',), # index=159
- ('Baccal\xc3\xa0 alla lucana',), # index=160
- ('Nasi tumpang',), # index=161
- ('Gratin dauphinois',), # index=162
- ('Arroz chaufa',), # index=163
- ('Kuih',), # index=164
- ('Ayam goreng',), # index=165
- ('Chongos zamoranos',), # index=166
- ('NOT_HOT_DOG',), # index=167
- ('M\xc4\x83m\xc4\x83lig\xc4\x83',), # index=168
- ('Candied almonds',), # index=169
- ('Lasagne',), # index=170
- ('Pecel Lele',), # index=171
- ('Lettuce soup',), # index=172
- ('Acquacotta',), # index=173
- ('Pork blood soup',), # index=174
- ('Sai krok Isan',), # index=175
- ('Buridda',), # index=176
- ('Maccu',), # index=177
- ('Turkey Devonshire',), # index=178
- ('Ginestrata',), # index=179
- ('Garmugia',), # index=180
- ('Meringue',), # index=181
- ('Peanut butter and jelly sandwich',), # index=182
- ('Couque de Dinant',), # index=183
- ('Omo tuo',), # index=184
- ('Thapthim krop',), # index=185
- ('Pie tee',), # index=186
- ('Sutarfeni',), # index=187
- ('Raclette',), # index=188
- ('Wotou',), # index=189
- ('Punugulu',), # index=190
- ('Succotash',), # index=191
- ('Chim chum',), # index=192
- ('Wachipa',), # index=193
- ('Boat noodles',), # index=194
- ('Tantuni',), # index=195
- ('Shab Deg',), # index=196
- ('Ch\xe1\xba\xa3 gi\xc3\xb2',), # index=197
- ('Ciabatta Bacon Cheeseburger',), # index=198
- ('Mie kangkung',), # index=199
- ('Tuwo masara',), # index=200
- ('Kokonte',), # index=201
- ('Akple',), # index=202
- ('Plakali',), # index=203
- ('Kware\xc5\xbcimal',), # index=204
- ('Bento',), # index=205
- ('Osechi',), # index=206
- ('Okonomiyaki',), # index=207
- ('Miso soup',), # index=208
- ('Dango',), # index=209
- ('Onigiri',), # index=210
- ('Hiyayakko',), # index=211
- ('Tempura',), # index=212
- ('Mochi',), # index=213
- ('Peppersoup',), # index=214
- ('Caldo de queso',), # index=215
- ('Dodo ikire',), # index=216
- ('Uir\xc5\x8d',), # index=217
- ('Red bean soup',), # index=218
- ('Kakig\xc5\x8dri',), # index=219
- ('Khichu',), # index=220
- ('Bolo de arroz',), # index=221
- ('Chips and dip',), # index=222
- ('Murgh Musallam',), # index=223
- ('Utica greens',), # index=224
- ('Zaalouk',), # index=225
- ('Mutton curry',), # index=226
- ('Mughlai paratha',), # index=227
- ('Tuo Zaafi',), # index=228
- ('B\xc3\xa1nh b\xe1\xbb\x99t l\xe1\xbb\x8dc',), # index=229
- ('Kavarma',), # index=230
- ('Cheeseburger',), # index=231
- ('Jelly bean',), # index=232
- ('Apple pie',), # index=233
- ('Udon',), # index=234
- ('Falafel',), # index=235
- ('Agedashi tofu',), # index=236
- ('Dashi',), # index=237
- ('Tortell',), # index=238
- ('Omelette',), # index=239
- ('Cr\xc3\xa8me br\xc3\xbbl\xc3\xa9e',), # index=240
- ('Cucumber soup',), # index=241
- ('French toast',), # index=242
- ('Tripe',), # index=243
- ('Pepperoni',), # index=244
- ('Salami',), # index=245
- ('Kimchi',), # index=246
- ('Kn\xc3\xb6del',), # index=247
- ('Takoyaki',), # index=248
- ('Halva',), # index=249
- ('Pigs in blankets',), # index=250
- ('Spanakopita',), # index=251
- ('Pumpkin pie',), # index=252
- ('Jambalaya',), # index=253
- ('Club sandwich',), # index=254
- ('Churro',), # index=255
- ('Turducken',), # index=256
- ('Welsh rarebit',), # index=257
- ('Hot dog',), # index=258
- ('Oyakodon',), # index=259
- ('Meatball',), # index=260
- ('Waldorf salad',), # index=261
- ('Potato salad',), # index=262
- ('Satay',), # index=263
- ('Pemmican',), # index=264
- ('M\xc3\xa4mmi',), # index=265
- ('Fideu\xc3\xa0',), # index=266
- ('Waffle',), # index=267
- ('Pancake',), # index=268
- ('Quiche',), # index=269
- ('Borscht',), # index=270
- ('Bratwurst',), # index=271
- ('Foie gras',), # index=272
- ('Burrito',), # index=273
- ('Goulash',), # index=274
- ('Spotted dick',), # index=275
- ('Coq au vin',), # index=276
- ('Ratatouille',), # index=277
- ('Cornbread',), # index=278
- ('Souvlaki',), # index=279
- ('Chow mein',), # index=280
- ('Roast beef',), # index=281
- ('Peking duck',), # index=282
- ('Fried chicken',), # index=283
- ('Croquembouche',), # index=284
- ('Tahini',), # index=285
- ('Gumbo',), # index=286
- ('Fajita',), # index=287
- ('Chicken fried steak',), # index=288
- ('Sukiyaki',), # index=289
- ('Scrapple',), # index=290
- ('Chili con carne',), # index=291
- ('Monte Cristo sandwich',), # index=292
- ('Kielbasa',), # index=293
- ('Polenta',), # index=294
- ('Reuben sandwich',), # index=295
- ("S'more",), # index=296
- ('Andouille',), # index=297
- ('Beignet',), # index=298
- ('Cr\xc3\xaape',), # index=299
- ('Gulai',), # index=300
- ('Breakfast sausage',), # index=301
- ('Chorizo',), # index=302
- ('Gyro',), # index=303
- ('Nachos',), # index=304
- ('Larb',), # index=305
- ('Couscous',), # index=306
- ('Meze',), # index=307
- ('Cheesesteak',), # index=308
- ('Frozen yogurt',), # index=309
- ('Injera',), # index=310
- ('Muesli',), # index=311
- ('Meatloaf',), # index=312
- ('Fuet',), # index=313
- ('Natt\xc5\x8d',), # index=314
- ('Banana split',), # index=315
- ('P\xc4\x85czki',), # index=316
- ('Pound cake',), # index=317
- ('Fuqi feipian',), # index=318
- ('Nasi lemak',), # index=319
- ('Flan',), # index=320
- ('Pad thai',), # index=321
- ('Yakitori',), # index=322
- ('Amanatt\xc5\x8d',), # index=323
- ('Tom kha kai',), # index=324
- ('Lokma',), # index=325
- ('Mooncake',), # index=326
- ('Idli',), # index=327
- ('Sp\xc3\xa4tzle',), # index=328
- ('Nopalito',), # index=329
- ('Sincronizada',), # index=330
- ('\xc5\xbdganci',), # index=331
- ('Totopo',), # index=332
- ('Folar',), # index=333
- ('Cherry pie',), # index=334
- ('Umeboshi',), # index=335
- ('Patty',), # index=336
- ('Saltah',), # index=337
- ('Khinkali',), # index=338
- ('Shkedei marak',), # index=339
- ('Tekkadon',), # index=340
- ('Chadachadi',), # index=341
- ('Kaipen',), # index=342
- ('Draw soup',), # index=343
- ('Shahan ful',), # index=344
- ('Shiro',), # index=345
- ("Ga'at",), # index=346
- ('Skordalia',), # index=347
- ('Budae jjigae',), # index=348
- ('Anju',), # index=349
- ('Fried Coke',), # index=350
- ('Lemang',), # index=351
- ('Basundi',), # index=352
- ('Brown Betty',), # index=353
- ('Khabees',), # index=354
- ('Kottu',), # index=355
- ('Isterband',), # index=356
- ('Ciauscolo',), # index=357
- ('Khatkhate',), # index=358
- ('Pan de muerto',), # index=359
- ('Caponata',), # index=360
- ('Pulla',), # index=361
- ('Sabaayad',), # index=362
- ('Miyeok-guk',), # index=363
- ('Imoni',), # index=364
- ('Pitha',), # index=365
- ('Kedgeree',), # index=366
- ('Bife a cavalo',), # index=367
- ('Yaki udon',), # index=368
- ('She-crab soup',), # index=369
- ('Koozh',), # index=370
- ('Ke\xc5\x9fkek',), # index=371
- ('Cabidela',), # index=372
- ('Gerber sandwich',), # index=373
- ('Zagorski \xc5\xa0trukli',), # index=374
- ('Himbasha',), # index=375
- ('Satara\xc5\xa1',), # index=376
- ('Kakuni',), # index=377
- ('Enormous Omelet Sandwich',), # index=378
- ('Turr\xc3\xb3n',), # index=379
- ('Tsukudani',), # index=380
- ('Hawaiian haystack',), # index=381
- ('Kateh',), # index=382
- ('Stoemp',), # index=383
- ('Pajeon',), # index=384
- ('\xc4\xa0bejna',), # index=385
- ('Kaya toast',), # index=386
- ('Fit-fit',), # index=387
- ('Kitcha',), # index=388
- ('Thalipeeth',), # index=389
- ('Figgy pudding',), # index=390
- ('Cachupa',), # index=391
- ('Cherries jubilee',), # index=392
- ('Crappit heid',), # index=393
- ('Mince and tatties',), # index=394
- ('Anadama bread',), # index=395
- ('Carbonara',), # index=396
- ('Kladdkaka',), # index=397
- ('Shakshouka',), # index=398
- ('Chicken Vesuvio',), # index=399
- ('Jibarito',), # index=400
- ('Chicken Divan',), # index=401
- ('Motsunabe',), # index=402
- ('Sonofabitch stew',), # index=403
- ('Pudding corn',), # index=404
- ('Johnny Marzetti',), # index=405
- ('Mostarda',), # index=406
- ('Maafe',), # index=407
- ('Churma',), # index=408
- ('Chole bhature',), # index=409
- ('Dobos torte',), # index=410
- ('Carne de porco \xc3\xa0 alentejana',), # index=411
- ('Khao soi',), # index=412
- ('Kissel',), # index=413
- ('Cottage loaf',), # index=414
- ('Silver needle noodles',), # index=415
- ('Shrimp DeJonghe',), # index=416
- ('Kiritanpo',), # index=417
- ('Bean pie',), # index=418
- ('Churchkhela',), # index=419
- ('Yahni',), # index=420
- ('Gringas',), # index=421
- ('Annin tofu',), # index=422
- ('Jiaozi',), # index=423
- ('Breakfast sandwich',), # index=424
- ('Tanghulu',), # index=425
- ('Black sesame soup',), # index=426
- ('Goug\xc3\xa8re',), # index=427
- ('Namul',), # index=428
- ('Kosambari',), # index=429
- ("Ma'amoul",), # index=430
- ('Caldo de pollo',), # index=431
- ('Loukaniko',), # index=432
- ('Doberge cake',), # index=433
- ('Nasi campur',), # index=434
- ('Snack cake',), # index=435
- ('Taiyaki',), # index=436
- ('Karn\xc4\xb1yar\xc4\xb1k',), # index=437
- ('Pierogi',), # index=438
- ('Macaroni and cheese',), # index=439
- ('Huevos motule\xc3\xb1os',), # index=440
- ('Chislic',), # index=441
- ('Corn dog',), # index=442
- ('Shawarma',), # index=443
- ('Zongzi',), # index=444
- ('Dumpling',), # index=445
- ('Syrniki',), # index=446
- ('King cake',), # index=447
- ('Souffl\xc3\xa9',), # index=448
- ('Gy\xc5\xabdon',), # index=449
- ('Chicken nugget',), # index=450
- ('Bulgogi',), # index=451
- ('Eggs Benedict',), # index=452
- ('Hot dry noodles',), # index=453
- ('Mashed potato',), # index=454
- ('Anpan',), # index=455
- ('Quesadilla',), # index=456
- ('Youtiao',), # index=457
- ('Congee',), # index=458
- ('Sekihan',), # index=459
- ('Semla',), # index=460
- ('Arctic roll',), # index=461
- ('Castella',), # index=462
- ('Hanabiramochi',), # index=463
- ('Falukorv',), # index=464
- ('Ketupat',), # index=465
- ('Rendang',), # index=466
- ('Chocolate brownie',), # index=467
- ('Mapo doufu',), # index=468
- ('Chinese noodles',), # index=469
- ('Empanada',), # index=470
- ('Fried rice',), # index=471
- ('Chicago-style pizza',), # index=472
- ('Cuban sandwich',), # index=473
- ('Tarte Tatin',), # index=474
- ('Yakisoba',), # index=475
- ('Dagwood sandwich',), # index=476
- ('Cheesecake',), # index=477
- ('Samosa',), # index=478
- ("Devil's food cake",), # index=479
- ('Shashlik',), # index=480
- ('Horseshoe sandwich',), # index=481
- ('City chicken',), # index=482
- ('Key lime pie',), # index=483
- ('Potato skins',), # index=484
- ('Haejang-guk',), # index=485
- ('Burmese tofu',), # index=486
- ('Shumai',), # index=487
- ('Sour cherry soup',), # index=488
- ('Gigandes plaki',), # index=489
- ('Kabsa',), # index=490
- ('Chicken curry',), # index=491
- ('Shrimp Creole',), # index=492
- ('Pork tenderloin sandwich',), # index=493
- ('Dampfnudel',), # index=494
- ('Finnan haddie',), # index=495
- ('Kenkey',), # index=496
- ('Pincho',), # index=497
- ('Gundruk',), # index=498
- ('Chilorio',), # index=499
- ('Koulourakia',), # index=500
- ('Bryndzov\xc3\xa9 halu\xc5\xa1ky',), # index=501
- ('Imagawayaki',), # index=502
- ('Vasilopita',), # index=503
- ('Strapa\xc4\x8dky',), # index=504
- ("Po' boy",), # index=505
- ('Capirotada',), # index=506
- ('Beef Manhattan',), # index=507
- ('Sandwich loaf',), # index=508
- ('Jian dui',), # index=509
- ('Almond biscuit',), # index=510
- ('North Slavic fermented cereal soups',), # index=511
- ('Fried plantain',), # index=512
- ('Stuffed peppers',), # index=513
- ('Piperade',), # index=514
- ('Rogan josh',), # index=515
- ('Fabada asturiana',), # index=516
- ('Potato wedges',), # index=517
- ('Calisson',), # index=518
- ('Prawn ball',), # index=519
- ('Kushikatsu',), # index=520
- ('Lo mai chi',), # index=521
- ('Manchet',), # index=522
- ('Leek soup',), # index=523
- ('Vanillerostbraten',), # index=524
- ('Hangtown fry',), # index=525
- ('Cabbie claw',), # index=526
- ('Chitranna',), # index=527
- ('Ragi mudde',), # index=528
- ('Denver sandwich',), # index=529
- ('Laver',), # index=530
- ('Elote',), # index=531
- ('Kulolo',), # index=532
- ('Oxtail soup',), # index=533
- ('Pantua',), # index=534
- ('Corn relish',), # index=535
- ('Poga\xc4\x8da',), # index=536
- ('Qubani ka meetha',), # index=537
- ('Boondi',), # index=538
- ('Arrosticini',), # index=539
- ('Panelle',), # index=540
- ('Santula',), # index=541
- ('Tofu skin roll',), # index=542
- ('Crispy fried chicken',), # index=543
- ('Steamed meatball',), # index=544
- ('Lobio',), # index=545
- ('Suman',), # index=546
- ('H\xc5\x8dt\xc5\x8d',), # index=547
- ('Matbukha',), # index=548
- ('Stuffed squash',), # index=549
- ('A\xc3\xa7orda',), # index=550
- ('Makdous',), # index=551
- ('Soto',), # index=552
- ('Frangollo',), # index=553
- ('Patty melt',), # index=554
- ('Taro dumpling',), # index=555
- ('Entomatada',), # index=556
- ('B\xc3\xa1nh cu\xe1\xbb\x91n',), # index=557
- ('Corunda',), # index=558
- ('Zhaliang',), # index=559
- ('Cassoulet',), # index=560
- ('Debrecener',), # index=561
- ('Scampi',), # index=562
- ('Pilaf',), # index=563
- ('Sambar',), # index=564
- ('Century egg',), # index=565
- ('Escargot',), # index=566
- ('Cong you bing',), # index=567
- ('Beef noodle soup',), # index=568
- ('Magiritsa',), # index=569
- ('Gugelhupf',), # index=570
- ('Sachima',), # index=571
- ('White rice',), # index=572
- ('Maultasche',), # index=573
- ('American chop suey',), # index=574
- ('Fish slice',), # index=575
- ('Sea cucumber as food',), # index=576
- ('Beef ball',), # index=577
- ('Siu yuk',), # index=578
- ('Seafood birdsnest',), # index=579
- ('White cut chicken',), # index=580
- ('Pinchitos',), # index=581
- ('Satsivi',), # index=582
- ('Malpua',), # index=583
- ('Chhena gaja',), # index=584
- ('Flying Jacob',), # index=585
- ('Steak de Burgo',), # index=586
- ('Crab Louie',), # index=587
- ('Butter chicken',), # index=588
- ('Amok trey',), # index=589
- ('Menemen',), # index=590
- ('Piadina',), # index=591
- ('Orange cuttlefish',), # index=592
- ('Fudge',), # index=593
- ('Cottage Pudding',), # index=594
- ('Meatcake',), # index=595
- ('Buttermilk pie',), # index=596
- ('Kalamay',), # index=597
- ('Puto',), # index=598
- ('Dal makhani',), # index=599
- ('Mixiote',), # index=600
- ('Bagel dog',), # index=601
- ('B\xc3\xban ri\xc3\xaau',), # index=602
- ('Feijoada',), # index=603
- ('Pho',), # index=604
- ('Milk toast',), # index=605
- ('Liver and onions',), # index=606
- ('Iced bun',), # index=607
- ('Sheer khurma',), # index=608
- ('Yi mein',), # index=609
- ('Shrimp roe noodles',), # index=610
- ('Lai fun',), # index=611
- ('Oil noodles',), # index=612
- ('Kal-guksu',), # index=613
- ('Youmian',), # index=614
- ('Avgolemono',), # index=615
- ('Pork roll',), # index=616
- ('Tart',), # index=617
- ('Leberk\xc3\xa4se',), # index=618
- ('Kalakukko',), # index=619
- ('Mustamakkara',), # index=620
- ('Baba ghanoush',), # index=621
- ('Karelian pasty',), # index=622
- ('Shortcake',), # index=623
- ('Profiterole',), # index=624
- ('Moussaka',), # index=625
- ('Dulce de leche',), # index=626
- ('Blaa',), # index=627
- ('Risotto',), # index=628
- ('Funnel cake',), # index=629
- ('Fried dough',), # index=630
- ('Consomm\xc3\xa9',), # index=631
- ('Clam chowder',), # index=632
- ('Tartiflette',), # index=633
- ('Red curry',), # index=634
- ('Tandoori chicken',), # index=635
- ('Gazpacho',), # index=636
- ('Prosciutto',), # index=637
- ('Boerewors',), # index=638
- ('Baked potato',), # index=639
- ('Bouillabaisse',), # index=640
- ('Kralan',), # index=641
- ('Chireta',), # index=642
- ('Bakewell tart',), # index=643
- ('Grits',), # index=644
- ('Shaved ice',), # index=645
- ('Choco pie',), # index=646
- ('Cumian',), # index=647
- ('Jokbal',), # index=648
- ('Grillades',), # index=649
- ('Hotteok',), # index=650
- ('Ezogelin soup',), # index=651
- ('Knedle',), # index=652
- ('Masgouf',), # index=653
- ('Sope',), # index=654
- ('Coconut rice',), # index=655
- ('Bakarkhani',), # index=656
- ('Asida',), # index=657
- ('Dirt cake',), # index=658
- ('Sel roti',), # index=659
- ('Kalakand',), # index=660
- ('Ghevar',), # index=661
- ('Sussex pond pudding',), # index=662
- ('Lontong',), # index=663
- ('B\xc3\xa1nh b\xc3\xa8o',), # index=664
- ('Pring\xc3\xa1',), # index=665
- ('Bull roast',), # index=666
- ('Stuffed ham',), # index=667
- ('Lablabi',), # index=668
- ('Gooey butter cake',), # index=669
- ('Carciofi alla giudia',), # index=670
- ('Yin si juan',), # index=671
- ('Babi panggang',), # index=672
- ('Chao hong guo',), # index=673
- ('Fun guo',), # index=674
- ('Khira sagara',), # index=675
- ('Coconut bar',), # index=676
- ('Sundae',), # index=677
- ('Tuna fish sandwich',), # index=678
- ('Zhangcha duck',), # index=679
- ('Marry girl cake',), # index=680
- ('Frijoles charros',), # index=681
- ('Rosca de reyes',), # index=682
- ('Happy Faces',), # index=683
- ('Deviled crab',), # index=684
- ('Sundubu-jjigae',), # index=685
- ('Sinseollo',), # index=686
- ('Dongchimi',), # index=687
- ('Nabak-kimchi',), # index=688
- ('Dhondas',), # index=689
- ('Soan papdi',), # index=690
- ('Baek-kimchi',), # index=691
- ('Chicken riggies',), # index=692
- ('Afelia',), # index=693
- ('Guly\xc3\xa1sleves',), # index=694
- ('Marie biscuit',), # index=695
- ('Caf\xc3\xa9 li\xc3\xa9geois',), # index=696
- ('Ch\xc3\xa8',), # index=697
- ('Pootharekulu',), # index=698
- ('Escalope',), # index=699
- ('Rajma',), # index=700
- ('Beshbarmak',), # index=701
- ('Torta Tre Monti',), # index=702
- ('French dip',), # index=703
- ('Pumpkin-coconut custard',), # index=704
- ('Rose hip soup',), # index=705
- ('Veggie burger',), # index=706
- ('Steak tartare',), # index=707
- ('Bologna sausage',), # index=708
- ('P\xc3\xa2t\xc3\xa9',), # index=709
- ('Bibimbap',), # index=710
- ('Shahi paneer',), # index=711
- ('Fufu',), # index=712
- ('Pyttipanna',), # index=713
- ('Chicken sandwich',), # index=714
- ('Ghari',), # index=715
- ('Michigan salad',), # index=716
- ('Cabinet pudding',), # index=717
- ('American fried rice',), # index=718
- ('Korovai',), # index=719
- ('Churrasco',), # index=720
- ('Pasulj',), # index=721
- ('Mitraillette',), # index=722
- ('Salat\xc4\x83 de boeuf',), # index=723
- ('Rice pudding',), # index=724
- ('R\xc3\xb6sti',), # index=725
- ('Naryn',), # index=726
- ('Kaldereta',), # index=727
- ('Makroudh',), # index=728
- ('Kachumbari',), # index=729
- ('Tsukemono',), # index=730
- ('Cheese fries',), # index=731
- ('Slatko',), # index=732
- ('Qatayef',), # index=733
- ('Passatelli',), # index=734
- ('Sweet potato soup',), # index=735
- ('Shchi',), # index=736
- ('Kulfi',), # index=737
- ('Dolma',), # index=738
- ('Kai yang',), # index=739
- ('Shark fin soup',), # index=740
- ('Pozole',), # index=741
- ('Pakora',), # index=742
- ('Chantilly cake',), # index=743
- ('Kr\xc3\xb3wki',), # index=744
- ('Russian tea cake',), # index=745
- ('Ox-tongue pastry',), # index=746
- ('Sachertorte',), # index=747
- ('Palitaw',), # index=748
- ('Jolpan',), # index=749
- ('Mantou',), # index=750
- ('Finger steaks',), # index=751
- ('Steak sandwich',), # index=752
- ('Talo',), # index=753
- ('Erkuai',), # index=754
- ('Mixian',), # index=755
- ('St. Louis-style pizza',), # index=756
- ('Moambe',), # index=757
- ('Upma',), # index=758
- ('Panjiri',), # index=759
- ('Eggs Sardou',), # index=760
- ('Shanghai fried noodles',), # index=761
- ('Quarkk\xc3\xa4ulchen',), # index=762
- ('Cupcake',), # index=763
- ('Snickerdoodle',), # index=764
- ('Farl',), # index=765
- ('Coleslaw',), # index=766
- ('Calas',), # index=767
- ('Beef Stroganoff',), # index=768
- ('Shimotsukare',), # index=769
- ('Squab',), # index=770
- ('Basbousa',), # index=771
- ('Watalappam',), # index=772
- ('Tepsi baytinijan',), # index=773
- ('Kuli-kuli',), # index=774
- ('Shabu-shabu',), # index=775
- ('Sundae',), # index=776
- ('Fried brain sandwich',), # index=777
- ('Rollmops',), # index=778
- ('Higashi',), # index=779
- ('Panna cotta',), # index=780
- ('Aloo gobi',), # index=781
- ('Aspic',), # index=782
- ('Obatzda',), # index=783
- ('Gulab jamun',), # index=784
- ('Tuna casserole',), # index=785
- ('Ribollita',), # index=786
- ('Chomchom',), # index=787
- ('Rassolnik',), # index=788
- ('Jeongol',), # index=789
- ('Cantonese seafood soup',), # index=790
- ('Mashed Eggplant Salad',), # index=791
- ('K\xc3\xbcrt\xc5\x91skal\xc3\xa1cs',), # index=792
- ('P\xc3\xb6lsa',), # index=793
- ('Lobster roll',), # index=794
- ('Sloppy joe',), # index=795
- ('Schnitzel',), # index=796
- ('Bacalhau',), # index=797
- ('Sfenj',), # index=798
- ('Menudo',), # index=799
- ('Gujia',), # index=800
- ('Liver soup',), # index=801
- ('Panocha',), # index=802
- ('Chakapuli',), # index=803
- ('Sklandrausis',), # index=804
- ('Liver p\xc3\xa2t\xc3\xa9',), # index=805
- ('Rullep\xc3\xb8lse',), # index=806
- ('Frikadeller',), # index=807
- ('Frikandel',), # index=808
- ('Cinnamon roll',), # index=809
- ('Scotch pie',), # index=810
- ('Hot wiener',), # index=811
- ('Wodzionka',), # index=812
- ('Greek salad',), # index=813
- ('Raita',), # index=814
- ("Dong'an chicken",), # index=815
- ('Boortsog',), # index=816
- ('Coca',), # index=817
- ('Champon',), # index=818
- ('Tabbouleh',), # index=819
- ('Korokke',), # index=820
- ('Chile relleno',), # index=821
- ('Brandade',), # index=822
- ('Hoppang',), # index=823
- ('Gozinaki',), # index=824
- ('Lazarakia',), # index=825
- ('Puff Puff',), # index=826
- ('Fatteh',), # index=827
- ('Speculaas',), # index=828
- ('Karasumi',), # index=829
- ('Brandy snaps',), # index=830
- ('Trdeln\xc3\xadk',), # index=831
- ('Cocido madrile\xc3\xb1o',), # index=832
- ('Red velvet cake',), # index=833
- ('Kringle',), # index=834
- ('Quenelle',), # index=835
- ('Toasted ravioli',), # index=836
- ('Tajine',), # index=837
- ('Cranachan',), # index=838
- ('Rusk',), # index=839
- ('Mille-feuille',), # index=840
- ('Acorn noodle soup',), # index=841
- ('Gachas',), # index=842
- ('Jingisukan',), # index=843
- ('Thekua',), # index=844
- ('Ghugni',), # index=845
- ('Taramasalata',), # index=846
- ('Italian beef',), # index=847
- ('Challah',), # index=848
- ('Fried ice cream',), # index=849
- ('Onion ring',), # index=850
- ('Smoked meat',), # index=851
- ('Dahi vada',), # index=852
- ('Mother-in-law',), # index=853
- ('Blondie',), # index=854
- ('Guk',), # index=855
- ('Hiyashi ch\xc5\xabka',), # index=856
- ('Sweet shells',), # index=857
- ('Salisbury steak',), # index=858
- ('Poffertjes',), # index=859
- ('Eggs Neptune',), # index=860
- ('Galbi-jjim',), # index=861
- ('Agwi-jjim',), # index=862
- ('Ladob',), # index=863
- ('Instant-boiled mutton',), # index=864
- ('Cincalok',), # index=865
- ('Jook-sing noodles',), # index=866
- ('Potbrood',), # index=867
- ('Burkinab\xc3\xa9 cuisine',), # index=868
- ('Taralli',), # index=869
- ('Carbonade flamande',), # index=870
- ('X\xc3\xb4i',), # index=871
- ('Sauerbraten',), # index=872
- ('Spiedie',), # index=873
- ('Gimbap',), # index=874
- ('Czernina',), # index=875
- ('Kroppkaka',), # index=876
- ("Buddha's delight",), # index=877
- ('Pain au chocolat',), # index=878
- ('Goetta',), # index=879
- ('German chocolate cake',), # index=880
- ('Melt sandwich',), # index=881
- ('Popiah',), # index=882
- ('Haleem',), # index=883
- ('Hornazo',), # index=884
- ('Janchi-guksu',), # index=885
- ('Kipper',), # index=886
- ('Bossam',), # index=887
- ('Arbroath smokie',), # index=888
- ('Bologna sandwich',), # index=889
- ('Cobbler',), # index=890
- ('Kouign-amann',), # index=891
- ('Char kway teow',), # index=892
- ('Rostbr\xc3\xa4tel',), # index=893
- ('Doenjang-jjigae',), # index=894
- ('Tharid',), # index=895
- ('Hainanese chicken rice',), # index=896
- ('Bak kut teh',), # index=897
- ('Cabbage roll',), # index=898
- ('Runza',), # index=899
- ('Bananas Foster',), # index=900
- ('Kozhukkatta',), # index=901
- ('K\xc5\xab\xc4\x8diukai',), # index=902
- ('Sm\xc3\xb8rrebr\xc3\xb8d',), # index=903
- ('Kutia',), # index=904
- ('Deviled egg',), # index=905
- ('Buchteln',), # index=906
- ('Apple strudel',), # index=907
- ('Wonton',), # index=908
- ('Chess pie',), # index=909
- ('Pirozhki',), # index=910
- ('Douzhi',), # index=911
- ('Macaroni soup',), # index=912
- ('Crossing the bridge noodles',), # index=913
- ('Lechazo',), # index=914
- ('Rolled oyster',), # index=915
- ('Asam pedas',), # index=916
- ('Mi krop',), # index=917
- ('Patoleo',), # index=918
- ('Rig\xc3\xb3 Jancsi',), # index=919
- ('Ollada',), # index=920
- ('Garbure',), # index=921
- ('Sabudana Khichadi',), # index=922
- ('Pot\xc3\xa9e',), # index=923
- ('Phanaeng curry',), # index=924
- ('Madeleine',), # index=925
- ('Mashed pumpkin',), # index=926
- ('Suet pudding',), # index=927
- ('Bombay mix',), # index=928
- ('Namagashi',), # index=929
- ('Struffoli',), # index=930
- ('Dak-galbi',), # index=931
- ('Dumpling',), # index=932
- ('Misal',), # index=933
- ('Patatnik',), # index=934
- ('Yuxiang',), # index=935
- ('Frozen banana',), # index=936
- ('Psarosoupa',), # index=937
- ('Mekitsa',), # index=938
- ('Sanna',), # index=939
- ('Kazy',), # index=940
- ('Sorbetes',), # index=941
- ("Potatoes O'Brien",), # index=942
- ('Tom yum',), # index=943
- ('Balushahi',), # index=944
- ('Arroz a la cubana',), # index=945
- ('Jalebi',), # index=946
- ('Sopaipilla',), # index=947
- ('Ukha',), # index=948
- ('Sv\xc3\xad\xc4\x8dkov\xc3\xa1',), # index=949
- ('T\xc3\xbar\xc3\xb3s csusza',), # index=950
- ('Pinnekj\xc3\xb8tt',), # index=951
- ('Salty liquorice',), # index=952
- ('Lemon ice box pie',), # index=953
- ('Knickerbocker glory',), # index=954
- ('Zhajiangmian',), # index=955
- ('Cobb salad',), # index=956
- ('Misua',), # index=957
- ('Shoofly pie',), # index=958
- ('Bhakri',), # index=959
- ('Apple cake',), # index=960
- ('Orange chicken',), # index=961
- ('Jam\xc3\xb3n serrano',), # index=962
- ('Bundt cake',), # index=963
- ('Bara brith',), # index=964
- ('Hot pot',), # index=965
- ('Kung Pao chicken',), # index=966
- ('Mulukhiyah',), # index=967
- ('Piti',), # index=968
- ('Double ka meetha',), # index=969
- ('Choila',), # index=970
- ('Moustalevria',), # index=971
- ('Arizona cheese crisp',), # index=972
- ('Rice Krispies Treats',), # index=973
- ('Liangpi',), # index=974
- ('Prinskorv',), # index=975
- ('Salmorejo',), # index=976
- ('Chicken Fran\xc3\xa7aise',), # index=977
- ('Fl\xc3\xa4skkorv',), # index=978
- ('Glorified rice',), # index=979
- ('Shishbarak',), # index=980
- ('Stinky tofu',), # index=981
- ('Muffuletta',), # index=982
- ('Soy sauce chicken',), # index=983
- ('Chicken fingers',), # index=984
- ('Pecan pie',), # index=985
- ('Eba',), # index=986
- ('Parfait',), # index=987
- ('Ndol\xc3\xa9',), # index=988
- ('Cheese sandwich',), # index=989
- ("Carne de vinha d'alhos",), # index=990
- ('Bob Andy pie',), # index=991
- ('Cincinnati chili',), # index=992
- ('Frico',), # index=993
- ('Tapioca pudding',), # index=994
- ('Minestrone',), # index=995
- ('Boxty',), # index=996
- ('Naengmyeon',), # index=997
- ('Seven-layer salad',), # index=998
- ('Samgyeopsal',), # index=999
- ('Cawl',), # index=1000
- ('Chocolate pudding',), # index=1001
- ('Hotdish',), # index=1002
- ('Ciccioli',), # index=1003
- ('Douhua',), # index=1004
- ('Berliner',), # index=1005
- ('Fried fish',), # index=1006
- ('Apple crisp',), # index=1007
- ('Boudin',), # index=1008
- ('Yusheng',), # index=1009
- ('Babka',), # index=1010
- ('Pizzoccheri',), # index=1011
- ('Welsh cake',), # index=1012
- ('Parker House roll',), # index=1013
- ('Tripe soups',), # index=1014
- ('Chimichanga',), # index=1015
- ('Jucy Lucy',), # index=1016
- ('Dodger Dog',), # index=1017
- ('Pastiera',), # index=1018
- ('Huarache',), # index=1019
- ('Solkadhi',), # index=1020
- ('Schupfnudel',), # index=1021
- ('Waldorf pudding',), # index=1022
- ('Harees',), # index=1023
- ('Ash reshteh',), # index=1024
- ('Celery Victor',), # index=1025
- ('Diples',), # index=1026
- ('Kompot',), # index=1027
- ('French onion soup',), # index=1028
- ('Tres leches cake',), # index=1029
- ('Torta caprese',), # index=1030
- ('Black Forest gateau',), # index=1031
- ('P\xc3\xa2t\xc3\xa9 aux pommes de terre',), # index=1032
- ('L\xc3\xa2pa',), # index=1033
- ('B\xc3\xbcndner Nusstorte',), # index=1034
- ('Hachee',), # index=1035
- ('Spaghetti aglio e olio',), # index=1036
- ('Whoopie pie',), # index=1037
- ('Ais kacang',), # index=1038
- ('Chermoula',), # index=1039
- ('Gado-gado',), # index=1040
- ('Merguez',), # index=1041
- ('Snickers salad',), # index=1042
- ('Giouvetsi',), # index=1043
- ('Kharcho',), # index=1044
- ('Chicken fried bacon',), # index=1045
- ('Dessert bar',), # index=1046
- ('Coulibiac',), # index=1047
- ('Thieboudienne',), # index=1048
- ('Rabri',), # index=1049
- ('Sapin-sapin',), # index=1050
- ('Sealed crustless sandwich',), # index=1051
- ('Carne asada',), # index=1052
- ('Coyotas',), # index=1053
- ('Chocolate-covered bacon',), # index=1054
- ('Stroopwafel',), # index=1055
- ('Gravlax',), # index=1056
- ('Pot pie',), # index=1057
- ('Ghormeh sabzi',), # index=1058
- ('Surf and turf',), # index=1059
- ('Brunswick stew',), # index=1060
- ('Mititei',), # index=1061
- ('Fluffernutter',), # index=1062
- ('Khaja',), # index=1063
- ('Stottie cake',), # index=1064
- ('London broil',), # index=1065
- ('Fasolada',), # index=1066
- ('Strudel',), # index=1067
- ('\xc3\x98llebr\xc3\xb8d',), # index=1068
- ('Tamago kake gohan',), # index=1069
- ('Hot water corn bread',), # index=1070
- ('Philippine adobo',), # index=1071
- ('Hulatang',), # index=1072
- ('Dyrl\xc3\xa6gens natmad',), # index=1073
- ('Chistorra',), # index=1074
- ('Polkagris',), # index=1075
- ('Galbi-tang',), # index=1076
- ('Mrouzia',), # index=1077
- ('Gopchang-jeongol',), # index=1078
- ('Miang kham',), # index=1079
- ('Clams casino',), # index=1080
- ('Nanbanzuke',), # index=1081
- ('Dripping cake',), # index=1082
- ('Cookie salad',), # index=1083
- ('Usal',), # index=1084
- ('Mandu-guk',), # index=1085
- ('Smalahove',), # index=1086
- ('Kokis',), # index=1087
- ('Ori-tang',), # index=1088
- ('Pakhala',), # index=1089
- ('Cream pie',), # index=1090
- ('Butajiru',), # index=1091
- ('New England boiled dinner',), # index=1092
- ('Chhena jalebi',), # index=1093
- ('Pastitsio',), # index=1094
- ('Panucho',), # index=1095
- ('Chhena kheeri',), # index=1096
- ('Kifli',), # index=1097
- ('Solyanka',), # index=1098
- ('Sadhya',), # index=1099
- ('Cullen skink',), # index=1100
- ('Chokladboll',), # index=1101
- ('Harira',), # index=1102
- ('Cornish game hen',), # index=1103
- ('Beef on weck',), # index=1104
- ('Tompouce',), # index=1105
- ('Caldo de siete mares',), # index=1106
- ('Millionb\xc3\xb8f',), # index=1107
- ('Chicago-style hot dog',), # index=1108
- ('Risalamande',), # index=1109
- ('Alinazik kebab',), # index=1110
- ('Medisterp\xc3\xb8lse',), # index=1111
- ('Sarson da saag',), # index=1112
- ('Liangfen',), # index=1113
- ('Pistolette',), # index=1114
- ('Steamed clams',), # index=1115
- ('Ulam',), # index=1116
- ('Kheer',), # index=1117
- ('Tlacoyo',), # index=1118
- ('Tarator',), # index=1119
- ('Hu tieu',), # index=1120
- ('Teja',), # index=1121
- ('Cochinita pibil',), # index=1122
- ('Buddha Jumps Over the Wall',), # index=1123
- ('Sfouf',), # index=1124
- ('Ham and cheese sandwich',), # index=1125
- ('Peanut butter', 'banana and bacon sandwich'), # index=1126
- ('Bacon', 'egg and cheese sandwich'), # index=1127
- ('Chicken karahi',), # index=1128
- ('Maple bacon donut',), # index=1129
- ('Litti',), # index=1130
- ('Nam khao',), # index=1131
- ('Nam tok',), # index=1132
- ('Baozi',), # index=1133
- ('Kibbeh',), # index=1134
- ('Kushari',), # index=1135
- ('Jiuniang',), # index=1136
- ('Aseed',), # index=1137
- ('Machher Jhol',), # index=1138
- ('Fahsa',), # index=1139
- ('Mysore pak',), # index=1140
- ('Chalupa',), # index=1141
- ('Swiss roll',), # index=1142
- ('Balkenbrij',), # index=1143
- ('Tortas de aceite',), # index=1144
- ('Popover',), # index=1145
- ('Falooda',), # index=1146
- ('Macaroni salad',), # index=1147
- ('Barbacoa',), # index=1148
- ('Hushpuppy',), # index=1149
- ('Luther Burger',), # index=1150
- ('Ragout',), # index=1151
- ('B\xc3\xa1nh bao',), # index=1152
- ('Moronga',), # index=1153
- ('Hayashi rice',), # index=1154
- ('Z\xc3\xbcrcher Geschnetzeltes',), # index=1155
- ('\xc3\x89clair',), # index=1156
- ('Colcannon',), # index=1157
- ('Bear claw',), # index=1158
- ('Francesinha',), # index=1159
- ('Wat',), # index=1160
- ('Loco moco',), # index=1161
- ('Hot milk cake',), # index=1162
- ('Hoe',), # index=1163
- ('Gordita',), # index=1164
- ('Macaron',), # index=1165
- ('Pepperoni roll',), # index=1166
- ('Rasgulla',), # index=1167
- ('Angel wings',), # index=1168
- ('Huevos rancheros',), # index=1169
- ('Caprese salad',), # index=1170
- ('Kombdi vade',), # index=1171
- ('Yong Tau Foo',), # index=1172
- ('Chai tow kway',), # index=1173
- ('Machaca',), # index=1174
- ('Ugali',), # index=1175
- ('Arr\xc3\xb2s negre',), # index=1176
- ('Kimchi fried rice',), # index=1177
- ('Frybread',), # index=1178
- ('Halo-halo',), # index=1179
- ('Shiokara',), # index=1180
- ('Janssons frestelse',), # index=1181
- ('Hot Brown',), # index=1182
- ('Torta',), # index=1183
- ('\xc4\x86evapi',), # index=1184
- ('Salt water taffy',), # index=1185
- ('\xc3\x87\xc4\xb1lb\xc4\xb1r',), # index=1186
- ('Murtabak',), # index=1187
- ('Tahu goreng',), # index=1188
- ('Soto ayam',), # index=1189
- ('Mee siam',), # index=1190
- ('Submarine sandwich',), # index=1191
- ('Halu\xc5\xa1ky',), # index=1192
- ('Kimchi-jjigae',), # index=1193
- ('Fish ball',), # index=1194
- ('Blodpalt',), # index=1195
- ('Lebanon bologna',), # index=1196
- ('Okroshka',), # index=1197
- ('Linzer torte',), # index=1198
- ('Shrikhand',), # index=1199
- ('Yakiniku',), # index=1200
- ('Huevos divorciados',), # index=1201
- ('Nihari',), # index=1202
- ('Saut\xc3\xa9ed reindeer',), # index=1203
- ('Hasty pudding',), # index=1204
- ('Mission burrito',), # index=1205
- ('Sweet and sour pork',), # index=1206
- ('R\xc3\xb8dgr\xc3\xb8d',), # index=1207
- ('Booyah',), # index=1208
- ('Bienenstich',), # index=1209
- ('Dressed herring',), # index=1210
- ('New York-style pizza',), # index=1211
- ('Bistek',), # index=1212
- ('Sinigang',), # index=1213
- ('Fios de ovos',), # index=1214
- ('Vitello tonnato',), # index=1215
- ('Bisque',), # index=1216
- ('Khao tom',), # index=1217
- ('Modak',), # index=1218
- ('New Haven-style pizza',), # index=1219
- ('California-style pizza',), # index=1220
- ('Wrap',), # index=1221
- ('Puri',), # index=1222
- ('Jam\xc3\xb3n',), # index=1223
- ('Khash',), # index=1224
- ('Beef bourguignon',), # index=1225
- ('Truffade',), # index=1226
- ('B\xc3\xb2 n\xc6\xb0\xe1\xbb\x9bng l\xc3\xa1 l\xe1\xbb\x91t',
- ), # index=1227
- ('Ful medames',), # index=1228
- ('Aligot',), # index=1229
- ('Kolach',), # index=1230
- ('Guaiwei',), # index=1231
- ('Kesme',), # index=1232
- ('Funeral potatoes',), # index=1233
- ('Sushi',), # index=1234
- ('Arancini',), # index=1235
- ('Creamed corn',), # index=1236
- ('Mozzarella sticks',), # index=1237
- ('American goulash',), # index=1238
- ('Gofio',), # index=1239
- ('Soup alla Canavese',), # index=1240
- ('Red beans and rice',), # index=1241
- ('R\xc3\xb6ssypottu',), # index=1242
- ('Fl\xc3\xa4skpannkaka',), # index=1243
- ('Hyderabadi biryani',), # index=1244
- ('Baeckeoffe',), # index=1245
- ('Eton mess',), # index=1246
- ('Khachapuri',), # index=1247
- ('Banoffee pie',), # index=1248
- ('Ants climbing a tree',), # index=1249
- ('Dandan noodles',), # index=1250
- ('Suanla chaoshou',), # index=1251
- ('Samgye-tang',), # index=1252
- ('Spam musubi',), # index=1253
- ('Bridie',), # index=1254
- ('Kaju katli',), # index=1255
- ('Chocolate-covered potato chips',), # index=1256
- ('Enne gai',), # index=1257
- ('Ruske kape',), # index=1258
- ('Spaghetti',), # index=1259
- ('Grass jelly',), # index=1260
- ('Salt potatoes',), # index=1261
- ('Katsudon',), # index=1262
- ('Pasanda',), # index=1263
- ('Banitsa',), # index=1264
- ('Tarte flamb\xc3\xa9e',), # index=1265
- ('Twice cooked pork',), # index=1266
- ('Kare-kare',), # index=1267
- ('Laobing',), # index=1268
- ('Banmian',), # index=1269
- ('Ontbijtkoek',), # index=1270
- ('Swiss wing',), # index=1271
- ('Michigan hot dog',), # index=1272
- ('Tong sui',), # index=1273
- ('Taco',), # index=1274
- ('Sosatie',), # index=1275
- ('Pap',), # index=1276
- ('Umngqusho',), # index=1277
- ('Malva pudding',), # index=1278
- ('Vichyssoise',), # index=1279
- ('Z\xc5\x8dni',), # index=1280
- ('Maxwell Street Polish',), # index=1281
- ('Vetkoek',), # index=1282
- ('Mealie bread',), # index=1283
- ('Chakalaka',), # index=1284
- ('Frikkadel',), # index=1285
- ('Pizza strips',), # index=1286
- ('Tteokguk',), # index=1287
- ('Coney Island hot dog',), # index=1288
- ('Tirokafteri',), # index=1289
- ('Fesikh',), # index=1290
- ('Boston cream pie',), # index=1291
- ('Buttermilk koldsk\xc3\xa5l',), # index=1292
- ('White boiled shrimp',), # index=1293
- ('Bagnun',), # index=1294
- ('Buntil',), # index=1295
- ('Kaiserschmarrn',), # index=1296
- ('Pisto',), # index=1297
- ('Dhokla',), # index=1298
- ('Al pastor',), # index=1299
- ('St. Paul sandwich',), # index=1300
- ('Melonpan',), # index=1301
- ('Haupia',), # index=1302
- ('L\xc3\xa1ngos',), # index=1303
- ('\xc3\x89touff\xc3\xa9e',), # index=1304
- ('Galaktoboureko',), # index=1305
- ('B\xc3\xb6rek',), # index=1306
- ('Suya',), # index=1307
- ('Rye bread',), # index=1308
- ("Escudella i carn d'olla",), # index=1309
- ('Gari',), # index=1310
- ('Tilkut',), # index=1311
- ('Botok',), # index=1312
- ('Tatws Pum Munud',), # index=1313
- ('Char siu',), # index=1314
- ('Burgoo',), # index=1315
- ('Cac\xc4\xb1k',), # index=1316
- ('Barfi',), # index=1317
- ('Mulligan stew',), # index=1318
- ('Biangbiang noodles',), # index=1319
- ('Banana pudding',), # index=1320
- ('Crab cake',), # index=1321
- ('Chinese sausage',), # index=1322
- ('Veal',), # index=1323
- ('Curry bread',), # index=1324
- ('Pastry heart',), # index=1325
- ('Cr\xc3\xa8me caramel',), # index=1326
- ('Panada',), # index=1327
- ('Pie \xc3\xa0 la Mode',), # index=1328
- ('Bonus Jack',), # index=1329
- ('Princess cake',), # index=1330
- ('Harihari-nabe',), # index=1331
- ('Hot chicken',), # index=1332
- ('Chhena Jhili',), # index=1333
- ('Grape pie',), # index=1334
- ('Chicken bog',), # index=1335
- ('Sausage gravy',), # index=1336
- ('Derby Pie',), # index=1337
- ('Ice cream cake',), # index=1338
- ('Swiss steak',), # index=1339
- ('Bagna c\xc3\xa0uda',), # index=1340
- ('Stack cake',), # index=1341
- ('Lobster Newberg',), # index=1342
- ('Nikujaga',), # index=1343
- ('Manti',), # index=1344
- ('Parmigiana',), # index=1345
- ('Palatschinke',), # index=1346
- ('Gujeolpan',), # index=1347
- ('Rajas con crema',), # index=1348
- ('Mak-guksu',), # index=1349
- ('Tetrazzini',), # index=1350
- ('Squid as food',), # index=1351
- ('Palak paneer',), # index=1352
- ('Krumkake',), # index=1353
- ('Bolani',), # index=1354
- ('Pork and beans',), # index=1355
- ('Nian gao',), # index=1356
- ('Oysters Rockefeller',), # index=1357
- ('Tav\xc4\x8de grav\xc4\x8de',), # index=1358
- ('Bakkwa',), # index=1359
- ('Xacuti',), # index=1360
- ('Sarapatel',), # index=1361
- ('Taquito',), # index=1362
- ('Egg drop soup',), # index=1363
- ('Shaobing',), # index=1364
- ('Chawanmushi',), # index=1365
- ('Nshima',), # index=1366
- ('Pollock roe',), # index=1367
- ('Slinger',), # index=1368
- ('Japchae',), # index=1369
- ('St. Honor\xc3\xa9 cake',), # index=1370
- ('Barm cake',), # index=1371
- ('Tulumba',), # index=1372
- ('Xiaolongbao',), # index=1373
- ('Delmonico steak',), # index=1374
- ('Stromboli',), # index=1375
- ('Kanafeh',), # index=1376
- ('Hamdog',), # index=1377
- ('Garri',), # index=1378
- ('Kofta',), # index=1379
- ('Chana masala',), # index=1380
- ('Salo',), # index=1381
- ('Lung fung soup',), # index=1382
- ('Dirty rice',), # index=1383
- ('Urnebes',), # index=1384
- ('Andouillette',), # index=1385
- ('Landj\xc3\xa4ger',), # index=1386
- ("Fisherman's soup",), # index=1387
- ('Romeritos',), # index=1388
- ('Lane cake',), # index=1389
- ('Pork jelly',), # index=1390
- ('Idiyappam',), # index=1391
- ('Sm\xc3\xb6rg\xc3\xa5st\xc3\xa5rta',), # index=1392
- ('Sma\xc5\xbeen\xc3\xbd s\xc3\xbdr',), # index=1393
- ('Arroz con pollo',), # index=1394
- ('Lahmacun',), # index=1395
- ('Molten chocolate cake',), # index=1396
- ('Tea egg',), # index=1397
- ('Cocada amarela',), # index=1398
- ('Japanese curry',), # index=1399
- ('Keema',), # index=1400
- ('Unagi',), # index=1401
- ("Hoppin' John",), # index=1402
- ('Gy\xc5\xabhi',), # index=1403
- ('Clafoutis',), # index=1404
- ('Green curry',), # index=1405
- ('G\xe1\xbb\x8fi cu\xe1\xbb\x91n',), # index=1406
- ('Chilli crab',), # index=1407
- ('Lo mai gai',), # index=1408
- ('Lo mein',), # index=1409
- ('Puttu',), # index=1410
- ('Fried pie',), # index=1411
- ('Spanish rice',), # index=1412
- ('Nuea phat phrik',), # index=1413
- ('Jeow bong',), # index=1414
- ('Massaman curry',), # index=1415
- ('Ostkaka',), # index=1416
- ('Guilinggao',), # index=1417
- ('Spettekaka',), # index=1418
- ('Cudighi',), # index=1419
- ('Saltimbocca',), # index=1420
- ('Sfogliatella',), # index=1421
- ('Beef chow fun',), # index=1422
- ('Chow mein sandwich',), # index=1423
- ('Carnitas',), # index=1424
- ('Chinese steamed eggs',), # index=1425
- ('Oyster omelette',), # index=1426
- ('Garden salad',), # index=1427
- ('Salade ni\xc3\xa7oise',), # index=1428
- ('Dal bhat',), # index=1429
- ('Biscuits and gravy',), # index=1430
- ('Omurice',), # index=1431
- ('Pao cai',), # index=1432
- ('Nasi liwet',), # index=1433
- ('Thai suki',), # index=1434
- ('Moo shu pork',), # index=1435
- ('Corn crab soup',), # index=1436
- ('Fabes con almejas',), # index=1437
- ('Golden Opulence Sundae',), # index=1438
- ('Ketoprak',), # index=1439
- ('Mala Mogodu',), # index=1440
- ('Tekwan',), # index=1441
- ('Vatrushka',), # index=1442
- ('Yin Yang fish',), # index=1443
- ('Boston cream doughnut',), # index=1444
- ('Ramen',), # index=1445
- ('Home fries',), # index=1446
- ('Mustacciuoli',), # index=1447
- ('Clam cake',), # index=1448
- ('Sarma',), # index=1449
- ('Shahe fen',), # index=1450
- ('Charleston red rice',), # index=1451
- ('Fish head curry',), # index=1452
- ('Podvarak',), # index=1453
- ('Pihtije',), # index=1454
- ('Popara',), # index=1455
- ('Ka\xc4\x8damak',), # index=1456
- ('Seolleongtang',), # index=1457
- ('Go\xc5\x82\xc4\x85bki',), # index=1458
- ('Szaloncukor',), # index=1459
- ('Kalduny',), # index=1460
- ('Zrazy',), # index=1461
- ('Panettone',), # index=1462
- ('Ambelopoulia',), # index=1463
- ('Persimmon pudding',), # index=1464
- ('Floating island',), # index=1465
- ('Zeeuwse bolus',), # index=1466
- ('Ambuyat',), # index=1467
- ('Smulpaj',), # index=1468
- ('Moravian spice cookies',), # index=1469
- ('Mee pok',), # index=1470
- ('Jjigae',), # index=1471
- ('Pizza bagel',), # index=1472
- ('Tteok',), # index=1473
- ('Br\xc3\xa6ndende k\xc3\xa6rlighed',), # index=1474
- ('Beaten biscuit',), # index=1475
- ('\xc3\x86blefl\xc3\xa6sk',), # index=1476
- ('Chicken paprikash',), # index=1477
- ('Tangyuan',), # index=1478
- ('Tuna pot',), # index=1479
- ('Burnt ends',), # index=1480
- ('Jam\xc3\xb3n ib\xc3\xa9rico',), # index=1481
- ('Rakfisk',), # index=1482
- ('Zarangollo',), # index=1483
- ('T\xc3\xbar\xc3\xb3 Rudi',), # index=1484
- ('Flummery',), # index=1485
- ('Cecina',), # index=1486
- ('Galinha \xc3\xa0 portuguesa',), # index=1487
- ('Ankimo',), # index=1488
- ('Galinha \xc3\xa0 africana',), # index=1489
- ('Cha siu bao',), # index=1490
- ('Fugu chiri',), # index=1491
- ('Assidat Zgougou',), # index=1492
- ('Oxtail stew',), # index=1493
- ('Laping',), # index=1494
- ('Chaku',), # index=1495
- ('Caldillo de perro',), # index=1496
- ('Sopa de Gato',), # index=1497
- ('Keledo\xc5\x9f',), # index=1498
- ('M\xc3\xbccver',), # index=1499
- ('Brotzeit',), # index=1500
- ('Shekerbura',), # index=1501
- ('Oeufs en meurette',), # index=1502
- ('Pappa al pomodoro',), # index=1503
- ('Teurgoule',), # index=1504
- ('B\xc3\xa1nh x\xc3\xa8o',), # index=1505
- ('Musakhan',), # index=1506
- ('Maqluba',), # index=1507
- ('Bob chorba',), # index=1508
- ('Rum baba',), # index=1509
- ('Veda bread',), # index=1510
- ('Fried prawn',), # index=1511
- ('Pastilla',), # index=1512
- ('Strawberry Delight',), # index=1513
- ('Cheese dream',), # index=1514
- ('Frejon',), # index=1515
- ('Gyeran-jjim',), # index=1516
- ('Revithia',), # index=1517
- ('Nasi bogana',), # index=1518
- ('Torta de gazpacho',), # index=1519
- ('Double Down',), # index=1520
- ('Seri Muka',), # index=1521
- ('Obi non',), # index=1522
- ('Garganelli',), # index=1523
- ('Kig ha farz',), # index=1524
- ('Mississippi mud pie',), # index=1525
- ("Eve's pudding",), # index=1526
- ('Amala',), # index=1527
- ('Okinawa soba',), # index=1528
- ('Lamian',), # index=1529
- ('Soki',), # index=1530
- ('Chicken Maryland',), # index=1531
- ('Chanpur\xc5\xab',), # index=1532
- ('Mlinci',), # index=1533
- ('Smyrna meatballs',), # index=1534
- ('Tavern sandwich',), # index=1535
- ('Yangzhou fried rice',), # index=1536
- ('Qutab',), # index=1537
- ('Dum Aloo',), # index=1538
- ('Queijo do Pico',), # index=1539
- ('Cocadas',), # index=1540
- ("Calf's liver and bacon",), # index=1541
- ('Moules-frites',), # index=1542
- ('Anarsa',), # index=1543
- ('Tlayuda',), # index=1544
- ('\xc5\xa0akotis',), # index=1545
- ('Jollof rice',), # index=1546
- ('Moin moin',), # index=1547
- ('Jam roly-poly',), # index=1548
- ('Hochzeitssuppe',), # index=1549
- ('Mucenici',), # index=1550
- ('Ema datshi',), # index=1551
- ('Ngo hiang',), # index=1552
- ('Jello salad',), # index=1553
- ('Claypot chicken rice',), # index=1554
- ('Maeun-tang',), # index=1555
- ('Cifantuan',), # index=1556
- ('Rhubarb pie',), # index=1557
- ('Olla podrida',), # index=1558
- ('Har gow',), # index=1559
- ('Sayur lodeh',), # index=1560
- ('Memela',), # index=1561
- ('Wenchang chicken',), # index=1562
- ('Galinhada',), # index=1563
- ('Lecs\xc3\xb3',), # index=1564
- ('Gypsy tart',), # index=1565
- ('Bougatsa',), # index=1566
- ('Germkn\xc3\xb6del',), # index=1567
- ('Haystack',), # index=1568
- ('Yule log',), # index=1569
- ('Butter cookie',), # index=1570
- ('Chicken \xc3\xa0 la King',), # index=1571
- ('M\xc3\xa9choui',), # index=1572
- ('Croquette',), # index=1573
- ('Shami kebab',), # index=1574
- ('Chicken and waffles',), # index=1575
- ('Poke',), # index=1576
- ('Punsch-roll',), # index=1577
- ('Turtle soup',), # index=1578
- ('Kansar',), # index=1579
- ('Glamorgan sausage',), # index=1580
- ('Mango pudding',), # index=1581
- ('B\xc3\xa1nh canh',), # index=1582
- ('Caparrones',), # index=1583
- ('Zopf',), # index=1584
- ('Bath bun',), # index=1585
- ('Chelsea bun',), # index=1586
- ('London bun',), # index=1587
- ('Saffron bun',), # index=1588
- ('Chakhchoukha',), # index=1589
- ('Angel food cake',), # index=1590
- ('Lalab',), # index=1591
- ('Suckling pig',), # index=1592
- ('Barmbrack',), # index=1593
- ('Kotlet schabowy',), # index=1594
- ('Pastel de nata',), # index=1595
- ('Shave ice',), # index=1596
- ('Tipsy cake',), # index=1597
- ('Creamed eggs on toast',), # index=1598
- ('Kerak telor',), # index=1599
- ('Ogok-bap',), # index=1600
- ('Mortadella',), # index=1601
- ('Nut roll',), # index=1602
- ('Fried green tomatoes',), # index=1603
- ('Beondegi',), # index=1604
- ('Tsoureki',), # index=1605
- ('Tiropita',), # index=1606
- ('Pljeskavica',), # index=1607
- ('Kara\xc4\x91or\xc4\x91eva \xc5\xa1nicla',), # index=1608
- ('Kokoretsi',), # index=1609
- ('Skilpadjies',), # index=1610
- ('Corn chowder',), # index=1611
- ('Tarhana',), # index=1612
- ('Tufahije',), # index=1613
- ('Birria',), # index=1614
- ('Veal Orloff',), # index=1615
- ('Fattoush',), # index=1616
- ('Pane carasau',), # index=1617
- ('Rab cake',), # index=1618
- ('Buffalo burger',), # index=1619
- ('Treacle tart',), # index=1620
- ('Hamburger',), # index=1621
- ('Stamppot',), # index=1622
- ('Kopytka',), # index=1623
- ('Khai yat sai',), # index=1624
- ('Minchee',), # index=1625
- ('Kinema',), # index=1626
- ('Sgabeo',), # index=1627
- ('Chili dog',), # index=1628
- ('Spaghetti alle vongole',), # index=1629
- ('Bavarian cream',), # index=1630
- ('Bhaji',), # index=1631
- ('Kachori',), # index=1632
- ('Chowder',), # index=1633
- ('Scotch broth',), # index=1634
- ('Pea soup',), # index=1635
- ('Kitfo',), # index=1636
- ('Gored gored',), # index=1637
- ('B\xc3\xa1nh ch\xc6\xb0ng',), # index=1638
- ('B\xc3\xban b\xc3\xb2 Hu\xe1\xba\xbf',), # index=1639
- ('B\xc3\xb2 7 m\xc3\xb3n',), # index=1640
- ('C\xc6\xa1m t\xe1\xba\xa5m',), # index=1641
- ('Ambrosia',), # index=1642
- ('R\xc3\xb6ntt\xc3\xb6nen',), # index=1643
- ('Balch\xc3\xa3o',), # index=1644
- ('Gibassier',), # index=1645
- ('Bacalhau \xc3\xa0 Z\xc3\xa9 do Pipo',), # index=1646
- ('Pane di Altamura',), # index=1647
- ('Mykyrokka',), # index=1648
- ('Paska',), # index=1649
- ('Blackberry pie',), # index=1650
- ('Mince pie',), # index=1651
- ('Corn cookie',), # index=1652
- ('Francesinha poveira',), # index=1653
- ('Picadillo',), # index=1654
- ('Runeberg torte',), # index=1655
- ('Khakhra',), # index=1656
- ('Ohn no khao sw\xc3\xa8',), # index=1657
- ('Sultsina',), # index=1658
- ('Kabab torsh',), # index=1659
- ('Paella',), # index=1660
- ('Espetada',), # index=1661
- ('Pathiri',), # index=1662
- ('Horumonyaki',), # index=1663
- ('Khubz',), # index=1664
- ('Ciorb\xc4\x83',), # index=1665
- ('Kimchi-buchimgae',), # index=1666
- ('Sesame chicken',), # index=1667
- ('Thukpa',), # index=1668
- ('Chwinamul',), # index=1669
- ('Kabuni',), # index=1670
- ('Jhunka',), # index=1671
- ('Jolada rotti',), # index=1672
- ('Spoonbread',), # index=1673
- ('Kulich',), # index=1674
- ('Phat khing',), # index=1675
- ('Namasu',), # index=1676
- ('Wonton noodles',), # index=1677
- ('Johnnycake',), # index=1678
- ('Panellets',), # index=1679
- ('Manj\xc5\xab',), # index=1680
- ('Mandi',), # index=1681
- ('Fortune cookie',), # index=1682
- ('Noppe',), # index=1683
- ('Slavink',), # index=1684
- ('Cockle bread',), # index=1685
- ('Caruru',), # index=1686
- ('Ch\xe1\xba\xa3 l\xe1\xbb\xa5a',), # index=1687
- ('Pan bagnat',), # index=1688
- ('Sardenara',), # index=1689
- ('Enchilada',), # index=1690
- ('Sausage sandwich',), # index=1691
- ('Pistachio pudding',), # index=1692
- ('Chikki',), # index=1693
- ('Champorado',), # index=1694
- ('Coconut cake',), # index=1695
- ('Kaassouffl\xc3\xa9',), # index=1696
- ('Carne pizzaiola',), # index=1697
- ('Khauk sw\xc3\xa8 thoke',), # index=1698
- ('Gamja-tang',), # index=1699
- ('Kadhi',), # index=1700
- ('Green bean casserole',), # index=1701
- ('Apple dumpling',), # index=1702
- ('Tsoureki',), # index=1703
- ('Pissaladi\xc3\xa8re',), # index=1704
- ('Phat si-io',), # index=1705
- ('Drunken noodles',), # index=1706
- ('Jing Jiang Rou Si',), # index=1707
- ('Enduri Pitha',), # index=1708
- ('Kakara pitha',), # index=1709
- ('Tarta de Santiago',), # index=1710
- ('Spoon sweets',), # index=1711
- ('Sheftalia',), # index=1712
- ('Soybean sprout',), # index=1713
- ('Italian hot dog',), # index=1714
- ('Makchang',), # index=1715
- ('Meeshay',), # index=1716
- ('Bacalhau com natas',), # index=1717
- ('Mazurek',), # index=1718
- ('Nan gyi thohk',), # index=1719
- ('Ajapsandali',), # index=1720
- ('Carac',), # index=1721
- ('Mont di',), # index=1722
- ('Geng',), # index=1723
- ('Vispipuuro',), # index=1724
- ('Bakso',), # index=1725
- ('Canjica',), # index=1726
- ('Fougasse',), # index=1727
- ("Fool's Gold Loaf",), # index=1728
- ('Blueberry pie',), # index=1729
- ('Cucumber Salad',), # index=1730
- ('Ogbono soup',), # index=1731
- ('Champ',), # index=1732
- ('Oysters en brochette',), # index=1733
- ('Paskha',), # index=1734
- ('Shish taouk',), # index=1735
- ('Acaraj\xc3\xa9',), # index=1736
- ('Ras malai',), # index=1737
- ('San-nakji',), # index=1738
- ('Bungeo-ppang',), # index=1739
- ('Skilandis',), # index=1740
- ('Gosh-e Fil',), # index=1741
- ('Nasi dagang',), # index=1742
- ('Gheimeh',), # index=1743
- ('Fesenj\xc4\x81n',), # index=1744
- ('Bacalhau \xc3\xa0 Gomes de S\xc3\xa1',), # index=1745
- ('F\xc3\xa5rik\xc3\xa5l',), # index=1746
- ('Bedfordshire clanger',), # index=1747
- ('Tonkatsu',), # index=1748
- ('Thai fried rice',), # index=1749
- ('Manakish',), # index=1750
- ('Schweinshaxe',), # index=1751
- ('Chorba',), # index=1752
- ('Oliebol',), # index=1753
- ('Ropa vieja',), # index=1754
- ('Natchitoches meat pie',), # index=1755
- ('Icebox cake',), # index=1756
- ('Sorrel soup',), # index=1757
- ('Lahoh',), # index=1758
- ('Bolillo',), # index=1759
- ('Mollete',), # index=1760
- ('Caldeirada',), # index=1761
- ('Ogi',), # index=1762
- ('Watergate salad',), # index=1763
- ('Yaksik',), # index=1764
- ('Half-smoke',), # index=1765
- ('Dakos',), # index=1766
- ('Sweet potato pie',), # index=1767
- ('Cappon magro',), # index=1768
- ('Serundeng',), # index=1769
- ('Rijstevlaai',), # index=1770
- ('Ajoblanco',), # index=1771
- ('Yaka mein',), # index=1772
- ('Jujeh kabab',), # index=1773
- ('Soy egg',), # index=1774
- ('Shuizhu',), # index=1775
- ('Puliyogare',), # index=1776
- ('Sago',), # index=1777
- ('Laulau',), # index=1778
- ('Curtido',), # index=1779
- ('Tapai',), # index=1780
- ('Press cake',), # index=1781
- ('Cuchifritos',), # index=1782
- ('Vlaai',), # index=1783
- ('Malvern pudding',), # index=1784
- ('Baklava',), # index=1785
- ('Cheese dog',), # index=1786
- ('Luchi',), # index=1787
- ('Cowboy beans',), # index=1788
- ('Sandesh',), # index=1789
- ('Steak Diane',), # index=1790
- ('Lobster stew',), # index=1791
- ('Finikia',), # index=1792
- ('Bibingka',), # index=1793
- ('Tafelspitz',), # index=1794
- ('Ploye',), # index=1795
- ('Sayur asem',), # index=1796
- ('Trinxat',), # index=1797
- ('Nikuman',), # index=1798
- ('Cozido \xc3\xa0 portuguesa',), # index=1799
- ('Bacalhau \xc3\xa0 Br\xc3\xa1s',), # index=1800
- ('Tomato compote',), # index=1801
- ('Sesame seed candy',), # index=1802
- ('Dhebra',), # index=1803
- ('Kaeng pa',), # index=1804
- ('Mas riha',), # index=1805
- ('Zosui',), # index=1806
- ('Yassa',), # index=1807
- ('Pambazo',), # index=1808
- ('Imarti',), # index=1809
- ('Bacalhau com todos',), # index=1810
- ('Black pepper crab',), # index=1811
- ('Queso flameado',), # index=1812
- ('Black and white cookie',), # index=1813
- ('Red braised pork belly',), # index=1814
- ('Krofne',), # index=1815
- ('U\xc5\xa1tipci',), # index=1816
- ('Ro\xc5\xbeata',), # index=1817
- ('Punjena paprika',), # index=1818
- ('Fusi',), # index=1819
- ('Mane\xc5\xa1tra',), # index=1820
- ('Kro\xc5\xa1tule',), # index=1821
- ('Fritule',), # index=1822
- ('Protein bar',), # index=1823
- ('Cordon bleu',), # index=1824
- ('Pirog',), # index=1825
- ('Pachi Pulusu',), # index=1826
- ('Frig\xc4\x83rui',), # index=1827
- ('Chhena poda',), # index=1828
- ('Poornalu',), # index=1829
- ('Ponganalu',), # index=1830
- ('Bing',), # index=1831
- ('Flaouna',), # index=1832
- ('Chakodi',), # index=1833
- ('Aloo paratha',), # index=1834
- ('Konro',), # index=1835
- ('Cemita',), # index=1836
- ('Asinan',), # index=1837
- ('Broa',), # index=1838
- ('Trifle',), # index=1839
- ('Rat na',), # index=1840
- ('Borlengo',), # index=1841
- ('Gazpachuelo',), # index=1842
- ('Esterh\xc3\xa1zy torte',), # index=1843
- ('Magenbrot',), # index=1844
- ('Detroit-style pizza',), # index=1845
- ('Fuling jiabing',), # index=1846
- ('Lakhamari',), # index=1847
- ('Mu\xc4\x87kalica',), # index=1848
- ('Sukhdi',), # index=1849
- ('Kilishi',), # index=1850
- ('Baji',), # index=1851
- ('Peanut butter cookie',), # index=1852
- ('Rabbit pie',), # index=1853
- ("Paling in 't groen",), # index=1854
- ('Chataamari',), # index=1855
- ('Lawar',), # index=1856
- ('Arisa Pitha',), # index=1857
- ('Empal gentong',), # index=1858
- ('Carne asada fries',), # index=1859
- ('Takikomi gohan',), # index=1860
- ('Kamameshi',), # index=1861
- ('Pasta salad',), # index=1862
- ('Fasole cu c\xc3\xa2rna\xc8\x9bi',), # index=1863
- ('Zelnik',), # index=1864
- ('Pl\xc4\x83cint\xc4\x83',), # index=1865
- ('Tongseng',), # index=1866
- ('Soto mie',), # index=1867
- ('Sarburma',), # index=1868
- ('Lutefisk',), # index=1869
- ('Khichdi',), # index=1870
- ('Briouat',), # index=1871
- ('Chili burger',), # index=1872
- ('Bolo de mel',), # index=1873
- ('Clootie',), # index=1874
- ('Seswaa',), # index=1875
- ('Tahu sumedang',), # index=1876
- ('Pichelsteiner',), # index=1877
- ('Bread soup',), # index=1878
- ('Scotcheroos',), # index=1879
- ('Kartoffelk\xc3\xa4se',), # index=1880
- ('Schuxen',), # index=1881
- ('Caramel',), # index=1882
- ('Zwetschgenkuchen',), # index=1883
- ('Alloco',), # index=1884
- ('Vangibath',), # index=1885
- ('Torricado',), # index=1886
- ('Phat phrik khing',), # index=1887
- ('Tomato and egg soup',), # index=1888
- ('Dushbara',), # index=1889
- ('Spanakorizo',), # index=1890
- ('Ostropel',), # index=1891
- ('Tamale',), # index=1892
- ('Seattle-style hot dog',), # index=1893
- ('Ammonia cookie',), # index=1894
- ('Boston baked beans',), # index=1895
- ('Amandine',), # index=1896
- ('Duck blood and vermicelli soup',), # index=1897
- ('Azerbaijani pakhlava',), # index=1898
- ('Bakwan',), # index=1899
- ('Wallenbergare',), # index=1900
- ('Pastry',), # index=1901
- ('Melomakarono',), # index=1902
- ('Cocido lebaniego',), # index=1903
- ('Koi',), # index=1904
- ('Stir-fried tomato and scrambled eggs',), # index=1905
- ('Fl\xc3\xa6skesteg',), # index=1906
- ("Beggar's Chicken",), # index=1907
- ('Lymonnyk',), # index=1908
- ('Konkonte',), # index=1909
- ('Stuffed zucchini',), # index=1910
- ('Kaeng som',), # index=1911
- ('Kentucky jam cake',), # index=1912
- ('Mur\xc4\x83turi',), # index=1913
- ('Tochitur\xc4\x83',), # index=1914
- ('Urap',), # index=1915
- ('Cornule\xc8\x9be',), # index=1916
- ('Quad City-style pizza',), # index=1917
- ('Paneer tikka',), # index=1918
- ('Ciorb\xc4\x83 de peri\xc8\x99oare',), # index=1919
- ('Semolina porridge',), # index=1920
- ('Shaker Lemon Pie',), # index=1921
- ('Doodhpak',), # index=1922
- ('Ceviche',), # index=1923
- ('Cabbage soup',), # index=1924
- ('Nasi timbel',), # index=1925
- ('Pa amb tom\xc3\xa0quet',), # index=1926
- ('Escalivada',), # index=1927
- ('Me\xc4\x91imurska gibanica',), # index=1928
- ('Khanom chan',), # index=1929
- ('Ohaw',), # index=1930
- ('Baghrir',), # index=1931
- ('Hummingbird cake',), # index=1932
- ('Neapolitan pizza',), # index=1933
- ('Doughnut',), # index=1934
- ('Hummus',), # index=1935
- ('Nimono',), # index=1936
- ('Chocolate chip cookie',), # index=1937
- ('B\xc3\xban \xe1\xbb\x91c',), # index=1938
- ('Cheese straw',), # index=1939
- ('Sausage',), # index=1940
- ('Frogeye salad',), # index=1941
- ('Senate bean soup',), # index=1942
- ('Botifarra',), # index=1943
- ('Leberkn\xc3\xb6del',), # index=1944
- ('Laziji',), # index=1945
- ('Quzi',), # index=1946
- ('Chazuke',), # index=1947
- ('Sandwich',), # index=1948
- ('BLT',), # index=1949
- ('Chikhirtma',), # index=1950
- ('Pico de gallo',), # index=1951
- ('Oden',), # index=1952
- ('Tostada',), # index=1953
- ('Chilaquiles',), # index=1954
- ('Cocido monta\xc3\xb1\xc3\xa9s',), # index=1955
- ('Lontong Cap Go Meh',), # index=1956
- ('Porra antequerana',), # index=1957
- ('Kedjenou',), # index=1958
- ('Tourin',), # index=1959
- ('Atti\xc3\xa9k\xc3\xa9',), # index=1960
- ('Dak-bokkeum-tang',), # index=1961
- ('\xc5\xbdemlovka',), # index=1962
- ('Dovga',), # index=1963
- ('Rice and gravy',), # index=1964
- ('Sai ua',), # index=1965
- ('Nam ngiao',), # index=1966
- ('Kaeng khae',), # index=1967
- ('Kaeng tai pla',), # index=1968
- ('Dim sum',), # index=1969
- ('Tahri',), # index=1970
- ('Bolo do caco',), # index=1971
- ('Buffalo wing',), # index=1972
- ('Pustakari',), # index=1973
- ('Pieds paquets',), # index=1974
- ('Tinginys',), # index=1975
- ('Sunnundallu',), # index=1976
- ('Lapskaus',), # index=1977
- ('Caldo tlalpe\xc3\xb1o',), # index=1978
- ('Milho frito',), # index=1979
- ('Kalu dodol',), # index=1980
- ('Poppyseed muffin',), # index=1981
- ('Peanut soup',), # index=1982
- ('Tarte \xc3\xa0 la Bouillie',), # index=1983
- ('Caldo gallego',), # index=1984
- ('Samay Baji',), # index=1985
- ('Limburger sandwich',), # index=1986
- ('Huachinango a la Veracruzana',), # index=1987
- ('Sambal stingray',), # index=1988
- ('Kuluban',), # index=1989
- ('Modjeska',), # index=1990
- ('Pan dulce',), # index=1991
- ('Florina pepper',), # index=1992
- ('Oysters Bienville',), # index=1993
- ('Cronut',), # index=1994
- ('Duck rice',), # index=1995
- ('Sulu k\xc3\xb6fte',), # index=1996
- ('Toyga soup',), # index=1997
- ('Majjige huli',), # index=1998
- ('Ikan goreng',), # index=1999
- ('Lekor',), # index=2000
- ('Ciulama',), # index=2001
- ('Ayam bakar',), # index=2002
- ('Hinava',), # index=2003
- ('Waakye',), # index=2004
- ('Salbute',), # index=2005
- ('Kuchmachi',), # index=2006
- ('Kibinai',), # index=2007
- ('Lobiani',), # index=2008
- ('Chanakhi',), # index=2009
- ('Baghala ghatogh',), # index=2010
- ('Pkhali',), # index=2011
- ('Poc Chuc',), # index=2012
- ('Bionico',), # index=2013
- ('Bamischijf',), # index=2014
- ('Racuchy',), # index=2015
- ('Kuurdak',), # index=2016
- ('Hokkien fried rice',), # index=2017
- ('Mu kratha',), # index=2018
- ('Thong yip',), # index=2019
- ('Zuppa toscana',), # index=2020
- ('Dhindo',), # index=2021
- ('Thiakry',), # index=2022
- ('Kondowole',), # index=2023
-)
diff --git a/src/aiy/vision/models/face_detection.py b/src/aiy/vision/models/face_detection.py
deleted file mode 100644
index 078cdeab..00000000
--- a/src/aiy/vision/models/face_detection.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""API for Face Detection."""
-
-from __future__ import division
-
-from aiy.vision.inference import ModelDescriptor
-from aiy.vision.models import utils
-
-_COMPUTE_GRAPH_NAME = 'face_detection.binaryproto'
-
-
-def _reshape(array, width):
- assert len(array) % width == 0
- height = len(array) // width
- return [array[i * width:(i + 1) * width] for i in range(height)]
-
-
-class Face(object):
- """Face detection result."""
-
- def __init__(self, bounding_box, face_score, joy_score):
- """Creates a new Face instance.
-
- Args:
- bounding_box: (x, y, width, height).
- face_score: float, face confidence score.
- joy_score: float, face joy score.
- """
- self.bounding_box = bounding_box
- self.face_score = face_score
- self.joy_score = joy_score
-
- def __str__(self):
- return 'face_score=%f, joy_score=%f, bbox=%s' % (self.face_score,
- self.joy_score,
- str(self.bounding_box))
-
-
-def model():
- # Face detection model has special implementation in VisionBonnet firmware.
- # input_shape, input_normalizer, and computate_graph params have on effect.
- return ModelDescriptor(
- name='FaceDetection',
- input_shape=(1, 0, 0, 3),
- input_normalizer=(0, 0),
- compute_graph=utils.load_compute_graph(_COMPUTE_GRAPH_NAME))
-
-
-def get_faces(result):
- """Retunrs list of Face objects decoded from the inference result."""
- assert len(result.tensors) == 3
- # TODO(dkovalev): check tensor shapes
- bboxes = _reshape(result.tensors['bounding_boxes'].data, 4)
- face_scores = result.tensors['face_scores'].data
- joy_scores = result.tensors['joy_scores'].data
- assert len(bboxes) == len(joy_scores)
- assert len(bboxes) == len(face_scores)
- return [
- Face(tuple(bbox), face_score, joy_score)
- for bbox, face_score, joy_score in zip(bboxes, face_scores, joy_scores)
- ]
diff --git a/src/aiy/vision/models/image_classification.py b/src/aiy/vision/models/image_classification.py
deleted file mode 100644
index 20bd89dd..00000000
--- a/src/aiy/vision/models/image_classification.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""API for Image Classification tasks."""
-
-from aiy.vision.inference import ModelDescriptor
-from aiy.vision.models import utils
-from aiy.vision.models.image_classification_classes import CLASSES
-
-# There are two models in our repository that can do image classification. One
-# based on MobileNet model structure, the other based on SqueezeNet model
-# structure.
-#
-# MobileNet based model has 59.9% top-1 accuracy on ImageNet.
-# SqueezeNet based model has 45.3% top-1 accuracy on ImageNet.
-MOBILENET = 'image_classification_mobilenet'
-SQUEEZENET = 'image_classification_squeezenet'
-_COMPUTE_GRAPH_NAME_MAP = {
- MOBILENET: 'mobilenet_v1_160res_0.5_imagenet.binaryproto',
- SQUEEZENET: 'squeezenet_160res_5x5_0.75.binaryproto',
-}
-_OUTPUT_TENSOR_NAME_MAP = {
- MOBILENET: 'MobilenetV1/Predictions/Softmax',
- SQUEEZENET: 'Prediction',
-}
-
-
-def model(model_type=MOBILENET):
- return ModelDescriptor(
- name=model_type,
- input_shape=(1, 160, 160, 3),
- input_normalizer=(128.0, 128.0),
- compute_graph=utils.load_compute_graph(
- _COMPUTE_GRAPH_NAME_MAP[model_type]))
-
-
-def get_classes(result, max_num_objects=None, object_prob_threshold=0.0):
- """Converts image classification model output to list of detected objects.
-
- Args:
- result: output tensor from image classification model.
- max_num_objects: int; max number of objects to return.
- object_prob_threshold: float; min probability of each returned object.
-
- Returns:
- A list of (class_name: string, probability: float) pairs ordered by
- probability from highest to lowest. The number of pairs is not greater than
- max_num_objects. Each probability is greater than object_prob_threshold. For
- example:
-
- [('Egyptian cat', 0.767578)
- ('tiger cat, 0.163574)
- ('lynx/catamount', 0.039795)]
- """
- assert len(result.tensors) == 1
- tensor_name = _OUTPUT_TENSOR_NAME_MAP[result.model_name]
- tensor = result.tensors[tensor_name]
- probs, shape = tensor.data, tensor.shape
- assert (shape.batch, shape.height, shape.width, shape.depth) == (1, 1, 1,
- 1001)
-
- pairs = [pair for pair in enumerate(probs) if pair[1] > object_prob_threshold]
- pairs = sorted(pairs, key=lambda pair: pair[1], reverse=True)
- pairs = pairs[0:max_num_objects]
- return [('/'.join(CLASSES[index]), prob) for index, prob in pairs]
diff --git a/src/aiy/vision/models/image_classification_classes.py b/src/aiy/vision/models/image_classification_classes.py
deleted file mode 100644
index c3bddce8..00000000
--- a/src/aiy/vision/models/image_classification_classes.py
+++ /dev/null
@@ -1,1076 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Predefined image classes for image classification model."""
-
-CLASSES = (
- ('background',), # index=0
- ('tench', 'Tinca tinca'), # index=1
- ('goldfish', 'Carassius auratus'), # index=2
- ('great white shark', 'white shark', 'man-eater', 'man-eating shark',
- 'Carcharodon carcharias'), # index=3
- ('tiger shark', 'Galeocerdo cuvieri'), # index=4
- ('hammerhead', 'hammerhead shark'), # index=5
- ('electric ray', 'crampfish', 'numbfish', 'torpedo'), # index=6
- ('stingray',), # index=7
- ('cock',), # index=8
- ('hen',), # index=9
- ('ostrich', 'Struthio camelus'), # index=10
- ('brambling', 'Fringilla montifringilla'), # index=11
- ('goldfinch', 'Carduelis carduelis'), # index=12
- ('house finch', 'linnet', 'Carpodacus mexicanus'), # index=13
- ('junco', 'snowbird'), # index=14
- ('indigo bunting', 'indigo finch', 'indigo bird',
- 'Passerina cyanea'), # index=15
- ('robin', 'American robin', 'Turdus migratorius'), # index=16
- ('bulbul',), # index=17
- ('jay',), # index=18
- ('magpie',), # index=19
- ('chickadee',), # index=20
- ('water ouzel', 'dipper'), # index=21
- ('kite',), # index=22
- ('bald eagle', 'American eagle', 'Haliaeetus leucocephalus'), # index=23
- ('vulture',), # index=24
- ('great grey owl', 'great gray owl', 'Strix nebulosa'), # index=25
- ('European fire salamander', 'Salamandra salamandra'), # index=26
- ('common newt', 'Triturus vulgaris'), # index=27
- ('eft',), # index=28
- ('spotted salamander', 'Ambystoma maculatum'), # index=29
- ('axolotl', 'mud puppy', 'Ambystoma mexicanum'), # index=30
- ('bullfrog', 'Rana catesbeiana'), # index=31
- ('tree frog', 'tree-frog'), # index=32
- ('tailed frog', 'bell toad', 'ribbed toad', 'tailed toad',
- 'Ascaphus trui'), # index=33
- ('loggerhead', 'loggerhead turtle', 'Caretta caretta'), # index=34
- ('leatherback turtle', 'leatherback', 'leathery turtle',
- 'Dermochelys coriacea'), # index=35
- ('mud turtle',), # index=36
- ('terrapin',), # index=37
- ('box turtle', 'box tortoise'), # index=38
- ('banded gecko',), # index=39
- ('common iguana', 'iguana', 'Iguana iguana'), # index=40
- ('American chameleon', 'anole', 'Anolis carolinensis'), # index=41
- ('whiptail', 'whiptail lizard'), # index=42
- ('agama',), # index=43
- ('frilled lizard', 'Chlamydosaurus kingi'), # index=44
- ('alligator lizard',), # index=45
- ('Gila monster', 'Heloderma suspectum'), # index=46
- ('green lizard', 'Lacerta viridis'), # index=47
- ('African chameleon', 'Chamaeleo chamaeleon'), # index=48
- ('Komodo dragon', 'Komodo lizard', 'dragon lizard', 'giant lizard',
- 'Varanus komodoensis'), # index=49
- ('African crocodile', 'Nile crocodile', 'Crocodylus niloticus'), # index=50
- ('American alligator', 'Alligator mississipiensis'), # index=51
- ('triceratops',), # index=52
- ('thunder snake', 'worm snake', 'Carphophis amoenus'), # index=53
- ('ringneck snake', 'ring-necked snake', 'ring snake'), # index=54
- ('hognose snake', 'puff adder', 'sand viper'), # index=55
- ('green snake', 'grass snake'), # index=56
- ('king snake', 'kingsnake'), # index=57
- ('garter snake', 'grass snake'), # index=58
- ('water snake',), # index=59
- ('vine snake',), # index=60
- ('night snake', 'Hypsiglena torquata'), # index=61
- ('boa constrictor', 'Constrictor constrictor'), # index=62
- ('rock python', 'rock snake', 'Python sebae'), # index=63
- ('Indian cobra', 'Naja naja'), # index=64
- ('green mamba',), # index=65
- ('sea snake',), # index=66
- ('horned viper', 'cerastes', 'sand viper', 'horned asp',
- 'Cerastes cornutus'), # index=67
- ('diamondback', 'diamondback rattlesnake',
- 'Crotalus adamanteus'), # index=68
- ('sidewinder', 'horned rattlesnake', 'Crotalus cerastes'), # index=69
- ('trilobite',), # index=70
- ('harvestman', 'daddy longlegs', 'Phalangium opilio'), # index=71
- ('scorpion',), # index=72
- ('black and gold garden spider', 'Argiope aurantia'), # index=73
- ('barn spider', 'Araneus cavaticus'), # index=74
- ('garden spider', 'Aranea diademata'), # index=75
- ('black widow', 'Latrodectus mactans'), # index=76
- ('tarantula',), # index=77
- ('wolf spider', 'hunting spider'), # index=78
- ('tick',), # index=79
- ('centipede',), # index=80
- ('black grouse',), # index=81
- ('ptarmigan',), # index=82
- ('ruffed grouse', 'partridge', 'Bonasa umbellus'), # index=83
- ('prairie chicken', 'prairie grouse', 'prairie fowl'), # index=84
- ('peacock',), # index=85
- ('quail',), # index=86
- ('partridge',), # index=87
- ('African grey', 'African gray', 'Psittacus erithacus'), # index=88
- ('macaw',), # index=89
- ('sulphur-crested cockatoo', 'Kakatoe galerita',
- 'Cacatua galerita'), # index=90
- ('lorikeet',), # index=91
- ('coucal',), # index=92
- ('bee eater',), # index=93
- ('hornbill',), # index=94
- ('hummingbird',), # index=95
- ('jacamar',), # index=96
- ('toucan',), # index=97
- ('drake',), # index=98
- ('red-breasted merganser', 'Mergus serrator'), # index=99
- ('goose',), # index=100
- ('black swan', 'Cygnus atratus'), # index=101
- ('tusker',), # index=102
- ('echidna', 'spiny anteater', 'anteater'), # index=103
- ('platypus', 'duckbill', 'duckbilled platypus', 'duck-billed platypus',
- 'Ornithorhynchus anatinus'), # index=104
- ('wallaby', 'brush kangaroo'), # index=105
- ('koala', 'koala bear', 'kangaroo bear', 'native bear',
- 'Phascolarctos cinereus'), # index=106
- ('wombat',), # index=107
- ('jellyfish',), # index=108
- ('sea anemone', 'anemone'), # index=109
- ('brain coral',), # index=110
- ('flatworm', 'platyhelminth'), # index=111
- ('nematode', 'nematode worm', 'roundworm'), # index=112
- ('conch',), # index=113
- ('snail',), # index=114
- ('slug',), # index=115
- ('sea slug', 'nudibranch'), # index=116
- ('chiton', 'coat-of-mail shell', 'sea cradle',
- 'polyplacophore'), # index=117
- ('chambered nautilus', 'pearly nautilus', 'nautilus'), # index=118
- ('Dungeness crab', 'Cancer magister'), # index=119
- ('rock crab', 'Cancer irroratus'), # index=120
- ('fiddler crab',), # index=121
- ('king crab', 'Alaska crab', 'Alaskan king crab', 'Alaska king crab',
- 'Paralithodes camtschatica'), # index=122
- ('American lobster', 'Northern lobster', 'Maine lobster',
- 'Homarus americanus'), # index=123
- ('spiny lobster', 'langouste', 'rock lobster', 'crawfish', 'crayfish',
- 'sea crawfish'), # index=124
- ('crayfish', 'crawfish', 'crawdad', 'crawdaddy'), # index=125
- ('hermit crab',), # index=126
- ('isopod',), # index=127
- ('white stork', 'Ciconia ciconia'), # index=128
- ('black stork', 'Ciconia nigra'), # index=129
- ('spoonbill',), # index=130
- ('flamingo',), # index=131
- ('little blue heron', 'Egretta caerulea'), # index=132
- ('American egret', 'great white heron', 'Egretta albus'), # index=133
- ('bittern',), # index=134
- ('crane',), # index=135
- ('limpkin', 'Aramus pictus'), # index=136
- ('European gallinule', 'Porphyrio porphyrio'), # index=137
- ('American coot', 'marsh hen', 'mud hen', 'water hen',
- 'Fulica americana'), # index=138
- ('bustard',), # index=139
- ('ruddy turnstone', 'Arenaria interpres'), # index=140
- ('red-backed sandpiper', 'dunlin', 'Erolia alpina'), # index=141
- ('redshank', 'Tringa totanus'), # index=142
- ('dowitcher',), # index=143
- ('oystercatcher', 'oyster catcher'), # index=144
- ('pelican',), # index=145
- ('king penguin', 'Aptenodytes patagonica'), # index=146
- ('albatross', 'mollymawk'), # index=147
- ('grey whale', 'gray whale', 'devilfish', 'Eschrichtius gibbosus',
- 'Eschrichtius robustus'), # index=148
- ('killer whale', 'killer', 'orca', 'grampus', 'sea wolf',
- 'Orcinus orca'), # index=149
- ('dugong', 'Dugong dugon'), # index=150
- ('sea lion',), # index=151
- ('Chihuahua',), # index=152
- ('Japanese spaniel',), # index=153
- ('Maltese dog', 'Maltese terrier', 'Maltese'), # index=154
- ('Pekinese', 'Pekingese', 'Peke'), # index=155
- ('Shih-Tzu',), # index=156
- ('Blenheim spaniel',), # index=157
- ('papillon',), # index=158
- ('toy terrier',), # index=159
- ('Rhodesian ridgeback',), # index=160
- ('Afghan hound', 'Afghan'), # index=161
- ('basset', 'basset hound'), # index=162
- ('beagle',), # index=163
- ('bloodhound', 'sleuthhound'), # index=164
- ('bluetick',), # index=165
- ('black-and-tan coonhound',), # index=166
- ('Walker hound', 'Walker foxhound'), # index=167
- ('English foxhound',), # index=168
- ('redbone',), # index=169
- ('borzoi', 'Russian wolfhound'), # index=170
- ('Irish wolfhound',), # index=171
- ('Italian greyhound',), # index=172
- ('whippet',), # index=173
- ('Ibizan hound', 'Ibizan Podenco'), # index=174
- ('Norwegian elkhound', 'elkhound'), # index=175
- ('otterhound', 'otter hound'), # index=176
- ('Saluki', 'gazelle hound'), # index=177
- ('Scottish deerhound', 'deerhound'), # index=178
- ('Weimaraner',), # index=179
- ('Staffordshire bullterrier', 'Staffordshire bull terrier'), # index=180
- ('American Staffordshire terrier', 'Staffordshire terrier',
- 'American pit bull terrier', 'pit bull terrier'), # index=181
- ('Bedlington terrier',), # index=182
- ('Border terrier',), # index=183
- ('Kerry blue terrier',), # index=184
- ('Irish terrier',), # index=185
- ('Norfolk terrier',), # index=186
- ('Norwich terrier',), # index=187
- ('Yorkshire terrier',), # index=188
- ('wire-haired fox terrier',), # index=189
- ('Lakeland terrier',), # index=190
- ('Sealyham terrier', 'Sealyham'), # index=191
- ('Airedale', 'Airedale terrier'), # index=192
- ('cairn', 'cairn terrier'), # index=193
- ('Australian terrier',), # index=194
- ('Dandie Dinmont', 'Dandie Dinmont terrier'), # index=195
- ('Boston bull', 'Boston terrier'), # index=196
- ('miniature schnauzer',), # index=197
- ('giant schnauzer',), # index=198
- ('standard schnauzer',), # index=199
- ('Scotch terrier', 'Scottish terrier', 'Scottie'), # index=200
- ('Tibetan terrier', 'chrysanthemum dog'), # index=201
- ('silky terrier', 'Sydney silky'), # index=202
- ('soft-coated wheaten terrier',), # index=203
- ('West Highland white terrier',), # index=204
- ('Lhasa', 'Lhasa apso'), # index=205
- ('flat-coated retriever',), # index=206
- ('curly-coated retriever',), # index=207
- ('golden retriever',), # index=208
- ('Labrador retriever',), # index=209
- ('Chesapeake Bay retriever',), # index=210
- ('German short-haired pointer',), # index=211
- ('vizsla', 'Hungarian pointer'), # index=212
- ('English setter',), # index=213
- ('Irish setter', 'red setter'), # index=214
- ('Gordon setter',), # index=215
- ('Brittany spaniel',), # index=216
- ('clumber', 'clumber spaniel'), # index=217
- ('English springer', 'English springer spaniel'), # index=218
- ('Welsh springer spaniel',), # index=219
- ('cocker spaniel', 'English cocker spaniel', 'cocker'), # index=220
- ('Sussex spaniel',), # index=221
- ('Irish water spaniel',), # index=222
- ('kuvasz',), # index=223
- ('schipperke',), # index=224
- ('groenendael',), # index=225
- ('malinois',), # index=226
- ('briard',), # index=227
- ('kelpie',), # index=228
- ('komondor',), # index=229
- ('Old English sheepdog', 'bobtail'), # index=230
- ('Shetland sheepdog', 'Shetland sheep dog', 'Shetland'), # index=231
- ('collie',), # index=232
- ('Border collie',), # index=233
- ('Bouvier des Flandres', 'Bouviers des Flandres'), # index=234
- ('Rottweiler',), # index=235
- ('German shepherd', 'German shepherd dog', 'German police dog',
- 'alsatian'), # index=236
- ('Doberman', 'Doberman pinscher'), # index=237
- ('miniature pinscher',), # index=238
- ('Greater Swiss Mountain dog',), # index=239
- ('Bernese mountain dog',), # index=240
- ('Appenzeller',), # index=241
- ('EntleBucher',), # index=242
- ('boxer',), # index=243
- ('bull mastiff',), # index=244
- ('Tibetan mastiff',), # index=245
- ('French bulldog',), # index=246
- ('Great Dane',), # index=247
- ('Saint Bernard', 'St Bernard'), # index=248
- ('Eskimo dog', 'husky'), # index=249
- ('malamute', 'malemute', 'Alaskan malamute'), # index=250
- ('Siberian husky',), # index=251
- ('dalmatian', 'coach dog', 'carriage dog'), # index=252
- ('affenpinscher', 'monkey pinscher', 'monkey dog'), # index=253
- ('basenji',), # index=254
- ('pug', 'pug-dog'), # index=255
- ('Leonberg',), # index=256
- ('Newfoundland', 'Newfoundland dog'), # index=257
- ('Great Pyrenees',), # index=258
- ('Samoyed', 'Samoyede'), # index=259
- ('Pomeranian',), # index=260
- ('chow', 'chow chow'), # index=261
- ('keeshond',), # index=262
- ('Brabancon griffon',), # index=263
- ('Pembroke', 'Pembroke Welsh corgi'), # index=264
- ('Cardigan', 'Cardigan Welsh corgi'), # index=265
- ('toy poodle',), # index=266
- ('miniature poodle',), # index=267
- ('standard poodle',), # index=268
- ('Mexican hairless',), # index=269
- ('timber wolf', 'grey wolf', 'gray wolf', 'Canis lupus'), # index=270
- ('white wolf', 'Arctic wolf', 'Canis lupus tundrarum'), # index=271
- ('red wolf', 'maned wolf', 'Canis rufus', 'Canis niger'), # index=272
- ('coyote', 'prairie wolf', 'brush wolf', 'Canis latrans'), # index=273
- ('dingo', 'warrigal', 'warragal', 'Canis dingo'), # index=274
- ('dhole', 'Cuon alpinus'), # index=275
- ('African hunting dog', 'hyena dog', 'Cape hunting dog',
- 'Lycaon pictus'), # index=276
- ('hyena', 'hyaena'), # index=277
- ('red fox', 'Vulpes vulpes'), # index=278
- ('kit fox', 'Vulpes macrotis'), # index=279
- ('Arctic fox', 'white fox', 'Alopex lagopus'), # index=280
- ('grey fox', 'gray fox', 'Urocyon cinereoargenteus'), # index=281
- ('tabby', 'tabby cat'), # index=282
- ('tiger cat',), # index=283
- ('Persian cat',), # index=284
- ('Siamese cat', 'Siamese'), # index=285
- ('Egyptian cat',), # index=286
- ('cougar', 'puma', 'catamount', 'mountain lion', 'painter', 'panther',
- 'Felis concolor'), # index=287
- ('lynx', 'catamount'), # index=288
- ('leopard', 'Panthera pardus'), # index=289
- ('snow leopard', 'ounce', 'Panthera uncia'), # index=290
- ('jaguar', 'panther', 'Panthera onca', 'Felis onca'), # index=291
- ('lion', 'king of beasts', 'Panthera leo'), # index=292
- ('tiger', 'Panthera tigris'), # index=293
- ('cheetah', 'chetah', 'Acinonyx jubatus'), # index=294
- ('brown bear', 'bruin', 'Ursus arctos'), # index=295
- ('American black bear', 'black bear', 'Ursus americanus',
- 'Euarctos americanus'), # index=296
- ('ice bear', 'polar bear', 'Ursus Maritimus',
- 'Thalarctos maritimus'), # index=297
- ('sloth bear', 'Melursus ursinus', 'Ursus ursinus'), # index=298
- ('mongoose',), # index=299
- ('meerkat', 'mierkat'), # index=300
- ('tiger beetle',), # index=301
- ('ladybug', 'ladybeetle', 'lady beetle', 'ladybird',
- 'ladybird beetle'), # index=302
- ('ground beetle', 'carabid beetle'), # index=303
- ('long-horned beetle', 'longicorn', 'longicorn beetle'), # index=304
- ('leaf beetle', 'chrysomelid'), # index=305
- ('dung beetle',), # index=306
- ('rhinoceros beetle',), # index=307
- ('weevil',), # index=308
- ('fly',), # index=309
- ('bee',), # index=310
- ('ant', 'emmet', 'pismire'), # index=311
- ('grasshopper', 'hopper'), # index=312
- ('cricket',), # index=313
- ('walking stick', 'walkingstick', 'stick insect'), # index=314
- ('cockroach', 'roach'), # index=315
- ('mantis', 'mantid'), # index=316
- ('cicada', 'cicala'), # index=317
- ('leafhopper',), # index=318
- ('lacewing', 'lacewing fly'), # index=319
- ('dragonfly', 'darning needle', "devil's darning needle", 'sewing needle',
- 'snake feeder', 'snake doctor', 'mosquito hawk',
- 'skeeter hawk'), # index=320
- ('damselfly',), # index=321
- ('admiral',), # index=322
- ('ringlet', 'ringlet butterfly'), # index=323
- ('monarch', 'monarch butterfly', 'milkweed butterfly',
- 'Danaus plexippus'), # index=324
- ('cabbage butterfly',), # index=325
- ('sulphur butterfly', 'sulfur butterfly'), # index=326
- ('lycaenid', 'lycaenid butterfly'), # index=327
- ('starfish', 'sea star'), # index=328
- ('sea urchin',), # index=329
- ('sea cucumber', 'holothurian'), # index=330
- ('wood rabbit', 'cottontail', 'cottontail rabbit'), # index=331
- ('hare',), # index=332
- ('Angora', 'Angora rabbit'), # index=333
- ('hamster',), # index=334
- ('porcupine', 'hedgehog'), # index=335
- ('fox squirrel', 'eastern fox squirrel', 'Sciurus niger'), # index=336
- ('marmot',), # index=337
- ('beaver',), # index=338
- ('guinea pig', 'Cavia cobaya'), # index=339
- ('sorrel',), # index=340
- ('zebra',), # index=341
- ('hog', 'pig', 'grunter', 'squealer', 'Sus scrofa'), # index=342
- ('wild boar', 'boar', 'Sus scrofa'), # index=343
- ('warthog',), # index=344
- ('hippopotamus', 'hippo', 'river horse',
- 'Hippopotamus amphibius'), # index=345
- ('ox',), # index=346
- ('water buffalo', 'water ox', 'Asiatic buffalo',
- 'Bubalus bubalis'), # index=347
- ('bison',), # index=348
- ('ram', 'tup'), # index=349
- ('bighorn', 'bighorn sheep', 'cimarron', 'Rocky Mountain bighorn',
- 'Rocky Mountain sheep', 'Ovis canadensis'), # index=350
- ('ibex', 'Capra ibex'), # index=351
- ('hartebeest',), # index=352
- ('impala', 'Aepyceros melampus'), # index=353
- ('gazelle',), # index=354
- ('Arabian camel', 'dromedary', 'Camelus dromedarius'), # index=355
- ('llama',), # index=356
- ('weasel',), # index=357
- ('mink',), # index=358
- ('polecat', 'fitch', 'foulmart', 'foumart',
- 'Mustela putorius'), # index=359
- ('black-footed ferret', 'ferret', 'Mustela nigripes'), # index=360
- ('otter',), # index=361
- ('skunk', 'polecat', 'wood pussy'), # index=362
- ('badger',), # index=363
- ('armadillo',), # index=364
- ('three-toed sloth', 'ai', 'Bradypus tridactylus'), # index=365
- ('orangutan', 'orang', 'orangutang', 'Pongo pygmaeus'), # index=366
- ('gorilla', 'Gorilla gorilla'), # index=367
- ('chimpanzee', 'chimp', 'Pan troglodytes'), # index=368
- ('gibbon', 'Hylobates lar'), # index=369
- ('siamang', 'Hylobates syndactylus',
- 'Symphalangus syndactylus'), # index=370
- ('guenon', 'guenon monkey'), # index=371
- ('patas', 'hussar monkey', 'Erythrocebus patas'), # index=372
- ('baboon',), # index=373
- ('macaque',), # index=374
- ('langur',), # index=375
- ('colobus', 'colobus monkey'), # index=376
- ('proboscis monkey', 'Nasalis larvatus'), # index=377
- ('marmoset',), # index=378
- ('capuchin', 'ringtail', 'Cebus capucinus'), # index=379
- ('howler monkey', 'howler'), # index=380
- ('titi', 'titi monkey'), # index=381
- ('spider monkey', 'Ateles geoffroyi'), # index=382
- ('squirrel monkey', 'Saimiri sciureus'), # index=383
- ('Madagascar cat', 'ring-tailed lemur', 'Lemur catta'), # index=384
- ('indri', 'indris', 'Indri indri', 'Indri brevicaudatus'), # index=385
- ('Indian elephant', 'Elephas maximus'), # index=386
- ('African elephant', 'Loxodonta africana'), # index=387
- ('lesser panda', 'red panda', 'panda', 'bear cat', 'cat bear',
- 'Ailurus fulgens'), # index=388
- ('giant panda', 'panda', 'panda bear', 'coon bear',
- 'Ailuropoda melanoleuca'), # index=389
- ('barracouta', 'snoek'), # index=390
- ('eel',), # index=391
- ('coho', 'cohoe', 'coho salmon', 'blue jack', 'silver salmon',
- 'Oncorhynchus kisutch'), # index=392
- ('rock beauty', 'Holocanthus tricolor'), # index=393
- ('anemone fish',), # index=394
- ('sturgeon',), # index=395
- ('gar', 'garfish', 'garpike', 'billfish',
- 'Lepisosteus osseus'), # index=396
- ('lionfish',), # index=397
- ('puffer', 'pufferfish', 'blowfish', 'globefish'), # index=398
- ('abacus',), # index=399
- ('abaya',), # index=400
- ('academic gown', 'academic robe', "judge's robe"), # index=401
- ('accordion', 'piano accordion', 'squeeze box'), # index=402
- ('acoustic guitar',), # index=403
- ('aircraft carrier', 'carrier', 'flattop',
- 'attack aircraft carrier'), # index=404
- ('airliner',), # index=405
- ('airship', 'dirigible'), # index=406
- ('altar',), # index=407
- ('ambulance',), # index=408
- ('amphibian', 'amphibious vehicle'), # index=409
- ('analog clock',), # index=410
- ('apiary', 'bee house'), # index=411
- ('apron',), # index=412
- ('ashcan', 'trash can', 'garbage can', 'wastebin', 'ash bin', 'ash-bin',
- 'ashbin', 'dustbin', 'trash barrel', 'trash bin'), # index=413
- ('assault rifle', 'assault gun'), # index=414
- ('backpack', 'back pack', 'knapsack', 'packsack', 'rucksack',
- 'haversack'), # index=415
- ('bakery', 'bakeshop', 'bakehouse'), # index=416
- ('balance beam', 'beam'), # index=417
- ('balloon',), # index=418
- ('ballpoint', 'ballpoint pen', 'ballpen', 'Biro'), # index=419
- ('Band Aid',), # index=420
- ('banjo',), # index=421
- ('bannister', 'banister', 'balustrade', 'balusters',
- 'handrail'), # index=422
- ('barbell',), # index=423
- ('barber chair',), # index=424
- ('barbershop',), # index=425
- ('barn',), # index=426
- ('barometer',), # index=427
- ('barrel', 'cask'), # index=428
- ('barrow', 'garden cart', 'lawn cart', 'wheelbarrow'), # index=429
- ('baseball',), # index=430
- ('basketball',), # index=431
- ('bassinet',), # index=432
- ('bassoon',), # index=433
- ('bathing cap', 'swimming cap'), # index=434
- ('bath towel',), # index=435
- ('bathtub', 'bathing tub', 'bath', 'tub'), # index=436
- ('beach wagon', 'station wagon', 'wagon', 'estate car', 'beach waggon',
- 'station waggon', 'waggon'), # index=437
- ('beacon', 'lighthouse', 'beacon light', 'pharos'), # index=438
- ('beaker',), # index=439
- ('bearskin', 'busby', 'shako'), # index=440
- ('beer bottle',), # index=441
- ('beer glass',), # index=442
- ('bell cote', 'bell cot'), # index=443
- ('bib',), # index=444
- ('bicycle-built-for-two', 'tandem bicycle', 'tandem'), # index=445
- ('bikini', 'two-piece'), # index=446
- ('binder', 'ring-binder'), # index=447
- ('binoculars', 'field glasses', 'opera glasses'), # index=448
- ('birdhouse',), # index=449
- ('boathouse',), # index=450
- ('bobsled', 'bobsleigh', 'bob'), # index=451
- ('bolo tie', 'bolo', 'bola tie', 'bola'), # index=452
- ('bonnet', 'poke bonnet'), # index=453
- ('bookcase',), # index=454
- ('bookshop', 'bookstore', 'bookstall'), # index=455
- ('bottlecap',), # index=456
- ('bow',), # index=457
- ('bow tie', 'bow-tie', 'bowtie'), # index=458
- ('brass', 'memorial tablet', 'plaque'), # index=459
- ('brassiere', 'bra', 'bandeau'), # index=460
- ('breakwater', 'groin', 'groyne', 'mole', 'bulwark', 'seawall',
- 'jetty'), # index=461
- ('breastplate', 'aegis', 'egis'), # index=462
- ('broom',), # index=463
- ('bucket', 'pail'), # index=464
- ('buckle',), # index=465
- ('bulletproof vest',), # index=466
- ('bullet train', 'bullet'), # index=467
- ('butcher shop', 'meat market'), # index=468
- ('cab', 'hack', 'taxi', 'taxicab'), # index=469
- ('caldron', 'cauldron'), # index=470
- ('candle', 'taper', 'wax light'), # index=471
- ('cannon',), # index=472
- ('canoe',), # index=473
- ('can opener', 'tin opener'), # index=474
- ('cardigan',), # index=475
- ('car mirror',), # index=476
- ('carousel', 'carrousel', 'merry-go-round', 'roundabout',
- 'whirligig'), # index=477
- ("carpenter's kit", 'tool kit'), # index=478
- ('carton',), # index=479
- ('car wheel',), # index=480
- ('cash machine', 'cash dispenser', 'automated teller machine',
- 'automatic teller machine', 'automated teller', 'automatic teller',
- 'ATM'), # index=481
- ('cassette',), # index=482
- ('cassette player',), # index=483
- ('castle',), # index=484
- ('catamaran',), # index=485
- ('CD player',), # index=486
- ('cello', 'violoncello'), # index=487
- ('cellular telephone', 'cellular phone', 'cellphone', 'cell',
- 'mobile phone'), # index=488
- ('chain',), # index=489
- ('chainlink fence',), # index=490
- ('chain mail', 'ring mail', 'mail', 'chain armor', 'chain armour',
- 'ring armor', 'ring armour'), # index=491
- ('chain saw', 'chainsaw'), # index=492
- ('chest',), # index=493
- ('chiffonier', 'commode'), # index=494
- ('chime', 'bell', 'gong'), # index=495
- ('china cabinet', 'china closet'), # index=496
- ('Christmas stocking',), # index=497
- ('church', 'church building'), # index=498
- ('cinema', 'movie theater', 'movie theatre', 'movie house',
- 'picture palace'), # index=499
- ('cleaver', 'meat cleaver', 'chopper'), # index=500
- ('cliff dwelling',), # index=501
- ('cloak',), # index=502
- ('clog', 'geta', 'patten', 'sabot'), # index=503
- ('cocktail shaker',), # index=504
- ('coffee mug',), # index=505
- ('coffeepot',), # index=506
- ('coil', 'spiral', 'volute', 'whorl', 'helix'), # index=507
- ('combination lock',), # index=508
- ('computer keyboard', 'keypad'), # index=509
- ('confectionery', 'confectionary', 'candy store'), # index=510
- ('container ship', 'containership', 'container vessel'), # index=511
- ('convertible',), # index=512
- ('corkscrew', 'bottle screw'), # index=513
- ('cornet', 'horn', 'trumpet', 'trump'), # index=514
- ('cowboy boot',), # index=515
- ('cowboy hat', 'ten-gallon hat'), # index=516
- ('cradle',), # index=517
- ('crane',), # index=518
- ('crash helmet',), # index=519
- ('crate',), # index=520
- ('crib', 'cot'), # index=521
- ('Crock Pot',), # index=522
- ('croquet ball',), # index=523
- ('crutch',), # index=524
- ('cuirass',), # index=525
- ('dam', 'dike', 'dyke'), # index=526
- ('desk',), # index=527
- ('desktop computer',), # index=528
- ('dial telephone', 'dial phone'), # index=529
- ('diaper', 'nappy', 'napkin'), # index=530
- ('digital clock',), # index=531
- ('digital watch',), # index=532
- ('dining table', 'board'), # index=533
- ('dishrag', 'dishcloth'), # index=534
- ('dishwasher', 'dish washer', 'dishwashing machine'), # index=535
- ('disk brake', 'disc brake'), # index=536
- ('dock', 'dockage', 'docking facility'), # index=537
- ('dogsled', 'dog sled', 'dog sleigh'), # index=538
- ('dome',), # index=539
- ('doormat', 'welcome mat'), # index=540
- ('drilling platform', 'offshore rig'), # index=541
- ('drum', 'membranophone', 'tympan'), # index=542
- ('drumstick',), # index=543
- ('dumbbell',), # index=544
- ('Dutch oven',), # index=545
- ('electric fan', 'blower'), # index=546
- ('electric guitar',), # index=547
- ('electric locomotive',), # index=548
- ('entertainment center',), # index=549
- ('envelope',), # index=550
- ('espresso maker',), # index=551
- ('face powder',), # index=552
- ('feather boa', 'boa'), # index=553
- ('file', 'file cabinet', 'filing cabinet'), # index=554
- ('fireboat',), # index=555
- ('fire engine', 'fire truck'), # index=556
- ('fire screen', 'fireguard'), # index=557
- ('flagpole', 'flagstaff'), # index=558
- ('flute', 'transverse flute'), # index=559
- ('folding chair',), # index=560
- ('football helmet',), # index=561
- ('forklift',), # index=562
- ('fountain',), # index=563
- ('fountain pen',), # index=564
- ('four-poster',), # index=565
- ('freight car',), # index=566
- ('French horn', 'horn'), # index=567
- ('frying pan', 'frypan', 'skillet'), # index=568
- ('fur coat',), # index=569
- ('garbage truck', 'dustcart'), # index=570
- ('gasmask', 'respirator', 'gas helmet'), # index=571
- ('gas pump', 'gasoline pump', 'petrol pump',
- 'island dispenser'), # index=572
- ('goblet',), # index=573
- ('go-kart',), # index=574
- ('golf ball',), # index=575
- ('golfcart', 'golf cart'), # index=576
- ('gondola',), # index=577
- ('gong', 'tam-tam'), # index=578
- ('gown',), # index=579
- ('grand piano', 'grand'), # index=580
- ('greenhouse', 'nursery', 'glasshouse'), # index=581
- ('grille', 'radiator grille'), # index=582
- ('grocery store', 'grocery', 'food market', 'market'), # index=583
- ('guillotine',), # index=584
- ('hair slide',), # index=585
- ('hair spray',), # index=586
- ('half track',), # index=587
- ('hammer',), # index=588
- ('hamper',), # index=589
- ('hand blower', 'blow dryer', 'blow drier', 'hair dryer',
- 'hair drier'), # index=590
- ('hand-held computer', 'hand-held microcomputer'), # index=591
- ('handkerchief', 'hankie', 'hanky', 'hankey'), # index=592
- ('hard disc', 'hard disk', 'fixed disk'), # index=593
- ('harmonica', 'mouth organ', 'harp', 'mouth harp'), # index=594
- ('harp',), # index=595
- ('harvester', 'reaper'), # index=596
- ('hatchet',), # index=597
- ('holster',), # index=598
- ('home theater', 'home theatre'), # index=599
- ('honeycomb',), # index=600
- ('hook', 'claw'), # index=601
- ('hoopskirt', 'crinoline'), # index=602
- ('horizontal bar', 'high bar'), # index=603
- ('horse cart', 'horse-cart'), # index=604
- ('hourglass',), # index=605
- ('iPod',), # index=606
- ('iron', 'smoothing iron'), # index=607
- ("jack-o'-lantern",), # index=608
- ('jean', 'blue jean', 'denim'), # index=609
- ('jeep', 'landrover'), # index=610
- ('jersey', 'T-shirt', 'tee shirt'), # index=611
- ('jigsaw puzzle',), # index=612
- ('jinrikisha', 'ricksha', 'rickshaw'), # index=613
- ('joystick',), # index=614
- ('kimono',), # index=615
- ('knee pad',), # index=616
- ('knot',), # index=617
- ('lab coat', 'laboratory coat'), # index=618
- ('ladle',), # index=619
- ('lampshade', 'lamp shade'), # index=620
- ('laptop', 'laptop computer'), # index=621
- ('lawn mower', 'mower'), # index=622
- ('lens cap', 'lens cover'), # index=623
- ('letter opener', 'paper knife', 'paperknife'), # index=624
- ('library',), # index=625
- ('lifeboat',), # index=626
- ('lighter', 'light', 'igniter', 'ignitor'), # index=627
- ('limousine', 'limo'), # index=628
- ('liner', 'ocean liner'), # index=629
- ('lipstick', 'lip rouge'), # index=630
- ('Loafer',), # index=631
- ('lotion',), # index=632
- ('loudspeaker', 'speaker', 'speaker unit', 'loudspeaker system',
- 'speaker system'), # index=633
- ('loupe', "jeweler's loupe"), # index=634
- ('lumbermill', 'sawmill'), # index=635
- ('magnetic compass',), # index=636
- ('mailbag', 'postbag'), # index=637
- ('mailbox', 'letter box'), # index=638
- ('maillot',), # index=639
- ('maillot', 'tank suit'), # index=640
- ('manhole cover',), # index=641
- ('maraca',), # index=642
- ('marimba', 'xylophone'), # index=643
- ('mask',), # index=644
- ('matchstick',), # index=645
- ('maypole',), # index=646
- ('maze', 'labyrinth'), # index=647
- ('measuring cup',), # index=648
- ('medicine chest', 'medicine cabinet'), # index=649
- ('megalith', 'megalithic structure'), # index=650
- ('microphone', 'mike'), # index=651
- ('microwave', 'microwave oven'), # index=652
- ('military uniform',), # index=653
- ('milk can',), # index=654
- ('minibus',), # index=655
- ('miniskirt', 'mini'), # index=656
- ('minivan',), # index=657
- ('missile',), # index=658
- ('mitten',), # index=659
- ('mixing bowl',), # index=660
- ('mobile home', 'manufactured home'), # index=661
- ('Model T',), # index=662
- ('modem',), # index=663
- ('monastery',), # index=664
- ('monitor',), # index=665
- ('moped',), # index=666
- ('mortar',), # index=667
- ('mortarboard',), # index=668
- ('mosque',), # index=669
- ('mosquito net',), # index=670
- ('motor scooter', 'scooter'), # index=671
- ('mountain bike', 'all-terrain bike', 'off-roader'), # index=672
- ('mountain tent',), # index=673
- ('mouse', 'computer mouse'), # index=674
- ('mousetrap',), # index=675
- ('moving van',), # index=676
- ('muzzle',), # index=677
- ('nail',), # index=678
- ('neck brace',), # index=679
- ('necklace',), # index=680
- ('nipple',), # index=681
- ('notebook', 'notebook computer'), # index=682
- ('obelisk',), # index=683
- ('oboe', 'hautboy', 'hautbois'), # index=684
- ('ocarina', 'sweet potato'), # index=685
- ('odometer', 'hodometer', 'mileometer', 'milometer'), # index=686
- ('oil filter',), # index=687
- ('organ', 'pipe organ'), # index=688
- ('oscilloscope', 'scope', 'cathode-ray oscilloscope', 'CRO'), # index=689
- ('overskirt',), # index=690
- ('oxcart',), # index=691
- ('oxygen mask',), # index=692
- ('packet',), # index=693
- ('paddle', 'boat paddle'), # index=694
- ('paddlewheel', 'paddle wheel'), # index=695
- ('padlock',), # index=696
- ('paintbrush',), # index=697
- ('pajama', 'pyjama', "pj's", 'jammies'), # index=698
- ('palace',), # index=699
- ('panpipe', 'pandean pipe', 'syrinx'), # index=700
- ('paper towel',), # index=701
- ('parachute', 'chute'), # index=702
- ('parallel bars', 'bars'), # index=703
- ('park bench',), # index=704
- ('parking meter',), # index=705
- ('passenger car', 'coach', 'carriage'), # index=706
- ('patio', 'terrace'), # index=707
- ('pay-phone', 'pay-station'), # index=708
- ('pedestal', 'plinth', 'footstall'), # index=709
- ('pencil box', 'pencil case'), # index=710
- ('pencil sharpener',), # index=711
- ('perfume', 'essence'), # index=712
- ('Petri dish',), # index=713
- ('photocopier',), # index=714
- ('pick', 'plectrum', 'plectron'), # index=715
- ('pickelhaube',), # index=716
- ('picket fence', 'paling'), # index=717
- ('pickup', 'pickup truck'), # index=718
- ('pier',), # index=719
- ('piggy bank', 'penny bank'), # index=720
- ('pill bottle',), # index=721
- ('pillow',), # index=722
- ('ping-pong ball',), # index=723
- ('pinwheel',), # index=724
- ('pirate', 'pirate ship'), # index=725
- ('pitcher', 'ewer'), # index=726
- ('plane', "carpenter's plane", 'woodworking plane'), # index=727
- ('planetarium',), # index=728
- ('plastic bag',), # index=729
- ('plate rack',), # index=730
- ('plow', 'plough'), # index=731
- ('plunger', "plumber's helper"), # index=732
- ('Polaroid camera', 'Polaroid Land camera'), # index=733
- ('pole',), # index=734
- ('police van', 'police wagon', 'paddy wagon', 'patrol wagon', 'wagon',
- 'black Maria'), # index=735
- ('poncho',), # index=736
- ('pool table', 'billiard table', 'snooker table'), # index=737
- ('pop bottle', 'soda bottle'), # index=738
- ('pot', 'flowerpot'), # index=739
- ("potter's wheel",), # index=740
- ('power drill',), # index=741
- ('prayer rug', 'prayer mat'), # index=742
- ('printer',), # index=743
- ('prison', 'prison house'), # index=744
- ('projectile', 'missile'), # index=745
- ('projector',), # index=746
- ('puck', 'hockey puck'), # index=747
- ('punching bag', 'punch bag', 'punching ball', 'punchball'), # index=748
- ('purse',), # index=749
- ('quill', 'quill pen'), # index=750
- ('quilt', 'comforter', 'comfort', 'puff'), # index=751
- ('racer', 'race car', 'racing car'), # index=752
- ('racket', 'racquet'), # index=753
- ('radiator',), # index=754
- ('radio', 'wireless'), # index=755
- ('radio telescope', 'radio reflector'), # index=756
- ('rain barrel',), # index=757
- ('recreational vehicle', 'RV', 'R.V.'), # index=758
- ('reel',), # index=759
- ('reflex camera',), # index=760
- ('refrigerator', 'icebox'), # index=761
- ('remote control', 'remote'), # index=762
- ('restaurant', 'eating house', 'eating place', 'eatery'), # index=763
- ('revolver', 'six-gun', 'six-shooter'), # index=764
- ('rifle',), # index=765
- ('rocking chair', 'rocker'), # index=766
- ('rotisserie',), # index=767
- ('rubber eraser', 'rubber', 'pencil eraser'), # index=768
- ('rugby ball',), # index=769
- ('rule', 'ruler'), # index=770
- ('running shoe',), # index=771
- ('safe',), # index=772
- ('safety pin',), # index=773
- ('saltshaker', 'salt shaker'), # index=774
- ('sandal',), # index=775
- ('sarong',), # index=776
- ('sax', 'saxophone'), # index=777
- ('scabbard',), # index=778
- ('scale', 'weighing machine'), # index=779
- ('school bus',), # index=780
- ('schooner',), # index=781
- ('scoreboard',), # index=782
- ('screen', 'CRT screen'), # index=783
- ('screw',), # index=784
- ('screwdriver',), # index=785
- ('seat belt', 'seatbelt'), # index=786
- ('sewing machine',), # index=787
- ('shield', 'buckler'), # index=788
- ('shoe shop', 'shoe-shop', 'shoe store'), # index=789
- ('shoji',), # index=790
- ('shopping basket',), # index=791
- ('shopping cart',), # index=792
- ('shovel',), # index=793
- ('shower cap',), # index=794
- ('shower curtain',), # index=795
- ('ski',), # index=796
- ('ski mask',), # index=797
- ('sleeping bag',), # index=798
- ('slide rule', 'slipstick'), # index=799
- ('sliding door',), # index=800
- ('slot', 'one-armed bandit'), # index=801
- ('snorkel',), # index=802
- ('snowmobile',), # index=803
- ('snowplow', 'snowplough'), # index=804
- ('soap dispenser',), # index=805
- ('soccer ball',), # index=806
- ('sock',), # index=807
- ('solar dish', 'solar collector', 'solar furnace'), # index=808
- ('sombrero',), # index=809
- ('soup bowl',), # index=810
- ('space bar',), # index=811
- ('space heater',), # index=812
- ('space shuttle',), # index=813
- ('spatula',), # index=814
- ('speedboat',), # index=815
- ('spider web', "spider's web"), # index=816
- ('spindle',), # index=817
- ('sports car', 'sport car'), # index=818
- ('spotlight', 'spot'), # index=819
- ('stage',), # index=820
- ('steam locomotive',), # index=821
- ('steel arch bridge',), # index=822
- ('steel drum',), # index=823
- ('stethoscope',), # index=824
- ('stole',), # index=825
- ('stone wall',), # index=826
- ('stopwatch', 'stop watch'), # index=827
- ('stove',), # index=828
- ('strainer',), # index=829
- ('streetcar', 'tram', 'tramcar', 'trolley', 'trolley car'), # index=830
- ('stretcher',), # index=831
- ('studio couch', 'day bed'), # index=832
- ('stupa', 'tope'), # index=833
- ('submarine', 'pigboat', 'sub', 'U-boat'), # index=834
- ('suit', 'suit of clothes'), # index=835
- ('sundial',), # index=836
- ('sunglass',), # index=837
- ('sunglasses', 'dark glasses', 'shades'), # index=838
- ('sunscreen', 'sunblock', 'sun blocker'), # index=839
- ('suspension bridge',), # index=840
- ('swab', 'swob', 'mop'), # index=841
- ('sweatshirt',), # index=842
- ('swimming trunks', 'bathing trunks'), # index=843
- ('swing',), # index=844
- ('switch', 'electric switch', 'electrical switch'), # index=845
- ('syringe',), # index=846
- ('table lamp',), # index=847
- ('tank', 'army tank', 'armored combat vehicle',
- 'armoured combat vehicle'), # index=848
- ('tape player',), # index=849
- ('teapot',), # index=850
- ('teddy', 'teddy bear'), # index=851
- ('television', 'television system'), # index=852
- ('tennis ball',), # index=853
- ('thatch', 'thatched roof'), # index=854
- ('theater curtain', 'theatre curtain'), # index=855
- ('thimble',), # index=856
- ('thresher', 'thrasher', 'threshing machine'), # index=857
- ('throne',), # index=858
- ('tile roof',), # index=859
- ('toaster',), # index=860
- ('tobacco shop', 'tobacconist shop', 'tobacconist'), # index=861
- ('toilet seat',), # index=862
- ('torch',), # index=863
- ('totem pole',), # index=864
- ('tow truck', 'tow car', 'wrecker'), # index=865
- ('toyshop',), # index=866
- ('tractor',), # index=867
- ('trailer truck', 'tractor trailer', 'trucking rig', 'rig',
- 'articulated lorry', 'semi'), # index=868
- ('tray',), # index=869
- ('trench coat',), # index=870
- ('tricycle', 'trike', 'velocipede'), # index=871
- ('trimaran',), # index=872
- ('tripod',), # index=873
- ('triumphal arch',), # index=874
- ('trolleybus', 'trolley coach', 'trackless trolley'), # index=875
- ('trombone',), # index=876
- ('tub', 'vat'), # index=877
- ('turnstile',), # index=878
- ('typewriter keyboard',), # index=879
- ('umbrella',), # index=880
- ('unicycle', 'monocycle'), # index=881
- ('upright', 'upright piano'), # index=882
- ('vacuum', 'vacuum cleaner'), # index=883
- ('vase',), # index=884
- ('vault',), # index=885
- ('velvet',), # index=886
- ('vending machine',), # index=887
- ('vestment',), # index=888
- ('viaduct',), # index=889
- ('violin', 'fiddle'), # index=890
- ('volleyball',), # index=891
- ('waffle iron',), # index=892
- ('wall clock',), # index=893
- ('wallet', 'billfold', 'notecase', 'pocketbook'), # index=894
- ('wardrobe', 'closet', 'press'), # index=895
- ('warplane', 'military plane'), # index=896
- ('washbasin', 'handbasin', 'washbowl', 'lavabo',
- 'wash-hand basin'), # index=897
- ('washer', 'automatic washer', 'washing machine'), # index=898
- ('water bottle',), # index=899
- ('water jug',), # index=900
- ('water tower',), # index=901
- ('whiskey jug',), # index=902
- ('whistle',), # index=903
- ('wig',), # index=904
- ('window screen',), # index=905
- ('window shade',), # index=906
- ('Windsor tie',), # index=907
- ('wine bottle',), # index=908
- ('wing',), # index=909
- ('wok',), # index=910
- ('wooden spoon',), # index=911
- ('wool', 'woolen', 'woollen'), # index=912
- ('worm fence', 'snake fence', 'snake-rail fence',
- 'Virginia fence'), # index=913
- ('wreck',), # index=914
- ('yawl',), # index=915
- ('yurt',), # index=916
- ('web site', 'website', 'internet site', 'site'), # index=917
- ('comic book',), # index=918
- ('crossword puzzle', 'crossword'), # index=919
- ('street sign',), # index=920
- ('traffic light', 'traffic signal', 'stoplight'), # index=921
- ('book jacket', 'dust cover', 'dust jacket', 'dust wrapper'), # index=922
- ('menu',), # index=923
- ('plate',), # index=924
- ('guacamole',), # index=925
- ('consomme',), # index=926
- ('hot pot', 'hotpot'), # index=927
- ('trifle',), # index=928
- ('ice cream', 'icecream'), # index=929
- ('ice lolly', 'lolly', 'lollipop', 'popsicle'), # index=930
- ('French loaf',), # index=931
- ('bagel', 'beigel'), # index=932
- ('pretzel',), # index=933
- ('cheeseburger',), # index=934
- ('hotdog', 'hot dog', 'red hot'), # index=935
- ('mashed potato',), # index=936
- ('head cabbage',), # index=937
- ('broccoli',), # index=938
- ('cauliflower',), # index=939
- ('zucchini', 'courgette'), # index=940
- ('spaghetti squash',), # index=941
- ('acorn squash',), # index=942
- ('butternut squash',), # index=943
- ('cucumber', 'cuke'), # index=944
- ('artichoke', 'globe artichoke'), # index=945
- ('bell pepper',), # index=946
- ('cardoon',), # index=947
- ('mushroom',), # index=948
- ('Granny Smith',), # index=949
- ('strawberry',), # index=950
- ('orange',), # index=951
- ('lemon',), # index=952
- ('fig',), # index=953
- ('pineapple', 'ananas'), # index=954
- ('banana',), # index=955
- ('jackfruit', 'jak', 'jack'), # index=956
- ('custard apple',), # index=957
- ('pomegranate',), # index=958
- ('hay',), # index=959
- ('carbonara',), # index=960
- ('chocolate sauce', 'chocolate syrup'), # index=961
- ('dough',), # index=962
- ('meat loaf', 'meatloaf'), # index=963
- ('pizza', 'pizza pie'), # index=964
- ('potpie',), # index=965
- ('burrito',), # index=966
- ('red wine',), # index=967
- ('espresso',), # index=968
- ('cup',), # index=969
- ('eggnog',), # index=970
- ('alp',), # index=971
- ('bubble',), # index=972
- ('cliff', 'drop', 'drop-off'), # index=973
- ('coral reef',), # index=974
- ('geyser',), # index=975
- ('lakeside', 'lakeshore'), # index=976
- ('promontory', 'headland', 'head', 'foreland'), # index=977
- ('sandbar', 'sand bar'), # index=978
- ('seashore', 'coast', 'seacoast', 'sea-coast'), # index=979
- ('valley', 'vale'), # index=980
- ('volcano',), # index=981
- ('ballplayer', 'baseball player'), # index=982
- ('groom', 'bridegroom'), # index=983
- ('scuba diver',), # index=984
- ('rapeseed',), # index=985
- ('daisy',), # index=986
- ("yellow lady's slipper", 'yellow lady-slipper', 'Cypripedium calceolus',
- 'Cypripedium parviflorum'), # index=987
- ('corn',), # index=988
- ('acorn',), # index=989
- ('hip', 'rose hip', 'rosehip'), # index=990
- ('buckeye', 'horse chestnut', 'conker'), # index=991
- ('coral fungus',), # index=992
- ('agaric',), # index=993
- ('gyromitra',), # index=994
- ('stinkhorn', 'carrion fungus'), # index=995
- ('earthstar',), # index=996
- ('hen-of-the-woods', 'hen of the woods', 'Polyporus frondosus',
- 'Grifola frondosa'), # index=997
- ('bolete',), # index=998
- ('ear', 'spike', 'capitulum'), # index=999
- ('toilet tissue', 'toilet paper', 'bathroom tissue'), # index=1000
-)
diff --git a/src/aiy/vision/models/object_detection.py b/src/aiy/vision/models/object_detection.py
deleted file mode 100644
index 47d264f0..00000000
--- a/src/aiy/vision/models/object_detection.py
+++ /dev/null
@@ -1,230 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""API for Object Detection tasks."""
-import math
-import sys
-
-from aiy.vision.inference import ModelDescriptor
-from aiy.vision.models import utils
-from aiy.vision.models.object_detection_anchors import ANCHORS
-
-_COMPUTE_GRAPH_NAME = 'mobilenet_ssd_256res_0.125_person_cat_dog.binaryproto'
-_NUM_ANCHORS = len(ANCHORS)
-_MACHINE_EPS = sys.float_info.epsilon
-
-
-class Object(object):
- """Object detection result."""
- BACKGROUND = 0
- PERSON = 1
- CAT = 2
- DOG = 3
-
- _LABELS = {
- BACKGROUND: 'BACKGROUND',
- PERSON: 'PERSON',
- CAT: 'CAT',
- DOG: 'DOG',
- }
-
- def __init__(self, bounding_box, kind, score):
- """Initialization.
-
- Args:
- bounding_box: a tuple of 4 ints, (x, y, width, height) order.
- kind: int, tells what object is in the bounding box.
- score: float, confidence score.
- """
- self.bounding_box = bounding_box
- self.kind = kind
- self.score = score
-
- def __str__(self):
- return 'kind=%s(%d), score=%f, bbox=%s' % (self._LABELS[self.kind],
- self.kind, self.score,
- str(self.bounding_box))
-
-
-def _decode_detection_result(logit_scores, box_encodings, anchors,
- score_threshold, image_size, offset):
- """Decodes result as bounding boxes.
-
- Args:
- logit_scores: list of scores
- box_encodings: list of bounding boxes
- anchors: list of anchors
- score_threshold: float, bounding box candidates below this threshold will
- be rejected.
- image_size: (width, height)
- offset: (x, y)
- Returns:
- A list of ObjectDetection.Result.
- """
- assert len(box_encodings) == 4 * _NUM_ANCHORS
- assert len(logit_scores) == 4 * _NUM_ANCHORS
-
- x0, y0 = offset
- width, height = image_size
- objs = []
-
- score_threshold = max(score_threshold, _MACHINE_EPS)
- logit_score_threshold = math.log(score_threshold / (1 - score_threshold))
- for i in range(_NUM_ANCHORS):
- logits = logit_scores[4 * i: 4 * (i + 1)]
- max_logit_score = max(logits)
- max_score_index = logits.index(max_logit_score)
- # Skip if max score is below threshold or max score is 'background'.
- if max_score_index == 0 or max_logit_score <= logit_score_threshold:
- continue
-
- box_encoding = box_encodings[4 * i: 4 * (i + 1)]
- xmin, ymin, xmax, ymax = _decode_box_encoding(box_encoding, anchors[i])
- x = int(x0 + xmin * width)
- y = int(y0 + ymin * height)
- w = int((xmax - xmin) * width)
- h = int((ymax - ymin) * height)
- max_score = 1.0 / (1.0 + math.exp(-max_logit_score))
- objs.append(Object((x, y, w, h), max_score_index, max_score))
- return objs
-
-
-def _clamp(value):
- """Clamps value to range [0.0, 1.0]."""
- return min(max(0.0, value), 1.0)
-
-
-def _decode_box_encoding(box_encoding, anchor):
- """Decodes bounding box encoding.
-
- Args:
- box_encoding: a tuple of 4 floats.
- anchor: a tuple of 4 floats.
- Returns:
- A tuple of 4 floats (xmin, ymin, xmax, ymax), each has range [0.0, 1.0].
- """
- assert len(box_encoding) == 4
- assert len(anchor) == 4
- y_scale = 10.0
- x_scale = 10.0
- height_scale = 5.0
- width_scale = 5.0
-
- rel_y_translation = box_encoding[0] / y_scale
- rel_x_translation = box_encoding[1] / x_scale
- rel_height_dilation = box_encoding[2] / height_scale
- rel_width_dilation = box_encoding[3] / width_scale
-
- anchor_ymin, anchor_xmin, anchor_ymax, anchor_xmax = anchor
- anchor_ycenter = (anchor_ymax + anchor_ymin) / 2
- anchor_xcenter = (anchor_xmax + anchor_xmin) / 2
- anchor_height = anchor_ymax - anchor_ymin
- anchor_width = anchor_xmax - anchor_xmin
-
- ycenter = anchor_ycenter + anchor_height * rel_y_translation
- xcenter = anchor_xcenter + anchor_width * rel_x_translation
- height = math.exp(rel_height_dilation) * anchor_height
- width = math.exp(rel_width_dilation) * anchor_width
-
- # Clamp value to [0.0, 1.0] range, otherwise, part of the bounding box may
- # fall outside of the image.
- xmin = _clamp(xcenter - width / 2)
- ymin = _clamp(ycenter - height / 2)
- xmax = _clamp(xcenter + width / 2)
- ymax = _clamp(ycenter + height / 2)
-
- return (xmin, ymin, xmax, ymax)
-
-
-def _area(box):
- _, _, width, height = box
- area = width * height
- assert area >= 0
- return area
-
-
-def _intersection_area(box1, box2):
- x1, y1, width1, height1 = box1
- x2, y2, width2, height2 = box2
- x = max(x1, x2)
- y = max(y1, y2)
- width = max(min(x1 + width1, x2 + width2) - x, 0)
- height = max(min(y1 + height1, y2 + height2) - y, 0)
- area = width * height
- assert area >= 0
- return area
-
-
-def _overlap_ratio(box1, box2):
- """Computes overlap ratio of two bounding boxes.
-
- Args:
- box1: (x, y, width, height).
- box2: (x, y, width, height).
-
- Returns:
- float, represents overlap ratio between given boxes.
- """
- intersection_area = _intersection_area(box1, box2)
- union_area = _area(box1) + _area(box2) - intersection_area
- assert union_area >= 0
- if union_area > 0:
- return float(intersection_area) / float(union_area)
- return 1.0
-
-
-def _non_maximum_suppression(objs, overlap_threshold=0.5):
- """Runs Non Maximum Suppression.
-
- Removes candidate that overlaps with existing candidate who has higher
- score.
-
- Args:
- objs: list of ObjectDetection.Object
- overlap_threshold: float
- Returns:
- A list of ObjectDetection.Object
- """
- objs = sorted(objs, key=lambda x: x.score, reverse=True)
- for i in range(len(objs)):
- if objs[i].score < 0.0:
- continue
- # Suppress any nearby bounding boxes having lower score than boxes[i]
- for j in range(i + 1, len(objs)):
- if objs[j].score < 0.0:
- continue
- if _overlap_ratio(objs[i].bounding_box,
- objs[j].bounding_box) > overlap_threshold:
- objs[j].score = -1.0 # Suppress box
-
- return [obj for obj in objs if obj.score >= 0.0] # Exclude suppressed boxes
-
-
-def model():
- return ModelDescriptor(
- name='object_detection',
- input_shape=(1, 256, 256, 3),
- input_normalizer=(128.0, 128.0),
- compute_graph=utils.load_compute_graph(_COMPUTE_GRAPH_NAME))
-
-
-# TODO: check all tensor shapes
-def get_objects(result, score_threshold=0.3, offset=(0, 0)):
- assert len(result.tensors) == 2
- logit_scores = tuple(result.tensors['concat_1'].data)
- box_encodings = tuple(result.tensors['concat'].data)
-
- size = (result.window.width, result.window.height)
- objs = _decode_detection_result(logit_scores, box_encodings, ANCHORS,
- score_threshold, size, offset)
- return _non_maximum_suppression(objs)
diff --git a/src/aiy/vision/models/object_detection_anchors.py b/src/aiy/vision/models/object_detection_anchors.py
deleted file mode 100644
index dd2b7d2c..00000000
--- a/src/aiy/vision/models/object_detection_anchors.py
+++ /dev/null
@@ -1,1295 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Predefined anchors for object detection model."""
-
-ANCHORS = (
- (-0.018750000745, -0.018750000745, 0.08124999702, 0.08124999702),
- (-0.039460681379, -0.11017136276, 0.10196068138, 0.17267136276),
- (-0.11017136276, -0.039460681379, 0.17267136276, 0.10196068138),
- (-0.018750000745, 0.043749999255, 0.08124999702, 0.14374999702),
- (-0.039460681379, -0.047671362758, 0.10196068138, 0.23517136276),
- (-0.11017136276, 0.023039318621, 0.17267136276, 0.16446068883),
- (-0.018750000745, 0.10625000298, 0.08124999702, 0.20624999702),
- (-0.039460681379, 0.014828637242, 0.10196068138, 0.29767137766),
- (-0.11017136276, 0.085539318621, 0.17267136276, 0.22696068883),
- (-0.018750000745, 0.16875000298, 0.08124999702, 0.26875001192),
- (-0.039460681379, 0.077328637242, 0.10196068138, 0.36017137766),
- (-0.11017136276, 0.14803931117, 0.17267136276, 0.28946068883),
- (-0.018750000745, 0.23125000298, 0.08124999702, 0.33125001192),
- (-0.039460681379, 0.13982863724, 0.10196068138, 0.42267137766),
- (-0.11017136276, 0.21053931117, 0.17267136276, 0.35196068883),
- (-0.018750000745, 0.29374998808, 0.08124999702, 0.39375001192),
- (-0.039460681379, 0.20232863724, 0.10196068138, 0.48517137766),
- (-0.11017136276, 0.27303931117, 0.17267136276, 0.41446068883),
- (-0.018750000745, 0.35624998808, 0.08124999702, 0.45625001192),
- (-0.039460681379, 0.26482862234, 0.10196068138, 0.54767137766),
- (-0.11017136276, 0.33553931117, 0.17267136276, 0.47696068883),
- (-0.018750000745, 0.41874998808, 0.08124999702, 0.51875001192),
- (-0.039460681379, 0.32732862234, 0.10196068138, 0.61017137766),
- (-0.11017136276, 0.39803931117, 0.17267136276, 0.53946065903),
- (-0.018750000745, 0.48124998808, 0.08124999702, 0.58125001192),
- (-0.039460681379, 0.38982862234, 0.10196068138, 0.67267137766),
- (-0.11017136276, 0.46053931117, 0.17267136276, 0.60196065903),
- (-0.018750000745, 0.54374998808, 0.08124999702, 0.64375001192),
- (-0.039460681379, 0.45232862234, 0.10196068138, 0.73517137766),
- (-0.11017136276, 0.52303934097, 0.17267136276, 0.66446065903),
- (-0.018750000745, 0.60624998808, 0.08124999702, 0.70625001192),
- (-0.039460681379, 0.51482862234, 0.10196068138, 0.79767137766),
- (-0.11017136276, 0.58553934097, 0.17267136276, 0.72696065903),
- (-0.018750000745, 0.66874998808, 0.08124999702, 0.76875001192),
- (-0.039460681379, 0.57732862234, 0.10196068138, 0.86017137766),
- (-0.11017136276, 0.64803934097, 0.17267136276, 0.78946065903),
- (-0.018750000745, 0.73124998808, 0.08124999702, 0.83125001192),
- (-0.039460681379, 0.63982862234, 0.10196068138, 0.92267137766),
- (-0.11017136276, 0.71053934097, 0.17267136276, 0.85196065903),
- (-0.018750000745, 0.79374998808, 0.08124999702, 0.89375001192),
- (-0.039460681379, 0.70232862234, 0.10196068138, 0.98517137766),
- (-0.11017136276, 0.77303934097, 0.17267136276, 0.91446065903),
- (-0.018750000745, 0.85624998808, 0.08124999702, 0.95625001192),
- (-0.039460681379, 0.76482862234, 0.10196068138, 1.0476713181),
- (-0.11017136276, 0.83553934097, 0.17267136276, 0.97696065903),
- (-0.018750000745, 0.91874998808, 0.08124999702, 1.0187499523),
- (-0.039460681379, 0.82732862234, 0.10196068138, 1.1101713181),
- (-0.11017136276, 0.89803934097, 0.17267136276, 1.039460659),
- (0.043749999255, -0.018750000745, 0.14374999702, 0.08124999702),
- (0.023039318621, -0.11017136276, 0.16446068883, 0.17267136276),
- (-0.047671362758, -0.039460681379, 0.23517136276, 0.10196068138),
- (0.043749999255, 0.043749999255, 0.14374999702, 0.14374999702),
- (0.023039318621, -0.047671362758, 0.16446068883, 0.23517136276),
- (-0.047671362758, 0.023039318621, 0.23517136276, 0.16446068883),
- (0.043749999255, 0.10625000298, 0.14374999702, 0.20624999702),
- (0.023039318621, 0.014828637242, 0.16446068883, 0.29767137766),
- (-0.047671362758, 0.085539318621, 0.23517136276, 0.22696068883),
- (0.043749999255, 0.16875000298, 0.14374999702, 0.26875001192),
- (0.023039318621, 0.077328637242, 0.16446068883, 0.36017137766),
- (-0.047671362758, 0.14803931117, 0.23517136276, 0.28946068883),
- (0.043749999255, 0.23125000298, 0.14374999702, 0.33125001192),
- (0.023039318621, 0.13982863724, 0.16446068883, 0.42267137766),
- (-0.047671362758, 0.21053931117, 0.23517136276, 0.35196068883),
- (0.043749999255, 0.29374998808, 0.14374999702, 0.39375001192),
- (0.023039318621, 0.20232863724, 0.16446068883, 0.48517137766),
- (-0.047671362758, 0.27303931117, 0.23517136276, 0.41446068883),
- (0.043749999255, 0.35624998808, 0.14374999702, 0.45625001192),
- (0.023039318621, 0.26482862234, 0.16446068883, 0.54767137766),
- (-0.047671362758, 0.33553931117, 0.23517136276, 0.47696068883),
- (0.043749999255, 0.41874998808, 0.14374999702, 0.51875001192),
- (0.023039318621, 0.32732862234, 0.16446068883, 0.61017137766),
- (-0.047671362758, 0.39803931117, 0.23517136276, 0.53946065903),
- (0.043749999255, 0.48124998808, 0.14374999702, 0.58125001192),
- (0.023039318621, 0.38982862234, 0.16446068883, 0.67267137766),
- (-0.047671362758, 0.46053931117, 0.23517136276, 0.60196065903),
- (0.043749999255, 0.54374998808, 0.14374999702, 0.64375001192),
- (0.023039318621, 0.45232862234, 0.16446068883, 0.73517137766),
- (-0.047671362758, 0.52303934097, 0.23517136276, 0.66446065903),
- (0.043749999255, 0.60624998808, 0.14374999702, 0.70625001192),
- (0.023039318621, 0.51482862234, 0.16446068883, 0.79767137766),
- (-0.047671362758, 0.58553934097, 0.23517136276, 0.72696065903),
- (0.043749999255, 0.66874998808, 0.14374999702, 0.76875001192),
- (0.023039318621, 0.57732862234, 0.16446068883, 0.86017137766),
- (-0.047671362758, 0.64803934097, 0.23517136276, 0.78946065903),
- (0.043749999255, 0.73124998808, 0.14374999702, 0.83125001192),
- (0.023039318621, 0.63982862234, 0.16446068883, 0.92267137766),
- (-0.047671362758, 0.71053934097, 0.23517136276, 0.85196065903),
- (0.043749999255, 0.79374998808, 0.14374999702, 0.89375001192),
- (0.023039318621, 0.70232862234, 0.16446068883, 0.98517137766),
- (-0.047671362758, 0.77303934097, 0.23517136276, 0.91446065903),
- (0.043749999255, 0.85624998808, 0.14374999702, 0.95625001192),
- (0.023039318621, 0.76482862234, 0.16446068883, 1.0476713181),
- (-0.047671362758, 0.83553934097, 0.23517136276, 0.97696065903),
- (0.043749999255, 0.91874998808, 0.14374999702, 1.0187499523),
- (0.023039318621, 0.82732862234, 0.16446068883, 1.1101713181),
- (-0.047671362758, 0.89803934097, 0.23517136276, 1.039460659),
- (0.10625000298, -0.018750000745, 0.20624999702, 0.08124999702),
- (0.085539318621, -0.11017136276, 0.22696068883, 0.17267136276),
- (0.014828637242, -0.039460681379, 0.29767137766, 0.10196068138),
- (0.10625000298, 0.043749999255, 0.20624999702, 0.14374999702),
- (0.085539318621, -0.047671362758, 0.22696068883, 0.23517136276),
- (0.014828637242, 0.023039318621, 0.29767137766, 0.16446068883),
- (0.10625000298, 0.10625000298, 0.20624999702, 0.20624999702),
- (0.085539318621, 0.014828637242, 0.22696068883, 0.29767137766),
- (0.014828637242, 0.085539318621, 0.29767137766, 0.22696068883),
- (0.10625000298, 0.16875000298, 0.20624999702, 0.26875001192),
- (0.085539318621, 0.077328637242, 0.22696068883, 0.36017137766),
- (0.014828637242, 0.14803931117, 0.29767137766, 0.28946068883),
- (0.10625000298, 0.23125000298, 0.20624999702, 0.33125001192),
- (0.085539318621, 0.13982863724, 0.22696068883, 0.42267137766),
- (0.014828637242, 0.21053931117, 0.29767137766, 0.35196068883),
- (0.10625000298, 0.29374998808, 0.20624999702, 0.39375001192),
- (0.085539318621, 0.20232863724, 0.22696068883, 0.48517137766),
- (0.014828637242, 0.27303931117, 0.29767137766, 0.41446068883),
- (0.10625000298, 0.35624998808, 0.20624999702, 0.45625001192),
- (0.085539318621, 0.26482862234, 0.22696068883, 0.54767137766),
- (0.014828637242, 0.33553931117, 0.29767137766, 0.47696068883),
- (0.10625000298, 0.41874998808, 0.20624999702, 0.51875001192),
- (0.085539318621, 0.32732862234, 0.22696068883, 0.61017137766),
- (0.014828637242, 0.39803931117, 0.29767137766, 0.53946065903),
- (0.10625000298, 0.48124998808, 0.20624999702, 0.58125001192),
- (0.085539318621, 0.38982862234, 0.22696068883, 0.67267137766),
- (0.014828637242, 0.46053931117, 0.29767137766, 0.60196065903),
- (0.10625000298, 0.54374998808, 0.20624999702, 0.64375001192),
- (0.085539318621, 0.45232862234, 0.22696068883, 0.73517137766),
- (0.014828637242, 0.52303934097, 0.29767137766, 0.66446065903),
- (0.10625000298, 0.60624998808, 0.20624999702, 0.70625001192),
- (0.085539318621, 0.51482862234, 0.22696068883, 0.79767137766),
- (0.014828637242, 0.58553934097, 0.29767137766, 0.72696065903),
- (0.10625000298, 0.66874998808, 0.20624999702, 0.76875001192),
- (0.085539318621, 0.57732862234, 0.22696068883, 0.86017137766),
- (0.014828637242, 0.64803934097, 0.29767137766, 0.78946065903),
- (0.10625000298, 0.73124998808, 0.20624999702, 0.83125001192),
- (0.085539318621, 0.63982862234, 0.22696068883, 0.92267137766),
- (0.014828637242, 0.71053934097, 0.29767137766, 0.85196065903),
- (0.10625000298, 0.79374998808, 0.20624999702, 0.89375001192),
- (0.085539318621, 0.70232862234, 0.22696068883, 0.98517137766),
- (0.014828637242, 0.77303934097, 0.29767137766, 0.91446065903),
- (0.10625000298, 0.85624998808, 0.20624999702, 0.95625001192),
- (0.085539318621, 0.76482862234, 0.22696068883, 1.0476713181),
- (0.014828637242, 0.83553934097, 0.29767137766, 0.97696065903),
- (0.10625000298, 0.91874998808, 0.20624999702, 1.0187499523),
- (0.085539318621, 0.82732862234, 0.22696068883, 1.1101713181),
- (0.014828637242, 0.89803934097, 0.29767137766, 1.039460659),
- (0.16875000298, -0.018750000745, 0.26875001192, 0.08124999702),
- (0.14803931117, -0.11017136276, 0.28946068883, 0.17267136276),
- (0.077328637242, -0.039460681379, 0.36017137766, 0.10196068138),
- (0.16875000298, 0.043749999255, 0.26875001192, 0.14374999702),
- (0.14803931117, -0.047671362758, 0.28946068883, 0.23517136276),
- (0.077328637242, 0.023039318621, 0.36017137766, 0.16446068883),
- (0.16875000298, 0.10625000298, 0.26875001192, 0.20624999702),
- (0.14803931117, 0.014828637242, 0.28946068883, 0.29767137766),
- (0.077328637242, 0.085539318621, 0.36017137766, 0.22696068883),
- (0.16875000298, 0.16875000298, 0.26875001192, 0.26875001192),
- (0.14803931117, 0.077328637242, 0.28946068883, 0.36017137766),
- (0.077328637242, 0.14803931117, 0.36017137766, 0.28946068883),
- (0.16875000298, 0.23125000298, 0.26875001192, 0.33125001192),
- (0.14803931117, 0.13982863724, 0.28946068883, 0.42267137766),
- (0.077328637242, 0.21053931117, 0.36017137766, 0.35196068883),
- (0.16875000298, 0.29374998808, 0.26875001192, 0.39375001192),
- (0.14803931117, 0.20232863724, 0.28946068883, 0.48517137766),
- (0.077328637242, 0.27303931117, 0.36017137766, 0.41446068883),
- (0.16875000298, 0.35624998808, 0.26875001192, 0.45625001192),
- (0.14803931117, 0.26482862234, 0.28946068883, 0.54767137766),
- (0.077328637242, 0.33553931117, 0.36017137766, 0.47696068883),
- (0.16875000298, 0.41874998808, 0.26875001192, 0.51875001192),
- (0.14803931117, 0.32732862234, 0.28946068883, 0.61017137766),
- (0.077328637242, 0.39803931117, 0.36017137766, 0.53946065903),
- (0.16875000298, 0.48124998808, 0.26875001192, 0.58125001192),
- (0.14803931117, 0.38982862234, 0.28946068883, 0.67267137766),
- (0.077328637242, 0.46053931117, 0.36017137766, 0.60196065903),
- (0.16875000298, 0.54374998808, 0.26875001192, 0.64375001192),
- (0.14803931117, 0.45232862234, 0.28946068883, 0.73517137766),
- (0.077328637242, 0.52303934097, 0.36017137766, 0.66446065903),
- (0.16875000298, 0.60624998808, 0.26875001192, 0.70625001192),
- (0.14803931117, 0.51482862234, 0.28946068883, 0.79767137766),
- (0.077328637242, 0.58553934097, 0.36017137766, 0.72696065903),
- (0.16875000298, 0.66874998808, 0.26875001192, 0.76875001192),
- (0.14803931117, 0.57732862234, 0.28946068883, 0.86017137766),
- (0.077328637242, 0.64803934097, 0.36017137766, 0.78946065903),
- (0.16875000298, 0.73124998808, 0.26875001192, 0.83125001192),
- (0.14803931117, 0.63982862234, 0.28946068883, 0.92267137766),
- (0.077328637242, 0.71053934097, 0.36017137766, 0.85196065903),
- (0.16875000298, 0.79374998808, 0.26875001192, 0.89375001192),
- (0.14803931117, 0.70232862234, 0.28946068883, 0.98517137766),
- (0.077328637242, 0.77303934097, 0.36017137766, 0.91446065903),
- (0.16875000298, 0.85624998808, 0.26875001192, 0.95625001192),
- (0.14803931117, 0.76482862234, 0.28946068883, 1.0476713181),
- (0.077328637242, 0.83553934097, 0.36017137766, 0.97696065903),
- (0.16875000298, 0.91874998808, 0.26875001192, 1.0187499523),
- (0.14803931117, 0.82732862234, 0.28946068883, 1.1101713181),
- (0.077328637242, 0.89803934097, 0.36017137766, 1.039460659),
- (0.23125000298, -0.018750000745, 0.33125001192, 0.08124999702),
- (0.21053931117, -0.11017136276, 0.35196068883, 0.17267136276),
- (0.13982863724, -0.039460681379, 0.42267137766, 0.10196068138),
- (0.23125000298, 0.043749999255, 0.33125001192, 0.14374999702),
- (0.21053931117, -0.047671362758, 0.35196068883, 0.23517136276),
- (0.13982863724, 0.023039318621, 0.42267137766, 0.16446068883),
- (0.23125000298, 0.10625000298, 0.33125001192, 0.20624999702),
- (0.21053931117, 0.014828637242, 0.35196068883, 0.29767137766),
- (0.13982863724, 0.085539318621, 0.42267137766, 0.22696068883),
- (0.23125000298, 0.16875000298, 0.33125001192, 0.26875001192),
- (0.21053931117, 0.077328637242, 0.35196068883, 0.36017137766),
- (0.13982863724, 0.14803931117, 0.42267137766, 0.28946068883),
- (0.23125000298, 0.23125000298, 0.33125001192, 0.33125001192),
- (0.21053931117, 0.13982863724, 0.35196068883, 0.42267137766),
- (0.13982863724, 0.21053931117, 0.42267137766, 0.35196068883),
- (0.23125000298, 0.29374998808, 0.33125001192, 0.39375001192),
- (0.21053931117, 0.20232863724, 0.35196068883, 0.48517137766),
- (0.13982863724, 0.27303931117, 0.42267137766, 0.41446068883),
- (0.23125000298, 0.35624998808, 0.33125001192, 0.45625001192),
- (0.21053931117, 0.26482862234, 0.35196068883, 0.54767137766),
- (0.13982863724, 0.33553931117, 0.42267137766, 0.47696068883),
- (0.23125000298, 0.41874998808, 0.33125001192, 0.51875001192),
- (0.21053931117, 0.32732862234, 0.35196068883, 0.61017137766),
- (0.13982863724, 0.39803931117, 0.42267137766, 0.53946065903),
- (0.23125000298, 0.48124998808, 0.33125001192, 0.58125001192),
- (0.21053931117, 0.38982862234, 0.35196068883, 0.67267137766),
- (0.13982863724, 0.46053931117, 0.42267137766, 0.60196065903),
- (0.23125000298, 0.54374998808, 0.33125001192, 0.64375001192),
- (0.21053931117, 0.45232862234, 0.35196068883, 0.73517137766),
- (0.13982863724, 0.52303934097, 0.42267137766, 0.66446065903),
- (0.23125000298, 0.60624998808, 0.33125001192, 0.70625001192),
- (0.21053931117, 0.51482862234, 0.35196068883, 0.79767137766),
- (0.13982863724, 0.58553934097, 0.42267137766, 0.72696065903),
- (0.23125000298, 0.66874998808, 0.33125001192, 0.76875001192),
- (0.21053931117, 0.57732862234, 0.35196068883, 0.86017137766),
- (0.13982863724, 0.64803934097, 0.42267137766, 0.78946065903),
- (0.23125000298, 0.73124998808, 0.33125001192, 0.83125001192),
- (0.21053931117, 0.63982862234, 0.35196068883, 0.92267137766),
- (0.13982863724, 0.71053934097, 0.42267137766, 0.85196065903),
- (0.23125000298, 0.79374998808, 0.33125001192, 0.89375001192),
- (0.21053931117, 0.70232862234, 0.35196068883, 0.98517137766),
- (0.13982863724, 0.77303934097, 0.42267137766, 0.91446065903),
- (0.23125000298, 0.85624998808, 0.33125001192, 0.95625001192),
- (0.21053931117, 0.76482862234, 0.35196068883, 1.0476713181),
- (0.13982863724, 0.83553934097, 0.42267137766, 0.97696065903),
- (0.23125000298, 0.91874998808, 0.33125001192, 1.0187499523),
- (0.21053931117, 0.82732862234, 0.35196068883, 1.1101713181),
- (0.13982863724, 0.89803934097, 0.42267137766, 1.039460659),
- (0.29374998808, -0.018750000745, 0.39375001192, 0.08124999702),
- (0.27303931117, -0.11017136276, 0.41446068883, 0.17267136276),
- (0.20232863724, -0.039460681379, 0.48517137766, 0.10196068138),
- (0.29374998808, 0.043749999255, 0.39375001192, 0.14374999702),
- (0.27303931117, -0.047671362758, 0.41446068883, 0.23517136276),
- (0.20232863724, 0.023039318621, 0.48517137766, 0.16446068883),
- (0.29374998808, 0.10625000298, 0.39375001192, 0.20624999702),
- (0.27303931117, 0.014828637242, 0.41446068883, 0.29767137766),
- (0.20232863724, 0.085539318621, 0.48517137766, 0.22696068883),
- (0.29374998808, 0.16875000298, 0.39375001192, 0.26875001192),
- (0.27303931117, 0.077328637242, 0.41446068883, 0.36017137766),
- (0.20232863724, 0.14803931117, 0.48517137766, 0.28946068883),
- (0.29374998808, 0.23125000298, 0.39375001192, 0.33125001192),
- (0.27303931117, 0.13982863724, 0.41446068883, 0.42267137766),
- (0.20232863724, 0.21053931117, 0.48517137766, 0.35196068883),
- (0.29374998808, 0.29374998808, 0.39375001192, 0.39375001192),
- (0.27303931117, 0.20232863724, 0.41446068883, 0.48517137766),
- (0.20232863724, 0.27303931117, 0.48517137766, 0.41446068883),
- (0.29374998808, 0.35624998808, 0.39375001192, 0.45625001192),
- (0.27303931117, 0.26482862234, 0.41446068883, 0.54767137766),
- (0.20232863724, 0.33553931117, 0.48517137766, 0.47696068883),
- (0.29374998808, 0.41874998808, 0.39375001192, 0.51875001192),
- (0.27303931117, 0.32732862234, 0.41446068883, 0.61017137766),
- (0.20232863724, 0.39803931117, 0.48517137766, 0.53946065903),
- (0.29374998808, 0.48124998808, 0.39375001192, 0.58125001192),
- (0.27303931117, 0.38982862234, 0.41446068883, 0.67267137766),
- (0.20232863724, 0.46053931117, 0.48517137766, 0.60196065903),
- (0.29374998808, 0.54374998808, 0.39375001192, 0.64375001192),
- (0.27303931117, 0.45232862234, 0.41446068883, 0.73517137766),
- (0.20232863724, 0.52303934097, 0.48517137766, 0.66446065903),
- (0.29374998808, 0.60624998808, 0.39375001192, 0.70625001192),
- (0.27303931117, 0.51482862234, 0.41446068883, 0.79767137766),
- (0.20232863724, 0.58553934097, 0.48517137766, 0.72696065903),
- (0.29374998808, 0.66874998808, 0.39375001192, 0.76875001192),
- (0.27303931117, 0.57732862234, 0.41446068883, 0.86017137766),
- (0.20232863724, 0.64803934097, 0.48517137766, 0.78946065903),
- (0.29374998808, 0.73124998808, 0.39375001192, 0.83125001192),
- (0.27303931117, 0.63982862234, 0.41446068883, 0.92267137766),
- (0.20232863724, 0.71053934097, 0.48517137766, 0.85196065903),
- (0.29374998808, 0.79374998808, 0.39375001192, 0.89375001192),
- (0.27303931117, 0.70232862234, 0.41446068883, 0.98517137766),
- (0.20232863724, 0.77303934097, 0.48517137766, 0.91446065903),
- (0.29374998808, 0.85624998808, 0.39375001192, 0.95625001192),
- (0.27303931117, 0.76482862234, 0.41446068883, 1.0476713181),
- (0.20232863724, 0.83553934097, 0.48517137766, 0.97696065903),
- (0.29374998808, 0.91874998808, 0.39375001192, 1.0187499523),
- (0.27303931117, 0.82732862234, 0.41446068883, 1.1101713181),
- (0.20232863724, 0.89803934097, 0.48517137766, 1.039460659),
- (0.35624998808, -0.018750000745, 0.45625001192, 0.08124999702),
- (0.33553931117, -0.11017136276, 0.47696068883, 0.17267136276),
- (0.26482862234, -0.039460681379, 0.54767137766, 0.10196068138),
- (0.35624998808, 0.043749999255, 0.45625001192, 0.14374999702),
- (0.33553931117, -0.047671362758, 0.47696068883, 0.23517136276),
- (0.26482862234, 0.023039318621, 0.54767137766, 0.16446068883),
- (0.35624998808, 0.10625000298, 0.45625001192, 0.20624999702),
- (0.33553931117, 0.014828637242, 0.47696068883, 0.29767137766),
- (0.26482862234, 0.085539318621, 0.54767137766, 0.22696068883),
- (0.35624998808, 0.16875000298, 0.45625001192, 0.26875001192),
- (0.33553931117, 0.077328637242, 0.47696068883, 0.36017137766),
- (0.26482862234, 0.14803931117, 0.54767137766, 0.28946068883),
- (0.35624998808, 0.23125000298, 0.45625001192, 0.33125001192),
- (0.33553931117, 0.13982863724, 0.47696068883, 0.42267137766),
- (0.26482862234, 0.21053931117, 0.54767137766, 0.35196068883),
- (0.35624998808, 0.29374998808, 0.45625001192, 0.39375001192),
- (0.33553931117, 0.20232863724, 0.47696068883, 0.48517137766),
- (0.26482862234, 0.27303931117, 0.54767137766, 0.41446068883),
- (0.35624998808, 0.35624998808, 0.45625001192, 0.45625001192),
- (0.33553931117, 0.26482862234, 0.47696068883, 0.54767137766),
- (0.26482862234, 0.33553931117, 0.54767137766, 0.47696068883),
- (0.35624998808, 0.41874998808, 0.45625001192, 0.51875001192),
- (0.33553931117, 0.32732862234, 0.47696068883, 0.61017137766),
- (0.26482862234, 0.39803931117, 0.54767137766, 0.53946065903),
- (0.35624998808, 0.48124998808, 0.45625001192, 0.58125001192),
- (0.33553931117, 0.38982862234, 0.47696068883, 0.67267137766),
- (0.26482862234, 0.46053931117, 0.54767137766, 0.60196065903),
- (0.35624998808, 0.54374998808, 0.45625001192, 0.64375001192),
- (0.33553931117, 0.45232862234, 0.47696068883, 0.73517137766),
- (0.26482862234, 0.52303934097, 0.54767137766, 0.66446065903),
- (0.35624998808, 0.60624998808, 0.45625001192, 0.70625001192),
- (0.33553931117, 0.51482862234, 0.47696068883, 0.79767137766),
- (0.26482862234, 0.58553934097, 0.54767137766, 0.72696065903),
- (0.35624998808, 0.66874998808, 0.45625001192, 0.76875001192),
- (0.33553931117, 0.57732862234, 0.47696068883, 0.86017137766),
- (0.26482862234, 0.64803934097, 0.54767137766, 0.78946065903),
- (0.35624998808, 0.73124998808, 0.45625001192, 0.83125001192),
- (0.33553931117, 0.63982862234, 0.47696068883, 0.92267137766),
- (0.26482862234, 0.71053934097, 0.54767137766, 0.85196065903),
- (0.35624998808, 0.79374998808, 0.45625001192, 0.89375001192),
- (0.33553931117, 0.70232862234, 0.47696068883, 0.98517137766),
- (0.26482862234, 0.77303934097, 0.54767137766, 0.91446065903),
- (0.35624998808, 0.85624998808, 0.45625001192, 0.95625001192),
- (0.33553931117, 0.76482862234, 0.47696068883, 1.0476713181),
- (0.26482862234, 0.83553934097, 0.54767137766, 0.97696065903),
- (0.35624998808, 0.91874998808, 0.45625001192, 1.0187499523),
- (0.33553931117, 0.82732862234, 0.47696068883, 1.1101713181),
- (0.26482862234, 0.89803934097, 0.54767137766, 1.039460659),
- (0.41874998808, -0.018750000745, 0.51875001192, 0.08124999702),
- (0.39803931117, -0.11017136276, 0.53946065903, 0.17267136276),
- (0.32732862234, -0.039460681379, 0.61017137766, 0.10196068138),
- (0.41874998808, 0.043749999255, 0.51875001192, 0.14374999702),
- (0.39803931117, -0.047671362758, 0.53946065903, 0.23517136276),
- (0.32732862234, 0.023039318621, 0.61017137766, 0.16446068883),
- (0.41874998808, 0.10625000298, 0.51875001192, 0.20624999702),
- (0.39803931117, 0.014828637242, 0.53946065903, 0.29767137766),
- (0.32732862234, 0.085539318621, 0.61017137766, 0.22696068883),
- (0.41874998808, 0.16875000298, 0.51875001192, 0.26875001192),
- (0.39803931117, 0.077328637242, 0.53946065903, 0.36017137766),
- (0.32732862234, 0.14803931117, 0.61017137766, 0.28946068883),
- (0.41874998808, 0.23125000298, 0.51875001192, 0.33125001192),
- (0.39803931117, 0.13982863724, 0.53946065903, 0.42267137766),
- (0.32732862234, 0.21053931117, 0.61017137766, 0.35196068883),
- (0.41874998808, 0.29374998808, 0.51875001192, 0.39375001192),
- (0.39803931117, 0.20232863724, 0.53946065903, 0.48517137766),
- (0.32732862234, 0.27303931117, 0.61017137766, 0.41446068883),
- (0.41874998808, 0.35624998808, 0.51875001192, 0.45625001192),
- (0.39803931117, 0.26482862234, 0.53946065903, 0.54767137766),
- (0.32732862234, 0.33553931117, 0.61017137766, 0.47696068883),
- (0.41874998808, 0.41874998808, 0.51875001192, 0.51875001192),
- (0.39803931117, 0.32732862234, 0.53946065903, 0.61017137766),
- (0.32732862234, 0.39803931117, 0.61017137766, 0.53946065903),
- (0.41874998808, 0.48124998808, 0.51875001192, 0.58125001192),
- (0.39803931117, 0.38982862234, 0.53946065903, 0.67267137766),
- (0.32732862234, 0.46053931117, 0.61017137766, 0.60196065903),
- (0.41874998808, 0.54374998808, 0.51875001192, 0.64375001192),
- (0.39803931117, 0.45232862234, 0.53946065903, 0.73517137766),
- (0.32732862234, 0.52303934097, 0.61017137766, 0.66446065903),
- (0.41874998808, 0.60624998808, 0.51875001192, 0.70625001192),
- (0.39803931117, 0.51482862234, 0.53946065903, 0.79767137766),
- (0.32732862234, 0.58553934097, 0.61017137766, 0.72696065903),
- (0.41874998808, 0.66874998808, 0.51875001192, 0.76875001192),
- (0.39803931117, 0.57732862234, 0.53946065903, 0.86017137766),
- (0.32732862234, 0.64803934097, 0.61017137766, 0.78946065903),
- (0.41874998808, 0.73124998808, 0.51875001192, 0.83125001192),
- (0.39803931117, 0.63982862234, 0.53946065903, 0.92267137766),
- (0.32732862234, 0.71053934097, 0.61017137766, 0.85196065903),
- (0.41874998808, 0.79374998808, 0.51875001192, 0.89375001192),
- (0.39803931117, 0.70232862234, 0.53946065903, 0.98517137766),
- (0.32732862234, 0.77303934097, 0.61017137766, 0.91446065903),
- (0.41874998808, 0.85624998808, 0.51875001192, 0.95625001192),
- (0.39803931117, 0.76482862234, 0.53946065903, 1.0476713181),
- (0.32732862234, 0.83553934097, 0.61017137766, 0.97696065903),
- (0.41874998808, 0.91874998808, 0.51875001192, 1.0187499523),
- (0.39803931117, 0.82732862234, 0.53946065903, 1.1101713181),
- (0.32732862234, 0.89803934097, 0.61017137766, 1.039460659),
- (0.48124998808, -0.018750000745, 0.58125001192, 0.08124999702),
- (0.46053931117, -0.11017136276, 0.60196065903, 0.17267136276),
- (0.38982862234, -0.039460681379, 0.67267137766, 0.10196068138),
- (0.48124998808, 0.043749999255, 0.58125001192, 0.14374999702),
- (0.46053931117, -0.047671362758, 0.60196065903, 0.23517136276),
- (0.38982862234, 0.023039318621, 0.67267137766, 0.16446068883),
- (0.48124998808, 0.10625000298, 0.58125001192, 0.20624999702),
- (0.46053931117, 0.014828637242, 0.60196065903, 0.29767137766),
- (0.38982862234, 0.085539318621, 0.67267137766, 0.22696068883),
- (0.48124998808, 0.16875000298, 0.58125001192, 0.26875001192),
- (0.46053931117, 0.077328637242, 0.60196065903, 0.36017137766),
- (0.38982862234, 0.14803931117, 0.67267137766, 0.28946068883),
- (0.48124998808, 0.23125000298, 0.58125001192, 0.33125001192),
- (0.46053931117, 0.13982863724, 0.60196065903, 0.42267137766),
- (0.38982862234, 0.21053931117, 0.67267137766, 0.35196068883),
- (0.48124998808, 0.29374998808, 0.58125001192, 0.39375001192),
- (0.46053931117, 0.20232863724, 0.60196065903, 0.48517137766),
- (0.38982862234, 0.27303931117, 0.67267137766, 0.41446068883),
- (0.48124998808, 0.35624998808, 0.58125001192, 0.45625001192),
- (0.46053931117, 0.26482862234, 0.60196065903, 0.54767137766),
- (0.38982862234, 0.33553931117, 0.67267137766, 0.47696068883),
- (0.48124998808, 0.41874998808, 0.58125001192, 0.51875001192),
- (0.46053931117, 0.32732862234, 0.60196065903, 0.61017137766),
- (0.38982862234, 0.39803931117, 0.67267137766, 0.53946065903),
- (0.48124998808, 0.48124998808, 0.58125001192, 0.58125001192),
- (0.46053931117, 0.38982862234, 0.60196065903, 0.67267137766),
- (0.38982862234, 0.46053931117, 0.67267137766, 0.60196065903),
- (0.48124998808, 0.54374998808, 0.58125001192, 0.64375001192),
- (0.46053931117, 0.45232862234, 0.60196065903, 0.73517137766),
- (0.38982862234, 0.52303934097, 0.67267137766, 0.66446065903),
- (0.48124998808, 0.60624998808, 0.58125001192, 0.70625001192),
- (0.46053931117, 0.51482862234, 0.60196065903, 0.79767137766),
- (0.38982862234, 0.58553934097, 0.67267137766, 0.72696065903),
- (0.48124998808, 0.66874998808, 0.58125001192, 0.76875001192),
- (0.46053931117, 0.57732862234, 0.60196065903, 0.86017137766),
- (0.38982862234, 0.64803934097, 0.67267137766, 0.78946065903),
- (0.48124998808, 0.73124998808, 0.58125001192, 0.83125001192),
- (0.46053931117, 0.63982862234, 0.60196065903, 0.92267137766),
- (0.38982862234, 0.71053934097, 0.67267137766, 0.85196065903),
- (0.48124998808, 0.79374998808, 0.58125001192, 0.89375001192),
- (0.46053931117, 0.70232862234, 0.60196065903, 0.98517137766),
- (0.38982862234, 0.77303934097, 0.67267137766, 0.91446065903),
- (0.48124998808, 0.85624998808, 0.58125001192, 0.95625001192),
- (0.46053931117, 0.76482862234, 0.60196065903, 1.0476713181),
- (0.38982862234, 0.83553934097, 0.67267137766, 0.97696065903),
- (0.48124998808, 0.91874998808, 0.58125001192, 1.0187499523),
- (0.46053931117, 0.82732862234, 0.60196065903, 1.1101713181),
- (0.38982862234, 0.89803934097, 0.67267137766, 1.039460659),
- (0.54374998808, -0.018750000745, 0.64375001192, 0.08124999702),
- (0.52303934097, -0.11017136276, 0.66446065903, 0.17267136276),
- (0.45232862234, -0.039460681379, 0.73517137766, 0.10196068138),
- (0.54374998808, 0.043749999255, 0.64375001192, 0.14374999702),
- (0.52303934097, -0.047671362758, 0.66446065903, 0.23517136276),
- (0.45232862234, 0.023039318621, 0.73517137766, 0.16446068883),
- (0.54374998808, 0.10625000298, 0.64375001192, 0.20624999702),
- (0.52303934097, 0.014828637242, 0.66446065903, 0.29767137766),
- (0.45232862234, 0.085539318621, 0.73517137766, 0.22696068883),
- (0.54374998808, 0.16875000298, 0.64375001192, 0.26875001192),
- (0.52303934097, 0.077328637242, 0.66446065903, 0.36017137766),
- (0.45232862234, 0.14803931117, 0.73517137766, 0.28946068883),
- (0.54374998808, 0.23125000298, 0.64375001192, 0.33125001192),
- (0.52303934097, 0.13982863724, 0.66446065903, 0.42267137766),
- (0.45232862234, 0.21053931117, 0.73517137766, 0.35196068883),
- (0.54374998808, 0.29374998808, 0.64375001192, 0.39375001192),
- (0.52303934097, 0.20232863724, 0.66446065903, 0.48517137766),
- (0.45232862234, 0.27303931117, 0.73517137766, 0.41446068883),
- (0.54374998808, 0.35624998808, 0.64375001192, 0.45625001192),
- (0.52303934097, 0.26482862234, 0.66446065903, 0.54767137766),
- (0.45232862234, 0.33553931117, 0.73517137766, 0.47696068883),
- (0.54374998808, 0.41874998808, 0.64375001192, 0.51875001192),
- (0.52303934097, 0.32732862234, 0.66446065903, 0.61017137766),
- (0.45232862234, 0.39803931117, 0.73517137766, 0.53946065903),
- (0.54374998808, 0.48124998808, 0.64375001192, 0.58125001192),
- (0.52303934097, 0.38982862234, 0.66446065903, 0.67267137766),
- (0.45232862234, 0.46053931117, 0.73517137766, 0.60196065903),
- (0.54374998808, 0.54374998808, 0.64375001192, 0.64375001192),
- (0.52303934097, 0.45232862234, 0.66446065903, 0.73517137766),
- (0.45232862234, 0.52303934097, 0.73517137766, 0.66446065903),
- (0.54374998808, 0.60624998808, 0.64375001192, 0.70625001192),
- (0.52303934097, 0.51482862234, 0.66446065903, 0.79767137766),
- (0.45232862234, 0.58553934097, 0.73517137766, 0.72696065903),
- (0.54374998808, 0.66874998808, 0.64375001192, 0.76875001192),
- (0.52303934097, 0.57732862234, 0.66446065903, 0.86017137766),
- (0.45232862234, 0.64803934097, 0.73517137766, 0.78946065903),
- (0.54374998808, 0.73124998808, 0.64375001192, 0.83125001192),
- (0.52303934097, 0.63982862234, 0.66446065903, 0.92267137766),
- (0.45232862234, 0.71053934097, 0.73517137766, 0.85196065903),
- (0.54374998808, 0.79374998808, 0.64375001192, 0.89375001192),
- (0.52303934097, 0.70232862234, 0.66446065903, 0.98517137766),
- (0.45232862234, 0.77303934097, 0.73517137766, 0.91446065903),
- (0.54374998808, 0.85624998808, 0.64375001192, 0.95625001192),
- (0.52303934097, 0.76482862234, 0.66446065903, 1.0476713181),
- (0.45232862234, 0.83553934097, 0.73517137766, 0.97696065903),
- (0.54374998808, 0.91874998808, 0.64375001192, 1.0187499523),
- (0.52303934097, 0.82732862234, 0.66446065903, 1.1101713181),
- (0.45232862234, 0.89803934097, 0.73517137766, 1.039460659),
- (0.60624998808, -0.018750000745, 0.70625001192, 0.08124999702),
- (0.58553934097, -0.11017136276, 0.72696065903, 0.17267136276),
- (0.51482862234, -0.039460681379, 0.79767137766, 0.10196068138),
- (0.60624998808, 0.043749999255, 0.70625001192, 0.14374999702),
- (0.58553934097, -0.047671362758, 0.72696065903, 0.23517136276),
- (0.51482862234, 0.023039318621, 0.79767137766, 0.16446068883),
- (0.60624998808, 0.10625000298, 0.70625001192, 0.20624999702),
- (0.58553934097, 0.014828637242, 0.72696065903, 0.29767137766),
- (0.51482862234, 0.085539318621, 0.79767137766, 0.22696068883),
- (0.60624998808, 0.16875000298, 0.70625001192, 0.26875001192),
- (0.58553934097, 0.077328637242, 0.72696065903, 0.36017137766),
- (0.51482862234, 0.14803931117, 0.79767137766, 0.28946068883),
- (0.60624998808, 0.23125000298, 0.70625001192, 0.33125001192),
- (0.58553934097, 0.13982863724, 0.72696065903, 0.42267137766),
- (0.51482862234, 0.21053931117, 0.79767137766, 0.35196068883),
- (0.60624998808, 0.29374998808, 0.70625001192, 0.39375001192),
- (0.58553934097, 0.20232863724, 0.72696065903, 0.48517137766),
- (0.51482862234, 0.27303931117, 0.79767137766, 0.41446068883),
- (0.60624998808, 0.35624998808, 0.70625001192, 0.45625001192),
- (0.58553934097, 0.26482862234, 0.72696065903, 0.54767137766),
- (0.51482862234, 0.33553931117, 0.79767137766, 0.47696068883),
- (0.60624998808, 0.41874998808, 0.70625001192, 0.51875001192),
- (0.58553934097, 0.32732862234, 0.72696065903, 0.61017137766),
- (0.51482862234, 0.39803931117, 0.79767137766, 0.53946065903),
- (0.60624998808, 0.48124998808, 0.70625001192, 0.58125001192),
- (0.58553934097, 0.38982862234, 0.72696065903, 0.67267137766),
- (0.51482862234, 0.46053931117, 0.79767137766, 0.60196065903),
- (0.60624998808, 0.54374998808, 0.70625001192, 0.64375001192),
- (0.58553934097, 0.45232862234, 0.72696065903, 0.73517137766),
- (0.51482862234, 0.52303934097, 0.79767137766, 0.66446065903),
- (0.60624998808, 0.60624998808, 0.70625001192, 0.70625001192),
- (0.58553934097, 0.51482862234, 0.72696065903, 0.79767137766),
- (0.51482862234, 0.58553934097, 0.79767137766, 0.72696065903),
- (0.60624998808, 0.66874998808, 0.70625001192, 0.76875001192),
- (0.58553934097, 0.57732862234, 0.72696065903, 0.86017137766),
- (0.51482862234, 0.64803934097, 0.79767137766, 0.78946065903),
- (0.60624998808, 0.73124998808, 0.70625001192, 0.83125001192),
- (0.58553934097, 0.63982862234, 0.72696065903, 0.92267137766),
- (0.51482862234, 0.71053934097, 0.79767137766, 0.85196065903),
- (0.60624998808, 0.79374998808, 0.70625001192, 0.89375001192),
- (0.58553934097, 0.70232862234, 0.72696065903, 0.98517137766),
- (0.51482862234, 0.77303934097, 0.79767137766, 0.91446065903),
- (0.60624998808, 0.85624998808, 0.70625001192, 0.95625001192),
- (0.58553934097, 0.76482862234, 0.72696065903, 1.0476713181),
- (0.51482862234, 0.83553934097, 0.79767137766, 0.97696065903),
- (0.60624998808, 0.91874998808, 0.70625001192, 1.0187499523),
- (0.58553934097, 0.82732862234, 0.72696065903, 1.1101713181),
- (0.51482862234, 0.89803934097, 0.79767137766, 1.039460659),
- (0.66874998808, -0.018750000745, 0.76875001192, 0.08124999702),
- (0.64803934097, -0.11017136276, 0.78946065903, 0.17267136276),
- (0.57732862234, -0.039460681379, 0.86017137766, 0.10196068138),
- (0.66874998808, 0.043749999255, 0.76875001192, 0.14374999702),
- (0.64803934097, -0.047671362758, 0.78946065903, 0.23517136276),
- (0.57732862234, 0.023039318621, 0.86017137766, 0.16446068883),
- (0.66874998808, 0.10625000298, 0.76875001192, 0.20624999702),
- (0.64803934097, 0.014828637242, 0.78946065903, 0.29767137766),
- (0.57732862234, 0.085539318621, 0.86017137766, 0.22696068883),
- (0.66874998808, 0.16875000298, 0.76875001192, 0.26875001192),
- (0.64803934097, 0.077328637242, 0.78946065903, 0.36017137766),
- (0.57732862234, 0.14803931117, 0.86017137766, 0.28946068883),
- (0.66874998808, 0.23125000298, 0.76875001192, 0.33125001192),
- (0.64803934097, 0.13982863724, 0.78946065903, 0.42267137766),
- (0.57732862234, 0.21053931117, 0.86017137766, 0.35196068883),
- (0.66874998808, 0.29374998808, 0.76875001192, 0.39375001192),
- (0.64803934097, 0.20232863724, 0.78946065903, 0.48517137766),
- (0.57732862234, 0.27303931117, 0.86017137766, 0.41446068883),
- (0.66874998808, 0.35624998808, 0.76875001192, 0.45625001192),
- (0.64803934097, 0.26482862234, 0.78946065903, 0.54767137766),
- (0.57732862234, 0.33553931117, 0.86017137766, 0.47696068883),
- (0.66874998808, 0.41874998808, 0.76875001192, 0.51875001192),
- (0.64803934097, 0.32732862234, 0.78946065903, 0.61017137766),
- (0.57732862234, 0.39803931117, 0.86017137766, 0.53946065903),
- (0.66874998808, 0.48124998808, 0.76875001192, 0.58125001192),
- (0.64803934097, 0.38982862234, 0.78946065903, 0.67267137766),
- (0.57732862234, 0.46053931117, 0.86017137766, 0.60196065903),
- (0.66874998808, 0.54374998808, 0.76875001192, 0.64375001192),
- (0.64803934097, 0.45232862234, 0.78946065903, 0.73517137766),
- (0.57732862234, 0.52303934097, 0.86017137766, 0.66446065903),
- (0.66874998808, 0.60624998808, 0.76875001192, 0.70625001192),
- (0.64803934097, 0.51482862234, 0.78946065903, 0.79767137766),
- (0.57732862234, 0.58553934097, 0.86017137766, 0.72696065903),
- (0.66874998808, 0.66874998808, 0.76875001192, 0.76875001192),
- (0.64803934097, 0.57732862234, 0.78946065903, 0.86017137766),
- (0.57732862234, 0.64803934097, 0.86017137766, 0.78946065903),
- (0.66874998808, 0.73124998808, 0.76875001192, 0.83125001192),
- (0.64803934097, 0.63982862234, 0.78946065903, 0.92267137766),
- (0.57732862234, 0.71053934097, 0.86017137766, 0.85196065903),
- (0.66874998808, 0.79374998808, 0.76875001192, 0.89375001192),
- (0.64803934097, 0.70232862234, 0.78946065903, 0.98517137766),
- (0.57732862234, 0.77303934097, 0.86017137766, 0.91446065903),
- (0.66874998808, 0.85624998808, 0.76875001192, 0.95625001192),
- (0.64803934097, 0.76482862234, 0.78946065903, 1.0476713181),
- (0.57732862234, 0.83553934097, 0.86017137766, 0.97696065903),
- (0.66874998808, 0.91874998808, 0.76875001192, 1.0187499523),
- (0.64803934097, 0.82732862234, 0.78946065903, 1.1101713181),
- (0.57732862234, 0.89803934097, 0.86017137766, 1.039460659),
- (0.73124998808, -0.018750000745, 0.83125001192, 0.08124999702),
- (0.71053934097, -0.11017136276, 0.85196065903, 0.17267136276),
- (0.63982862234, -0.039460681379, 0.92267137766, 0.10196068138),
- (0.73124998808, 0.043749999255, 0.83125001192, 0.14374999702),
- (0.71053934097, -0.047671362758, 0.85196065903, 0.23517136276),
- (0.63982862234, 0.023039318621, 0.92267137766, 0.16446068883),
- (0.73124998808, 0.10625000298, 0.83125001192, 0.20624999702),
- (0.71053934097, 0.014828637242, 0.85196065903, 0.29767137766),
- (0.63982862234, 0.085539318621, 0.92267137766, 0.22696068883),
- (0.73124998808, 0.16875000298, 0.83125001192, 0.26875001192),
- (0.71053934097, 0.077328637242, 0.85196065903, 0.36017137766),
- (0.63982862234, 0.14803931117, 0.92267137766, 0.28946068883),
- (0.73124998808, 0.23125000298, 0.83125001192, 0.33125001192),
- (0.71053934097, 0.13982863724, 0.85196065903, 0.42267137766),
- (0.63982862234, 0.21053931117, 0.92267137766, 0.35196068883),
- (0.73124998808, 0.29374998808, 0.83125001192, 0.39375001192),
- (0.71053934097, 0.20232863724, 0.85196065903, 0.48517137766),
- (0.63982862234, 0.27303931117, 0.92267137766, 0.41446068883),
- (0.73124998808, 0.35624998808, 0.83125001192, 0.45625001192),
- (0.71053934097, 0.26482862234, 0.85196065903, 0.54767137766),
- (0.63982862234, 0.33553931117, 0.92267137766, 0.47696068883),
- (0.73124998808, 0.41874998808, 0.83125001192, 0.51875001192),
- (0.71053934097, 0.32732862234, 0.85196065903, 0.61017137766),
- (0.63982862234, 0.39803931117, 0.92267137766, 0.53946065903),
- (0.73124998808, 0.48124998808, 0.83125001192, 0.58125001192),
- (0.71053934097, 0.38982862234, 0.85196065903, 0.67267137766),
- (0.63982862234, 0.46053931117, 0.92267137766, 0.60196065903),
- (0.73124998808, 0.54374998808, 0.83125001192, 0.64375001192),
- (0.71053934097, 0.45232862234, 0.85196065903, 0.73517137766),
- (0.63982862234, 0.52303934097, 0.92267137766, 0.66446065903),
- (0.73124998808, 0.60624998808, 0.83125001192, 0.70625001192),
- (0.71053934097, 0.51482862234, 0.85196065903, 0.79767137766),
- (0.63982862234, 0.58553934097, 0.92267137766, 0.72696065903),
- (0.73124998808, 0.66874998808, 0.83125001192, 0.76875001192),
- (0.71053934097, 0.57732862234, 0.85196065903, 0.86017137766),
- (0.63982862234, 0.64803934097, 0.92267137766, 0.78946065903),
- (0.73124998808, 0.73124998808, 0.83125001192, 0.83125001192),
- (0.71053934097, 0.63982862234, 0.85196065903, 0.92267137766),
- (0.63982862234, 0.71053934097, 0.92267137766, 0.85196065903),
- (0.73124998808, 0.79374998808, 0.83125001192, 0.89375001192),
- (0.71053934097, 0.70232862234, 0.85196065903, 0.98517137766),
- (0.63982862234, 0.77303934097, 0.92267137766, 0.91446065903),
- (0.73124998808, 0.85624998808, 0.83125001192, 0.95625001192),
- (0.71053934097, 0.76482862234, 0.85196065903, 1.0476713181),
- (0.63982862234, 0.83553934097, 0.92267137766, 0.97696065903),
- (0.73124998808, 0.91874998808, 0.83125001192, 1.0187499523),
- (0.71053934097, 0.82732862234, 0.85196065903, 1.1101713181),
- (0.63982862234, 0.89803934097, 0.92267137766, 1.039460659),
- (0.79374998808, -0.018750000745, 0.89375001192, 0.08124999702),
- (0.77303934097, -0.11017136276, 0.91446065903, 0.17267136276),
- (0.70232862234, -0.039460681379, 0.98517137766, 0.10196068138),
- (0.79374998808, 0.043749999255, 0.89375001192, 0.14374999702),
- (0.77303934097, -0.047671362758, 0.91446065903, 0.23517136276),
- (0.70232862234, 0.023039318621, 0.98517137766, 0.16446068883),
- (0.79374998808, 0.10625000298, 0.89375001192, 0.20624999702),
- (0.77303934097, 0.014828637242, 0.91446065903, 0.29767137766),
- (0.70232862234, 0.085539318621, 0.98517137766, 0.22696068883),
- (0.79374998808, 0.16875000298, 0.89375001192, 0.26875001192),
- (0.77303934097, 0.077328637242, 0.91446065903, 0.36017137766),
- (0.70232862234, 0.14803931117, 0.98517137766, 0.28946068883),
- (0.79374998808, 0.23125000298, 0.89375001192, 0.33125001192),
- (0.77303934097, 0.13982863724, 0.91446065903, 0.42267137766),
- (0.70232862234, 0.21053931117, 0.98517137766, 0.35196068883),
- (0.79374998808, 0.29374998808, 0.89375001192, 0.39375001192),
- (0.77303934097, 0.20232863724, 0.91446065903, 0.48517137766),
- (0.70232862234, 0.27303931117, 0.98517137766, 0.41446068883),
- (0.79374998808, 0.35624998808, 0.89375001192, 0.45625001192),
- (0.77303934097, 0.26482862234, 0.91446065903, 0.54767137766),
- (0.70232862234, 0.33553931117, 0.98517137766, 0.47696068883),
- (0.79374998808, 0.41874998808, 0.89375001192, 0.51875001192),
- (0.77303934097, 0.32732862234, 0.91446065903, 0.61017137766),
- (0.70232862234, 0.39803931117, 0.98517137766, 0.53946065903),
- (0.79374998808, 0.48124998808, 0.89375001192, 0.58125001192),
- (0.77303934097, 0.38982862234, 0.91446065903, 0.67267137766),
- (0.70232862234, 0.46053931117, 0.98517137766, 0.60196065903),
- (0.79374998808, 0.54374998808, 0.89375001192, 0.64375001192),
- (0.77303934097, 0.45232862234, 0.91446065903, 0.73517137766),
- (0.70232862234, 0.52303934097, 0.98517137766, 0.66446065903),
- (0.79374998808, 0.60624998808, 0.89375001192, 0.70625001192),
- (0.77303934097, 0.51482862234, 0.91446065903, 0.79767137766),
- (0.70232862234, 0.58553934097, 0.98517137766, 0.72696065903),
- (0.79374998808, 0.66874998808, 0.89375001192, 0.76875001192),
- (0.77303934097, 0.57732862234, 0.91446065903, 0.86017137766),
- (0.70232862234, 0.64803934097, 0.98517137766, 0.78946065903),
- (0.79374998808, 0.73124998808, 0.89375001192, 0.83125001192),
- (0.77303934097, 0.63982862234, 0.91446065903, 0.92267137766),
- (0.70232862234, 0.71053934097, 0.98517137766, 0.85196065903),
- (0.79374998808, 0.79374998808, 0.89375001192, 0.89375001192),
- (0.77303934097, 0.70232862234, 0.91446065903, 0.98517137766),
- (0.70232862234, 0.77303934097, 0.98517137766, 0.91446065903),
- (0.79374998808, 0.85624998808, 0.89375001192, 0.95625001192),
- (0.77303934097, 0.76482862234, 0.91446065903, 1.0476713181),
- (0.70232862234, 0.83553934097, 0.98517137766, 0.97696065903),
- (0.79374998808, 0.91874998808, 0.89375001192, 1.0187499523),
- (0.77303934097, 0.82732862234, 0.91446065903, 1.1101713181),
- (0.70232862234, 0.89803934097, 0.98517137766, 1.039460659),
- (0.85624998808, -0.018750000745, 0.95625001192, 0.08124999702),
- (0.83553934097, -0.11017136276, 0.97696065903, 0.17267136276),
- (0.76482862234, -0.039460681379, 1.0476713181, 0.10196068138),
- (0.85624998808, 0.043749999255, 0.95625001192, 0.14374999702),
- (0.83553934097, -0.047671362758, 0.97696065903, 0.23517136276),
- (0.76482862234, 0.023039318621, 1.0476713181, 0.16446068883),
- (0.85624998808, 0.10625000298, 0.95625001192, 0.20624999702),
- (0.83553934097, 0.014828637242, 0.97696065903, 0.29767137766),
- (0.76482862234, 0.085539318621, 1.0476713181, 0.22696068883),
- (0.85624998808, 0.16875000298, 0.95625001192, 0.26875001192),
- (0.83553934097, 0.077328637242, 0.97696065903, 0.36017137766),
- (0.76482862234, 0.14803931117, 1.0476713181, 0.28946068883),
- (0.85624998808, 0.23125000298, 0.95625001192, 0.33125001192),
- (0.83553934097, 0.13982863724, 0.97696065903, 0.42267137766),
- (0.76482862234, 0.21053931117, 1.0476713181, 0.35196068883),
- (0.85624998808, 0.29374998808, 0.95625001192, 0.39375001192),
- (0.83553934097, 0.20232863724, 0.97696065903, 0.48517137766),
- (0.76482862234, 0.27303931117, 1.0476713181, 0.41446068883),
- (0.85624998808, 0.35624998808, 0.95625001192, 0.45625001192),
- (0.83553934097, 0.26482862234, 0.97696065903, 0.54767137766),
- (0.76482862234, 0.33553931117, 1.0476713181, 0.47696068883),
- (0.85624998808, 0.41874998808, 0.95625001192, 0.51875001192),
- (0.83553934097, 0.32732862234, 0.97696065903, 0.61017137766),
- (0.76482862234, 0.39803931117, 1.0476713181, 0.53946065903),
- (0.85624998808, 0.48124998808, 0.95625001192, 0.58125001192),
- (0.83553934097, 0.38982862234, 0.97696065903, 0.67267137766),
- (0.76482862234, 0.46053931117, 1.0476713181, 0.60196065903),
- (0.85624998808, 0.54374998808, 0.95625001192, 0.64375001192),
- (0.83553934097, 0.45232862234, 0.97696065903, 0.73517137766),
- (0.76482862234, 0.52303934097, 1.0476713181, 0.66446065903),
- (0.85624998808, 0.60624998808, 0.95625001192, 0.70625001192),
- (0.83553934097, 0.51482862234, 0.97696065903, 0.79767137766),
- (0.76482862234, 0.58553934097, 1.0476713181, 0.72696065903),
- (0.85624998808, 0.66874998808, 0.95625001192, 0.76875001192),
- (0.83553934097, 0.57732862234, 0.97696065903, 0.86017137766),
- (0.76482862234, 0.64803934097, 1.0476713181, 0.78946065903),
- (0.85624998808, 0.73124998808, 0.95625001192, 0.83125001192),
- (0.83553934097, 0.63982862234, 0.97696065903, 0.92267137766),
- (0.76482862234, 0.71053934097, 1.0476713181, 0.85196065903),
- (0.85624998808, 0.79374998808, 0.95625001192, 0.89375001192),
- (0.83553934097, 0.70232862234, 0.97696065903, 0.98517137766),
- (0.76482862234, 0.77303934097, 1.0476713181, 0.91446065903),
- (0.85624998808, 0.85624998808, 0.95625001192, 0.95625001192),
- (0.83553934097, 0.76482862234, 0.97696065903, 1.0476713181),
- (0.76482862234, 0.83553934097, 1.0476713181, 0.97696065903),
- (0.85624998808, 0.91874998808, 0.95625001192, 1.0187499523),
- (0.83553934097, 0.82732862234, 0.97696065903, 1.1101713181),
- (0.76482862234, 0.89803934097, 1.0476713181, 1.039460659),
- (0.91874998808, -0.018750000745, 1.0187499523, 0.08124999702),
- (0.89803934097, -0.11017136276, 1.039460659, 0.17267136276),
- (0.82732862234, -0.039460681379, 1.1101713181, 0.10196068138),
- (0.91874998808, 0.043749999255, 1.0187499523, 0.14374999702),
- (0.89803934097, -0.047671362758, 1.039460659, 0.23517136276),
- (0.82732862234, 0.023039318621, 1.1101713181, 0.16446068883),
- (0.91874998808, 0.10625000298, 1.0187499523, 0.20624999702),
- (0.89803934097, 0.014828637242, 1.039460659, 0.29767137766),
- (0.82732862234, 0.085539318621, 1.1101713181, 0.22696068883),
- (0.91874998808, 0.16875000298, 1.0187499523, 0.26875001192),
- (0.89803934097, 0.077328637242, 1.039460659, 0.36017137766),
- (0.82732862234, 0.14803931117, 1.1101713181, 0.28946068883),
- (0.91874998808, 0.23125000298, 1.0187499523, 0.33125001192),
- (0.89803934097, 0.13982863724, 1.039460659, 0.42267137766),
- (0.82732862234, 0.21053931117, 1.1101713181, 0.35196068883),
- (0.91874998808, 0.29374998808, 1.0187499523, 0.39375001192),
- (0.89803934097, 0.20232863724, 1.039460659, 0.48517137766),
- (0.82732862234, 0.27303931117, 1.1101713181, 0.41446068883),
- (0.91874998808, 0.35624998808, 1.0187499523, 0.45625001192),
- (0.89803934097, 0.26482862234, 1.039460659, 0.54767137766),
- (0.82732862234, 0.33553931117, 1.1101713181, 0.47696068883),
- (0.91874998808, 0.41874998808, 1.0187499523, 0.51875001192),
- (0.89803934097, 0.32732862234, 1.039460659, 0.61017137766),
- (0.82732862234, 0.39803931117, 1.1101713181, 0.53946065903),
- (0.91874998808, 0.48124998808, 1.0187499523, 0.58125001192),
- (0.89803934097, 0.38982862234, 1.039460659, 0.67267137766),
- (0.82732862234, 0.46053931117, 1.1101713181, 0.60196065903),
- (0.91874998808, 0.54374998808, 1.0187499523, 0.64375001192),
- (0.89803934097, 0.45232862234, 1.039460659, 0.73517137766),
- (0.82732862234, 0.52303934097, 1.1101713181, 0.66446065903),
- (0.91874998808, 0.60624998808, 1.0187499523, 0.70625001192),
- (0.89803934097, 0.51482862234, 1.039460659, 0.79767137766),
- (0.82732862234, 0.58553934097, 1.1101713181, 0.72696065903),
- (0.91874998808, 0.66874998808, 1.0187499523, 0.76875001192),
- (0.89803934097, 0.57732862234, 1.039460659, 0.86017137766),
- (0.82732862234, 0.64803934097, 1.1101713181, 0.78946065903),
- (0.91874998808, 0.73124998808, 1.0187499523, 0.83125001192),
- (0.89803934097, 0.63982862234, 1.039460659, 0.92267137766),
- (0.82732862234, 0.71053934097, 1.1101713181, 0.85196065903),
- (0.91874998808, 0.79374998808, 1.0187499523, 0.89375001192),
- (0.89803934097, 0.70232862234, 1.039460659, 0.98517137766),
- (0.82732862234, 0.77303934097, 1.1101713181, 0.91446065903),
- (0.91874998808, 0.85624998808, 1.0187499523, 0.95625001192),
- (0.89803934097, 0.76482862234, 1.039460659, 1.0476713181),
- (0.82732862234, 0.83553934097, 1.1101713181, 0.97696065903),
- (0.91874998808, 0.91874998808, 1.0187499523, 1.0187499523),
- (0.89803934097, 0.82732862234, 1.039460659, 1.1101713181),
- (0.82732862234, 0.89803934097, 1.1101713181, 1.039460659),
- (-0.13125000894, -0.13124997914, 0.25625002384, 0.25624996424),
- (-0.074501946568, -0.21150383353, 0.19950194657, 0.33650383353),
- (-0.21150389314, -0.074501916766, 0.33650389314, 0.19950191677),
- (-0.049361616373, -0.27308481932, 0.17436161637, 0.39808481932),
- (-0.27310159802, -0.049356020987, 0.39810159802, 0.17435601354),
- (-0.17351509631, -0.17351509631, 0.29851508141, 0.29851508141),
- (-0.13125000894, -0.0062499791384, 0.25625002384, 0.38124996424),
- (-0.074501946568, -0.086503833532, 0.19950194657, 0.46150383353),
- (-0.21150389314, 0.050498083234, 0.33650389314, 0.32450193167),
- (-0.049361616373, -0.14808481932, 0.17436161637, 0.52308481932),
- (-0.27310159802, 0.075643979013, 0.39810159802, 0.29935601354),
- (-0.17351509631, -0.048515096307, 0.29851508141, 0.42351508141),
- (-0.13125000894, 0.11875002086, 0.25625002384, 0.50624996424),
- (-0.074501946568, 0.038496166468, 0.19950194657, 0.58650386333),
- (-0.21150389314, 0.17549808323, 0.33650389314, 0.44950193167),
- (-0.049361616373, -0.023084819317, 0.17436161637, 0.64808481932),
- (-0.27310159802, 0.20064398646, 0.39810159802, 0.42435601354),
- (-0.17351509631, 0.076484903693, 0.29851508141, 0.54851508141),
- (-0.13125000894, 0.24375002086, 0.25625002384, 0.63124996424),
- (-0.074501946568, 0.16349616647, 0.19950194657, 0.71150386333),
- (-0.21150389314, 0.30049806833, 0.33650389314, 0.57450193167),
- (-0.049361616373, 0.10191518068, 0.17436161637, 0.77308481932),
- (-0.27310159802, 0.32564398646, 0.39810159802, 0.54935604334),
- (-0.17351509631, 0.20148490369, 0.29851508141, 0.67351508141),
- (-0.13125000894, 0.36875003576, 0.25625002384, 0.75624996424),
- (-0.074501946568, 0.28849616647, 0.19950194657, 0.83650386333),
- (-0.21150389314, 0.42549806833, 0.33650389314, 0.69950193167),
- (-0.049361616373, 0.22691518068, 0.17436161637, 0.89808481932),
- (-0.27310159802, 0.45064398646, 0.39810159802, 0.67435604334),
- (-0.17351509631, 0.32648491859, 0.29851508141, 0.79851508141),
- (-0.13125000894, 0.49375003576, 0.25625002384, 0.88124996424),
- (-0.074501946568, 0.41349616647, 0.19950194657, 0.96150386333),
- (-0.21150389314, 0.55049806833, 0.33650389314, 0.82450193167),
- (-0.049361616373, 0.35191518068, 0.17436161637, 1.0230848789),
- (-0.27310159802, 0.57564395666, 0.39810159802, 0.79935604334),
- (-0.17351509631, 0.45148491859, 0.29851508141, 0.92351508141),
- (-0.13125000894, 0.61875003576, 0.25625002384, 1.0062500238),
- (-0.074501946568, 0.53849613667, 0.19950194657, 1.0865038633),
- (-0.21150389314, 0.67549806833, 0.33650389314, 0.94950193167),
- (-0.049361616373, 0.47691518068, 0.17436161637, 1.1480848789),
- (-0.27310159802, 0.70064395666, 0.39810159802, 0.92435604334),
- (-0.17351509631, 0.57648491859, 0.29851508141, 1.0485150814),
- (-0.13125000894, 0.74375003576, 0.25625002384, 1.1312500238),
- (-0.074501946568, 0.66349613667, 0.19950194657, 1.2115038633),
- (-0.21150389314, 0.80049806833, 0.33650389314, 1.0745018721),
- (-0.049361616373, 0.60191518068, 0.17436161637, 1.2730848789),
- (-0.27310159802, 0.82564395666, 0.39810159802, 1.0493559837),
- (-0.17351509631, 0.70148491859, 0.29851508141, 1.1735150814),
- (-0.0062500089407, -0.13124997914, 0.38125002384, 0.25624996424),
- (0.050498053432, -0.21150383353, 0.32450193167, 0.33650383353),
- (-0.086503893137, -0.074501916766, 0.46150389314, 0.19950191677),
- (0.075638383627, -0.27308481932, 0.29936161637, 0.39808481932),
- (-0.14810159802, -0.049356020987, 0.52310156822, 0.17435601354),
- (-0.048515096307, -0.17351509631, 0.42351508141, 0.29851508141),
- (-0.0062500089407, -0.0062499791384, 0.38125002384, 0.38124996424),
- (0.050498053432, -0.086503833532, 0.32450193167, 0.46150383353),
- (-0.086503893137, 0.050498083234, 0.46150389314, 0.32450193167),
- (0.075638383627, -0.14808481932, 0.29936161637, 0.52308481932),
- (-0.14810159802, 0.075643979013, 0.52310156822, 0.29935601354),
- (-0.048515096307, -0.048515096307, 0.42351508141, 0.42351508141),
- (-0.0062500089407, 0.11875002086, 0.38125002384, 0.50624996424),
- (0.050498053432, 0.038496166468, 0.32450193167, 0.58650386333),
- (-0.086503893137, 0.17549808323, 0.46150389314, 0.44950193167),
- (0.075638383627, -0.023084819317, 0.29936161637, 0.64808481932),
- (-0.14810159802, 0.20064398646, 0.52310156822, 0.42435601354),
- (-0.048515096307, 0.076484903693, 0.42351508141, 0.54851508141),
- (-0.0062500089407, 0.24375002086, 0.38125002384, 0.63124996424),
- (0.050498053432, 0.16349616647, 0.32450193167, 0.71150386333),
- (-0.086503893137, 0.30049806833, 0.46150389314, 0.57450193167),
- (0.075638383627, 0.10191518068, 0.29936161637, 0.77308481932),
- (-0.14810159802, 0.32564398646, 0.52310156822, 0.54935604334),
- (-0.048515096307, 0.20148490369, 0.42351508141, 0.67351508141),
- (-0.0062500089407, 0.36875003576, 0.38125002384, 0.75624996424),
- (0.050498053432, 0.28849616647, 0.32450193167, 0.83650386333),
- (-0.086503893137, 0.42549806833, 0.46150389314, 0.69950193167),
- (0.075638383627, 0.22691518068, 0.29936161637, 0.89808481932),
- (-0.14810159802, 0.45064398646, 0.52310156822, 0.67435604334),
- (-0.048515096307, 0.32648491859, 0.42351508141, 0.79851508141),
- (-0.0062500089407, 0.49375003576, 0.38125002384, 0.88124996424),
- (0.050498053432, 0.41349616647, 0.32450193167, 0.96150386333),
- (-0.086503893137, 0.55049806833, 0.46150389314, 0.82450193167),
- (0.075638383627, 0.35191518068, 0.29936161637, 1.0230848789),
- (-0.14810159802, 0.57564395666, 0.52310156822, 0.79935604334),
- (-0.048515096307, 0.45148491859, 0.42351508141, 0.92351508141),
- (-0.0062500089407, 0.61875003576, 0.38125002384, 1.0062500238),
- (0.050498053432, 0.53849613667, 0.32450193167, 1.0865038633),
- (-0.086503893137, 0.67549806833, 0.46150389314, 0.94950193167),
- (0.075638383627, 0.47691518068, 0.29936161637, 1.1480848789),
- (-0.14810159802, 0.70064395666, 0.52310156822, 0.92435604334),
- (-0.048515096307, 0.57648491859, 0.42351508141, 1.0485150814),
- (-0.0062500089407, 0.74375003576, 0.38125002384, 1.1312500238),
- (0.050498053432, 0.66349613667, 0.32450193167, 1.2115038633),
- (-0.086503893137, 0.80049806833, 0.46150389314, 1.0745018721),
- (0.075638383627, 0.60191518068, 0.29936161637, 1.2730848789),
- (-0.14810159802, 0.82564395666, 0.52310156822, 1.0493559837),
- (-0.048515096307, 0.70148491859, 0.42351508141, 1.1735150814),
- (0.11874999106, -0.13124997914, 0.50625002384, 0.25624996424),
- (0.17549805343, -0.21150383353, 0.44950193167, 0.33650383353),
- (0.038496106863, -0.074501916766, 0.58650386333, 0.19950191677),
- (0.20063838363, -0.27308481932, 0.42436161637, 0.39808481932),
- (-0.023101598024, -0.049356020987, 0.64810156822, 0.17435601354),
- (0.076484903693, -0.17351509631, 0.54851508141, 0.29851508141),
- (0.11874999106, -0.0062499791384, 0.50625002384, 0.38124996424),
- (0.17549805343, -0.086503833532, 0.44950193167, 0.46150383353),
- (0.038496106863, 0.050498083234, 0.58650386333, 0.32450193167),
- (0.20063838363, -0.14808481932, 0.42436161637, 0.52308481932),
- (-0.023101598024, 0.075643979013, 0.64810156822, 0.29935601354),
- (0.076484903693, -0.048515096307, 0.54851508141, 0.42351508141),
- (0.11874999106, 0.11875002086, 0.50625002384, 0.50624996424),
- (0.17549805343, 0.038496166468, 0.44950193167, 0.58650386333),
- (0.038496106863, 0.17549808323, 0.58650386333, 0.44950193167),
- (0.20063838363, -0.023084819317, 0.42436161637, 0.64808481932),
- (-0.023101598024, 0.20064398646, 0.64810156822, 0.42435601354),
- (0.076484903693, 0.076484903693, 0.54851508141, 0.54851508141),
- (0.11874999106, 0.24375002086, 0.50625002384, 0.63124996424),
- (0.17549805343, 0.16349616647, 0.44950193167, 0.71150386333),
- (0.038496106863, 0.30049806833, 0.58650386333, 0.57450193167),
- (0.20063838363, 0.10191518068, 0.42436161637, 0.77308481932),
- (-0.023101598024, 0.32564398646, 0.64810156822, 0.54935604334),
- (0.076484903693, 0.20148490369, 0.54851508141, 0.67351508141),
- (0.11874999106, 0.36875003576, 0.50625002384, 0.75624996424),
- (0.17549805343, 0.28849616647, 0.44950193167, 0.83650386333),
- (0.038496106863, 0.42549806833, 0.58650386333, 0.69950193167),
- (0.20063838363, 0.22691518068, 0.42436161637, 0.89808481932),
- (-0.023101598024, 0.45064398646, 0.64810156822, 0.67435604334),
- (0.076484903693, 0.32648491859, 0.54851508141, 0.79851508141),
- (0.11874999106, 0.49375003576, 0.50625002384, 0.88124996424),
- (0.17549805343, 0.41349616647, 0.44950193167, 0.96150386333),
- (0.038496106863, 0.55049806833, 0.58650386333, 0.82450193167),
- (0.20063838363, 0.35191518068, 0.42436161637, 1.0230848789),
- (-0.023101598024, 0.57564395666, 0.64810156822, 0.79935604334),
- (0.076484903693, 0.45148491859, 0.54851508141, 0.92351508141),
- (0.11874999106, 0.61875003576, 0.50625002384, 1.0062500238),
- (0.17549805343, 0.53849613667, 0.44950193167, 1.0865038633),
- (0.038496106863, 0.67549806833, 0.58650386333, 0.94950193167),
- (0.20063838363, 0.47691518068, 0.42436161637, 1.1480848789),
- (-0.023101598024, 0.70064395666, 0.64810156822, 0.92435604334),
- (0.076484903693, 0.57648491859, 0.54851508141, 1.0485150814),
- (0.11874999106, 0.74375003576, 0.50625002384, 1.1312500238),
- (0.17549805343, 0.66349613667, 0.44950193167, 1.2115038633),
- (0.038496106863, 0.80049806833, 0.58650386333, 1.0745018721),
- (0.20063838363, 0.60191518068, 0.42436161637, 1.2730848789),
- (-0.023101598024, 0.82564395666, 0.64810156822, 1.0493559837),
- (0.076484903693, 0.70148491859, 0.54851508141, 1.1735150814),
- (0.24374999106, -0.13124997914, 0.63125002384, 0.25624996424),
- (0.30049806833, -0.21150383353, 0.57450193167, 0.33650383353),
- (0.16349610686, -0.074501916766, 0.71150386333, 0.19950191677),
- (0.32563838363, -0.27308481932, 0.54936158657, 0.39808481932),
- (0.10189840198, -0.049356020987, 0.77310156822, 0.17435601354),
- (0.20148490369, -0.17351509631, 0.67351508141, 0.29851508141),
- (0.24374999106, -0.0062499791384, 0.63125002384, 0.38124996424),
- (0.30049806833, -0.086503833532, 0.57450193167, 0.46150383353),
- (0.16349610686, 0.050498083234, 0.71150386333, 0.32450193167),
- (0.32563838363, -0.14808481932, 0.54936158657, 0.52308481932),
- (0.10189840198, 0.075643979013, 0.77310156822, 0.29935601354),
- (0.20148490369, -0.048515096307, 0.67351508141, 0.42351508141),
- (0.24374999106, 0.11875002086, 0.63125002384, 0.50624996424),
- (0.30049806833, 0.038496166468, 0.57450193167, 0.58650386333),
- (0.16349610686, 0.17549808323, 0.71150386333, 0.44950193167),
- (0.32563838363, -0.023084819317, 0.54936158657, 0.64808481932),
- (0.10189840198, 0.20064398646, 0.77310156822, 0.42435601354),
- (0.20148490369, 0.076484903693, 0.67351508141, 0.54851508141),
- (0.24374999106, 0.24375002086, 0.63125002384, 0.63124996424),
- (0.30049806833, 0.16349616647, 0.57450193167, 0.71150386333),
- (0.16349610686, 0.30049806833, 0.71150386333, 0.57450193167),
- (0.32563838363, 0.10191518068, 0.54936158657, 0.77308481932),
- (0.10189840198, 0.32564398646, 0.77310156822, 0.54935604334),
- (0.20148490369, 0.20148490369, 0.67351508141, 0.67351508141),
- (0.24374999106, 0.36875003576, 0.63125002384, 0.75624996424),
- (0.30049806833, 0.28849616647, 0.57450193167, 0.83650386333),
- (0.16349610686, 0.42549806833, 0.71150386333, 0.69950193167),
- (0.32563838363, 0.22691518068, 0.54936158657, 0.89808481932),
- (0.10189840198, 0.45064398646, 0.77310156822, 0.67435604334),
- (0.20148490369, 0.32648491859, 0.67351508141, 0.79851508141),
- (0.24374999106, 0.49375003576, 0.63125002384, 0.88124996424),
- (0.30049806833, 0.41349616647, 0.57450193167, 0.96150386333),
- (0.16349610686, 0.55049806833, 0.71150386333, 0.82450193167),
- (0.32563838363, 0.35191518068, 0.54936158657, 1.0230848789),
- (0.10189840198, 0.57564395666, 0.77310156822, 0.79935604334),
- (0.20148490369, 0.45148491859, 0.67351508141, 0.92351508141),
- (0.24374999106, 0.61875003576, 0.63125002384, 1.0062500238),
- (0.30049806833, 0.53849613667, 0.57450193167, 1.0865038633),
- (0.16349610686, 0.67549806833, 0.71150386333, 0.94950193167),
- (0.32563838363, 0.47691518068, 0.54936158657, 1.1480848789),
- (0.10189840198, 0.70064395666, 0.77310156822, 0.92435604334),
- (0.20148490369, 0.57648491859, 0.67351508141, 1.0485150814),
- (0.24374999106, 0.74375003576, 0.63125002384, 1.1312500238),
- (0.30049806833, 0.66349613667, 0.57450193167, 1.2115038633),
- (0.16349610686, 0.80049806833, 0.71150386333, 1.0745018721),
- (0.32563838363, 0.60191518068, 0.54936158657, 1.2730848789),
- (0.10189840198, 0.82564395666, 0.77310156822, 1.0493559837),
- (0.20148490369, 0.70148491859, 0.67351508141, 1.1735150814),
- (0.36874997616, -0.13124997914, 0.75625002384, 0.25624996424),
- (0.42549806833, -0.21150383353, 0.69950193167, 0.33650383353),
- (0.28849610686, -0.074501916766, 0.83650386333, 0.19950191677),
- (0.45063838363, -0.27308481932, 0.67436158657, 0.39808481932),
- (0.22689840198, -0.049356020987, 0.89810156822, 0.17435601354),
- (0.32648491859, -0.17351509631, 0.79851508141, 0.29851508141),
- (0.36874997616, -0.0062499791384, 0.75625002384, 0.38124996424),
- (0.42549806833, -0.086503833532, 0.69950193167, 0.46150383353),
- (0.28849610686, 0.050498083234, 0.83650386333, 0.32450193167),
- (0.45063838363, -0.14808481932, 0.67436158657, 0.52308481932),
- (0.22689840198, 0.075643979013, 0.89810156822, 0.29935601354),
- (0.32648491859, -0.048515096307, 0.79851508141, 0.42351508141),
- (0.36874997616, 0.11875002086, 0.75625002384, 0.50624996424),
- (0.42549806833, 0.038496166468, 0.69950193167, 0.58650386333),
- (0.28849610686, 0.17549808323, 0.83650386333, 0.44950193167),
- (0.45063838363, -0.023084819317, 0.67436158657, 0.64808481932),
- (0.22689840198, 0.20064398646, 0.89810156822, 0.42435601354),
- (0.32648491859, 0.076484903693, 0.79851508141, 0.54851508141),
- (0.36874997616, 0.24375002086, 0.75625002384, 0.63124996424),
- (0.42549806833, 0.16349616647, 0.69950193167, 0.71150386333),
- (0.28849610686, 0.30049806833, 0.83650386333, 0.57450193167),
- (0.45063838363, 0.10191518068, 0.67436158657, 0.77308481932),
- (0.22689840198, 0.32564398646, 0.89810156822, 0.54935604334),
- (0.32648491859, 0.20148490369, 0.79851508141, 0.67351508141),
- (0.36874997616, 0.36875003576, 0.75625002384, 0.75624996424),
- (0.42549806833, 0.28849616647, 0.69950193167, 0.83650386333),
- (0.28849610686, 0.42549806833, 0.83650386333, 0.69950193167),
- (0.45063838363, 0.22691518068, 0.67436158657, 0.89808481932),
- (0.22689840198, 0.45064398646, 0.89810156822, 0.67435604334),
- (0.32648491859, 0.32648491859, 0.79851508141, 0.79851508141),
- (0.36874997616, 0.49375003576, 0.75625002384, 0.88124996424),
- (0.42549806833, 0.41349616647, 0.69950193167, 0.96150386333),
- (0.28849610686, 0.55049806833, 0.83650386333, 0.82450193167),
- (0.45063838363, 0.35191518068, 0.67436158657, 1.0230848789),
- (0.22689840198, 0.57564395666, 0.89810156822, 0.79935604334),
- (0.32648491859, 0.45148491859, 0.79851508141, 0.92351508141),
- (0.36874997616, 0.61875003576, 0.75625002384, 1.0062500238),
- (0.42549806833, 0.53849613667, 0.69950193167, 1.0865038633),
- (0.28849610686, 0.67549806833, 0.83650386333, 0.94950193167),
- (0.45063838363, 0.47691518068, 0.67436158657, 1.1480848789),
- (0.22689840198, 0.70064395666, 0.89810156822, 0.92435604334),
- (0.32648491859, 0.57648491859, 0.79851508141, 1.0485150814),
- (0.36874997616, 0.74375003576, 0.75625002384, 1.1312500238),
- (0.42549806833, 0.66349613667, 0.69950193167, 1.2115038633),
- (0.28849610686, 0.80049806833, 0.83650386333, 1.0745018721),
- (0.45063838363, 0.60191518068, 0.67436158657, 1.2730848789),
- (0.22689840198, 0.82564395666, 0.89810156822, 1.0493559837),
- (0.32648491859, 0.70148491859, 0.79851508141, 1.1735150814),
- (0.49374997616, -0.13124997914, 0.88125002384, 0.25624996424),
- (0.55049806833, -0.21150383353, 0.82450193167, 0.33650383353),
- (0.41349610686, -0.074501916766, 0.96150386333, 0.19950191677),
- (0.57563841343, -0.27308481932, 0.79936158657, 0.39808481932),
- (0.35189840198, -0.049356020987, 1.0231015682, 0.17435601354),
- (0.45148491859, -0.17351509631, 0.92351508141, 0.29851508141),
- (0.49374997616, -0.0062499791384, 0.88125002384, 0.38124996424),
- (0.55049806833, -0.086503833532, 0.82450193167, 0.46150383353),
- (0.41349610686, 0.050498083234, 0.96150386333, 0.32450193167),
- (0.57563841343, -0.14808481932, 0.79936158657, 0.52308481932),
- (0.35189840198, 0.075643979013, 1.0231015682, 0.29935601354),
- (0.45148491859, -0.048515096307, 0.92351508141, 0.42351508141),
- (0.49374997616, 0.11875002086, 0.88125002384, 0.50624996424),
- (0.55049806833, 0.038496166468, 0.82450193167, 0.58650386333),
- (0.41349610686, 0.17549808323, 0.96150386333, 0.44950193167),
- (0.57563841343, -0.023084819317, 0.79936158657, 0.64808481932),
- (0.35189840198, 0.20064398646, 1.0231015682, 0.42435601354),
- (0.45148491859, 0.076484903693, 0.92351508141, 0.54851508141),
- (0.49374997616, 0.24375002086, 0.88125002384, 0.63124996424),
- (0.55049806833, 0.16349616647, 0.82450193167, 0.71150386333),
- (0.41349610686, 0.30049806833, 0.96150386333, 0.57450193167),
- (0.57563841343, 0.10191518068, 0.79936158657, 0.77308481932),
- (0.35189840198, 0.32564398646, 1.0231015682, 0.54935604334),
- (0.45148491859, 0.20148490369, 0.92351508141, 0.67351508141),
- (0.49374997616, 0.36875003576, 0.88125002384, 0.75624996424),
- (0.55049806833, 0.28849616647, 0.82450193167, 0.83650386333),
- (0.41349610686, 0.42549806833, 0.96150386333, 0.69950193167),
- (0.57563841343, 0.22691518068, 0.79936158657, 0.89808481932),
- (0.35189840198, 0.45064398646, 1.0231015682, 0.67435604334),
- (0.45148491859, 0.32648491859, 0.92351508141, 0.79851508141),
- (0.49374997616, 0.49375003576, 0.88125002384, 0.88124996424),
- (0.55049806833, 0.41349616647, 0.82450193167, 0.96150386333),
- (0.41349610686, 0.55049806833, 0.96150386333, 0.82450193167),
- (0.57563841343, 0.35191518068, 0.79936158657, 1.0230848789),
- (0.35189840198, 0.57564395666, 1.0231015682, 0.79935604334),
- (0.45148491859, 0.45148491859, 0.92351508141, 0.92351508141),
- (0.49374997616, 0.61875003576, 0.88125002384, 1.0062500238),
- (0.55049806833, 0.53849613667, 0.82450193167, 1.0865038633),
- (0.41349610686, 0.67549806833, 0.96150386333, 0.94950193167),
- (0.57563841343, 0.47691518068, 0.79936158657, 1.1480848789),
- (0.35189840198, 0.70064395666, 1.0231015682, 0.92435604334),
- (0.45148491859, 0.57648491859, 0.92351508141, 1.0485150814),
- (0.49374997616, 0.74375003576, 0.88125002384, 1.1312500238),
- (0.55049806833, 0.66349613667, 0.82450193167, 1.2115038633),
- (0.41349610686, 0.80049806833, 0.96150386333, 1.0745018721),
- (0.57563841343, 0.60191518068, 0.79936158657, 1.2730848789),
- (0.35189840198, 0.82564395666, 1.0231015682, 1.0493559837),
- (0.45148491859, 0.70148491859, 0.92351508141, 1.1735150814),
- (0.61874997616, -0.13124997914, 1.0062500238, 0.25624996424),
- (0.67549806833, -0.21150383353, 0.94950193167, 0.33650383353),
- (0.53849613667, -0.074501916766, 1.0865038633, 0.19950191677),
- (0.70063841343, -0.27308481932, 0.92436158657, 0.39808481932),
- (0.47689840198, -0.049356020987, 1.1481015682, 0.17435601354),
- (0.57648491859, -0.17351509631, 1.0485150814, 0.29851508141),
- (0.61874997616, -0.0062499791384, 1.0062500238, 0.38124996424),
- (0.67549806833, -0.086503833532, 0.94950193167, 0.46150383353),
- (0.53849613667, 0.050498083234, 1.0865038633, 0.32450193167),
- (0.70063841343, -0.14808481932, 0.92436158657, 0.52308481932),
- (0.47689840198, 0.075643979013, 1.1481015682, 0.29935601354),
- (0.57648491859, -0.048515096307, 1.0485150814, 0.42351508141),
- (0.61874997616, 0.11875002086, 1.0062500238, 0.50624996424),
- (0.67549806833, 0.038496166468, 0.94950193167, 0.58650386333),
- (0.53849613667, 0.17549808323, 1.0865038633, 0.44950193167),
- (0.70063841343, -0.023084819317, 0.92436158657, 0.64808481932),
- (0.47689840198, 0.20064398646, 1.1481015682, 0.42435601354),
- (0.57648491859, 0.076484903693, 1.0485150814, 0.54851508141),
- (0.61874997616, 0.24375002086, 1.0062500238, 0.63124996424),
- (0.67549806833, 0.16349616647, 0.94950193167, 0.71150386333),
- (0.53849613667, 0.30049806833, 1.0865038633, 0.57450193167),
- (0.70063841343, 0.10191518068, 0.92436158657, 0.77308481932),
- (0.47689840198, 0.32564398646, 1.1481015682, 0.54935604334),
- (0.57648491859, 0.20148490369, 1.0485150814, 0.67351508141),
- (0.61874997616, 0.36875003576, 1.0062500238, 0.75624996424),
- (0.67549806833, 0.28849616647, 0.94950193167, 0.83650386333),
- (0.53849613667, 0.42549806833, 1.0865038633, 0.69950193167),
- (0.70063841343, 0.22691518068, 0.92436158657, 0.89808481932),
- (0.47689840198, 0.45064398646, 1.1481015682, 0.67435604334),
- (0.57648491859, 0.32648491859, 1.0485150814, 0.79851508141),
- (0.61874997616, 0.49375003576, 1.0062500238, 0.88124996424),
- (0.67549806833, 0.41349616647, 0.94950193167, 0.96150386333),
- (0.53849613667, 0.55049806833, 1.0865038633, 0.82450193167),
- (0.70063841343, 0.35191518068, 0.92436158657, 1.0230848789),
- (0.47689840198, 0.57564395666, 1.1481015682, 0.79935604334),
- (0.57648491859, 0.45148491859, 1.0485150814, 0.92351508141),
- (0.61874997616, 0.61875003576, 1.0062500238, 1.0062500238),
- (0.67549806833, 0.53849613667, 0.94950193167, 1.0865038633),
- (0.53849613667, 0.67549806833, 1.0865038633, 0.94950193167),
- (0.70063841343, 0.47691518068, 0.92436158657, 1.1480848789),
- (0.47689840198, 0.70064395666, 1.1481015682, 0.92435604334),
- (0.57648491859, 0.57648491859, 1.0485150814, 1.0485150814),
- (0.61874997616, 0.74375003576, 1.0062500238, 1.1312500238),
- (0.67549806833, 0.66349613667, 0.94950193167, 1.2115038633),
- (0.53849613667, 0.80049806833, 1.0865038633, 1.0745018721),
- (0.70063841343, 0.60191518068, 0.92436158657, 1.2730848789),
- (0.47689840198, 0.82564395666, 1.1481015682, 1.0493559837),
- (0.57648491859, 0.70148491859, 1.0485150814, 1.1735150814),
- (0.74374997616, -0.13124997914, 1.1312500238, 0.25624996424),
- (0.80049806833, -0.21150383353, 1.0745019913, 0.33650383353),
- (0.66349613667, -0.074501916766, 1.2115038633, 0.19950191677),
- (0.82563841343, -0.27308481932, 1.0493615866, 0.39808481932),
- (0.60189843178, -0.049356020987, 1.2731015682, 0.17435601354),
- (0.70148491859, -0.17351509631, 1.1735150814, 0.29851508141),
- (0.74374997616, -0.0062499791384, 1.1312500238, 0.38124996424),
- (0.80049806833, -0.086503833532, 1.0745019913, 0.46150383353),
- (0.66349613667, 0.050498083234, 1.2115038633, 0.32450193167),
- (0.82563841343, -0.14808481932, 1.0493615866, 0.52308481932),
- (0.60189843178, 0.075643979013, 1.2731015682, 0.29935601354),
- (0.70148491859, -0.048515096307, 1.1735150814, 0.42351508141),
- (0.74374997616, 0.11875002086, 1.1312500238, 0.50624996424),
- (0.80049806833, 0.038496166468, 1.0745019913, 0.58650386333),
- (0.66349613667, 0.17549808323, 1.2115038633, 0.44950193167),
- (0.82563841343, -0.023084819317, 1.0493615866, 0.64808481932),
- (0.60189843178, 0.20064398646, 1.2731015682, 0.42435601354),
- (0.70148491859, 0.076484903693, 1.1735150814, 0.54851508141),
- (0.74374997616, 0.24375002086, 1.1312500238, 0.63124996424),
- (0.80049806833, 0.16349616647, 1.0745019913, 0.71150386333),
- (0.66349613667, 0.30049806833, 1.2115038633, 0.57450193167),
- (0.82563841343, 0.10191518068, 1.0493615866, 0.77308481932),
- (0.60189843178, 0.32564398646, 1.2731015682, 0.54935604334),
- (0.70148491859, 0.20148490369, 1.1735150814, 0.67351508141),
- (0.74374997616, 0.36875003576, 1.1312500238, 0.75624996424),
- (0.80049806833, 0.28849616647, 1.0745019913, 0.83650386333),
- (0.66349613667, 0.42549806833, 1.2115038633, 0.69950193167),
- (0.82563841343, 0.22691518068, 1.0493615866, 0.89808481932),
- (0.60189843178, 0.45064398646, 1.2731015682, 0.67435604334),
- (0.70148491859, 0.32648491859, 1.1735150814, 0.79851508141),
- (0.74374997616, 0.49375003576, 1.1312500238, 0.88124996424),
- (0.80049806833, 0.41349616647, 1.0745019913, 0.96150386333),
- (0.66349613667, 0.55049806833, 1.2115038633, 0.82450193167),
- (0.82563841343, 0.35191518068, 1.0493615866, 1.0230848789),
- (0.60189843178, 0.57564395666, 1.2731015682, 0.79935604334),
- (0.70148491859, 0.45148491859, 1.1735150814, 0.92351508141),
- (0.74374997616, 0.61875003576, 1.1312500238, 1.0062500238),
- (0.80049806833, 0.53849613667, 1.0745019913, 1.0865038633),
- (0.66349613667, 0.67549806833, 1.2115038633, 0.94950193167),
- (0.82563841343, 0.47691518068, 1.0493615866, 1.1480848789),
- (0.60189843178, 0.70064395666, 1.2731015682, 0.92435604334),
- (0.70148491859, 0.57648491859, 1.1735150814, 1.0485150814),
- (0.74374997616, 0.74375003576, 1.1312500238, 1.1312500238),
- (0.80049806833, 0.66349613667, 1.0745019913, 1.2115038633),
- (0.66349613667, 0.80049806833, 1.2115038633, 1.0745018721),
- (0.82563841343, 0.60191518068, 1.0493615866, 1.2730848789),
- (0.60189843178, 0.82564395666, 1.2731015682, 1.0493559837),
- (0.70148491859, 0.70148491859, 1.1735150814, 1.1735150814),
- (-0.16250002384, -0.16249996424, 0.41250002384, 0.41249996424),
- (-0.078293219209, -0.28158634901, 0.32829320431, 0.53158634901),
- (-0.28158643842, -0.078293174505, 0.53158640862, 0.32829317451),
- (-0.040988206863, -0.37296459079, 0.29098820686, 0.62296462059),
- (-0.37298947573, -0.040979906917, 0.62298947573, 0.29097992182),
- (-0.20607307553, -0.20607307553, 0.45607307553, 0.45607307553),
- (-0.16250002384, 0.087500035763, 0.41250002384, 0.66249996424),
- (-0.078293219209, -0.03158634901, 0.32829320431, 0.78158634901),
- (-0.28158643842, 0.17170682549, 0.53158640862, 0.57829320431),
- (-0.040988206863, -0.12296459079, 0.29098820686, 0.87296462059),
- (-0.37298947573, 0.20902009308, 0.62298947573, 0.54097992182),
- (-0.20607307553, 0.043926924467, 0.45607307553, 0.70607304573),
- (-0.16250002384, 0.33750003576, 0.41250002384, 0.91249996424),
- (-0.078293219209, 0.21841365099, 0.32829320431, 1.0315864086),
- (-0.28158643842, 0.42170682549, 0.53158640862, 0.82829320431),
- (-0.040988206863, 0.12703540921, 0.29098820686, 1.1229646206),
- (-0.37298947573, 0.45902007818, 0.62298947573, 0.79097992182),
- (-0.20607307553, 0.29392692447, 0.45607307553, 0.95607304573),
- (-0.16250002384, 0.58750003576, 0.41250002384, 1.1624999046),
- (-0.078293219209, 0.46841365099, 0.32829320431, 1.2815864086),
- (-0.28158643842, 0.67170679569, 0.53158640862, 1.0782932043),
- (-0.040988206863, 0.37703540921, 0.29098820686, 1.3729646206),
- (-0.37298947573, 0.70902007818, 0.62298947573, 1.0409798622),
- (-0.20607307553, 0.54392695427, 0.45607307553, 1.2060730457),
- (0.087499976158, -0.16249996424, 0.66250002384, 0.41249996424),
- (0.17170678079, -0.28158634901, 0.57829320431, 0.53158634901),
- (-0.031586438417, -0.078293174505, 0.78158640862, 0.32829317451),
- (0.20901179314, -0.37296459079, 0.54098820686, 0.62296462059),
- (-0.12298947573, -0.040979906917, 0.87298947573, 0.29097992182),
- (0.043926924467, -0.20607307553, 0.70607304573, 0.45607307553),
- (0.087499976158, 0.087500035763, 0.66250002384, 0.66249996424),
- (0.17170678079, -0.03158634901, 0.57829320431, 0.78158634901),
- (-0.031586438417, 0.17170682549, 0.78158640862, 0.57829320431),
- (0.20901179314, -0.12296459079, 0.54098820686, 0.87296462059),
- (-0.12298947573, 0.20902009308, 0.87298947573, 0.54097992182),
- (0.043926924467, 0.043926924467, 0.70607304573, 0.70607304573),
- (0.087499976158, 0.33750003576, 0.66250002384, 0.91249996424),
- (0.17170678079, 0.21841365099, 0.57829320431, 1.0315864086),
- (-0.031586438417, 0.42170682549, 0.78158640862, 0.82829320431),
- (0.20901179314, 0.12703540921, 0.54098820686, 1.1229646206),
- (-0.12298947573, 0.45902007818, 0.87298947573, 0.79097992182),
- (0.043926924467, 0.29392692447, 0.70607304573, 0.95607304573),
- (0.087499976158, 0.58750003576, 0.66250002384, 1.1624999046),
- (0.17170678079, 0.46841365099, 0.57829320431, 1.2815864086),
- (-0.031586438417, 0.67170679569, 0.78158640862, 1.0782932043),
- (0.20901179314, 0.37703540921, 0.54098820686, 1.3729646206),
- (-0.12298947573, 0.70902007818, 0.87298947573, 1.0409798622),
- (0.043926924467, 0.54392695427, 0.70607304573, 1.2060730457),
- (0.33749997616, -0.16249996424, 0.91250002384, 0.41249996424),
- (0.42170679569, -0.28158634901, 0.82829320431, 0.53158634901),
- (0.21841356158, -0.078293174505, 1.0315864086, 0.32829317451),
- (0.45901179314, -0.37296459079, 0.79098820686, 0.62296462059),
- (0.12701052427, -0.040979906917, 1.1229894161, 0.29097992182),
- (0.29392692447, -0.20607307553, 0.95607304573, 0.45607307553),
- (0.33749997616, 0.087500035763, 0.91250002384, 0.66249996424),
- (0.42170679569, -0.03158634901, 0.82829320431, 0.78158634901),
- (0.21841356158, 0.17170682549, 1.0315864086, 0.57829320431),
- (0.45901179314, -0.12296459079, 0.79098820686, 0.87296462059),
- (0.12701052427, 0.20902009308, 1.1229894161, 0.54097992182),
- (0.29392692447, 0.043926924467, 0.95607304573, 0.70607304573),
- (0.33749997616, 0.33750003576, 0.91250002384, 0.91249996424),
- (0.42170679569, 0.21841365099, 0.82829320431, 1.0315864086),
- (0.21841356158, 0.42170682549, 1.0315864086, 0.82829320431),
- (0.45901179314, 0.12703540921, 0.79098820686, 1.1229646206),
- (0.12701052427, 0.45902007818, 1.1229894161, 0.79097992182),
- (0.29392692447, 0.29392692447, 0.95607304573, 0.95607304573),
- (0.33749997616, 0.58750003576, 0.91250002384, 1.1624999046),
- (0.42170679569, 0.46841365099, 0.82829320431, 1.2815864086),
- (0.21841356158, 0.67170679569, 1.0315864086, 1.0782932043),
- (0.45901179314, 0.37703540921, 0.79098820686, 1.3729646206),
- (0.12701052427, 0.70902007818, 1.1229894161, 1.0409798622),
- (0.29392692447, 0.54392695427, 0.95607304573, 1.2060730457),
- (0.58749997616, -0.16249996424, 1.1625000238, 0.41249996424),
- (0.67170679569, -0.28158634901, 1.0782932043, 0.53158634901),
- (0.46841356158, -0.078293174505, 1.2815864086, 0.32829317451),
- (0.70901179314, -0.37296459079, 1.0409882069, 0.62296462059),
- (0.37701052427, -0.040979906917, 1.3729894161, 0.29097992182),
- (0.54392695427, -0.20607307553, 1.2060730457, 0.45607307553),
- (0.58749997616, 0.087500035763, 1.1625000238, 0.66249996424),
- (0.67170679569, -0.03158634901, 1.0782932043, 0.78158634901),
- (0.46841356158, 0.17170682549, 1.2815864086, 0.57829320431),
- (0.70901179314, -0.12296459079, 1.0409882069, 0.87296462059),
- (0.37701052427, 0.20902009308, 1.3729894161, 0.54097992182),
- (0.54392695427, 0.043926924467, 1.2060730457, 0.70607304573),
- (0.58749997616, 0.33750003576, 1.1625000238, 0.91249996424),
- (0.67170679569, 0.21841365099, 1.0782932043, 1.0315864086),
- (0.46841356158, 0.42170682549, 1.2815864086, 0.82829320431),
- (0.70901179314, 0.12703540921, 1.0409882069, 1.1229646206),
- (0.37701052427, 0.45902007818, 1.3729894161, 0.79097992182),
- (0.54392695427, 0.29392692447, 1.2060730457, 0.95607304573),
- (0.58749997616, 0.58750003576, 1.1625000238, 1.1624999046),
- (0.67170679569, 0.46841365099, 1.0782932043, 1.2815864086),
- (0.46841356158, 0.67170679569, 1.2815864086, 1.0782932043),
- (0.70901179314, 0.37703540921, 1.0409882069, 1.3729646206),
- (0.37701052427, 0.70902007818, 1.3729894161, 1.0409798622),
- (0.54392695427, 0.54392695427, 1.2060730457, 1.2060730457),
- (-0.13125002384, -0.13124996424, 0.63125002384, 0.63124996424),
- (-0.019584476948, -0.28916883469, 0.51958447695, 0.78916883469),
- (-0.2891689539, -0.019584417343, 0.7891689539, 0.51958441734),
- (0.029885202646, -0.41034436226, 0.47011479735, 0.91034436226),
- (-0.41037738323, 0.029896214604, 0.91037738323, 0.4701038003),
- (-0.17555111647, -0.17555111647, 0.67555111647, 0.67555111647),
- (-0.13125002384, 0.36875003576, 0.63125002384, 1.1312499046),
- (-0.019584476948, 0.21083116531, 0.51958447695, 1.2891688347),
- (-0.2891689539, 0.48041558266, 0.7891689539, 1.0195844173),
- (0.029885202646, 0.089655637741, 0.47011479735, 1.4103443623),
- (-0.41037738323, 0.5298961997, 0.91037738323, 0.9701038003),
- (-0.17555111647, 0.32444888353, 0.67555111647, 1.1755511761),
- (0.36874997616, -0.13124996424, 1.1312500238, 0.63124996424),
- (0.48041552305, -0.28916883469, 1.0195844173, 0.78916883469),
- (0.2108310461, -0.019584417343, 1.2891689539, 0.51958441734),
- (0.52988517284, -0.41034436226, 0.97011482716, 0.91034436226),
- (0.089622616768, 0.029896214604, 1.4103773832, 0.4701038003),
- (0.32444888353, -0.17555111647, 1.1755511761, 0.67555111647),
- (0.36874997616, 0.36875003576, 1.1312500238, 1.1312499046),
- (0.48041552305, 0.21083116531, 1.0195844173, 1.2891688347),
- (0.2108310461, 0.48041558266, 1.2891689539, 1.0195844173),
- (0.52988517284, 0.089655637741, 0.97011482716, 1.4103443623),
- (0.089622616768, 0.5298961997, 1.4103773832, 0.9701038003),
- (0.32444888353, 0.32444888353, 1.1755511761, 1.1755511761),
- (0.024999976158, 0.025000035763, 0.97500002384, 0.97499996424),
- (0.16412425041, -0.17175137997, 0.83587574959, 1.17175138),
- (-0.17175149918, 0.16412431002, 1.1717514992, 0.83587568998),
- (0.22575861216, -0.32272410393, 0.77424138784, 1.3227241039),
- (-0.32276523113, 0.22577232122, 1.3227652311, 0.77422767878),
- (0.012660294771, 0.012660294771, 0.98733973503, 0.98733973503),
-)
diff --git a/src/aiy/vision/models/utils.py b/src/aiy/vision/models/utils.py
deleted file mode 100644
index 007705c5..00000000
--- a/src/aiy/vision/models/utils.py
+++ /dev/null
@@ -1,9 +0,0 @@
-"""Utility to load compute graphs from diffrent sources."""
-
-import os
-
-
-def load_compute_graph(name):
- path = os.environ.get('VISION_BONNET_MODELS_PATH', '/opt/aiy/models')
- with open(os.path.join(path, name), 'rb') as f:
- return f.read()
diff --git a/src/aiy/vision/pins.py b/src/aiy/vision/pins.py
deleted file mode 100644
index da2b7937..00000000
--- a/src/aiy/vision/pins.py
+++ /dev/null
@@ -1,673 +0,0 @@
-"""Pin definitions for use with gpiozero devices.
-
-Defines pin objects, and overrides the pin factory used by gpiozero devices to
-support the pins routed through the hat. Should not disrupt usage of other pins.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-import os
-from collections import namedtuple
-from copy import deepcopy
-from os import listdir
-import time
-from gpiozero import Device
-from gpiozero import Factory
-from gpiozero import Pin
-from gpiozero.exc import GPIOPinInUse
-from gpiozero.exc import InputDeviceError
-from gpiozero.exc import PinFixedPull
-from gpiozero.exc import PinInvalidBounce
-from gpiozero.exc import PinInvalidEdges
-from gpiozero.exc import PinPWMUnsupported
-from gpiozero.exc import PinSetInput
-from gpiozero.exc import PinUnsupported
-from gpiozero.threads import GPIOThread
-
-
-def _detect_gpio_offset(module_path):
- for folder in listdir(module_path):
- try:
- with open('%s/%s/base' % (module_path, folder), 'r') as offset:
- return int(offset.read())
- except IOError:
- pass
- return None
-
-
-_FsNodeSpec = namedtuple('_FsNodeSpec', ['pin', 'name'])
-
-VISIONBONNET_PRODUCT = r"AIY VisionBonnet"
-VOICEBONNET_PROUDCT = r"AIY VoiceBonnet"
-
-MCU_I2C_ADDRESS_DICT = {
- VISIONBONNET_PRODUCT: 0x51,
- VOICEBONNET_PROUDCT: 0x52
-}
-
-HAT_PRODUCT_NAME_PATH = "/sys/firmware/devicetree/base/hat/product"
-
-
-def _get_product_name():
- if not os.path.exists(HAT_PRODUCT_NAME_PATH):
- raise IOError('Hat not found.')
- with open(HAT_PRODUCT_NAME_PATH, "r") as f:
- hat_product_name = str(f.read()).strip("\x00").strip()
- return hat_product_name
-
-
-def _get_i2c_address():
- mcu_i2c_address = MCU_I2C_ADDRESS_DICT.get(_get_product_name())
- if mcu_i2c_address is None:
- raise ValueError('I2C address undetermined.')
- return mcu_i2c_address
-
-
-class GpioSpec(_FsNodeSpec):
- _MODULE_PATH = '/sys/bus/i2c/drivers/aiy-io-i2c/1-00%2X/gpio-aiy-io/gpio' % _get_i2c_address()
- _PIN_OFFSET = _detect_gpio_offset(_MODULE_PATH)
-
- def __new__(cls, pin, name):
- return super(GpioSpec, cls).__new__(cls, GpioSpec._PIN_OFFSET + pin, name)
-
- def __str__(self):
- return 'gpio %s (%d)' % (self.name, self.pin - self._PIN_OFFSET)
-
-
-class PwmSpec(_FsNodeSpec):
-
- def __str__(self):
- return 'pwm %d' % self.pin
-
-
-AIYPinSpec = namedtuple('AIYPinSpec', ['gpio_spec', 'pwm_spec'])
-
-PIN_A = AIYPinSpec(GpioSpec(2, 'AIY_USER0'), PwmSpec(0, 'pwm0'))
-PIN_B = AIYPinSpec(GpioSpec(3, 'AIY_USER1'), PwmSpec(1, 'pwm1'))
-PIN_C = AIYPinSpec(GpioSpec(8, 'AIY_USER2'), PwmSpec(2, 'pwm2'))
-PIN_D = AIYPinSpec(GpioSpec(9, 'AIY_USER3'), PwmSpec(3, 'pwm3'))
-LED_1 = AIYPinSpec(GpioSpec(13, 'AIY_LED0'), None)
-LED_2 = AIYPinSpec(GpioSpec(14, 'AIY_LED1'), None)
-
-BUZZER_GPIO_PIN = 22
-BUTTON_GPIO_PIN = 23
-
-_NS_PER_SECOND = 1000000000
-
-
-class SysFsPin(object):
- """Generic SysFsPin which implements generic SysFs driver functionality."""
-
- def __init__(self, spec, fs_root):
- self._pin = spec.pin
- self._name = spec.name
- self._fs_root = fs_root
- # Ensure things start out unexported.
- try:
- self.unexport()
- except IOError:
- pass
-
- def set_function(self, function):
- raise NotImplementedError('Setting function not supported')
-
- def get_function(self):
- raise NotImplementedError('Getting function not supported')
-
- def export(self):
- try:
- with open(self.root_path('export'), 'w') as export:
- export.write('%d' % self._pin)
- except IOError:
- raise GPIOPinInUse('Pin already in use')
-
- def unexport(self):
- with open(self.root_path('unexport'), 'w') as unexport:
- unexport.write('%d' % self._pin)
-
- def open(self):
- self.export()
-
- def close(self):
- self.unexport()
-
- def wait_for_permissions(self, prop):
- """Wait for write permissions on the given property.
-
- We must wait because the the file system needs to grant permissions for the
- newly created node."""
- while True:
- try:
- with open(self.property_path(prop), 'w'):
- pass
- return
- except IOError:
- time.sleep(.01)
-
- def get_value(self):
- raise NotImplementedError('Value getting not implemented')
-
- def set_value(self, value):
- raise NotImplementedError('Value setting not implemented')
-
- def write_property(self, prop, value):
- """Writes the given sysfs node property to the pin."""
- with open(self.property_path(prop), 'w') as node:
- node.write(value)
-
- def read_property(self, prop):
- """Reads the given sysfs node property from the pin."""
- with open(self.property_path(prop), 'r') as node:
- return node.read()
-
- def root_path(self, node):
- return '%s/%s' % (self._fs_root, node)
-
- def property_path(self, prop):
- return '%s/%s/%s' % (self._fs_root, self._name, prop)
-
-
-class SysFsGpioPin(SysFsPin):
- """SysFs support for GPIO pins.
-
- Supports the SysFs node for GPIO control.
- """
- _FS_ROOT = '/sys/class/gpio'
-
- def __init__(self, spec):
- super(SysFsGpioPin, self).__init__(spec, self._FS_ROOT)
- if not isinstance(spec, GpioSpec):
- raise TypeError('Pin specification not compatible with SysFS GPIO')
- self._spec = spec
- self._out = False
- self._value = None
-
- def _get_direction(self):
- return self.read_property('direction')
-
- def _set_direction(self, direction):
- if direction not in ('in', 'out'):
- raise ValueError('Direction must be either in or out')
- self.write_property('direction', direction)
-
- def _get_value(self):
- return self.read_property('value')
-
- def _set_value(self, value):
- self.write_property('value', value)
-
- def _get_active_low(self):
- return self.read_property('active_low')
-
- def _set_active_low(self, active_low):
- self.write_property('active_low', '1' if active_low else '0')
-
- def set_function(self, function):
- if function == 'input':
- self._set_direction('in')
- self._out = False
- elif function == 'output':
- self._set_direction('out')
- self._out = True
- else:
- raise ValueError('pin function must be either input or output')
-
- def get_function(self):
- direction = self._get_direction()
- if direction == 'input':
- return 'in'
- if direction == 'output':
- return 'out'
-
- def set_value(self, value):
- if not self._out:
- raise PinSetInput('Pin is not open for output')
- self._set_value('1' if value else '0')
- self._value = value
-
- def get_value(self):
- if self._out:
- return self._value
- return bool(int(self._get_value()))
-
- def open(self):
- super(SysFsGpioPin, self).open()
- self.wait_for_permissions('active_low')
- self.wait_for_permissions('direction')
- # GPIO pins on the hat seem to be inverted by default.
- self._set_active_low(True)
-
- def close(self):
- # Restore the default direction (turns off LED) before closing.
- self._set_direction('in')
- super(SysFsGpioPin, self).close()
-
-
-class SysFsPwmPin(SysFsPin):
- """SysFs support for PWM pins.
-
- Supports the SysFs node for pwm control.
- """
- _FS_ROOT = '/sys/class/pwm/pwmchip0'
-
- class PwmState(object):
- """Container for the state of the pwm.
-
- Used to recover after disable/enable and ensure consistency.
- """
-
- def __init__(self):
- self.duty_cycle = 0
- self.period_ns = _NS_PER_SECOND / 50
- self.enabled = False
- self.function = None
-
- def __init__(self, spec):
- super(SysFsPwmPin, self).__init__(spec, self._FS_ROOT)
- if not isinstance(spec, PwmSpec):
- raise TypeError('Pin specification not compatible with SysFS PWM')
- if spec.pin < 0 or spec.pin > 3:
- raise ValueError('Pin must be between 0 and 3 (inclusive)')
- self._spec = spec
- self._state = SysFsPwmPin.PwmState()
-
- def _set_enabled(self, enabled):
- self.write_property('enable', '1' if enabled else '0')
- self._state.enabled = enabled
-
- def _get_enabled(self):
- return int(self.read_property('enable')) != 0
-
- def _set_period_ns(self, period_ns):
- self.write_property('period', '%d' % period_ns)
- self._state.period_ns = int(period_ns)
-
- def _get_period_ns(self):
- return int(self.read_property('period'))
-
- def _set_duty_cycle(self, duty_cycle):
- self.write_property('duty_cycle', '%d' % duty_cycle)
- self._state.duty_cycle = duty_cycle
-
- def _get_duty_cycle(self):
- return int(self.read_property('duty_cycle'))
-
- def _update_state(self, new_state):
- # Each time we enable, we need to first re-set the period and duty cycle (in
- # that order).
- if new_state.period_ns != self._state.period_ns or (not self._state.enabled
- and new_state.enabled):
- self._set_period_ns(new_state.period_ns)
- if new_state.duty_cycle != self._state.duty_cycle or (
- not self._state.enabled and new_state.enabled):
- self._set_duty_cycle(new_state.duty_cycle)
- if new_state.enabled != self._state.enabled:
- self._set_enabled(new_state.enabled)
-
- def _read_state(self):
- self._state.period_ns = self._get_period_ns()
- self._state.enabled = self._get_enabled()
- self._state.duty_cycle = self._get_duty_cycle()
-
- def set_function(self, function):
- if function != 'pwm' and function != 'output':
- raise ValueError(
- 'PWM pins only support pwm and output functionality')
- self._state.function = function
-
- def get_function(self):
- return self._state.function
-
- def get_value(self):
- return self._state.duty_cycle / self._state.period_ns
-
- def set_value(self, value):
- new_state = deepcopy(self._state)
- if value is None:
- new_state.enabled = False
- else:
- new_state.enabled = True
- new_state.duty_cycle = value * self._state.period_ns
- self._update_state(new_state)
-
- def set_period_ns(self, period_ns):
- new_state = deepcopy(self._state)
- new_state.period_ns = period_ns
- self._update_state(new_state)
-
- def get_period_ns(self):
- return self._state.period_ns
-
- def open(self):
- super(SysFsPwmPin, self).open()
- self.wait_for_permissions('period')
- self.wait_for_permissions('enable')
- self._read_state()
- new_state = deepcopy(self._state)
- new_state.period_ns = _NS_PER_SECOND / 50
- new_state.enabled = True
- self._update_state(new_state)
-
- def close(self):
- self._set_enabled(False)
- super(SysFsPwmPin, self).close()
-
-
-# Debounce by making sure the last change wasn't less than d_time in the past ->
-# should be agnostic to direction.
-class DebouncingPoller(object):
- """Manages debouncing and polling a function periodically in the background.
-
- Calls a given getter periodically and when the debounced value changes such
- that detector(old, new) returns true, the callback is called. Only runs while
- detector, getter, and callback are set.
- """
- _MIN_POLL_INTERVAL = .0001
-
- def __init__(self, value_getter, callback, detector=lambda old, new: True):
- self._poll_thread = None
- self._debounce_time = .001
- self._poll_interval = .00051
- self._getter = value_getter
- self._detector = detector
- self._callback = callback
-
- @property
- def poll_interval(self):
- return self._poll_interval
-
- @poll_interval.setter
- def poll_interval(self, interval):
- self._poll_interval = max(interval, self._MIN_POLL_INTERVAL)
- self.restart_polling()
-
- @property
- def debounce_time(self):
- return self._debounce_time
-
- @debounce_time.setter
- def debounce_time(self, debounce_time):
- self._debounce_time = debounce_time
- self.restart_polling()
-
- @property
- def callback(self):
- return self._callback
-
- @callback.setter
- def callback(self, callback):
- self.stop_polling()
- self._callback = callback
- self.try_start_polling()
-
- @property
- def detector(self):
- return self._detector
-
- @detector.setter
- def detector(self, detector):
- self._detector = detector
- self.restart_polling()
-
- def try_start_polling(self):
- if (not self._poll_thread and self._getter and self._callback and
- self._detector):
- self._poll_thread = GPIOThread(
- target=self._poll,
- args=(self._poll_interval, self._debounce_time, self._getter,
- self._detector, self._callback))
- self._poll_thread.start()
-
- def stop_polling(self):
- if self._poll_thread:
- self._poll_thread.stop()
- self._poll_thread = None
-
- def restart_polling(self):
- self.stop_polling()
- self.try_start_polling()
-
- # Only called from the polling thread.
- def _poll(self, poll_interval, debounce_interval, getter, detector, callback):
- """Debounces and monitors the value retrieved by _getter.
-
- Triggers callback if detector(old_value, new_value) returns true.
- Args:
- poll_interval: positive float, time in seconds between polling the getter.
- debounce_interval: positive float, time in seconds to wait after a change
- to allow a future change to the value to trigger the callback.
- getter: function() -> value, gets the value. This will be called
- periodically and the value type will be the same type passed to the
- detector function.
- detector: function(old, new) -> bool, filters changes to determine when
- the callback should be called. Can be used for edge detection
- callback: function() to be invoked when detector conditions are met.
- """
- last_time = time.time()
- last_value = getter()
- while not self._poll_thread.stopping.wait(poll_interval):
- value = getter()
- new_time = time.time()
- if not debounce_interval or (new_time - last_time) > debounce_interval:
- if detector(last_value, value):
- callback()
- last_value = value
- last_time = new_time
-
-
-class HatPin(Pin):
- """A Pin implemenation that supports pins controlled by the hat's MCU.
-
- Only one HatPin should exist at a given time for a given pin system wide.
- Behavior is completely unpredictable if more than one pin exists concurrently.
- If the factory is used for construction there are protections in place to
- prevent this, however if multiple programs are running simultaneously the
- protections do not limit cross program duplication.
- """
- _EDGE_DETECTORS = {
- 'both': lambda old, new: old != new,
- 'rising': lambda old, new: not old and new,
- 'falling': lambda old, new: old and not new,
- None: None,
- }
-
- def __init__(self, spec, pwm=False):
- super(HatPin, self).__init__()
- self.gpio_pin = None
- self.pwm_pin = None
- self.pwm_active = False
- self.gpio_active = False
- if spec.gpio_spec is not None:
- self.gpio_pin = SysFsGpioPin(spec.gpio_spec)
-
- if spec.pwm_spec is not None:
- self.pwm_pin = SysFsPwmPin(spec.pwm_spec)
-
- self._closed = False
- self._poller = DebouncingPoller(self._get_state, None)
- self._edges = None
- self._set_bounce(.001)
- # Start out with gpio enabled for compatibility.
- self._enable_gpio()
-
- def _enable_pwm(self):
- if self._closed:
- return
- if self.pwm_pin is None:
- raise PinPWMUnsupported(
- 'PWM was enabled, but is not supported on pin %r' % self.pwm_pin)
- self._disable_gpio()
- if not self.pwm_active:
- self.pwm_pin.open()
- self.pwm_active = True
-
- def _disable_pwm(self):
- if self.pwm_active and self.pwm_pin is not None:
- self.pwm_pin.close()
- self.pwm_active = False
-
- def _enable_gpio(self):
- if self._closed:
- return
- if self.gpio_pin is None:
- raise PinUnsupported(
- 'GPIO was enabled, but is not supported on pin %r' % self.gpio_pin)
- self._disable_pwm()
- if not self.gpio_active:
- self.gpio_pin.open()
- self.gpio_active = True
-
- def _disable_gpio(self):
- if self.gpio_active and self.gpio_pin is not None:
- self.gpio_pin.close()
- self.gpio_active = False
-
- def close(self):
- self._closed = True
- self._poller.stop_polling()
- self._disable_pwm()
- self._disable_gpio()
-
- def _active_pin(self):
- if self.pwm_active:
- return self.pwm_pin
- if self.gpio_active:
- return self.gpio_pin
- return None
-
- def _get_function(self):
- return self._active_pin().get_function()
-
- def _set_function(self, value):
- if value == 'input':
- if self.pwm_active:
- raise InputDeviceError('PWM Pin cannot be set to input')
- self._enable_gpio()
- elif value == 'pwm':
- if self.gpio_active:
- raise PinPWMUnsupported('GPIO Pin cannot be set to pwm')
- self._enable_pwm()
- elif self._active_pin() is None:
- self._enable_gpio()
-
- if value != 'input':
- self._poller.stop_polling()
- self._active_pin().set_function(value)
-
- def _get_state(self):
- return self._active_pin().get_value()
-
- def _set_state(self, state):
- self._active_pin().set_value(state)
-
- def _get_frequency(self):
- if self.pwm_pin is None or not self.pwm_active:
- return None
- return _NS_PER_SECOND / self.pwm_pin.get_period_ns()
-
- def _set_frequency(self, frequency):
- if frequency is None:
- self._enable_gpio()
- else:
- self._enable_pwm()
- self.pwm_pin.set_period_ns(_NS_PER_SECOND / frequency)
-
- def _set_pull(self, pull):
- if pull != 'up':
- raise PinFixedPull(
- 'Only pull up is supported right now (%s)' % pull)
-
- def _get_pull(self):
- return 'up'
-
- def _set_edges(self, edges):
- if edges not in HatPin._EDGE_DETECTORS.keys():
- raise PinInvalidEdges(
- 'Edge must be "both", "falling", "rising", or None')
- self._poller.detector = HatPin._EDGE_DETECTORS[edges]
- self._edges = edges
-
- def _get_edges(self):
- return self._edges
-
- def _set_when_changed(self, callback):
- self._poller.callback = callback
-
- def _get_when_changed(self):
- return self._poller.callback
-
- def set_poll_interval(self, poll_interval):
- """Sets the time between polling the pin value.
-
- If a debounce time is set, this will be set to .51 * the debounce time.
- There is a natural minimum value of _MIN_POLL_INTERVAL to which all smaller
- values will be clipped.
- Args:
- poll_interval: positve float, time in seconds between polling the pin.
- """
- self._poller.poll_interval = poll_interval
-
- def _set_bounce(self, debounce_time):
- if debounce_time is None:
- self._poller.debounce_time = debounce_time
- elif debounce_time < 0:
- raise PinInvalidBounce('Bounce must be positive.')
- else:
- self._poller.debounce_time = debounce_time
- self.set_poll_interval(debounce_time * .51)
-
- def _get_bounce(self):
- return self._poller.debounce_time
-
-
-class HybridFactory(Factory):
- """Factory for selecting between other factories based on priority/success."""
-
- def __init__(self, *factories):
- super(HybridFactory, self).__init__()
- self.factories = factories
-
- def close(self):
- for factory in self.factories:
- factory.close()
-
- def pin(self, spec):
- for factory in self.factories:
- try:
- # Try to make the pin from each factory (in order), until one works.
- return factory.pin(spec)
- except (TypeError, ValueError):
- pass
- raise TypeError(
- 'No registered factory was able to construct a pin for the given '
- 'specification')
-
-
-class HatFactory(Factory):
- """Factory for pins accessed through the hat's MCU."""
- pins = {}
-
- def __init__(self):
- super(HatFactory, self).__init__()
-
- self.pins = HatFactory.pins
-
- def close(self):
- for pin in self.pins.values():
- pin.close()
-
- def pin(self, spec):
- if spec in self.pins:
- return self.pins.get(spec)
- if isinstance(spec, AIYPinSpec):
- pin = HatPin(spec)
- self.pins[spec] = pin
- return pin
- raise TypeError('Hat factory invoked on non-hat pin')
-
-
-# This overrides the default factory being used by all gpiozero devices. It will
-# defer to the previous default for all non-hat pins.
-hat_factory = HatFactory()
-Device.pin_factory = HybridFactory(hat_factory, Device.pin_factory)
diff --git a/src/aiy/vision/proto/__init__.py b/src/aiy/vision/proto/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/aiy/vision/proto/protocol_pb2.py b/src/aiy/vision/proto/protocol_pb2.py
deleted file mode 100644
index 17879726..00000000
--- a/src/aiy/vision/proto/protocol_pb2.py
+++ /dev/null
@@ -1,1324 +0,0 @@
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: protocol.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-from google.protobuf import descriptor_pb2
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='protocol.proto',
- package='spacepark.vision',
- syntax='proto3',
- serialized_pb=_b('\n\x0eprotocol.proto\x12\x10spacepark.vision\"@\n\tRectangle\x12\t\n\x01x\x18\x01 \x01(\x05\x12\t\n\x01y\x18\x02 \x01(\x05\x12\r\n\x05width\x18\x03 \x01(\x05\x12\x0e\n\x06height\x18\x04 \x01(\x05\"J\n\x0bTensorShape\x12\r\n\x05\x62\x61tch\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x05\x12\r\n\x05width\x18\x03 \x01(\x05\x12\r\n\x05\x64\x65pth\x18\x04 \x01(\x05\"H\n\nByteTensor\x12,\n\x05shape\x18\x01 \x01(\x0b\x32\x1d.spacepark.vision.TensorShape\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"I\n\x0b\x46loatTensor\x12,\n\x05shape\x18\x01 \x01(\x0b\x32\x1d.spacepark.vision.TensorShape\x12\x0c\n\x04\x64\x61ta\x18\x02 \x03(\x02\"0\n\x10TensorNormalizer\x12\x0c\n\x04mean\x18\x01 \x01(\x02\x12\x0e\n\x06stddev\x18\x02 \x01(\x02\"\xd5\n\n\x07Request\x12\x39\n\nload_model\x18\x01 \x01(\x0b\x32#.spacepark.vision.Request.LoadModelH\x00\x12=\n\x0cunload_model\x18\x02 \x01(\x0b\x32%.spacepark.vision.Request.UnloadModelH\x00\x12\x43\n\x0fimage_inference\x18\x03 \x01(\x0b\x32(.spacepark.vision.Request.ImageInferenceH\x00\x12P\n\x16start_camera_inference\x18\x04 \x01(\x0b\x32..spacepark.vision.Request.StartCameraInferenceH\x00\x12\x45\n\x10\x63\x61mera_inference\x18\x05 \x01(\x0b\x32).spacepark.vision.Request.CameraInferenceH\x00\x12N\n\x15stop_camera_inference\x18\x06 \x01(\x0b\x32-.spacepark.vision.Request.StopCameraInferenceH\x00\x12\x44\n\x10get_camera_state\x18\x07 \x01(\x0b\x32(.spacepark.vision.Request.GetCameraStateH\x00\x12>\n\rimu_self_test\x18\x08 \x01(\x0b\x32%.spacepark.vision.Request.ImuSelfTestH\x00\x12\x46\n\x11get_firmware_info\x18\t \x01(\x0b\x32).spacepark.vision.Request.GetFirmwareInfoH\x00\x1a\xa8\x01\n\tLoadModel\x12\x12\n\nmodel_name\x18\x01 \x01(\t\x12\x32\n\x0binput_shape\x18\x02 \x01(\x0b\x32\x1d.spacepark.vision.TensorShape\x12<\n\x10input_normalizer\x18\x03 \x01(\x0b\x32\".spacepark.vision.TensorNormalizer\x12\x15\n\rcompute_graph\x18\x04 \x01(\x0c\x1a!\n\x0bUnloadModel\x12\x12\n\nmodel_name\x18\x01 \x01(\t\x1a\xc7\x01\n\x0eImageInference\x12\x12\n\nmodel_name\x18\x01 \x01(\t\x12,\n\x06tensor\x18\x02 \x01(\x0b\x32\x1c.spacepark.vision.ByteTensor\x12\x44\n\x06params\x18\x03 \x03(\x0b\x32\x34.spacepark.vision.Request.ImageInference.ParamsEntry\x1a-\n\x0bParamsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\xd2\x01\n\x14StartCameraInference\x12\x12\n\nmodel_name\x18\x01 \x01(\t\x12+\n\x06window\x18\x02 \x01(\x0b\x32\x1b.spacepark.vision.Rectangle\x12J\n\x06params\x18\x03 \x03(\x0b\x32:.spacepark.vision.Request.StartCameraInference.ParamsEntry\x1a-\n\x0bParamsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x11\n\x0f\x43\x61meraInference\x1a\x15\n\x13StopCameraInference\x1a\x10\n\x0eGetCameraState\x1a\r\n\x0bImuSelfTest\x1a\x11\n\x0fGetFirmwareInfoB\t\n\x07request\"\xa9\x03\n\x0fInferenceResult\x12\x12\n\nmodel_name\x18\x01 \x01(\t\x12\r\n\x05width\x18\x02 \x01(\x05\x12\x0e\n\x06height\x18\x03 \x01(\x05\x12+\n\x06window\x18\x04 \x01(\x0b\x32\x1b.spacepark.vision.Rectangle\x12\x13\n\x0b\x64uration_ms\x18\x05 \x01(\x05\x12?\n\x07tensors\x18\x06 \x03(\x0b\x32..spacepark.vision.InferenceResult.TensorsEntry\x12\x36\n\x05\x66rame\x18\x07 \x01(\x0b\x32\'.spacepark.vision.InferenceResult.Frame\x1aM\n\x0cTensorsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.spacepark.vision.FloatTensor:\x02\x38\x01\x1aY\n\x05\x46rame\x12\r\n\x05index\x18\x01 \x01(\x05\x12\x14\n\x0ctimestamp_us\x18\x02 \x01(\x03\x12+\n\x05image\x18\x03 \x01(\x0b\x32\x1c.spacepark.vision.ByteTensor\"=\n\x0b\x43\x61meraState\x12\x0f\n\x07running\x18\x01 \x01(\x08\x12\r\n\x05width\x18\x02 \x01(\x05\x12\x0e\n\x06height\x18\x03 \x01(\x05\"<\n\x0c\x46irmwareInfo\x12\x15\n\rmajor_version\x18\x01 \x01(\x05\x12\x15\n\rminor_version\x18\x02 \x01(\x05\"\xe4\x02\n\x08Response\x12\x31\n\x06status\x18\x01 \x01(\x0b\x32!.spacepark.vision.Response.Status\x12=\n\x10inference_result\x18\x02 \x01(\x0b\x32!.spacepark.vision.InferenceResultH\x00\x12\x35\n\x0c\x63\x61mera_state\x18\x03 \x01(\x0b\x32\x1d.spacepark.vision.CameraStateH\x00\x12\x37\n\rfirmware_info\x18\x04 \x01(\x0b\x32\x1e.spacepark.vision.FirmwareInfoH\x00\x1aj\n\x06Status\x12\x34\n\x04\x63ode\x18\x01 \x01(\x0e\x32&.spacepark.vision.Response.Status.Code\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x19\n\x04\x43ode\x12\x06\n\x02OK\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x42\n\n\x08responseb\x06proto3')
-)
-
-
-
-_RESPONSE_STATUS_CODE = _descriptor.EnumDescriptor(
- name='Code',
- full_name='spacepark.vision.Response.Status.Code',
- filename=None,
- file=DESCRIPTOR,
- values=[
- _descriptor.EnumValueDescriptor(
- name='OK', index=0, number=0,
- options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='ERROR', index=1, number=1,
- options=None,
- type=None),
- ],
- containing_type=None,
- options=None,
- serialized_start=2618,
- serialized_end=2643,
-)
-_sym_db.RegisterEnumDescriptor(_RESPONSE_STATUS_CODE)
-
-
-_RECTANGLE = _descriptor.Descriptor(
- name='Rectangle',
- full_name='spacepark.vision.Rectangle',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='x', full_name='spacepark.vision.Rectangle.x', index=0,
- number=1, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='y', full_name='spacepark.vision.Rectangle.y', index=1,
- number=2, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='width', full_name='spacepark.vision.Rectangle.width', index=2,
- number=3, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='height', full_name='spacepark.vision.Rectangle.height', index=3,
- number=4, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=36,
- serialized_end=100,
-)
-
-
-_TENSORSHAPE = _descriptor.Descriptor(
- name='TensorShape',
- full_name='spacepark.vision.TensorShape',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='batch', full_name='spacepark.vision.TensorShape.batch', index=0,
- number=1, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='height', full_name='spacepark.vision.TensorShape.height', index=1,
- number=2, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='width', full_name='spacepark.vision.TensorShape.width', index=2,
- number=3, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='depth', full_name='spacepark.vision.TensorShape.depth', index=3,
- number=4, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=102,
- serialized_end=176,
-)
-
-
-_BYTETENSOR = _descriptor.Descriptor(
- name='ByteTensor',
- full_name='spacepark.vision.ByteTensor',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='shape', full_name='spacepark.vision.ByteTensor.shape', index=0,
- number=1, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='data', full_name='spacepark.vision.ByteTensor.data', index=1,
- number=2, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=178,
- serialized_end=250,
-)
-
-
-_FLOATTENSOR = _descriptor.Descriptor(
- name='FloatTensor',
- full_name='spacepark.vision.FloatTensor',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='shape', full_name='spacepark.vision.FloatTensor.shape', index=0,
- number=1, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='data', full_name='spacepark.vision.FloatTensor.data', index=1,
- number=2, type=2, cpp_type=6, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=252,
- serialized_end=325,
-)
-
-
-_TENSORNORMALIZER = _descriptor.Descriptor(
- name='TensorNormalizer',
- full_name='spacepark.vision.TensorNormalizer',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='mean', full_name='spacepark.vision.TensorNormalizer.mean', index=0,
- number=1, type=2, cpp_type=6, label=1,
- has_default_value=False, default_value=float(0),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='stddev', full_name='spacepark.vision.TensorNormalizer.stddev', index=1,
- number=2, type=2, cpp_type=6, label=1,
- has_default_value=False, default_value=float(0),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=327,
- serialized_end=375,
-)
-
-
-_REQUEST_LOADMODEL = _descriptor.Descriptor(
- name='LoadModel',
- full_name='spacepark.vision.Request.LoadModel',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='model_name', full_name='spacepark.vision.Request.LoadModel.model_name', index=0,
- number=1, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='input_shape', full_name='spacepark.vision.Request.LoadModel.input_shape', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='input_normalizer', full_name='spacepark.vision.Request.LoadModel.input_normalizer', index=2,
- number=3, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='compute_graph', full_name='spacepark.vision.Request.LoadModel.compute_graph', index=3,
- number=4, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1020,
- serialized_end=1188,
-)
-
-_REQUEST_UNLOADMODEL = _descriptor.Descriptor(
- name='UnloadModel',
- full_name='spacepark.vision.Request.UnloadModel',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='model_name', full_name='spacepark.vision.Request.UnloadModel.model_name', index=0,
- number=1, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1190,
- serialized_end=1223,
-)
-
-_REQUEST_IMAGEINFERENCE_PARAMSENTRY = _descriptor.Descriptor(
- name='ParamsEntry',
- full_name='spacepark.vision.Request.ImageInference.ParamsEntry',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='key', full_name='spacepark.vision.Request.ImageInference.ParamsEntry.key', index=0,
- number=1, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='value', full_name='spacepark.vision.Request.ImageInference.ParamsEntry.value', index=1,
- number=2, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')),
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1380,
- serialized_end=1425,
-)
-
-_REQUEST_IMAGEINFERENCE = _descriptor.Descriptor(
- name='ImageInference',
- full_name='spacepark.vision.Request.ImageInference',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='model_name', full_name='spacepark.vision.Request.ImageInference.model_name', index=0,
- number=1, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='tensor', full_name='spacepark.vision.Request.ImageInference.tensor', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='params', full_name='spacepark.vision.Request.ImageInference.params', index=2,
- number=3, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[_REQUEST_IMAGEINFERENCE_PARAMSENTRY, ],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1226,
- serialized_end=1425,
-)
-
-_REQUEST_STARTCAMERAINFERENCE_PARAMSENTRY = _descriptor.Descriptor(
- name='ParamsEntry',
- full_name='spacepark.vision.Request.StartCameraInference.ParamsEntry',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='key', full_name='spacepark.vision.Request.StartCameraInference.ParamsEntry.key', index=0,
- number=1, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='value', full_name='spacepark.vision.Request.StartCameraInference.ParamsEntry.value', index=1,
- number=2, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')),
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1380,
- serialized_end=1425,
-)
-
-_REQUEST_STARTCAMERAINFERENCE = _descriptor.Descriptor(
- name='StartCameraInference',
- full_name='spacepark.vision.Request.StartCameraInference',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='model_name', full_name='spacepark.vision.Request.StartCameraInference.model_name', index=0,
- number=1, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='window', full_name='spacepark.vision.Request.StartCameraInference.window', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='params', full_name='spacepark.vision.Request.StartCameraInference.params', index=2,
- number=3, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[_REQUEST_STARTCAMERAINFERENCE_PARAMSENTRY, ],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1428,
- serialized_end=1638,
-)
-
-_REQUEST_CAMERAINFERENCE = _descriptor.Descriptor(
- name='CameraInference',
- full_name='spacepark.vision.Request.CameraInference',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1640,
- serialized_end=1657,
-)
-
-_REQUEST_STOPCAMERAINFERENCE = _descriptor.Descriptor(
- name='StopCameraInference',
- full_name='spacepark.vision.Request.StopCameraInference',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1659,
- serialized_end=1680,
-)
-
-_REQUEST_GETCAMERASTATE = _descriptor.Descriptor(
- name='GetCameraState',
- full_name='spacepark.vision.Request.GetCameraState',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1682,
- serialized_end=1698,
-)
-
-_REQUEST_IMUSELFTEST = _descriptor.Descriptor(
- name='ImuSelfTest',
- full_name='spacepark.vision.Request.ImuSelfTest',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1700,
- serialized_end=1713,
-)
-
-_REQUEST_GETFIRMWAREINFO = _descriptor.Descriptor(
- name='GetFirmwareInfo',
- full_name='spacepark.vision.Request.GetFirmwareInfo',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1715,
- serialized_end=1732,
-)
-
-_REQUEST = _descriptor.Descriptor(
- name='Request',
- full_name='spacepark.vision.Request',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='load_model', full_name='spacepark.vision.Request.load_model', index=0,
- number=1, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='unload_model', full_name='spacepark.vision.Request.unload_model', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='image_inference', full_name='spacepark.vision.Request.image_inference', index=2,
- number=3, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='start_camera_inference', full_name='spacepark.vision.Request.start_camera_inference', index=3,
- number=4, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='camera_inference', full_name='spacepark.vision.Request.camera_inference', index=4,
- number=5, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='stop_camera_inference', full_name='spacepark.vision.Request.stop_camera_inference', index=5,
- number=6, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='get_camera_state', full_name='spacepark.vision.Request.get_camera_state', index=6,
- number=7, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='imu_self_test', full_name='spacepark.vision.Request.imu_self_test', index=7,
- number=8, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='get_firmware_info', full_name='spacepark.vision.Request.get_firmware_info', index=8,
- number=9, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[_REQUEST_LOADMODEL, _REQUEST_UNLOADMODEL, _REQUEST_IMAGEINFERENCE, _REQUEST_STARTCAMERAINFERENCE, _REQUEST_CAMERAINFERENCE, _REQUEST_STOPCAMERAINFERENCE, _REQUEST_GETCAMERASTATE, _REQUEST_IMUSELFTEST, _REQUEST_GETFIRMWAREINFO, ],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='request', full_name='spacepark.vision.Request.request',
- index=0, containing_type=None, fields=[]),
- ],
- serialized_start=378,
- serialized_end=1743,
-)
-
-
-_INFERENCERESULT_TENSORSENTRY = _descriptor.Descriptor(
- name='TensorsEntry',
- full_name='spacepark.vision.InferenceResult.TensorsEntry',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='key', full_name='spacepark.vision.InferenceResult.TensorsEntry.key', index=0,
- number=1, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='value', full_name='spacepark.vision.InferenceResult.TensorsEntry.value', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')),
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2003,
- serialized_end=2080,
-)
-
-_INFERENCERESULT_FRAME = _descriptor.Descriptor(
- name='Frame',
- full_name='spacepark.vision.InferenceResult.Frame',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='index', full_name='spacepark.vision.InferenceResult.Frame.index', index=0,
- number=1, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='timestamp_us', full_name='spacepark.vision.InferenceResult.Frame.timestamp_us', index=1,
- number=2, type=3, cpp_type=2, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='image', full_name='spacepark.vision.InferenceResult.Frame.image', index=2,
- number=3, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2082,
- serialized_end=2171,
-)
-
-_INFERENCERESULT = _descriptor.Descriptor(
- name='InferenceResult',
- full_name='spacepark.vision.InferenceResult',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='model_name', full_name='spacepark.vision.InferenceResult.model_name', index=0,
- number=1, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='width', full_name='spacepark.vision.InferenceResult.width', index=1,
- number=2, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='height', full_name='spacepark.vision.InferenceResult.height', index=2,
- number=3, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='window', full_name='spacepark.vision.InferenceResult.window', index=3,
- number=4, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='duration_ms', full_name='spacepark.vision.InferenceResult.duration_ms', index=4,
- number=5, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='tensors', full_name='spacepark.vision.InferenceResult.tensors', index=5,
- number=6, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='frame', full_name='spacepark.vision.InferenceResult.frame', index=6,
- number=7, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[_INFERENCERESULT_TENSORSENTRY, _INFERENCERESULT_FRAME, ],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1746,
- serialized_end=2171,
-)
-
-
-_CAMERASTATE = _descriptor.Descriptor(
- name='CameraState',
- full_name='spacepark.vision.CameraState',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='running', full_name='spacepark.vision.CameraState.running', index=0,
- number=1, type=8, cpp_type=7, label=1,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='width', full_name='spacepark.vision.CameraState.width', index=1,
- number=2, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='height', full_name='spacepark.vision.CameraState.height', index=2,
- number=3, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2173,
- serialized_end=2234,
-)
-
-
-_FIRMWAREINFO = _descriptor.Descriptor(
- name='FirmwareInfo',
- full_name='spacepark.vision.FirmwareInfo',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='major_version', full_name='spacepark.vision.FirmwareInfo.major_version', index=0,
- number=1, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='minor_version', full_name='spacepark.vision.FirmwareInfo.minor_version', index=1,
- number=2, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2236,
- serialized_end=2296,
-)
-
-
-_RESPONSE_STATUS = _descriptor.Descriptor(
- name='Status',
- full_name='spacepark.vision.Response.Status',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='code', full_name='spacepark.vision.Response.Status.code', index=0,
- number=1, type=14, cpp_type=8, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='message', full_name='spacepark.vision.Response.Status.message', index=1,
- number=2, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- _RESPONSE_STATUS_CODE,
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2537,
- serialized_end=2643,
-)
-
-_RESPONSE = _descriptor.Descriptor(
- name='Response',
- full_name='spacepark.vision.Response',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='status', full_name='spacepark.vision.Response.status', index=0,
- number=1, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='inference_result', full_name='spacepark.vision.Response.inference_result', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='camera_state', full_name='spacepark.vision.Response.camera_state', index=2,
- number=3, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='firmware_info', full_name='spacepark.vision.Response.firmware_info', index=3,
- number=4, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[_RESPONSE_STATUS, ],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='response', full_name='spacepark.vision.Response.response',
- index=0, containing_type=None, fields=[]),
- ],
- serialized_start=2299,
- serialized_end=2655,
-)
-
-_BYTETENSOR.fields_by_name['shape'].message_type = _TENSORSHAPE
-_FLOATTENSOR.fields_by_name['shape'].message_type = _TENSORSHAPE
-_REQUEST_LOADMODEL.fields_by_name['input_shape'].message_type = _TENSORSHAPE
-_REQUEST_LOADMODEL.fields_by_name['input_normalizer'].message_type = _TENSORNORMALIZER
-_REQUEST_LOADMODEL.containing_type = _REQUEST
-_REQUEST_UNLOADMODEL.containing_type = _REQUEST
-_REQUEST_IMAGEINFERENCE_PARAMSENTRY.containing_type = _REQUEST_IMAGEINFERENCE
-_REQUEST_IMAGEINFERENCE.fields_by_name['tensor'].message_type = _BYTETENSOR
-_REQUEST_IMAGEINFERENCE.fields_by_name['params'].message_type = _REQUEST_IMAGEINFERENCE_PARAMSENTRY
-_REQUEST_IMAGEINFERENCE.containing_type = _REQUEST
-_REQUEST_STARTCAMERAINFERENCE_PARAMSENTRY.containing_type = _REQUEST_STARTCAMERAINFERENCE
-_REQUEST_STARTCAMERAINFERENCE.fields_by_name['window'].message_type = _RECTANGLE
-_REQUEST_STARTCAMERAINFERENCE.fields_by_name['params'].message_type = _REQUEST_STARTCAMERAINFERENCE_PARAMSENTRY
-_REQUEST_STARTCAMERAINFERENCE.containing_type = _REQUEST
-_REQUEST_CAMERAINFERENCE.containing_type = _REQUEST
-_REQUEST_STOPCAMERAINFERENCE.containing_type = _REQUEST
-_REQUEST_GETCAMERASTATE.containing_type = _REQUEST
-_REQUEST_IMUSELFTEST.containing_type = _REQUEST
-_REQUEST_GETFIRMWAREINFO.containing_type = _REQUEST
-_REQUEST.fields_by_name['load_model'].message_type = _REQUEST_LOADMODEL
-_REQUEST.fields_by_name['unload_model'].message_type = _REQUEST_UNLOADMODEL
-_REQUEST.fields_by_name['image_inference'].message_type = _REQUEST_IMAGEINFERENCE
-_REQUEST.fields_by_name['start_camera_inference'].message_type = _REQUEST_STARTCAMERAINFERENCE
-_REQUEST.fields_by_name['camera_inference'].message_type = _REQUEST_CAMERAINFERENCE
-_REQUEST.fields_by_name['stop_camera_inference'].message_type = _REQUEST_STOPCAMERAINFERENCE
-_REQUEST.fields_by_name['get_camera_state'].message_type = _REQUEST_GETCAMERASTATE
-_REQUEST.fields_by_name['imu_self_test'].message_type = _REQUEST_IMUSELFTEST
-_REQUEST.fields_by_name['get_firmware_info'].message_type = _REQUEST_GETFIRMWAREINFO
-_REQUEST.oneofs_by_name['request'].fields.append(
- _REQUEST.fields_by_name['load_model'])
-_REQUEST.fields_by_name['load_model'].containing_oneof = _REQUEST.oneofs_by_name['request']
-_REQUEST.oneofs_by_name['request'].fields.append(
- _REQUEST.fields_by_name['unload_model'])
-_REQUEST.fields_by_name['unload_model'].containing_oneof = _REQUEST.oneofs_by_name['request']
-_REQUEST.oneofs_by_name['request'].fields.append(
- _REQUEST.fields_by_name['image_inference'])
-_REQUEST.fields_by_name['image_inference'].containing_oneof = _REQUEST.oneofs_by_name['request']
-_REQUEST.oneofs_by_name['request'].fields.append(
- _REQUEST.fields_by_name['start_camera_inference'])
-_REQUEST.fields_by_name['start_camera_inference'].containing_oneof = _REQUEST.oneofs_by_name['request']
-_REQUEST.oneofs_by_name['request'].fields.append(
- _REQUEST.fields_by_name['camera_inference'])
-_REQUEST.fields_by_name['camera_inference'].containing_oneof = _REQUEST.oneofs_by_name['request']
-_REQUEST.oneofs_by_name['request'].fields.append(
- _REQUEST.fields_by_name['stop_camera_inference'])
-_REQUEST.fields_by_name['stop_camera_inference'].containing_oneof = _REQUEST.oneofs_by_name['request']
-_REQUEST.oneofs_by_name['request'].fields.append(
- _REQUEST.fields_by_name['get_camera_state'])
-_REQUEST.fields_by_name['get_camera_state'].containing_oneof = _REQUEST.oneofs_by_name['request']
-_REQUEST.oneofs_by_name['request'].fields.append(
- _REQUEST.fields_by_name['imu_self_test'])
-_REQUEST.fields_by_name['imu_self_test'].containing_oneof = _REQUEST.oneofs_by_name['request']
-_REQUEST.oneofs_by_name['request'].fields.append(
- _REQUEST.fields_by_name['get_firmware_info'])
-_REQUEST.fields_by_name['get_firmware_info'].containing_oneof = _REQUEST.oneofs_by_name['request']
-_INFERENCERESULT_TENSORSENTRY.fields_by_name['value'].message_type = _FLOATTENSOR
-_INFERENCERESULT_TENSORSENTRY.containing_type = _INFERENCERESULT
-_INFERENCERESULT_FRAME.fields_by_name['image'].message_type = _BYTETENSOR
-_INFERENCERESULT_FRAME.containing_type = _INFERENCERESULT
-_INFERENCERESULT.fields_by_name['window'].message_type = _RECTANGLE
-_INFERENCERESULT.fields_by_name['tensors'].message_type = _INFERENCERESULT_TENSORSENTRY
-_INFERENCERESULT.fields_by_name['frame'].message_type = _INFERENCERESULT_FRAME
-_RESPONSE_STATUS.fields_by_name['code'].enum_type = _RESPONSE_STATUS_CODE
-_RESPONSE_STATUS.containing_type = _RESPONSE
-_RESPONSE_STATUS_CODE.containing_type = _RESPONSE_STATUS
-_RESPONSE.fields_by_name['status'].message_type = _RESPONSE_STATUS
-_RESPONSE.fields_by_name['inference_result'].message_type = _INFERENCERESULT
-_RESPONSE.fields_by_name['camera_state'].message_type = _CAMERASTATE
-_RESPONSE.fields_by_name['firmware_info'].message_type = _FIRMWAREINFO
-_RESPONSE.oneofs_by_name['response'].fields.append(
- _RESPONSE.fields_by_name['inference_result'])
-_RESPONSE.fields_by_name['inference_result'].containing_oneof = _RESPONSE.oneofs_by_name['response']
-_RESPONSE.oneofs_by_name['response'].fields.append(
- _RESPONSE.fields_by_name['camera_state'])
-_RESPONSE.fields_by_name['camera_state'].containing_oneof = _RESPONSE.oneofs_by_name['response']
-_RESPONSE.oneofs_by_name['response'].fields.append(
- _RESPONSE.fields_by_name['firmware_info'])
-_RESPONSE.fields_by_name['firmware_info'].containing_oneof = _RESPONSE.oneofs_by_name['response']
-DESCRIPTOR.message_types_by_name['Rectangle'] = _RECTANGLE
-DESCRIPTOR.message_types_by_name['TensorShape'] = _TENSORSHAPE
-DESCRIPTOR.message_types_by_name['ByteTensor'] = _BYTETENSOR
-DESCRIPTOR.message_types_by_name['FloatTensor'] = _FLOATTENSOR
-DESCRIPTOR.message_types_by_name['TensorNormalizer'] = _TENSORNORMALIZER
-DESCRIPTOR.message_types_by_name['Request'] = _REQUEST
-DESCRIPTOR.message_types_by_name['InferenceResult'] = _INFERENCERESULT
-DESCRIPTOR.message_types_by_name['CameraState'] = _CAMERASTATE
-DESCRIPTOR.message_types_by_name['FirmwareInfo'] = _FIRMWAREINFO
-DESCRIPTOR.message_types_by_name['Response'] = _RESPONSE
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-Rectangle = _reflection.GeneratedProtocolMessageType('Rectangle', (_message.Message,), dict(
- DESCRIPTOR = _RECTANGLE,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Rectangle)
- ))
-_sym_db.RegisterMessage(Rectangle)
-
-TensorShape = _reflection.GeneratedProtocolMessageType('TensorShape', (_message.Message,), dict(
- DESCRIPTOR = _TENSORSHAPE,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.TensorShape)
- ))
-_sym_db.RegisterMessage(TensorShape)
-
-ByteTensor = _reflection.GeneratedProtocolMessageType('ByteTensor', (_message.Message,), dict(
- DESCRIPTOR = _BYTETENSOR,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.ByteTensor)
- ))
-_sym_db.RegisterMessage(ByteTensor)
-
-FloatTensor = _reflection.GeneratedProtocolMessageType('FloatTensor', (_message.Message,), dict(
- DESCRIPTOR = _FLOATTENSOR,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.FloatTensor)
- ))
-_sym_db.RegisterMessage(FloatTensor)
-
-TensorNormalizer = _reflection.GeneratedProtocolMessageType('TensorNormalizer', (_message.Message,), dict(
- DESCRIPTOR = _TENSORNORMALIZER,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.TensorNormalizer)
- ))
-_sym_db.RegisterMessage(TensorNormalizer)
-
-Request = _reflection.GeneratedProtocolMessageType('Request', (_message.Message,), dict(
-
- LoadModel = _reflection.GeneratedProtocolMessageType('LoadModel', (_message.Message,), dict(
- DESCRIPTOR = _REQUEST_LOADMODEL,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.LoadModel)
- ))
- ,
-
- UnloadModel = _reflection.GeneratedProtocolMessageType('UnloadModel', (_message.Message,), dict(
- DESCRIPTOR = _REQUEST_UNLOADMODEL,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.UnloadModel)
- ))
- ,
-
- ImageInference = _reflection.GeneratedProtocolMessageType('ImageInference', (_message.Message,), dict(
-
- ParamsEntry = _reflection.GeneratedProtocolMessageType('ParamsEntry', (_message.Message,), dict(
- DESCRIPTOR = _REQUEST_IMAGEINFERENCE_PARAMSENTRY,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.ImageInference.ParamsEntry)
- ))
- ,
- DESCRIPTOR = _REQUEST_IMAGEINFERENCE,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.ImageInference)
- ))
- ,
-
- StartCameraInference = _reflection.GeneratedProtocolMessageType('StartCameraInference', (_message.Message,), dict(
-
- ParamsEntry = _reflection.GeneratedProtocolMessageType('ParamsEntry', (_message.Message,), dict(
- DESCRIPTOR = _REQUEST_STARTCAMERAINFERENCE_PARAMSENTRY,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.StartCameraInference.ParamsEntry)
- ))
- ,
- DESCRIPTOR = _REQUEST_STARTCAMERAINFERENCE,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.StartCameraInference)
- ))
- ,
-
- CameraInference = _reflection.GeneratedProtocolMessageType('CameraInference', (_message.Message,), dict(
- DESCRIPTOR = _REQUEST_CAMERAINFERENCE,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.CameraInference)
- ))
- ,
-
- StopCameraInference = _reflection.GeneratedProtocolMessageType('StopCameraInference', (_message.Message,), dict(
- DESCRIPTOR = _REQUEST_STOPCAMERAINFERENCE,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.StopCameraInference)
- ))
- ,
-
- GetCameraState = _reflection.GeneratedProtocolMessageType('GetCameraState', (_message.Message,), dict(
- DESCRIPTOR = _REQUEST_GETCAMERASTATE,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.GetCameraState)
- ))
- ,
-
- ImuSelfTest = _reflection.GeneratedProtocolMessageType('ImuSelfTest', (_message.Message,), dict(
- DESCRIPTOR = _REQUEST_IMUSELFTEST,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.ImuSelfTest)
- ))
- ,
-
- GetFirmwareInfo = _reflection.GeneratedProtocolMessageType('GetFirmwareInfo', (_message.Message,), dict(
- DESCRIPTOR = _REQUEST_GETFIRMWAREINFO,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request.GetFirmwareInfo)
- ))
- ,
- DESCRIPTOR = _REQUEST,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Request)
- ))
-_sym_db.RegisterMessage(Request)
-_sym_db.RegisterMessage(Request.LoadModel)
-_sym_db.RegisterMessage(Request.UnloadModel)
-_sym_db.RegisterMessage(Request.ImageInference)
-_sym_db.RegisterMessage(Request.ImageInference.ParamsEntry)
-_sym_db.RegisterMessage(Request.StartCameraInference)
-_sym_db.RegisterMessage(Request.StartCameraInference.ParamsEntry)
-_sym_db.RegisterMessage(Request.CameraInference)
-_sym_db.RegisterMessage(Request.StopCameraInference)
-_sym_db.RegisterMessage(Request.GetCameraState)
-_sym_db.RegisterMessage(Request.ImuSelfTest)
-_sym_db.RegisterMessage(Request.GetFirmwareInfo)
-
-InferenceResult = _reflection.GeneratedProtocolMessageType('InferenceResult', (_message.Message,), dict(
-
- TensorsEntry = _reflection.GeneratedProtocolMessageType('TensorsEntry', (_message.Message,), dict(
- DESCRIPTOR = _INFERENCERESULT_TENSORSENTRY,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.InferenceResult.TensorsEntry)
- ))
- ,
-
- Frame = _reflection.GeneratedProtocolMessageType('Frame', (_message.Message,), dict(
- DESCRIPTOR = _INFERENCERESULT_FRAME,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.InferenceResult.Frame)
- ))
- ,
- DESCRIPTOR = _INFERENCERESULT,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.InferenceResult)
- ))
-_sym_db.RegisterMessage(InferenceResult)
-_sym_db.RegisterMessage(InferenceResult.TensorsEntry)
-_sym_db.RegisterMessage(InferenceResult.Frame)
-
-CameraState = _reflection.GeneratedProtocolMessageType('CameraState', (_message.Message,), dict(
- DESCRIPTOR = _CAMERASTATE,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.CameraState)
- ))
-_sym_db.RegisterMessage(CameraState)
-
-FirmwareInfo = _reflection.GeneratedProtocolMessageType('FirmwareInfo', (_message.Message,), dict(
- DESCRIPTOR = _FIRMWAREINFO,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.FirmwareInfo)
- ))
-_sym_db.RegisterMessage(FirmwareInfo)
-
-Response = _reflection.GeneratedProtocolMessageType('Response', (_message.Message,), dict(
-
- Status = _reflection.GeneratedProtocolMessageType('Status', (_message.Message,), dict(
- DESCRIPTOR = _RESPONSE_STATUS,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Response.Status)
- ))
- ,
- DESCRIPTOR = _RESPONSE,
- __module__ = 'protocol_pb2'
- # @@protoc_insertion_point(class_scope:spacepark.vision.Response)
- ))
-_sym_db.RegisterMessage(Response)
-_sym_db.RegisterMessage(Response.Status)
-
-
-_REQUEST_IMAGEINFERENCE_PARAMSENTRY.has_options = True
-_REQUEST_IMAGEINFERENCE_PARAMSENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001'))
-_REQUEST_STARTCAMERAINFERENCE_PARAMSENTRY.has_options = True
-_REQUEST_STARTCAMERAINFERENCE_PARAMSENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001'))
-_INFERENCERESULT_TENSORSENTRY.has_options = True
-_INFERENCERESULT_TENSORSENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001'))
-# @@protoc_insertion_point(module_scope)
diff --git a/src/aiy/voicehat.py b/src/aiy/voicehat.py
deleted file mode 100644
index 57414394..00000000
--- a/src/aiy/voicehat.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Drivers for shared functionality provided by the VoiceHat."""
-
-import aiy._drivers._button
-import aiy._drivers._led
-import aiy._drivers._status_ui
-
-# GPIO definitions (BCM)
-_GPIO_BUTTON = 23
-_GPIO_LED = 25
-
-# Import LED class to expose the LED constants.
-LED = aiy._drivers._led.LED
-
-# Global variables. They are lazily initialized.
-_voicehat_button = None
-_voicehat_led = None
-_status_ui = None
-
-
-def get_button():
- """Returns a driver to the VoiceHat button.
-
- The button driver detects edges on _GPIO_BUTTON. It can be used both
- synchronously and asynchrously.
-
- Synchronous usage:
- button = aiy.voicehat.get_button()
- button.wait_for_press()
- # The above function does not return until the button is pressed.
- my_recognizer.recognize()
- ...
-
- Asynchronous usage:
- def on_button_press(_):
- print('The button is pressed!')
-
- button = aiy.voicehat.get_button()
- button.on_press(on_button_press)
- # The console will print 'The button is pressed!' every time the button is
- # pressed.
- ...
- # To cancel the callback, pass None:
- button.on_press(None)
- # Calling wait_for_press() also cancels any callback.
- """
- global _voicehat_button
- if not _voicehat_button:
- _voicehat_button = aiy._drivers._button.Button(channel=_GPIO_BUTTON)
- return _voicehat_button
-
-
-def get_led():
- """Returns a driver to control the VoiceHat LED light with various animations.
-
- led = aiy.voicehat.get_led()
-
- # You may set any LED animation:
- led.set_state(aiy.voicehat.LED.PULSE_QUICK)
- led.set_state(aiy.voicehat.LED.BLINK)
-
- # Or turn off the light but keep the driver running:
- led.set_state(aiy.voicehat.LED.OFF)
- """
- global _voicehat_led
- if not _voicehat_led:
- _voicehat_led = aiy._drivers._led.LED(channel=_GPIO_LED)
- _voicehat_led.start()
- return _voicehat_led
-
-
-def get_status_ui():
- """Returns a driver to control the LED via statuses.
-
- The supported statuses are:
- - "starting"
- - "ready"
- - "listening"
- - "thinking"
- - "stopping"
- - "power-off"
- - "error"
-
- Optionally, a sound may be played once when the status changes to
- "listening". For example, if you have a wave file at ~/ding.wav, you may set
- the trigger sound by:
- aiy.voicehat.get_status_ui().set_trigger_sound_wave('~/ding.wav')
-
- To set the status, use:
- aiy.voicehat.get_status_ui().set_state('starting')
- aiy.voicehat.get_status_ui().set_state('thinking')
- """
- global _status_ui
- if not _status_ui:
- _status_ui = aiy._drivers._status_ui._StatusUi()
- return _status_ui
diff --git a/src/examples/vision/annotator.py b/src/examples/vision/annotator.py
deleted file mode 100755
index 399a9eec..00000000
--- a/src/examples/vision/annotator.py
+++ /dev/null
@@ -1,180 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Annotation library for drawing overlays on the raspberry pi's camera preview.
-
-Annotations include bounding boxes, text overlays, and points.
-Annotations support partial opacity, however only with respect to the content in
-the preview. A transparent fill value will cover up previously drawn overlay
-under it, but not the camera content under it. A color of None can be given,
-which will then not cover up overlay content drawn under the region.
-
-Note: Overlays do not persist through to the storage layer so images saved from
-the camera, will not contain overlays.
-"""
-
-import picamera
-import time
-from PIL import Image
-from PIL import ImageDraw
-
-
-def _round_to_bit(value, power):
- """Rounds the given value to the next multiple of 2^power.
-
- Args:
- value: int to be rounded.
- power: power of two which the value should be rounded up to.
- Returns:
- the result of value rounded to the next multiple 2^power.
- """
- return (((value - 1) >> power) + 1) << power
-
-
-def _round_buffer_dims(dims):
- """Appropriately rounds the given dimensions for image overlaying.
-
- The overlay buffer must be rounded the next multiple of 32 for the hight, and
- the next multiple of 16 for the width."""
- return (_round_to_bit(dims[0], 5), _round_to_bit(dims[1], 4))
-
-
-# TODO(namiller): Add an annotator for images.
-class Annotator(object):
- """Utility for managing annotations on the camera preview.
-
- Args:
- camera: picamera.PiCamera camera object to overlay on top of.
- bg_color: PIL.ImageColor (with alpha) for the background of the overlays.
- default_color: PIL.ImageColor (with alpha) default for the drawn content.
- """
-
- def __init__(self, camera, bg_color=None, default_color=None,
- dimensions=None):
- self._dims = dimensions if dimensions else camera.resolution
- self._buffer_dims = _round_buffer_dims(self._dims)
- self._buffer = Image.new('RGBA', self._buffer_dims)
- self._overlay = camera.add_overlay(
- self._buffer.tobytes(), format='rgba', layer=3, size=self._buffer_dims)
- self._draw = ImageDraw.Draw(self._buffer)
- self._bg_color = bg_color if bg_color else (0, 0, 0, 0xA0)
- self._default_color = default_color if default_color else (0xFF, 0, 0, 0xFF)
-
- # MMALPort has a bug in enable.wrapper, where it always calls
- # self._pool.send_buffer(block=False) regardless of the port direction.
- # This is in contrast to setup time when it only calls
- # self._pool.send_all_buffers(block=False)
- # if self._port[0].type == mmal.MMAL_PORT_TYPE_OUTPUT.
- # Because of this bug updating an overlay once will log a MMAL_EAGAIN
- # error every update. This is safe to ignore as we the user is driving
- # the renderer input port with calls to update() that dequeue buffers
- # and sends them to the input port (so queue is empty on when
- # send_all_buffers(block=False) is called from wrapper).
- # As a workaround, monkey patch MMALPortPool.send_buffer and
- # silence the "error" if thrown by our overlay instance.
- original_send_buffer = picamera.mmalobj.MMALPortPool.send_buffer
-
- def silent_send_buffer(zelf, **kwargs):
- try:
- original_send_buffer(zelf, **kwargs)
- except picamera.exc.PiCameraMMALError as error:
- # Only silence MMAL_EAGAIN for our target instance.
- our_target = self._overlay.renderer.inputs[0].pool == zelf
- if not our_target or error.status != 14:
- raise error
-
- picamera.mmalobj.MMALPortPool.send_buffer = silent_send_buffer
-
- def update(self):
- """Updates the contents of the overlay."""
- self._overlay.update(self._buffer.tobytes())
-
- def stop(self):
- """Removes the overlay from the screen."""
- self._draw.rectangle((0, 0) + self._dims, fill=0)
- self.update()
-
- def clear(self):
- """Clears the contents of the overlay - leaving only the plain background.
- """
- self._draw.rectangle((0, 0) + self._dims, fill=self._bg_color)
-
- def bounding_box(self, rect, outline=None, fill=None):
- """Draws a bounding box around the specified rectangle.
-
- Args:
- rect: (x1, y1, x2, y2) rectangle to be drawn - where (x1,y1) and (x2, y2)
- are opposite corners of the desired rectangle.
- outline: PIL.ImageColor with which to draw the outline (defaults to the
- configured default_color).
- fill: PIL.ImageColor with which to fill the rectangel (defaults to None
- which will not cover up drawings under the region.
- """
- outline = self._default_color if outline is None else outline
- self._draw.rectangle(rect, fill=fill, outline=outline)
-
- # TODO(namiller): Add a font size parameter and load a truetype font.
- def text(self, location, text, color=None):
- """Draws the given text at the given location.
-
- Args:
- location: (x,y) point at which to draw the text (upper left corner).
- text: string to be drawn.
- color: PIL.ImageColor to draw the string in (defaults to default_color).
- """
- color = self._default_color if color is None else color
- self._draw.text(location, text, fill=color)
-
- def point(self, location, radius=1, color=None):
- """Draws a point of the given size at the given location.
-
- Args:
- location: (x,y) center of the point to be drawn.
- radius: the radius of the point to be drawn.
- color: The color to draw the point in (defaults to default_color).
- """
- color = self._default_color if color is None else color
- self._draw.ellipse(
- (location[0] - radius, location[1] - radius, location[0] + radius,
- location[1] + radius),
- fill=color)
-
-
-def _main():
- """Example usage of the annotator utility.
-
- Demonstrates setting up a camera preview, drawing slowly moving/intersecting
- animations over it, and clearing the overlays."""
- with picamera.PiCamera() as camera:
- # Resolution can be arbitrary.
- camera.resolution = (351, 561)
- camera.start_preview()
- annotator = Annotator(camera)
- for i in range(10):
- annotator.clear()
- annotator.bounding_box(
- (20, 20, 70, 70), outline=(0, 0xFF, 0, 0xFF), fill=0)
- annotator.bounding_box((10 * i, 10, 10 * i + 50, 60))
- annotator.bounding_box(
- (80, 0, 130, 50), outline=(0, 0, 0xFF, 0xFF), fill=0)
- annotator.text((100, 100), 'Hello World')
- annotator.point((10, 100), radius=5)
- annotator.update()
- time.sleep(1)
- annotator.stop()
- time.sleep(10)
-
-
-if __name__ == '__main__':
- _main()
diff --git a/src/examples/vision/dish_classifier.py b/src/examples/vision/dish_classifier.py
deleted file mode 100755
index 862b48f0..00000000
--- a/src/examples/vision/dish_classifier.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Dish classifier library demo."""
-
-import argparse
-from PIL import Image
-
-from aiy.vision.inference import ImageInference
-from aiy.vision.models import dish_classifier
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('--input', '-i', dest='input', required=True)
- args = parser.parse_args()
-
- with ImageInference(dish_classifier.model()) as inference:
- image = Image.open(args.input)
- classes = dish_classifier.get_classes(
- inference.run(image), max_num_objects=5, object_prob_threshold=0.1)
- for i, (label, score) in enumerate(classes):
- print('Result %d: %s (prob=%f)' % (i, label, score))
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/vision/face_camera_trigger.py b/src/examples/vision/face_camera_trigger.py
deleted file mode 100755
index 9c32ac37..00000000
--- a/src/examples/vision/face_camera_trigger.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Trigger PiCamera when face is detected."""
-
-from aiy.vision.inference import CameraInference
-from aiy.vision.models import face_detection
-from picamera import PiCamera
-
-
-def main():
- with PiCamera() as camera:
- # Configure camera
- camera.resolution = (1640, 922) # Full Frame, 16:9 (Camera v2)
- camera.start_preview()
-
- # Do inference on VisionBonnet
- with CameraInference(face_detection.model()) as inference:
- for result in inference.run():
- if len(face_detection.get_faces(result)) >= 1:
- camera.capture('faces.jpg')
- break
-
- # Stop preview
- camera.stop_preview()
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/vision/face_detection.py b/src/examples/vision/face_detection.py
deleted file mode 100755
index 9c8eb234..00000000
--- a/src/examples/vision/face_detection.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Face detection library demo.
-
- - Takes an input image and tries to detect faces.
- - Draws bounding boxes around detected objects.
- - Saves an image with bounding boxes around detected objects.
-"""
-import argparse
-import io
-import sys
-from PIL import Image
-from PIL import ImageDraw
-
-from aiy.vision.inference import ImageInference
-from aiy.vision.models import face_detection
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('--input', '-i', dest='input', required=True)
- parser.add_argument('--output', '-o', dest='output')
- args = parser.parse_args()
-
- with ImageInference(face_detection.model()) as inference:
- image = Image.open(
- io.BytesIO(sys.stdin.buffer.read())
- if args.input == '-' else args.input)
- draw = ImageDraw.Draw(image)
- for i, face in enumerate(face_detection.get_faces(inference.run(image))):
- print('Face #%d: %s' % (i, str(face)))
- x, y, width, height = face.bounding_box
- draw.rectangle((x, y, x + width, y + height), outline='red')
- if args.output:
- image.save(args.output)
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/vision/face_detection_camera.py b/src/examples/vision/face_detection_camera.py
deleted file mode 100755
index d7ba3f26..00000000
--- a/src/examples/vision/face_detection_camera.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Camera inference face detection demo code.
-
-Runs continuous face detection on the VisionBonnet and prints the number of
-detected faces.
-
-Example:
-face_detection_camera.py --num_frames 10
-"""
-import argparse
-
-from aiy.vision.inference import CameraInference
-from aiy.vision.models import face_detection
-from examples.vision.annotator import Annotator
-from picamera import PiCamera
-
-
-def main():
- """Face detection camera inference example."""
- parser = argparse.ArgumentParser()
- parser.add_argument(
- '--num_frames',
- '-n',
- type=int,
- dest='num_frames',
- default=-1,
- help='Sets the number of frames to run for, otherwise runs forever.')
- args = parser.parse_args()
-
- with PiCamera() as camera:
- # Forced sensor mode, 1640x1232, full FoV. See:
- # https://picamera.readthedocs.io/en/release-1.13/fov.html#sensor-modes
- # This is the resolution inference run on.
- camera.sensor_mode = 4
-
- # Scaled and cropped resolution. If different from sensor mode implied
- # resolution, inference results must be adjusted accordingly. This is
- # true in particular when camera.start_recording is used to record an
- # encoded h264 video stream as the Pi encoder can't encode all native
- # sensor resolutions, or a standard one like 1080p may be desired.
- camera.resolution = (1640, 1232)
-
- # Start the camera stream.
- camera.framerate = 30
- camera.start_preview()
-
- # Annotator renders in software so use a smaller size and scale results
- # for increased performace.
- annotator = Annotator(camera, dimensions=(320, 240))
- scale_x = 320 / 1640
- scale_y = 240 / 1232
-
- # Incoming boxes are of the form (x, y, width, height). Scale and
- # transform to the form (x1, y1, x2, y2).
- def transform(bounding_box):
- x, y, width, height = bounding_box
- return (scale_x * x, scale_y * y, scale_x * (x + width),
- scale_y * (y + height))
-
- with CameraInference(face_detection.model()) as inference:
- for i, result in enumerate(inference.run()):
- if i == args.num_frames:
- break
- faces = face_detection.get_faces(result)
- annotator.clear()
- for face in faces:
- annotator.bounding_box(transform(face.bounding_box), fill=0)
- annotator.update()
- print('Iteration #%d: num_faces=%d' % (i, len(faces)))
-
- camera.stop_preview()
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/vision/gpiozero/bonnet_button.py b/src/examples/vision/gpiozero/bonnet_button.py
deleted file mode 100755
index 7915548a..00000000
--- a/src/examples/vision/gpiozero/bonnet_button.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python3
-"""Example code that demonstrates using a button connected through the hat.
-
-The button uses a hat pin through the sysfs driver illustrating the edge
-detection polling.
-
-The demo will light up the on board LED whenever PIN_D is drawn high.
-"""
-from signal import pause
-from gpiozero import Button
-from gpiozero import LED
-from aiy.vision.pins import LED_1
-from aiy.vision.pins import PIN_D
-
-
-# Set up a gpiozero LED using the first onboard LED on the vision hat.
-led = LED(LED_1)
-# Set up a gpiozero Button using the 4th pin on the vision hat expansion.
-button = Button(PIN_D)
-
-# When the button is pressed, call the led.on() function (turn the led on)
-button.when_pressed = led.on
-# When the button is released, call the led.off() function (turn the led off)
-button.when_released = led.off
-
-# Wait for the user to kill the example.
-pause()
diff --git a/src/examples/vision/gpiozero/button_example.py b/src/examples/vision/gpiozero/button_example.py
deleted file mode 100755
index 075c2f8d..00000000
--- a/src/examples/vision/gpiozero/button_example.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python3
-"""Example code that demonstrates using a standard pin along with a hat pin.
-
-The button uses a standard GPIO pin through the raspberry pi's memory mapped io,
-while the led uses the hat's sysfs driver. This implemenation difference is
-transparent to the user.
-
-The demo will light up the on board LED whenever the user presses the button.
-"""
-from signal import pause
-from gpiozero import Button
-from gpiozero import LED
-from aiy.vision.pins import BUTTON_GPIO_PIN
-from aiy.vision.pins import LED_1
-
-# Set up a gpiozero LED using the first onboard LED on the vision hat.
-led = LED(LED_1)
-# Set up a gpiozero Button using the button included with the vision hat.
-button = Button(BUTTON_GPIO_PIN)
-
-# When the button is pressed, call the led.on() function (turn the led on)
-button.when_pressed = led.on
-# When the button is released, call the led.off() function (turn the led off)
-button.when_released = led.off
-
-# Wait for the user to kill the example.
-pause()
diff --git a/src/examples/vision/gpiozero/led_example.py b/src/examples/vision/gpiozero/led_example.py
deleted file mode 100755
index c5854d1d..00000000
--- a/src/examples/vision/gpiozero/led_example.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env python3
-"""Demonstrates on board LED support with correct polarity.
-
-Demo will turn on, then off the first LED on the hat.
-"""
-
-from time import sleep
-from gpiozero import LED
-from aiy.vision.pins import LED_1
-
-led = LED(LED_1)
-# Alternate turning the LED off and on until the user terminates the example.
-while True:
- led.on()
- sleep(1)
- led.off()
- sleep(1)
diff --git a/src/examples/vision/gpiozero/servo_example.py b/src/examples/vision/gpiozero/servo_example.py
deleted file mode 100755
index 737bd83e..00000000
--- a/src/examples/vision/gpiozero/servo_example.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env python3
-"""Demonstrates simultaneous control of two servos on the hat.
-
-One servo uses the simple default configuration, the other servo is tuned to
-ensure the full range is reachable.
-"""
-
-from time import sleep
-from gpiozero import Servo
-from aiy.vision.pins import PIN_A
-from aiy.vision.pins import PIN_B
-
-# Create a default servo that will not be able to use quite the full range.
-simple_servo = Servo(PIN_A)
-# Create a servo with the custom values to give the full dynamic range.
-tuned_servo = Servo(PIN_B, min_pulse_width=.0005, max_pulse_width=.0019)
-
-# Move the Servos back and forth until the user terminates the example.
-while True:
- simple_servo.min()
- tuned_servo.max()
- sleep(1)
- simple_servo.mid()
- tuned_servo.mid()
- sleep(1)
- simple_servo.max()
- tuned_servo.min()
- sleep(1)
diff --git a/src/examples/vision/gpiozero/simple_button_example.py b/src/examples/vision/gpiozero/simple_button_example.py
deleted file mode 100755
index cb5459cb..00000000
--- a/src/examples/vision/gpiozero/simple_button_example.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env python3
-"""Example code that demonstrates using a standard pin along with a hat pin.
-
-The button uses a standard GPIO pin through the raspberry pi's memory mapped io,
-while the led uses the hat's sysfs driver. This implemenation difference is
-transparent to the user.
-
-The demo will light up the on board LED whenever the user presses the button.
-"""
-from gpiozero import Button
-from gpiozero import LED
-from aiy.vision.pins import BUTTON_GPIO_PIN
-from aiy.vision.pins import LED_1
-
-# Set up a gpiozero LED using the first onboard LED on the vision hat.
-led = LED(LED_1)
-# Set up a gpiozero Button using the button included with the vision hat.
-button = Button(BUTTON_GPIO_PIN)
-
-while True:
- if button.is_pressed:
- led.on()
- else:
- led.off()
diff --git a/src/examples/vision/image_classification.py b/src/examples/vision/image_classification.py
deleted file mode 100755
index 07e764d2..00000000
--- a/src/examples/vision/image_classification.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Image classification library demo."""
-
-import argparse
-import io
-import sys
-from PIL import Image
-
-from aiy.vision.inference import ImageInference
-from aiy.vision.models import image_classification
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('--input', '-i', dest='input', required=True)
- args = parser.parse_args()
-
- # There are two models available for image classification task:
- # 1) MobileNet based (image_classification.MOBILENET), which has 59.9% top-1
- # accuracy on ImageNet;
- # 2) SqueezeNet based (image_classification.SQUEEZENET), which has 45.3% top-1
- # accuracy on ImageNet;
- model_type = image_classification.MOBILENET
- with ImageInference(image_classification.model(model_type)) as inference:
- image = Image.open(
- io.BytesIO(sys.stdin.buffer.read())
- if args.input == '-' else args.input)
- classes = image_classification.get_classes(
- inference.run(image), max_num_objects=5, object_prob_threshold=0.1)
- for i, (label, score) in enumerate(classes):
- print('Result %d: %s (prob=%f)' % (i, label, score))
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/vision/image_classification_camera.py b/src/examples/vision/image_classification_camera.py
deleted file mode 100755
index ee20f376..00000000
--- a/src/examples/vision/image_classification_camera.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Camera image classification demo code.
-
-Runs continuous image detection on the VisionBonnet and prints the object and
-probability for top three objects.
-
-Example:
-image_classification_camera.py --num_frames 10
-"""
-import argparse
-
-from aiy.vision.inference import CameraInference
-from aiy.vision.models import image_classification
-from picamera import PiCamera
-
-
-def main():
- """Image classification camera inference example."""
- parser = argparse.ArgumentParser()
- parser.add_argument(
- '--num_frames',
- '-n',
- type=int,
- dest='num_frames',
- default=-1,
- help='Sets the number of frames to run for, otherwise runs forever.')
-
- parser.add_argument(
- '--num_objects',
- '-c',
- type=int,
- dest='num_objects',
- default=3,
- help='Sets the number of object interences to print.')
-
- args = parser.parse_args()
-
- def print_classes(classes, object_count):
- s = ''
- for index, (obj, prob) in enumerate(classes):
- if index > object_count - 1:
- break
- s += '%s=%1.2f\t|\t' % (obj, prob)
- print('%s\r' % s)
-
- with PiCamera() as camera:
- # Forced sensor mode, 1640x1232, full FoV. See:
- # https://picamera.readthedocs.io/en/release-1.13/fov.html#sensor-modes
- # This is the resolution inference run on.
- camera.sensor_mode = 4
-
- # Scaled and cropped resolution. If different from sensor mode implied
- # resolution, inference results must be adjusted accordingly. This is
- # true in particular when camera.start_recording is used to record an
- # encoded h264 video stream as the Pi encoder can't encode all native
- # sensor resolutions, or a standard one like 1080p may be desired.
- camera.resolution = (1640, 1232)
-
- # Start the camera stream.
- camera.framerate = 30
- camera.start_preview()
-
- with CameraInference(image_classification.model()) as inference:
- for i, result in enumerate(inference.run()):
- if i == args.num_frames:
- break
- classes = image_classification.get_classes(result)
- print_classes(classes, args.num_objects)
-
- camera.stop_preview()
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/vision/joy/install-services.sh b/src/examples/vision/joy/install-services.sh
deleted file mode 100755
index 1a92ae27..00000000
--- a/src/examples/vision/joy/install-services.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-scripts_dir="$(dirname "${BASH_SOURCE[0]}")"
-cd "${scripts_dir}"
-
-sudo cp joy_detection_demo.service /lib/systemd/system
-systemctl enable joy_detection_demo.service
diff --git a/src/examples/vision/joy/joy_detection_demo.py b/src/examples/vision/joy/joy_detection_demo.py
deleted file mode 100755
index 34db62ed..00000000
--- a/src/examples/vision/joy/joy_detection_demo.py
+++ /dev/null
@@ -1,326 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Joy detection demo."""
-import argparse
-import collections
-import io
-import logging
-import math
-import os
-import queue
-import signal
-import threading
-import time
-
-from aiy._drivers._hat import get_aiy_device_name
-from aiy.toneplayer import TonePlayer
-from aiy.vision.inference import CameraInference
-from aiy.vision.leds import Leds
-from aiy.vision.leds import PrivacyLed
-from aiy.vision.models import face_detection
-
-from contextlib import contextmanager
-from gpiozero import Button
-from picamera import PiCamera
-
-from PIL import Image
-from PIL import ImageDraw
-from PIL import ImageFont
-
-logging.basicConfig(level=logging.INFO)
-logger = logging.getLogger(__name__)
-
-JOY_COLOR = (255, 70, 0)
-SAD_COLOR = (0, 0, 64)
-
-JOY_SCORE_PEAK = 0.85
-JOY_SCORE_MIN = 0.10
-
-JOY_SOUND = ('C5q', 'E5q', 'C6q')
-SAD_SOUND = ('C6q', 'E5q', 'C5q')
-MODEL_LOAD_SOUND = ('C6w', 'c6w', 'C6w')
-BEEP_SOUND = ('E6q', 'C6q')
-
-
-@contextmanager
-def stopwatch(message):
- try:
- logger.info('%s...', message)
- begin = time.time()
- yield
- finally:
- end = time.time()
- logger.info('%s done. (%fs)', message, end - begin)
-
-
-def blend(color_a, color_b, alpha):
- return tuple([math.ceil(alpha * color_a[i] + (1.0 - alpha) * color_b[i]) for i in range(3)])
-
-
-def average_joy_score(faces):
- if faces:
- return sum([face.joy_score for face in faces]) / len(faces)
- return 0.0
-
-
-def draw_rectangle(draw, x0, y0, x1, y1, border, fill=None, outline=None):
- assert border % 2 == 1
- for i in range(-border // 2, border // 2 + 1):
- draw.rectangle((x0 + i, y0 + i, x1 - i, y1 - i), fill=fill, outline=outline)
-
-
-class AtomicValue(object):
-
- def __init__(self, value):
- self._lock = threading.Lock()
- self._value = value
-
- @property
- def value(self):
- with self._lock:
- return self._value
-
- @value.setter
- def value(self, value):
- with self._lock:
- self._value = value
-
-
-class MovingAverage(object):
-
- def __init__(self, size):
- self._window = collections.deque(maxlen=size)
-
- def next(self, value):
- self._window.append(value)
- return sum(self._window) / len(self._window)
-
-
-class Service(object):
-
- def __init__(self):
- self._requests = queue.Queue()
- self._thread = threading.Thread(target=self._run)
- self._thread.start()
-
- def _run(self):
- while True:
- request = self._requests.get()
- if request is None:
- break
- self.process(request)
- self._requests.task_done()
-
- def join(self):
- self._thread.join()
-
- def stop(self):
- self._requests.put(None)
-
- def process(self, request):
- pass
-
- def submit(self, request):
- self._requests.put(request)
-
-
-class Player(Service):
- """Controls buzzer."""
-
- def __init__(self, gpio, bpm):
- super().__init__()
- self._toneplayer = TonePlayer(gpio, bpm)
-
- def process(self, sound):
- self._toneplayer.play(*sound)
-
- def play(self, sound):
- self.submit(sound)
-
-
-class Photographer(Service):
- """Saves photographs to disk."""
-
- def __init__(self, format, folder):
- super().__init__()
- assert format in ('jpeg', 'bmp', 'png')
-
- self._font = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeSans.ttf', size=25)
- self._faces = AtomicValue(())
- self._format = format
- self._folder = folder
-
- def _make_filename(self, timestamp, annotated):
- path = '%s/%s_annotated.%s' if annotated else '%s/%s.%s'
- return os.path.expanduser(path % (self._folder, timestamp, self._format))
-
- def _draw_face(self, draw, face):
- x, y, width, height = face.bounding_box
- text = 'Joy: %.2f' % face.joy_score
- _, text_height = self._font.getsize(text)
- margin = 3
- bottom = y + height
- text_bottom = bottom + margin + text_height + margin
- draw_rectangle(draw, x, y, x + width, bottom, 3, outline='white')
- draw_rectangle(draw, x, bottom, x + width, text_bottom, 3, fill='white', outline='white')
- draw.text((x + 1 + margin, y + height + 1 + margin), text, font=self._font, fill='black')
-
- def process(self, camera):
- faces = self._faces.value
- timestamp = time.strftime('%Y-%m-%d_%H.%M.%S')
-
- stream = io.BytesIO()
- with stopwatch('Taking photo'):
- camera.capture(stream, format=self._format, use_video_port=True)
-
- filename = self._make_filename(timestamp, annotated=False)
- with stopwatch('Saving original %s' % filename):
- stream.seek(0)
- with open(filename, 'wb') as file:
- file.write(stream.read())
-
- if faces:
- filename = self._make_filename(timestamp, annotated=True)
- with stopwatch('Saving annotated %s' % filename):
- stream.seek(0)
- image = Image.open(stream)
- draw = ImageDraw.Draw(image)
- for face in faces:
- self._draw_face(draw, face)
- del draw
- image.save(filename)
-
- def update_faces(self, faces):
- self._faces.value = faces
-
- def shoot(self, camera):
- self.submit(camera)
-
-
-class Animator(object):
- """Controls RGB LEDs."""
-
- def __init__(self, leds, done):
- self._leds = leds
- self._done = done
- self._joy_score = AtomicValue(0.0)
- self._thread = threading.Thread(target=self._run)
- self._thread.start()
-
- def _run(self):
- while not self._done.is_set():
- joy_score = self._joy_score.value
- if joy_score > 0:
- self._leds.update(Leds.rgb_on(blend(JOY_COLOR, SAD_COLOR, joy_score)))
- else:
- self._leds.update(Leds.rgb_off())
-
- def update_joy_score(self, value):
- self._joy_score.value = value
-
- def join(self):
- self._thread.join()
-
-
-class JoyDetector(object):
-
- def __init__(self):
- self._done = threading.Event()
- signal.signal(signal.SIGINT, lambda signal, frame: self.stop())
- signal.signal(signal.SIGTERM, lambda signal, frame: self.stop())
-
- def stop(self):
- logger.info('Stopping...')
- self._done.set()
-
- def run(self, num_frames, preview_alpha, image_format, image_folder):
- logger.info('Starting...')
- leds = Leds()
- player = Player(gpio=22, bpm=10)
- photographer = Photographer(image_format, image_folder)
- animator = Animator(leds, self._done)
-
- try:
- # Forced sensor mode, 1640x1232, full FoV. See:
- # https://picamera.readthedocs.io/en/release-1.13/fov.html#sensor-modes
- # This is the resolution inference run on.
- with PiCamera(sensor_mode=4, resolution=(1640, 1232)) as camera, PrivacyLed(leds):
- def take_photo():
- logger.info('Button pressed.')
- player.play(BEEP_SOUND)
- photographer.shoot(camera)
-
- # Blend the preview layer with the alpha value from the flags.
- camera.start_preview(alpha=preview_alpha)
-
- button = Button(23)
- button.when_pressed = take_photo
-
- joy_score_moving_average = MovingAverage(10)
- prev_joy_score = 0.0
- with CameraInference(face_detection.model()) as inference:
- logger.info('Model loaded.')
- player.play(MODEL_LOAD_SOUND)
- for i, result in enumerate(inference.run()):
- faces = face_detection.get_faces(result)
- photographer.update_faces(faces)
-
- joy_score = joy_score_moving_average.next(average_joy_score(faces))
- animator.update_joy_score(joy_score)
-
- if joy_score > JOY_SCORE_PEAK > prev_joy_score:
- player.play(JOY_SOUND)
- elif joy_score < JOY_SCORE_MIN < prev_joy_score:
- player.play(SAD_SOUND)
-
- prev_joy_score = joy_score
-
- if self._done.is_set() or i == num_frames:
- break
- finally:
- player.stop()
- photographer.stop()
-
- player.join()
- photographer.join()
- animator.join()
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('--num_frames', '-n', type=int, dest='num_frames', default=-1,
- help='Number of frames to run for, -1 to not terminate')
- parser.add_argument('--preview_alpha', '-pa', type=int, dest='preview_alpha', default=0,
- help='Transparency value of the preview overlay (0-255).')
- parser.add_argument('--image_format', type=str, dest='image_format', default='jpeg',
- choices=('jpeg', 'bmp', 'png'), help='Format of captured images.')
- parser.add_argument('--image_folder', type=str, dest='image_folder', default='~/Pictures',
- help='Folder to save captured images.')
- args = parser.parse_args()
-
- if args.preview_alpha < 0 or args.preview_alpha > 255:
- parser.error('Invalid preview_alpha value: %d' % args.preview_alpha)
-
- device = get_aiy_device_name()
- if not device or 'Vision' not in device:
- logger.error('AIY VisionBonnet is not detected.')
- return
-
- detector = JoyDetector()
- detector.run(args.num_frames, args.preview_alpha, args.image_format, args.image_folder)
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/vision/joy/joy_detection_demo.service b/src/examples/vision/joy/joy_detection_demo.service
deleted file mode 100644
index 43577770..00000000
--- a/src/examples/vision/joy/joy_detection_demo.service
+++ /dev/null
@@ -1,11 +0,0 @@
-[Unit]
-Description=AIY Joy Detection Demo
-
-[Service]
-Type=simple
-Restart=no
-User=pi
-ExecStart=/usr/bin/python3 /home/pi/AIY-projects-python/src/examples/vision/joy/joy_detection_demo.py
-
-[Install]
-WantedBy=multi-user.target
diff --git a/src/examples/vision/leds_example.py b/src/examples/vision/leds_example.py
deleted file mode 100755
index 6aaa56b9..00000000
--- a/src/examples/vision/leds_example.py
+++ /dev/null
@@ -1,153 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-import math
-import time
-
-from aiy.vision.leds import Leds
-from aiy.vision.leds import Pattern
-from aiy.vision.leds import PrivacyLed
-from aiy.vision.leds import RgbLeds
-
-RED = (0xFF, 0x00, 0x00)
-GREEN = (0x00, 0xFF, 0x00)
-YELLOW = (0xFF, 0xFF, 0x00)
-BLUE = (0x00, 0x00, 0xFF)
-PURPLE = (0xFF, 0x00, 0xFF)
-CYAN = (0x00, 0xFF, 0xFF)
-WHITE = (0xFF, 0xFF, 0xFF)
-
-
-def blend(color_a, color_b, alpha):
- return tuple([math.ceil(alpha * color_a[i] + (1.0 - alpha) * color_b[i]) for i in range(3)])
-
-
-leds = Leds()
-
-print('RGB: Solid RED for 1 second')
-leds.update(Leds.rgb_on(RED))
-time.sleep(1)
-
-print('RGB: Solid GREEN for 1 second')
-leds.update(Leds.rgb_on(GREEN))
-time.sleep(1)
-
-print('RGB: Solid YELLOW for 1 second')
-leds.update(Leds.rgb_on(YELLOW))
-time.sleep(1)
-
-print('RGB: Solid BLUE for 1 second')
-leds.update(Leds.rgb_on(BLUE))
-time.sleep(1)
-
-print('RGB: Solid PURPLE for 1 second')
-leds.update(Leds.rgb_on(PURPLE))
-time.sleep(1)
-
-print('RGB: Solid CYAN for 1 second')
-leds.update(Leds.rgb_on(CYAN))
-time.sleep(1)
-
-print('RGB: Solid WHITE for 1 second')
-leds.update(Leds.rgb_on(WHITE))
-time.sleep(1)
-
-print('RGB: Off for 1 second')
-leds.update(Leds.rgb_off())
-time.sleep(1)
-
-for _ in range(3):
- print('Privacy: On (brightness=default)')
- leds.update(Leds.privacy_on())
- time.sleep(1)
- print('Privacy: Off')
- leds.update(Leds.privacy_off())
- time.sleep(1)
-
-for _ in range(3):
- print('Privacy: On (brightness=5)')
- leds.update(Leds.privacy_on(5))
- time.sleep(1)
- print('Privacy: Off')
- leds.update(Leds.privacy_off())
- time.sleep(1)
-
-print('Set blink pattern: period=500ms (2Hz)')
-leds.pattern = Pattern.blink(500)
-
-print('RGB: Blink RED for 5 seconds')
-leds.update(Leds.rgb_pattern(RED))
-time.sleep(5)
-
-print('RGB: Blink GREEN for 5 seconds')
-leds.update(Leds.rgb_pattern(GREEN))
-time.sleep(5)
-
-print('RGB: Blink BLUE for 5 seconds')
-leds.update(Leds.rgb_pattern(BLUE))
-time.sleep(5)
-
-print('Set breathe pattern: period=1000ms (1Hz)')
-leds.pattern = Pattern.breathe(1000)
-
-print('RGB: Breathe RED for 5 seconds')
-leds.update(Leds.rgb_pattern(RED))
-time.sleep(5)
-
-print('RGB: Breathe GREEN for 5 seconds')
-leds.update(Leds.rgb_pattern(GREEN))
-time.sleep(5)
-
-print('RGB: Breathe BLUE for 5 seconds')
-leds.update(Leds.rgb_pattern(BLUE))
-time.sleep(5)
-
-print('RGB: Increase RED brightness for 3.2 seconds')
-for i in range(32):
- leds.update(Leds.rgb_on((8 * i, 0, 0)))
- time.sleep(0.1)
-
-print('RGB: Decrease RED brightness for 3.2 seconds')
-for i in reversed(range(32)):
- leds.update(Leds.rgb_on((8 * i, 0, 0)))
- time.sleep(0.1)
-
-print('RGB: Blend between GREEN and BLUE for 3.2 seconds')
-for i in range(32):
- leds.update(Leds.rgb_on(blend(BLUE, GREEN, i / 32)))
- time.sleep(0.1)
-
-print('RGB: Off for 1 second')
-leds.update(Leds.rgb_off())
-time.sleep(1)
-
-print('Privacy: On for 2 seconds')
-with PrivacyLed(leds):
- time.sleep(2)
-
-print('RGB: Solid GREEN for 2 seconds')
-with RgbLeds(leds, Leds.rgb_on(GREEN)):
- time.sleep(2)
-
-print('Custom configuration for 5 seconds')
-leds.update({
- 1: Leds.Channel(Leds.Channel.PATTERN, 128), # Red channel
- 2: Leds.Channel(Leds.Channel.OFF, 0), # Green channel
- 3: Leds.Channel(Leds.Channel.ON, 128), # Blue channel
- 4: Leds.Channel(Leds.Channel.PATTERN, 64), # Privacy channel
-})
-time.sleep(5)
-
-print('Done')
-leds.reset()
diff --git a/src/examples/vision/object_detection.py b/src/examples/vision/object_detection.py
deleted file mode 100755
index a5f3896a..00000000
--- a/src/examples/vision/object_detection.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Object detection library demo.
-
- - Takes an input image and tries to detect person, dog, or cat.
- - Draws bounding boxes around detected objects.
- - Saves an image with bounding boxes around detected objects.
-"""
-import argparse
-import io
-import sys
-from PIL import Image
-from PIL import ImageDraw
-
-from aiy.vision.inference import ImageInference
-from aiy.vision.models import object_detection
-
-
-def _crop_center(image):
- width, height = image.size
- size = min(width, height)
- x, y = (width - size) / 2, (height - size) / 2
- return image.crop((x, y, x + size, y + size)), (x, y)
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('--input', '-i', dest='input', required=True)
- parser.add_argument('--output', '-o', dest='output')
- args = parser.parse_args()
-
- with ImageInference(object_detection.model()) as inference:
- image = Image.open(
- io.BytesIO(sys.stdin.buffer.read())
- if args.input == '-' else args.input)
- image_center, offset = _crop_center(image)
- draw = ImageDraw.Draw(image)
- result = inference.run(image_center)
- for i, obj in enumerate(object_detection.get_objects(result, 0.3, offset)):
- print('Object #%d: %s' % (i, str(obj)))
- x, y, width, height = obj.bounding_box
- draw.rectangle((x, y, x + width, y + height), outline='red')
- if args.output:
- image.save(args.output)
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/vision/object_meter/README.md b/src/examples/vision/object_meter/README.md
deleted file mode 100644
index 18a4062f..00000000
--- a/src/examples/vision/object_meter/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Image classification demo
-
-## Physical Setup
-
-- VisionHat installed on a Raspberry Pi Zero
-- Servo connected to vision hat (signal - PIN_A, Vcc - POWER, Ground - GND)
- - Servo mounted in label display
-- (optional) Monitor connected to raspberry pi.
diff --git a/src/examples/vision/object_meter/install_services.sh b/src/examples/vision/object_meter/install_services.sh
deleted file mode 100755
index 0c643036..00000000
--- a/src/examples/vision/object_meter/install_services.sh
+++ /dev/null
@@ -1,18 +0,0 @@
- #!/bin/bash
-# Copyright 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-scripts_dir="$(dirname "${BASH_SOURCE[0]}")"
-cd "${scripts_dir}"
-sudo cp object_meter_demo.service /lib/systemd/system
-systemctl enable object_meter_demo.service
diff --git a/src/examples/vision/object_meter/object_meter.py b/src/examples/vision/object_meter/object_meter.py
deleted file mode 100755
index e0d1d47b..00000000
--- a/src/examples/vision/object_meter/object_meter.py
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Object detection with servo output demo."""
-import argparse
-import time
-import picamera
-
-from aiy.vision.pins import PIN_A
-from aiy.vision.pins import BUTTON_GPIO_PIN
-from aiy.vision.inference import CameraInference
-from aiy.vision.models import image_classification
-from examples.vision.annotator import Annotator
-from gpiozero import Button
-from gpiozero import AngularServo
-from wordnet_grouping import category_mapper
-
-
-class AutoButton(object):
- """Button utility that handles the io and state tracking."""
-
- def __init__(self, start_enabled=False, use_hardware=True):
- self._use_hardware = use_hardware
- if use_hardware:
- self._button = Button(BUTTON_GPIO_PIN)
- self._enabled = start_enabled
- if not start_enabled:
- self._button.when_pressed = self._enable
-
- def _enable(self):
- self._enabled = True
-
- def on(self):
- if not self._use_hardware or not self._enabled:
- return True
- # Button is currently pressed
- return self._button.is_pressed
-
-
-class OverlayManager(object):
- """Overlay utility for managing state and drawing of overlay."""
- LINE_HEIGHT = 12
- ROW_HEIGHT = 50
-
- def __init__(self, camera):
- self._clear_needed = False
- self._annotator = Annotator(camera, default_color=(0xFF, 0xFF, 0xFF, 0xFF),
- dimensions=(320, 240))
-
- def _draw_annotation(self, result, category, index):
- self._annotator.text((5,
- index * self.ROW_HEIGHT + 5 + 0 * self.LINE_HEIGHT),
- '{:.2%}'.format(result[1]))
- self._annotator.text((5,
- index * self.ROW_HEIGHT + 5 + 1 * self.LINE_HEIGHT),
- '{:25.25}'.format(result[0]))
- self._annotator.text((5,
- index * self.ROW_HEIGHT + 5 + 2 * self.LINE_HEIGHT),
- 'category: {:20.20}'.format(category))
-
- def clear(self):
- if self._clear_needed:
- self._annotator.stop()
- self._clear_needed = False
-
- def update(self, classes, categories):
- self._annotator.clear()
- self._clear_needed = True
- for i, result in enumerate(classes):
- self._draw_annotation(result, categories[i], i)
- self._annotator.update()
-
-
-class DummyOverlayManager(object):
- """Dummy implementation of overlay manager used when overlay is disabled."""
-
- def clear(self):
- pass
-
- def update(self, classes, categories):
- del classes, categories # Unused
-
-
-def main():
- parser = argparse.ArgumentParser(
- description='Example application for displaying a dial indicator for '
- 'what object is seen')
- parser.add_argument(
- '--output_overlay',
- default=True,
- type=bool,
- help='Should the visual overlay be generated')
- parser.add_argument(
- '--button_enabled',
- default=True,
- type=bool,
- help='Should the button be monitored')
- parser.add_argument(
- '--button_active',
- default=False,
- type=bool,
- help='Should the button start out active (true) or only be active once '
- 'pressed (false)')
- flags = parser.parse_args()
- load_model = time.time()
- category_count = len(category_mapper.get_categories())
- button = AutoButton(flags.button_active, flags.button_enabled)
-
- for category in category_mapper.get_categories():
- print('Category[%d]: %s' % (category_mapper.get_category_index(category),
- category))
- with picamera.PiCamera() as camera:
- camera.resolution = (1640, 1232)
- camera.start_preview()
- overlay = OverlayManager(
- camera) if flags.output_overlay else DummyOverlayManager()
- servo = AngularServo(PIN_A, min_pulse_width=.0005, max_pulse_width=.0019)
- with CameraInference(image_classification.model()) as classifier:
- print('Load Model %f' % (time.time() - load_model))
- for result in classifier.run():
- if not button.on():
- overlay.clear()
- servo.angle = -90
- continue
-
- classes = image_classification.get_classes(result)
-
- probs = [0] * (category_count + 1)
- result_categories = []
- for label, score in classes:
- category = category_mapper.get_category(label) or 'Other'
- probs[category_mapper.get_category_index(category) + 1] += score
- result_categories.append(category)
- overlay.update(classes, result_categories)
- max_prob = max(probs)
- best_category = probs.index(max_prob)
- if best_category == 0 and max_prob > .5:
- servo.angle = -90
- elif best_category != 0:
- servo.angle = -90 + (180 * best_category) / category_count
- print('category: %d - %s' %
- (best_category,
- category_mapper.get_categories()[best_category - 1]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/vision/object_meter/object_meter_demo.service b/src/examples/vision/object_meter/object_meter_demo.service
deleted file mode 100644
index e021b625..00000000
--- a/src/examples/vision/object_meter/object_meter_demo.service
+++ /dev/null
@@ -1,10 +0,0 @@
-[Unit]
-Description=AIY Object Meter Demo
-
-[Service]
-Type=simple
-Restart=no
-ExecStart=/home/pi/AIY-projects-python/env/bin/python /home/pi/AIY-projects-python/src/examples/vision/object_meter/object_meter.py
-
-[Install]
-WantedBy=multi-user.target
diff --git a/src/examples/vision/object_meter/wordnet_grouping/category_mapper.py b/src/examples/vision/object_meter/wordnet_grouping/category_mapper.py
deleted file mode 100755
index 7fe36509..00000000
--- a/src/examples/vision/object_meter/wordnet_grouping/category_mapper.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Utility for grouping ImageNet classifications under super-categories.
-
-Super categories are defined by the mapping_data.py file which uses labels from
-nodes above the grouped leaves in the wordnet for defining super-categories.
-"""
-
-from __future__ import print_function
-from .mapping_data import CATEGORIES
-from .mapping_data import MAPPINGS
-
-
-def get_category(word):
- return MAPPINGS.get(word)
-
-
-def get_categories():
- return CATEGORIES
-
-
-def get_word_index(word):
- category = get_category(word)
- if category is None:
- return -1
- return get_categories().index(category)
-
-
-def get_category_index(category):
- try:
- return get_categories().index(category)
- except ValueError:
- return -1
-
-
-def _example_usage():
- """Example usage for the category mapper utility."""
- print('~'.join(get_categories()))
- print(get_category('hay'))
- print(get_category('ballpoint/ballpoint pen/ballpen/Biro'))
- print(get_category('beer bottle'))
- print(get_category('NASDFOIAAS'))
- print(get_word_index('beer bottle'))
- print(get_word_index('NASDFLJ'))
- for cat in get_categories():
- print('%d : %s' % (get_category_index(cat), cat))
-
- cat = 'Other'
- print('%d : %s' % (get_category_index(cat), cat))
-
-
-if __name__ == '__main__':
- _example_usage()
diff --git a/src/examples/vision/object_meter/wordnet_grouping/mapping_data.py b/src/examples/vision/object_meter/wordnet_grouping/mapping_data.py
deleted file mode 100644
index da230c23..00000000
--- a/src/examples/vision/object_meter/wordnet_grouping/mapping_data.py
+++ /dev/null
@@ -1,1240 +0,0 @@
-# Copyright 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Auto generated wordnet mappings for imagenet values to categories."""
-
-MAPPINGS = {
- "black stork/Ciconia nigra":
- "animal, animate being, beast, brute, creature, fauna",
- "drake":
- "animal, animate being, beast, brute, creature, fauna",
- "guinea pig/Cavia cobaya":
- "animal, animate being, beast, brute, creature, fauna",
- "golden retriever":
- "dog, domestic dog, Canis familiaris",
- "echidna/spiny anteater/anteater":
- "animal, animate being, beast, brute, creature, fauna",
- "printer":
- "electronic equipment",
- "ruffed grouse/partridge/Bonasa umbellus":
- "animal, animate being, beast, brute, creature, fauna",
- "beer glass":
- "bottle",
- "Airedale/Airedale terrier":
- "dog, domestic dog, Canis familiaris",
- "hot pot/hotpot":
- "food, nutrient",
- "barrow/garden cart/lawn cart/wheelbarrow":
- "wheeled vehicle",
- "sweatshirt":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "admiral":
- "animal, animate being, beast, brute, creature, fauna",
- "boa constrictor/Constrictor constrictor":
- "animal, animate being, beast, brute, creature, fauna",
- "pizza/pizza pie":
- "food, nutrient",
- "Border terrier":
- "dog, domestic dog, Canis familiaris",
- "chiton/coat-of-mail shell/sea cradle/polyplacophore":
- "animal, animate being, beast, brute, creature, fauna",
- "puffer/pufferfish/blowfish/globefish":
- "animal, animate being, beast, brute, creature, fauna",
- "toy poodle":
- "dog, domestic dog, Canis familiaris",
- "American chameleon/anole/Anolis carolinensis":
- "animal, animate being, beast, brute, creature, fauna",
- "thunder snake/worm snake/Carphophis amoenus":
- "animal, animate being, beast, brute, creature, fauna",
- "fur coat":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "Tibetan terrier/chrysanthemum dog":
- "dog, domestic dog, Canis familiaris",
- "ibex/Capra ibex":
- "animal, animate being, beast, brute, creature, fauna",
- "cricket":
- "animal, animate being, beast, brute, creature, fauna",
- "trench coat":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "ptarmigan":
- "animal, animate being, beast, brute, creature, fauna",
- "abaya":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "European fire salamander/Salamandra salamandra":
- "animal, animate being, beast, brute, creature, fauna",
- "hand-held computer/hand-held microcomputer":
- "computer, computing machine, computing device, data processor, "
- "electronic computer, information processing system",
- "stole":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "mongoose":
- "animal, animate being, beast, brute, creature, fauna",
- "bull mastiff":
- "dog, domestic dog, Canis familiaris",
- "lynx/catamount":
- "animal, animate being, beast, brute, creature, fauna",
- "cab/hack/taxi/taxicab":
- "wheeled vehicle",
- "basset/basset hound":
- "dog, domestic dog, Canis familiaris",
- "sea anemone/anemone":
- "animal, animate being, beast, brute, creature, fauna",
- "fiddler crab":
- "animal, animate being, beast, brute, creature, fauna",
- "Indian cobra/Naja naja":
- "animal, animate being, beast, brute, creature, fauna",
- "black-footed ferret/ferret/Mustela nigripes":
- "animal, animate being, beast, brute, creature, fauna",
- "leaf beetle/chrysomelid":
- "animal, animate being, beast, brute, creature, fauna",
- "bald eagle/American eagle/Haliaeetus leucocephalus":
- "animal, animate being, beast, brute, creature, fauna",
- "Irish terrier":
- "dog, domestic dog, Canis familiaris",
- "beer bottle":
- "bottle",
- "Dungeness crab/Cancer magister":
- "animal, animate being, beast, brute, creature, fauna",
- "basenji":
- "dog, domestic dog, Canis familiaris",
- "grand piano/grand":
- "musical instrument, instrument",
- "black-and-tan coonhound":
- "dog, domestic dog, Canis familiaris",
- "giant panda/panda/panda bear/coon bear/Ailuropoda melanoleuca":
- "animal, animate being, beast, brute, creature, fauna",
- "capuchin/ringtail/Cebus capucinus":
- "animal, animate being, beast, brute, creature, fauna",
- "lycaenid/lycaenid butterfly":
- "animal, animate being, beast, brute, creature, fauna",
- "ladybug/ladybeetle/lady beetle/ladybird/ladybird beetle":
- "animal, animate being, beast, brute, creature, fauna",
- "tarantula":
- "animal, animate being, beast, brute, creature, fauna",
- "American Staffordshire terrier/Staffordshire terrier/American pit bull "
- "terrier/pit bull terrier":
- "dog, domestic dog, Canis familiaris",
- "kite":
- "animal, animate being, beast, brute, creature, fauna",
- "red wine":
- "food, nutrient",
- "black grouse":
- "animal, animate being, beast, brute, creature, fauna",
- "porcupine/hedgehog":
- "animal, animate being, beast, brute, creature, fauna",
- "water jug":
- "bottle",
- "French loaf":
- "food, nutrient",
- "titi/titi monkey":
- "animal, animate being, beast, brute, creature, fauna",
- "Italian greyhound":
- "animal, animate being, beast, brute, creature, fauna",
- "police van/police wagon/paddy wagon/patrol wagon/wagon/black Maria":
- "wheeled vehicle",
- "pill bottle":
- "bottle",
- "iPod":
- "electronic equipment",
- "borzoi/Russian wolfhound":
- "dog, domestic dog, Canis familiaris",
- "tree frog/tree-frog":
- "animal, animate being, beast, brute, creature, fauna",
- "grey whale/gray whale/devilfish/Eschrichtius gibbosus/"
- "Eschrichtius robustus":
- "animal, animate being, beast, brute, creature, fauna",
- "spotted salamander/Ambystoma maculatum":
- "animal, animate being, beast, brute, creature, fauna",
- "wine bottle":
- "bottle",
- "sulphur-crested cockatoo/Kakatoe galerita/Cacatua galerita":
- "animal, animate being, beast, brute, creature, fauna",
- "modem":
- "electronic equipment",
- "red-backed sandpiper/dunlin/Erolia alpina":
- "animal, animate being, beast, brute, creature, fauna",
- "gazelle":
- "animal, animate being, beast, brute, creature, fauna",
- "Eskimo dog/husky":
- "dog, domestic dog, Canis familiaris",
- "digital watch":
- "timepiece, timekeeper, horologe",
- "cheetah/chetah/Acinonyx jubatus":
- "animal, animate being, beast, brute, creature, fauna",
- "sombrero":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "seat belt/seatbelt":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "burrito":
- "food, nutrient",
- "slide rule/slipstick":
- "computer, computing machine, computing device, data processor, "
- "electronic computer, information processing system",
- "Bouvier des Flandres/Bouviers des Flandres":
- "dog, domestic dog, Canis familiaris",
- "mask":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "Doberman/Doberman pinscher":
- "dog, domestic dog, Canis familiaris",
- "rhinoceros beetle":
- "animal, animate being, beast, brute, creature, fauna",
- "daisy":
- "plant, flora, plant life",
- "monitor":
- "electronic equipment",
- "Komodo dragon/Komodo lizard/dragon lizard/giant lizard/"
- "Varanus komodoensis":
- "animal, animate being, beast, brute, creature, fauna",
- "garbage truck/dustcart":
- "wheeled vehicle",
- "Rhodesian ridgeback":
- "dog, domestic dog, Canis familiaris",
- "half track":
- "wheeled vehicle",
- "starfish/sea star":
- "animal, animate being, beast, brute, creature, fauna",
- "brambling/Fringilla montifringilla":
- "animal, animate being, beast, brute, creature, fauna",
- "convertible":
- "wheeled vehicle",
- "long-horned beetle/longicorn/longicorn beetle":
- "animal, animate being, beast, brute, creature, fauna",
- "academic gown/academic robe/judge's robe":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "computer keyboard/keypad":
- "electronic equipment",
- "Norwich terrier":
- "dog, domestic dog, Canis familiaris",
- "meerkat/mierkat":
- "animal, animate being, beast, brute, creature, fauna",
- "overskirt":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "toucan":
- "animal, animate being, beast, brute, creature, fauna",
- "apron":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "stopwatch/stop watch":
- "timepiece, timekeeper, horologe",
- "lab coat/laboratory coat":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "screen/CRT screen":
- "electronic equipment",
- "golfcart/golf cart":
- "wheeled vehicle",
- "digital clock":
- "timepiece, timekeeper, horologe",
- "Leonberg":
- "dog, domestic dog, Canis familiaris",
- "African crocodile/Nile crocodile/Crocodylus niloticus":
- "animal, animate being, beast, brute, creature, fauna",
- "lemon":
- "edible fruit",
- "Siberian husky":
- "dog, domestic dog, Canis familiaris",
- "bagel/beigel":
- "food, nutrient",
- "badger":
- "animal, animate being, beast, brute, creature, fauna",
- "scorpion":
- "animal, animate being, beast, brute, creature, fauna",
- "chow/chow chow":
- "dog, domestic dog, Canis familiaris",
- "Labrador retriever":
- "dog, domestic dog, Canis familiaris",
- "guenon/guenon monkey":
- "animal, animate being, beast, brute, creature, fauna",
- "military uniform":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "wood rabbit/cottontail/cottontail rabbit":
- "animal, animate being, beast, brute, creature, fauna",
- "jackfruit/jak/jack":
- "edible fruit",
- "oscilloscope/scope/cathode-ray oscilloscope/CRO":
- "electronic equipment",
- "jellyfish":
- "animal, animate being, beast, brute, creature, fauna",
- "Arctic fox/white fox/Alopex lagopus":
- "animal, animate being, beast, brute, creature, fauna",
- "feather boa/boa":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "bathing cap/swimming cap":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "cairn/cairn terrier":
- "dog, domestic dog, Canis familiaris",
- "German short-haired pointer":
- "dog, domestic dog, Canis familiaris",
- "hammerhead/hammerhead shark":
- "animal, animate being, beast, brute, creature, fauna",
- "violin/fiddle":
- "musical instrument, instrument",
- "green mamba":
- "animal, animate being, beast, brute, creature, fauna",
- "vizsla/Hungarian pointer":
- "dog, domestic dog, Canis familiaris",
- "moving van":
- "wheeled vehicle",
- "monarch/monarch butterfly/milkweed butterfly/Danaus plexippus":
- "animal, animate being, beast, brute, creature, fauna",
- "standard schnauzer":
- "dog, domestic dog, Canis familiaris",
- "tick":
- "animal, animate being, beast, brute, creature, fauna",
- "Gila monster/Heloderma suspectum":
- "animal, animate being, beast, brute, creature, fauna",
- "stingray":
- "animal, animate being, beast, brute, creature, fauna",
- "trilobite":
- "animal, animate being, beast, brute, creature, fauna",
- "knee pad":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "Boston bull/Boston terrier":
- "dog, domestic dog, Canis familiaris",
- "plate":
- "food, nutrient",
- "football helmet":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "electric ray/crampfish/numbfish/torpedo":
- "animal, animate being, beast, brute, creature, fauna",
- "sea urchin":
- "animal, animate being, beast, brute, creature, fauna",
- "ice cream/icecream":
- "food, nutrient",
- "red-breasted merganser/Mergus serrator":
- "animal, animate being, beast, brute, creature, fauna",
- "lesser panda/red panda/panda/bear cat/cat bear/Ailurus fulgens":
- "animal, animate being, beast, brute, creature, fauna",
- "barn spider/Araneus cavaticus":
- "animal, animate being, beast, brute, creature, fauna",
- "sea cucumber/holothurian":
- "animal, animate being, beast, brute, creature, fauna",
- "bulbul":
- "animal, animate being, beast, brute, creature, fauna",
- "quail":
- "animal, animate being, beast, brute, creature, fauna",
- "lacewing/lacewing fly":
- "animal, animate being, beast, brute, creature, fauna",
- "sulphur butterfly/sulfur butterfly":
- "animal, animate being, beast, brute, creature, fauna",
- "bicycle-built-for-two/tandem bicycle/tandem":
- "wheeled vehicle",
- "cheeseburger":
- "food, nutrient",
- "dial telephone/dial phone":
- "electronic equipment",
- "Australian terrier":
- "dog, domestic dog, Canis familiaris",
- "laptop/laptop computer":
- "computer, computing machine, computing device, data processor, "
- "electronic computer, information processing system",
- "lorikeet":
- "animal, animate being, beast, brute, creature, fauna",
- "Bedlington terrier":
- "dog, domestic dog, Canis familiaris",
- "black widow/Latrodectus mactans":
- "animal, animate being, beast, brute, creature, fauna",
- "baboon":
- "animal, animate being, beast, brute, creature, fauna",
- "agama":
- "animal, animate being, beast, brute, creature, fauna",
- "Saluki/gazelle hound":
- "dog, domestic dog, Canis familiaris",
- "curly-coated retriever":
- "dog, domestic dog, Canis familiaris",
- "mobile home/manufactured home":
- "wheeled vehicle",
- "brassiere/bra/bandeau":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "sarong":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "Siamese cat/Siamese":
- "animal, animate being, beast, brute, creature, fauna",
- "accordion/piano accordion/squeeze box":
- "musical instrument, instrument",
- "malamute/malemute/Alaskan malamute":
- "dog, domestic dog, Canis familiaris",
- "Welsh springer spaniel":
- "dog, domestic dog, Canis familiaris",
- "robin/American robin/Turdus migratorius":
- "animal, animate being, beast, brute, creature, fauna",
- "Persian cat":
- "animal, animate being, beast, brute, creature, fauna",
- "sock":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "skunk/polecat/wood pussy":
- "animal, animate being, beast, brute, creature, fauna",
- "collie":
- "dog, domestic dog, Canis familiaris",
- "warthog":
- "animal, animate being, beast, brute, creature, fauna",
- "king penguin/Aptenodytes patagonica":
- "animal, animate being, beast, brute, creature, fauna",
- "Saint Bernard/St Bernard":
- "dog, domestic dog, Canis familiaris",
- "black swan/Cygnus atratus":
- "animal, animate being, beast, brute, creature, fauna",
- "axolotl/mud puppy/Ambystoma mexicanum":
- "animal, animate being, beast, brute, creature, fauna",
- "chocolate sauce/chocolate syrup":
- "food, nutrient",
- "Arabian camel/dromedary/Camelus dromedarius":
- "animal, animate being, beast, brute, creature, fauna",
- "frilled lizard/Chlamydosaurus kingi":
- "animal, animate being, beast, brute, creature, fauna",
- "shopping cart":
- "wheeled vehicle",
- "Brabancon griffon":
- "dog, domestic dog, Canis familiaris",
- "Sealyham terrier/Sealyham":
- "dog, domestic dog, Canis familiaris",
- "forklift":
- "wheeled vehicle",
- "ant/emmet/pismire":
- "animal, animate being, beast, brute, creature, fauna",
- "pop bottle/soda bottle":
- "bottle",
- "electric guitar":
- "musical instrument, instrument",
- "tape player":
- "electronic equipment",
- "hummingbird":
- "animal, animate being, beast, brute, creature, fauna",
- "Model T":
- "wheeled vehicle",
- "gown":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "fox squirrel/eastern fox squirrel/Sciurus niger":
- "animal, animate being, beast, brute, creature, fauna",
- "bikini/two-piece":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "redbone":
- "dog, domestic dog, Canis familiaris",
- "house finch/linnet/Carpodacus mexicanus":
- "animal, animate being, beast, brute, creature, fauna",
- "bighorn/bighorn sheep/cimarron/Rocky Mountain bighorn/Rocky Mountain "
- "sheep/Ovis canadensis":
- "animal, animate being, beast, brute, creature, fauna",
- "carbonara":
- "food, nutrient",
- "English foxhound":
- "dog, domestic dog, Canis familiaris",
- "banjo":
- "musical instrument, instrument",
- "organ/pipe organ":
- "musical instrument, instrument",
- "American black bear/black bear/Ursus americanus/Euarctos americanus":
- "animal, animate being, beast, brute, creature, fauna",
- "impala/Aepyceros melampus":
- "animal, animate being, beast, brute, creature, fauna",
- "sea snake":
- "animal, animate being, beast, brute, creature, fauna",
- "coyote/prairie wolf/brush wolf/Canis latrans":
- "animal, animate being, beast, brute, creature, fauna",
- "silky terrier/Sydney silky":
- "dog, domestic dog, Canis familiaris",
- "Samoyed/Samoyede":
- "dog, domestic dog, Canis familiaris",
- "cello/violoncello":
- "musical instrument, instrument",
- "pineapple/ananas":
- "edible fruit",
- "damselfly":
- "animal, animate being, beast, brute, creature, fauna",
- "sax/saxophone":
- "musical instrument, instrument",
- "Chihuahua":
- "dog, domestic dog, Canis familiaris",
- "beagle":
- "dog, domestic dog, Canis familiaris",
- "harp":
- "musical instrument, instrument",
- "African elephant/Loxodonta africana":
- "animal, animate being, beast, brute, creature, fauna",
- "miniskirt/mini":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "dalmatian/coach dog/carriage dog":
- "dog, domestic dog, Canis familiaris",
- "strawberry":
- "edible fruit",
- "komondor":
- "dog, domestic dog, Canis familiaris",
- "hare":
- "animal, animate being, beast, brute, creature, fauna",
- "trailer truck/tractor trailer/trucking rig/rig/articulated lorry/semi":
- "wheeled vehicle",
- "goldfinch/Carduelis carduelis":
- "animal, animate being, beast, brute, creature, fauna",
- "prairie chicken/prairie grouse/prairie fowl":
- "animal, animate being, beast, brute, creature, fauna",
- "bearskin/busby/shako":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "sidewinder/horned rattlesnake/Crotalus cerastes":
- "animal, animate being, beast, brute, creature, fauna",
- "pug/pug-dog":
- "dog, domestic dog, Canis familiaris",
- "moped":
- "wheeled vehicle",
- "English springer/English springer spaniel":
- "dog, domestic dog, Canis familiaris",
- "malinois":
- "dog, domestic dog, Canis familiaris",
- "American coot/marsh hen/mud hen/water hen/Fulica americana":
- "animal, animate being, beast, brute, creature, fauna",
- "sea slug/nudibranch":
- "animal, animate being, beast, brute, creature, fauna",
- "steam locomotive":
- "wheeled vehicle",
- "cocker spaniel/English cocker spaniel/cocker":
- "dog, domestic dog, Canis familiaris",
- "upright/upright piano":
- "musical instrument, instrument",
- "goblet":
- "bottle",
- "grey fox/gray fox/Urocyon cinereoargenteus":
- "animal, animate being, beast, brute, creature, fauna",
- "Norwegian elkhound/elkhound":
- "dog, domestic dog, Canis familiaris",
- "Great Pyrenees":
- "dog, domestic dog, Canis familiaris",
- "rock crab/Cancer irroratus":
- "animal, animate being, beast, brute, creature, fauna",
- "Kerry blue terrier":
- "dog, domestic dog, Canis familiaris",
- "quill/quill pen":
- "writing implement",
- "terrapin":
- "animal, animate being, beast, brute, creature, fauna",
- "crane":
- "animal, animate being, beast, brute, creature, fauna",
- "gong/tam-tam":
- "musical instrument, instrument",
- "pajama/pyjama/pj's/jammies":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "bolo tie/bolo/bola tie/bola":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "Weimaraner":
- "dog, domestic dog, Canis familiaris",
- "water buffalo/water ox/Asiatic buffalo/Bubalus bubalis":
- "animal, animate being, beast, brute, creature, fauna",
- "Shetland sheepdog/Shetland sheep dog/Shetland":
- "dog, domestic dog, Canis familiaris",
- "tench/Tinca tinca":
- "animal, animate being, beast, brute, creature, fauna",
- "siamang/Hylobates syndactylus/Symphalangus syndactylus":
- "animal, animate being, beast, brute, creature, fauna",
- "loggerhead/loggerhead turtle/Caretta caretta":
- "animal, animate being, beast, brute, creature, fauna",
- "dung beetle":
- "animal, animate being, beast, brute, creature, fauna",
- "Granny Smith":
- "edible fruit",
- "Angora/Angora rabbit":
- "animal, animate being, beast, brute, creature, fauna",
- "dough":
- "food, nutrient",
- "hen":
- "animal, animate being, beast, brute, creature, fauna",
- "CD player":
- "electronic equipment",
- "howler monkey/howler":
- "animal, animate being, beast, brute, creature, fauna",
- "English setter":
- "dog, domestic dog, Canis familiaris",
- "West Highland white terrier":
- "dog, domestic dog, Canis familiaris",
- "pomegranate":
- "edible fruit",
- "timber wolf/grey wolf/gray wolf/Canis lupus":
- "animal, animate being, beast, brute, creature, fauna",
- "go-kart":
- "wheeled vehicle",
- "hornbill":
- "animal, animate being, beast, brute, creature, fauna",
- "Christmas stocking":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "alligator lizard":
- "animal, animate being, beast, brute, creature, fauna",
- "tabby/tabby cat":
- "animal, animate being, beast, brute, creature, fauna",
- "crash helmet":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "parking meter":
- "timepiece, timekeeper, horologe",
- "mantis/mantid":
- "animal, animate being, beast, brute, creature, fauna",
- "marmoset":
- "animal, animate being, beast, brute, creature, fauna",
- "Rottweiler":
- "dog, domestic dog, Canis familiaris",
- "whiskey jug":
- "bottle",
- "leopard/Panthera pardus":
- "animal, animate being, beast, brute, creature, fauna",
- "ram/tup":
- "animal, animate being, beast, brute, creature, fauna",
- "bison":
- "animal, animate being, beast, brute, creature, fauna",
- "horned viper/cerastes/sand viper/horned asp/Cerastes cornutus":
- "animal, animate being, beast, brute, creature, fauna",
- "anemone fish":
- "animal, animate being, beast, brute, creature, fauna",
- "sports car/sport car":
- "wheeled vehicle",
- "red fox/Vulpes vulpes":
- "animal, animate being, beast, brute, creature, fauna",
- "hog/pig/grunter/squealer/Sus scrofa":
- "animal, animate being, beast, brute, creature, fauna",
- "unicycle/monocycle":
- "wheeled vehicle",
- "macaque":
- "animal, animate being, beast, brute, creature, fauna",
- "drum/membranophone/tympan":
- "musical instrument, instrument",
- "king snake/kingsnake":
- "animal, animate being, beast, brute, creature, fauna",
- "affenpinscher/monkey pinscher/monkey dog":
- "dog, domestic dog, Canis familiaris",
- "custard apple":
- "edible fruit",
- "meat loaf/meatloaf":
- "food, nutrient",
- "American egret/great white heron/Egretta albus":
- "animal, animate being, beast, brute, creature, fauna",
- "whiptail/whiptail lizard":
- "animal, animate being, beast, brute, creature, fauna",
- "joystick":
- "electronic equipment",
- "spoonbill":
- "animal, animate being, beast, brute, creature, fauna",
- "espresso":
- "food, nutrient",
- "mortarboard":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "jersey/T-shirt/tee shirt":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "kimono":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "squirrel monkey/Saimiri sciureus":
- "animal, animate being, beast, brute, creature, fauna",
- "hartebeest":
- "animal, animate being, beast, brute, creature, fauna",
- "marimba/xylophone":
- "musical instrument, instrument",
- "ice lolly/lolly/lollipop/popsicle":
- "food, nutrient",
- "marmot":
- "animal, animate being, beast, brute, creature, fauna",
- "beaver":
- "animal, animate being, beast, brute, creature, fauna",
- "Afghan hound/Afghan":
- "dog, domestic dog, Canis familiaris",
- "keeshond":
- "dog, domestic dog, Canis familiaris",
- "eggnog":
- "food, nutrient",
- "cougar/puma/catamount/mountain lion/painter/panther/Felis concolor":
- "animal, animate being, beast, brute, creature, fauna",
- "bonnet/poke bonnet":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "koala/koala bear/kangaroo bear/native bear/Phascolarctos cinereus":
- "animal, animate being, beast, brute, creature, fauna",
- "trombone":
- "musical instrument, instrument",
- "fig":
- "edible fruit",
- "gorilla/Gorilla gorilla":
- "animal, animate being, beast, brute, creature, fauna",
- "Japanese spaniel":
- "dog, domestic dog, Canis familiaris",
- "Lakeland terrier":
- "dog, domestic dog, Canis familiaris",
- "tiger cat":
- "animal, animate being, beast, brute, creature, fauna",
- "streetcar/tram/tramcar/trolley/trolley car":
- "wheeled vehicle",
- "tiger beetle":
- "animal, animate being, beast, brute, creature, fauna",
- "Pembroke/Pembroke Welsh corgi":
- "dog, domestic dog, Canis familiaris",
- "tank/army tank/armored combat vehicle/armoured combat vehicle":
- "wheeled vehicle",
- "ringneck snake/ring-necked snake/ring snake":
- "animal, animate being, beast, brute, creature, fauna",
- "Mexican hairless":
- "dog, domestic dog, Canis familiaris",
- "great grey owl/great gray owl/Strix nebulosa":
- "animal, animate being, beast, brute, creature, fauna",
- "bloodhound/sleuthhound":
- "dog, domestic dog, Canis familiaris",
- "racer/race car/racing car":
- "wheeled vehicle",
- "armadillo":
- "animal, animate being, beast, brute, creature, fauna",
- "bulletproof vest":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "triceratops":
- "animal, animate being, beast, brute, creature, fauna",
- "hyena/hyaena":
- "animal, animate being, beast, brute, creature, fauna",
- "ox":
- "animal, animate being, beast, brute, creature, fauna",
- "beach wagon/station wagon/wagon/estate car/beach waggon/station "
- "waggon/waggon":
- "wheeled vehicle",
- "wall clock":
- "timepiece, timekeeper, horologe",
- "mink":
- "animal, animate being, beast, brute, creature, fauna",
- "EntleBucher":
- "dog, domestic dog, Canis familiaris",
- "magpie":
- "animal, animate being, beast, brute, creature, fauna",
- "cockroach/roach":
- "animal, animate being, beast, brute, creature, fauna",
- "slug":
- "animal, animate being, beast, brute, creature, fauna",
- "albatross/mollymawk":
- "animal, animate being, beast, brute, creature, fauna",
- "Irish setter/red setter":
- "dog, domestic dog, Canis familiaris",
- "maraca":
- "musical instrument, instrument",
- "acoustic guitar":
- "musical instrument, instrument",
- "green snake/grass snake":
- "animal, animate being, beast, brute, creature, fauna",
- "yellow lady's slipper/yellow lady-slipper/Cypripedium "
- "calceolus/Cypripedium parviflorum":
- "plant, flora, plant life",
- "jaguar/panther/Panthera onca/Felis onca":
- "animal, animate being, beast, brute, creature, fauna",
- "dugong/Dugong dugon":
- "animal, animate being, beast, brute, creature, fauna",
- "potpie":
- "food, nutrient",
- "Madagascar cat/ring-tailed lemur/Lemur catta":
- "animal, animate being, beast, brute, creature, fauna",
- "hay":
- "food, nutrient",
- "fire engine/fire truck":
- "wheeled vehicle",
- "water bottle":
- "bottle",
- "tiger/Panthera tigris":
- "animal, animate being, beast, brute, creature, fauna",
- "redshank/Tringa totanus":
- "animal, animate being, beast, brute, creature, fauna",
- "tailed frog/bell toad/ribbed toad/tailed toad/Ascaphus trui":
- "animal, animate being, beast, brute, creature, fauna",
- "Yorkshire terrier":
- "dog, domestic dog, Canis familiaris",
- "freight car":
- "wheeled vehicle",
- "patas/hussar monkey/Erythrocebus patas":
- "animal, animate being, beast, brute, creature, fauna",
- "Norfolk terrier":
- "dog, domestic dog, Canis familiaris",
- "ringlet/ringlet butterfly":
- "animal, animate being, beast, brute, creature, fauna",
- "leafhopper":
- "animal, animate being, beast, brute, creature, fauna",
- "polecat/fitch/foulmart/foumart/Mustela putorius":
- "animal, animate being, beast, brute, creature, fauna",
- "zebra":
- "animal, animate being, beast, brute, creature, fauna",
- "ground beetle/carabid beetle":
- "animal, animate being, beast, brute, creature, fauna",
- "hermit crab":
- "animal, animate being, beast, brute, creature, fauna",
- "spider monkey/Ateles geoffroyi":
- "animal, animate being, beast, brute, creature, fauna",
- "analog clock":
- "timepiece, timekeeper, horologe",
- "limpkin/Aramus pictus":
- "animal, animate being, beast, brute, creature, fauna",
- "Irish water spaniel":
- "dog, domestic dog, Canis familiaris",
- "ballpoint/ballpoint pen/ballpen/Biro":
- "writing implement",
- "papillon":
- "dog, domestic dog, Canis familiaris",
- "banded gecko":
- "animal, animate being, beast, brute, creature, fauna",
- "Greater Swiss Mountain dog":
- "dog, domestic dog, Canis familiaris",
- "Staffordshire bullterrier/Staffordshire bull terrier":
- "dog, domestic dog, Canis familiaris",
- "bustard":
- "animal, animate being, beast, brute, creature, fauna",
- "night snake/Hypsiglena torquata":
- "animal, animate being, beast, brute, creature, fauna",
- "lion/king of beasts/Panthera leo":
- "animal, animate being, beast, brute, creature, fauna",
- "wig":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "flamingo":
- "animal, animate being, beast, brute, creature, fauna",
- "isopod":
- "animal, animate being, beast, brute, creature, fauna",
- "barracouta/snoek":
- "animal, animate being, beast, brute, creature, fauna",
- "swimming trunks/bathing trunks":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "Ibizan hound/Ibizan Podenco":
- "dog, domestic dog, Canis familiaris",
- "sundial":
- "timepiece, timekeeper, horologe",
- "fly":
- "animal, animate being, beast, brute, creature, fauna",
- "otter":
- "animal, animate being, beast, brute, creature, fauna",
- "banana":
- "edible fruit",
- "nematode/nematode worm/roundworm":
- "animal, animate being, beast, brute, creature, fauna",
- "green lizard/Lacerta viridis":
- "animal, animate being, beast, brute, creature, fauna",
- "bassoon":
- "musical instrument, instrument",
- "cellular telephone/cellular phone/cellphone/cell/mobile phone":
- "electronic equipment",
- "vestment":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "ruddy turnstone/Arenaria interpres":
- "animal, animate being, beast, brute, creature, fauna",
- "white wolf/Arctic wolf/Canis lupus tundrarum":
- "animal, animate being, beast, brute, creature, fauna",
- "vine snake":
- "animal, animate being, beast, brute, creature, fauna",
- "pelican":
- "animal, animate being, beast, brute, creature, fauna",
- "Windsor tie":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "tow truck/tow car/wrecker":
- "wheeled vehicle",
- "dingo/warrigal/warragal/Canis dingo":
- "animal, animate being, beast, brute, creature, fauna",
- "Appenzeller":
- "dog, domestic dog, Canis familiaris",
- "kit fox/Vulpes macrotis":
- "animal, animate being, beast, brute, creature, fauna",
- "ostrich/Struthio camelus":
- "animal, animate being, beast, brute, creature, fauna",
- "gar/garfish/garpike/billfish/Lepisosteus osseus":
- "animal, animate being, beast, brute, creature, fauna",
- "little blue heron/Egretta caerulea":
- "animal, animate being, beast, brute, creature, fauna",
- "French horn/horn":
- "musical instrument, instrument",
- "red wolf/maned wolf/Canis rufus/Canis niger":
- "animal, animate being, beast, brute, creature, fauna",
- "Great Dane":
- "dog, domestic dog, Canis familiaris",
- "pretzel":
- "food, nutrient",
- "Dandie Dinmont/Dandie Dinmont terrier":
- "dog, domestic dog, Canis familiaris",
- "macaw":
- "animal, animate being, beast, brute, creature, fauna",
- "Chesapeake Bay retriever":
- "dog, domestic dog, Canis familiaris",
- "diaper/nappy/napkin":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "French bulldog":
- "dog, domestic dog, Canis familiaris",
- "indri/indris/Indri indri/Indri brevicaudatus":
- "animal, animate being, beast, brute, creature, fauna",
- "flute/transverse flute":
- "musical instrument, instrument",
- "ocarina/sweet potato":
- "musical instrument, instrument",
- "tractor":
- "wheeled vehicle",
- "goldfish/Carassius auratus":
- "animal, animate being, beast, brute, creature, fauna",
- "toy terrier":
- "dog, domestic dog, Canis familiaris",
- "Blenheim spaniel":
- "dog, domestic dog, Canis familiaris",
- "orange":
- "edible fruit",
- "motor scooter/scooter":
- "wheeled vehicle",
- "snowmobile":
- "wheeled vehicle",
- "mitten":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "brown bear/bruin/Ursus arctos":
- "animal, animate being, beast, brute, creature, fauna",
- "shower cap":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "Border collie":
- "dog, domestic dog, Canis familiaris",
- "hourglass":
- "timepiece, timekeeper, horologe",
- "briard":
- "dog, domestic dog, Canis familiaris",
- "European gallinule/Porphyrio porphyrio":
- "animal, animate being, beast, brute, creature, fauna",
- "leatherback turtle/leatherback/leathery turtle/Dermochelys coriacea":
- "animal, animate being, beast, brute, creature, fauna",
- "tusker":
- "animal, animate being, beast, brute, creature, fauna",
- "Shih-Tzu":
- "dog, domestic dog, Canis familiaris",
- "proboscis monkey/Nasalis larvatus":
- "animal, animate being, beast, brute, creature, fauna",
- "otterhound/otter hound":
- "dog, domestic dog, Canis familiaris",
- "African chameleon/Chamaeleo chamaeleon":
- "animal, animate being, beast, brute, creature, fauna",
- "lionfish":
- "animal, animate being, beast, brute, creature, fauna",
- "water snake":
- "animal, animate being, beast, brute, creature, fauna",
- "recreational vehicle/RV/R.V.":
- "wheeled vehicle",
- "Brittany spaniel":
- "dog, domestic dog, Canis familiaris",
- "rock python/rock snake/Python sebae":
- "animal, animate being, beast, brute, creature, fauna",
- "menu":
- "food, nutrient",
- "eel":
- "animal, animate being, beast, brute, creature, fauna",
- "peacock":
- "animal, animate being, beast, brute, creature, fauna",
- "Bernese mountain dog":
- "dog, domestic dog, Canis familiaris",
- "desktop computer":
- "computer, computing machine, computing device, data processor, "
- "electronic computer, information processing system",
- "crayfish/crawfish/crawdad/crawdaddy":
- "animal, animate being, beast, brute, creature, fauna",
- "brain coral":
- "animal, animate being, beast, brute, creature, fauna",
- "oystercatcher/oyster catcher":
- "animal, animate being, beast, brute, creature, fauna",
- "killer whale/killer/orca/grampus/sea wolf/Orcinus orca":
- "animal, animate being, beast, brute, creature, fauna",
- "cup":
- "bottle",
- "giant schnauzer":
- "dog, domestic dog, Canis familiaris",
- "jean/blue jean/denim":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "wild boar/boar/Sus scrofa":
- "animal, animate being, beast, brute, creature, fauna",
- "steel drum":
- "musical instrument, instrument",
- "chime/bell/gong":
- "musical instrument, instrument",
- "snail":
- "animal, animate being, beast, brute, creature, fauna",
- "bluetick":
- "dog, domestic dog, Canis familiaris",
- "wire-haired fox terrier":
- "dog, domestic dog, Canis familiaris",
- "limousine/limo":
- "wheeled vehicle",
- "conch":
- "animal, animate being, beast, brute, creature, fauna",
- "Sussex spaniel":
- "dog, domestic dog, Canis familiaris",
- "Tibetan mastiff":
- "dog, domestic dog, Canis familiaris",
- "German shepherd/German shepherd dog/German police dog/alsatian":
- "dog, domestic dog, Canis familiaris",
- "schipperke":
- "dog, domestic dog, Canis familiaris",
- "goose":
- "animal, animate being, beast, brute, creature, fauna",
- "dhole/Cuon alpinus":
- "animal, animate being, beast, brute, creature, fauna",
- "soft-coated wheaten terrier":
- "dog, domestic dog, Canis familiaris",
- "oxcart":
- "wheeled vehicle",
- "flatworm/platyhelminth":
- "animal, animate being, beast, brute, creature, fauna",
- "clumber/clumber spaniel":
- "dog, domestic dog, Canis familiaris",
- "suit/suit of clothes":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "colobus/colobus monkey":
- "animal, animate being, beast, brute, creature, fauna",
- "Pomeranian":
- "dog, domestic dog, Canis familiaris",
- "mud turtle":
- "animal, animate being, beast, brute, creature, fauna",
- "cicada/cicala":
- "animal, animate being, beast, brute, creature, fauna",
- "orangutan/orang/orangutang/Pongo pygmaeus":
- "animal, animate being, beast, brute, creature, fauna",
- "Gordon setter":
- "dog, domestic dog, Canis familiaris",
- "panpipe/pandean pipe/syrinx":
- "musical instrument, instrument",
- "chambered nautilus/pearly nautilus/nautilus":
- "animal, animate being, beast, brute, creature, fauna",
- "harmonica/mouth organ/harp/mouth harp":
- "musical instrument, instrument",
- "snow leopard/ounce/Panthera uncia":
- "animal, animate being, beast, brute, creature, fauna",
- "cock":
- "animal, animate being, beast, brute, creature, fauna",
- "sloth bear/Melursus ursinus/Ursus ursinus":
- "animal, animate being, beast, brute, creature, fauna",
- "rock beauty/Holocanthus tricolor":
- "animal, animate being, beast, brute, creature, fauna",
- "hamster":
- "animal, animate being, beast, brute, creature, fauna",
- "miniature schnauzer":
- "dog, domestic dog, Canis familiaris",
- "horse cart/horse-cart":
- "wheeled vehicle",
- "African hunting dog/hyena dog/Cape hunting dog/Lycaon pictus":
- "animal, animate being, beast, brute, creature, fauna",
- "cabbage butterfly":
- "animal, animate being, beast, brute, creature, fauna",
- "great white shark/white shark/man-eater/man-eating shark/Carcharodon "
- "carcharias":
- "animal, animate being, beast, brute, creature, fauna",
- "flat-coated retriever":
- "dog, domestic dog, Canis familiaris",
- "llama":
- "animal, animate being, beast, brute, creature, fauna",
- "mashed potato":
- "food, nutrient",
- "groenendael":
- "dog, domestic dog, Canis familiaris",
- "centipede":
- "animal, animate being, beast, brute, creature, fauna",
- "whippet":
- "animal, animate being, beast, brute, creature, fauna",
- "jacamar":
- "animal, animate being, beast, brute, creature, fauna",
- "standard poodle":
- "dog, domestic dog, Canis familiaris",
- "Pekinese/Pekingese/Peke":
- "dog, domestic dog, Canis familiaris",
- "poncho":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "tricycle/trike/velocipede":
- "wheeled vehicle",
- "wolf spider/hunting spider":
- "animal, animate being, beast, brute, creature, fauna",
- "Walker hound/Walker foxhound":
- "dog, domestic dog, Canis familiaris",
- "hognose snake/puff adder/sand viper":
- "animal, animate being, beast, brute, creature, fauna",
- "miniature pinscher":
- "dog, domestic dog, Canis familiaris",
- "kuvasz":
- "dog, domestic dog, Canis familiaris",
- "dowitcher":
- "animal, animate being, beast, brute, creature, fauna",
- "notebook/notebook computer":
- "computer, computing machine, computing device, data processor, "
- "electronic computer, information processing system",
- "sorrel":
- "animal, animate being, beast, brute, creature, fauna",
- "chickadee":
- "animal, animate being, beast, brute, creature, fauna",
- "common iguana/iguana/Iguana iguana":
- "animal, animate being, beast, brute, creature, fauna",
- "snowplow/snowplough":
- "wheeled vehicle",
- "boxer":
- "dog, domestic dog, Canis familiaris",
- "diamondback/diamondback rattlesnake/Crotalus adamanteus":
- "animal, animate being, beast, brute, creature, fauna",
- "cornet/horn/trumpet/trump":
- "musical instrument, instrument",
- "Indian elephant/Elephas maximus":
- "animal, animate being, beast, brute, creature, fauna",
- "hippopotamus/hippo/river horse/Hippopotamus amphibius":
- "animal, animate being, beast, brute, creature, fauna",
- "ambulance":
- "wheeled vehicle",
- "weasel":
- "animal, animate being, beast, brute, creature, fauna",
- "cowboy hat/ten-gallon hat":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "American lobster/Northern lobster/Maine lobster/Homarus americanus":
- "animal, animate being, beast, brute, creature, fauna",
- "weevil":
- "animal, animate being, beast, brute, creature, fauna",
- "oboe/hautboy/hautbois":
- "musical instrument, instrument",
- "maillot":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "three-toed sloth/ai/Bradypus tridactylus":
- "animal, animate being, beast, brute, creature, fauna",
- "platypus/duckbill/duckbilled platypus/duck-billed "
- "platypus/Ornithorhynchus anatinus":
- "animal, animate being, beast, brute, creature, fauna",
- "white stork/Ciconia ciconia":
- "animal, animate being, beast, brute, creature, fauna",
- "bee eater":
- "animal, animate being, beast, brute, creature, fauna",
- "Newfoundland/Newfoundland dog":
- "dog, domestic dog, Canis familiaris",
- "dragonfly/darning needle/devil's darning needle/sewing needle/snake "
- "feeder/snake doctor/mosquito hawk/skeeter hawk":
- "animal, animate being, beast, brute, creature, fauna",
- "spiny lobster/langouste/rock lobster/crawfish/crayfish/sea crawfish":
- "animal, animate being, beast, brute, creature, fauna",
- "Old English sheepdog/bobtail":
- "dog, domestic dog, Canis familiaris",
- "partridge":
- "animal, animate being, beast, brute, creature, fauna",
- "Lhasa/Lhasa apso":
- "dog, domestic dog, Canis familiaris",
- "bee":
- "animal, animate being, beast, brute, creature, fauna",
- "American alligator/Alligator mississipiensis":
- "animal, animate being, beast, brute, creature, fauna",
- "harvestman/daddy longlegs/Phalangium opilio":
- "animal, animate being, beast, brute, creature, fauna",
- "common newt/Triturus vulgaris":
- "animal, animate being, beast, brute, creature, fauna",
- "water ouzel/dipper":
- "animal, animate being, beast, brute, creature, fauna",
- "jeep/landrover":
- "wheeled vehicle",
- "walking stick/walkingstick/stick insect":
- "animal, animate being, beast, brute, creature, fauna",
- "guacamole":
- "food, nutrient",
- "mountain bike/all-terrain bike/off-roader":
- "wheeled vehicle",
- "grasshopper/hopper":
- "animal, animate being, beast, brute, creature, fauna",
- "bullfrog/Rana catesbeiana":
- "animal, animate being, beast, brute, creature, fauna",
- "garden spider/Aranea diademata":
- "animal, animate being, beast, brute, creature, fauna",
- "amphibian/amphibious vehicle":
- "wheeled vehicle",
- "langur":
- "animal, animate being, beast, brute, creature, fauna",
- "vulture":
- "animal, animate being, beast, brute, creature, fauna",
- "wallaby/brush kangaroo":
- "animal, animate being, beast, brute, creature, fauna",
- "gibbon/Hylobates lar":
- "animal, animate being, beast, brute, creature, fauna",
- "bittern":
- "animal, animate being, beast, brute, creature, fauna",
- "ice bear/polar bear/Ursus Maritimus/Thalarctos maritimus":
- "animal, animate being, beast, brute, creature, fauna",
- "pickup/pickup truck":
- "wheeled vehicle",
- "fountain pen":
- "writing implement",
- "trifle":
- "food, nutrient",
- "pay-phone/pay-station":
- "electronic equipment",
- "Scotch terrier/Scottish terrier/Scottie":
- "dog, domestic dog, Canis familiaris",
- "web site/website/internet site/site":
- "computer, computing machine, computing device, data processor, "
- "electronic computer, information processing system",
- "coho/cohoe/coho salmon/blue jack/silver salmon/Oncorhynchus kisutch":
- "animal, animate being, beast, brute, creature, fauna",
- "Maltese dog/Maltese terrier/Maltese":
- "dog, domestic dog, Canis familiaris",
- "coucal":
- "animal, animate being, beast, brute, creature, fauna",
- "tiger shark/Galeocerdo cuvieri":
- "animal, animate being, beast, brute, creature, fauna",
- "indigo bunting/indigo finch/indigo bird/Passerina cyanea":
- "animal, animate being, beast, brute, creature, fauna",
- "hotdog/hot dog/red hot":
- "food, nutrient",
- "minivan":
- "wheeled vehicle",
- "passenger car/coach/carriage":
- "wheeled vehicle",
- "sea lion":
- "animal, animate being, beast, brute, creature, fauna",
- "cardigan":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "jinrikisha/ricksha/rickshaw":
- "wheeled vehicle",
- "chimpanzee/chimp/Pan troglodytes":
- "animal, animate being, beast, brute, creature, fauna",
- "African grey/African gray/Psittacus erithacus":
- "animal, animate being, beast, brute, creature, fauna",
- "black and gold garden spider/Argiope aurantia":
- "animal, animate being, beast, brute, creature, fauna",
- "miniature poodle":
- "dog, domestic dog, Canis familiaris",
- "electric locomotive":
- "wheeled vehicle",
- "Cardigan/Cardigan Welsh corgi":
- "dog, domestic dog, Canis familiaris",
- "box turtle/box tortoise":
- "animal, animate being, beast, brute, creature, fauna",
- "sturgeon":
- "animal, animate being, beast, brute, creature, fauna",
- "Irish wolfhound":
- "dog, domestic dog, Canis familiaris",
- "maillot/tank suit":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "kelpie":
- "dog, domestic dog, Canis familiaris",
- "cassette player":
- "electronic equipment",
- "hoopskirt/crinoline":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "bow tie/bow-tie/bowtie":
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "junco/snowbird":
- "animal, animate being, beast, brute, creature, fauna",
- "Scottish deerhound/deerhound":
- "dog, domestic dog, Canis familiaris",
- "king crab/Alaska crab/Alaskan king crab/Alaska king crab/Paralithodes "
- "camtschatica":
- "animal, animate being, beast, brute, creature, fauna",
- "Egyptian cat":
- "animal, animate being, beast, brute, creature, fauna",
- "jay":
- "animal, animate being, beast, brute, creature, fauna",
- "eft":
- "animal, animate being, beast, brute, creature, fauna",
- "garter snake/grass snake":
- "animal, animate being, beast, brute, creature, fauna",
- "wombat":
- "animal, animate being, beast, brute, creature, fauna",
- "consomme":
- "food, nutrient",
-}
-
-CATEGORIES = (
- "food, nutrient",
- "edible fruit",
- "electronic equipment",
- "wheeled vehicle",
- "dog, domestic dog, Canis familiaris",
- "animal, animate being, beast, brute, creature, fauna",
- "plant, flora, plant life",
- "clothing, article of clothing, vesture, wear, wearable, habiliment",
- "writing implement",
- "computer, computing machine, computing device, data processor, electronic"
- " computer, information processing system",
- "timepiece, timekeeper, horologe",
- "bottle",
- "musical instrument, instrument",
-)
diff --git a/src/examples/voice/assistant_grpc_demo.py b/src/examples/voice/assistant_grpc_demo.py
deleted file mode 100755
index 23456e19..00000000
--- a/src/examples/voice/assistant_grpc_demo.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""A demo of the Google Assistant GRPC recognizer."""
-
-import logging
-
-import aiy.assistant.grpc
-import aiy.audio
-import aiy.voicehat
-
-logging.basicConfig(
- level=logging.INFO,
- format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s"
-)
-
-
-def main():
- status_ui = aiy.voicehat.get_status_ui()
- status_ui.status('starting')
- assistant = aiy.assistant.grpc.get_assistant()
- button = aiy.voicehat.get_button()
- with aiy.audio.get_recorder():
- while True:
- status_ui.status('ready')
- print('Press the button and speak')
- button.wait_for_press()
- status_ui.status('listening')
- print('Listening...')
- text, audio = assistant.recognize()
- if text:
- if text == 'goodbye':
- status_ui.status('stopping')
- print('Bye!')
- break
- print('You said "', text, '"')
- if audio:
- aiy.audio.play_audio(audio)
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/voice/assistant_library_with_button_demo.py b/src/examples/voice/assistant_library_with_button_demo.py
deleted file mode 100755
index e7ac93e8..00000000
--- a/src/examples/voice/assistant_library_with_button_demo.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Run a recognizer using the Google Assistant Library with button support.
-
-The Google Assistant Library has direct access to the audio API, so this Python
-code doesn't need to record audio. Hot word detection "OK, Google" is supported.
-
-It is available for Raspberry Pi 2/3 only; Pi Zero is not supported.
-"""
-
-import logging
-import platform
-import sys
-import threading
-
-import aiy.assistant.auth_helpers
-from aiy.assistant.library import Assistant
-import aiy.voicehat
-from google.assistant.library.event import EventType
-
-logging.basicConfig(
- level=logging.INFO,
- format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s"
-)
-
-
-class MyAssistant(object):
- """An assistant that runs in the background.
-
- The Google Assistant Library event loop blocks the running thread entirely.
- To support the button trigger, we need to run the event loop in a separate
- thread. Otherwise, the on_button_pressed() method will never get a chance to
- be invoked.
- """
-
- def __init__(self):
- self._task = threading.Thread(target=self._run_task)
- self._can_start_conversation = False
- self._assistant = None
-
- def start(self):
- """Starts the assistant.
-
- Starts the assistant event loop and begin processing events.
- """
- self._task.start()
-
- def _run_task(self):
- credentials = aiy.assistant.auth_helpers.get_assistant_credentials()
- with Assistant(credentials) as assistant:
- self._assistant = assistant
- for event in assistant.start():
- self._process_event(event)
-
- def _process_event(self, event):
- status_ui = aiy.voicehat.get_status_ui()
- if event.type == EventType.ON_START_FINISHED:
- status_ui.status('ready')
- self._can_start_conversation = True
- # Start the voicehat button trigger.
- aiy.voicehat.get_button().on_press(self._on_button_pressed)
- if sys.stdout.isatty():
- print('Say "OK, Google" or press the button, then speak. '
- 'Press Ctrl+C to quit...')
-
- elif event.type == EventType.ON_CONVERSATION_TURN_STARTED:
- self._can_start_conversation = False
- status_ui.status('listening')
-
- elif event.type == EventType.ON_END_OF_UTTERANCE:
- status_ui.status('thinking')
-
- elif (event.type == EventType.ON_CONVERSATION_TURN_FINISHED
- or event.type == EventType.ON_CONVERSATION_TURN_TIMEOUT
- or event.type == EventType.ON_NO_RESPONSE):
- status_ui.status('ready')
- self._can_start_conversation = True
-
- elif event.type == EventType.ON_ASSISTANT_ERROR and event.args and event.args['is_fatal']:
- sys.exit(1)
-
- def _on_button_pressed(self):
- # Check if we can start a conversation. 'self._can_start_conversation'
- # is False when either:
- # 1. The assistant library is not yet ready; OR
- # 2. The assistant library is already in a conversation.
- if self._can_start_conversation:
- self._assistant.start_conversation()
-
-
-def main():
- if platform.machine() == 'armv6l':
- print('Cannot run hotword demo on Pi Zero!')
- exit(-1)
- MyAssistant().start()
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/examples/voice/cloudspeech_demo.py b/src/examples/voice/cloudspeech_demo.py
deleted file mode 100755
index 13eedfbf..00000000
--- a/src/examples/voice/cloudspeech_demo.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""A demo of the Google CloudSpeech recognizer."""
-
-import aiy.audio
-import aiy.cloudspeech
-import aiy.voicehat
-
-
-def main():
- recognizer = aiy.cloudspeech.get_recognizer()
- recognizer.expect_phrase('turn off the light')
- recognizer.expect_phrase('turn on the light')
- recognizer.expect_phrase('blink')
-
- button = aiy.voicehat.get_button()
- led = aiy.voicehat.get_led()
- aiy.audio.get_recorder().start()
-
- while True:
- print('Press the button and speak')
- button.wait_for_press()
- print('Listening...')
- text = recognizer.recognize()
- if not text:
- print('Sorry, I did not hear you.')
- else:
- print('You said "', text, '"')
- if 'turn on the light' in text:
- led.set_state(aiy.voicehat.LED.ON)
- elif 'turn off the light' in text:
- led.set_state(aiy.voicehat.LED.OFF)
- elif 'blink' in text:
- led.set_state(aiy.voicehat.LED.BLINK)
- elif 'goodbye' in text:
- break
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/setup.py b/src/setup.py
deleted file mode 100644
index d51fb433..00000000
--- a/src/setup.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from setuptools import setup, find_packages
-
-setup(
- name='aiy-projects-python',
- version='1.0',
- author='Peter Malkin',
- author_email='petermalkin@google.com',
- packages=find_packages(),
- url="https://aiyprojects.withgoogle.com/",
- license='LICENSE.txt',
- description="AIY Python API",
- data_files=[
- ('share/doc/aiy', ['README.md']),
- ('share/doc/aiy/examples', [
- "examples/vision/buzzer/congratulations.track",
- "examples/vision/buzzer/dramatic.track",
- "examples/vision/buzzer/laughing.track",
- "examples/vision/buzzer/sadtrombone.track",
- "examples/vision/buzzer/tetris.track",
- ]),
- ],
- install_requires=[
- 'google-assistant-grpc>=0.1.0',
- 'google-cloud-speech>=0.30.0',
- 'google-auth-oauthlib>=0.2.0',
- 'pyasn1>=0.4.2',
- 'grpcio>=1.7.0',
- ],
- python_requires='~=3.5',
- scripts=[
- "examples/vision/annotator.py",
- "examples/vision/buzzer/buzzer_demo.py",
- "examples/vision/buzzer/buzzer_tracker_demo.py",
- "examples/vision/dish_classifier.py",
- "examples/vision/face_camera_trigger.py",
- "examples/vision/face_detection.py",
- "examples/vision/face_detection_camera.py",
- "examples/vision/gpiozero/bonnet_button.py",
- "examples/vision/gpiozero/button_example.py",
- "examples/vision/gpiozero/led_example.py",
- "examples/vision/gpiozero/servo_example.py",
- "examples/vision/gpiozero/simple_button_example.py",
- "examples/vision/image_classification.py",
- "examples/vision/image_classification_camera.py",
- "examples/vision/joy/joy_detection_demo.py",
- "examples/vision/leds_example.py",
- "examples/vision/object_detection.py",
- "examples/vision/object_meter/object_meter.py",
- "examples/vision/object_meter/wordnet_grouping/category_mapper.py",
- "examples/vision/object_meter/wordnet_grouping/mapping_data.py",
- "examples/voice/assistant_grpc_demo.py",
- "examples/voice/assistant_library_demo.py",
- "examples/voice/assistant_library_with_button_demo.py",
- "examples/voice/assistant_library_with_local_commands_demo.py",
- "examples/voice/cloudspeech_demo.py",
- ])
diff --git a/systemd/alsa-init.service b/systemd/alsa-init.service
deleted file mode 100644
index 0841d7c3..00000000
--- a/systemd/alsa-init.service
+++ /dev/null
@@ -1,16 +0,0 @@
-# Play 1 s of silence if asound.state does not exists so lxpanel's volumealsa
-# can initialize properly.
-
-[Unit]
-Description=alsa init service
-ConditionPathExists=!/etc/alsa/state-daemon.conf
-ConditionPathExists=!/var/lib/alsa/asound.state
-DefaultDependencies=no
-After=local-fs.target sysinit.target
-
-[Service]
-Type=oneshot
-ExecStart=-/usr/bin/aplay -q -d 1 -c 1 -t raw -f S32_LE /dev/zero
-
-[Install]
-WantedBy=basic.target
diff --git a/systemd/ntpdate.service b/systemd/ntpdate.service
deleted file mode 100644
index 7db6d822..00000000
--- a/systemd/ntpdate.service
+++ /dev/null
@@ -1,14 +0,0 @@
-[Unit]
-Description=Set time with ntpdate
-After=network.target
-
-[Service]
-# use -u to avoid conflict with ntpd
-ExecStart=/usr/sbin/ntpdate -u pool.ntp.org
-
-# we may not have network yet, so retry until success
-Restart=on-failure
-RestartSec=60s
-
-[Install]
-WantedBy=multi-user.target
diff --git a/systemd/voice-recognizer.service b/systemd/voice-recognizer.service
deleted file mode 100644
index db0191ba..00000000
--- a/systemd/voice-recognizer.service
+++ /dev/null
@@ -1,19 +0,0 @@
-# This service can be used to run your code automatically on startup. Look in
-# HACKING.md for instructions on creating main.py and enabling it.
-
-[Unit]
-Description=voice recognizer
-After=network.target ntpdate.service
-
-[Service]
-Environment=VIRTUAL_ENV=/home/pi/AIY-projects-python/env
-Environment=PATH=/home/pi/AIY-projects-python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
-ExecStart=/home/pi/AIY-projects-python/env/bin/python3 -u src/main.py
-WorkingDirectory=/home/pi/AIY-projects-python
-StandardOutput=inherit
-StandardError=inherit
-Restart=always
-User=pi
-
-[Install]
-WantedBy=multi-user.target