├── test
├── test_helper.exs
├── live_onnx_web
│ ├── views
│ │ ├── page_view_test.exs
│ │ ├── layout_view_test.exs
│ │ └── error_view_test.exs
│ └── controllers
│ │ └── page_controller_test.exs
└── support
│ ├── channel_case.ex
│ └── conn_case.ex
├── priv
├── static
│ ├── favicon.ico
│ ├── images
│ │ └── phoenix.png
│ └── robots.txt
└── gettext
│ ├── en
│ └── LC_MESSAGES
│ │ └── errors.po
│ └── errors.pot
├── lib
├── live_onnx
│ ├── mailer.ex
│ └── application.ex
├── live_onnx_web
│ ├── views
│ │ ├── page_view.ex
│ │ ├── layout_view.ex
│ │ ├── error_view.ex
│ │ └── error_helpers.ex
│ ├── controllers
│ │ └── page_controller.ex
│ ├── templates
│ │ ├── layout
│ │ │ ├── app.html.heex
│ │ │ ├── live.html.heex
│ │ │ └── root.html.heex
│ │ └── page
│ │ │ └── index.html.heex
│ ├── gettext.ex
│ ├── telemetry.ex
│ ├── endpoint.ex
│ ├── router.ex
│ └── live
│ │ ├── page_live.html.heex
│ │ └── page_live.ex
├── live_onnx.ex
└── live_onnx_web.ex
├── .formatter.exs
├── config
├── test.exs
├── config.exs
├── prod.exs
├── dev.exs
└── runtime.exs
├── model
├── resnet18
│ └── README.md
├── convnext
│ └── README.md
├── squeezenet
│ └── README.md
├── vgg16
│ └── README.md
├── alexnet
│ └── README.md
└── classlist.json
├── .gitignore
├── README.md
├── assets
├── js
│ └── app.js
├── css
│ ├── app.css
│ └── phoenix.css
└── vendor
│ └── topbar.js
├── mix.exs
└── mix.lock
/test/test_helper.exs:
--------------------------------------------------------------------------------
1 | ExUnit.start()
2 |
--------------------------------------------------------------------------------
/priv/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thehaigo/live_onnx/HEAD/priv/static/favicon.ico
--------------------------------------------------------------------------------
/lib/live_onnx/mailer.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnx.Mailer do
2 | use Swoosh.Mailer, otp_app: :live_onnx
3 | end
4 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/views/page_view.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.PageView do
2 | use LiveOnnxWeb, :view
3 | end
4 |
--------------------------------------------------------------------------------
/priv/static/images/phoenix.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thehaigo/live_onnx/HEAD/priv/static/images/phoenix.png
--------------------------------------------------------------------------------
/.formatter.exs:
--------------------------------------------------------------------------------
1 | [
2 | import_deps: [:phoenix],
3 | inputs: ["*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}"]
4 | ]
5 |
--------------------------------------------------------------------------------
/test/live_onnx_web/views/page_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.PageViewTest do
2 | use LiveOnnxWeb.ConnCase, async: true
3 | end
4 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/controllers/page_controller.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.PageController do
2 | use LiveOnnxWeb, :controller
3 |
4 | def index(conn, _params) do
5 | render(conn, "index.html")
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/priv/static/robots.txt:
--------------------------------------------------------------------------------
1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/templates/layout/app.html.heex:
--------------------------------------------------------------------------------
1 |
2 | <%= get_flash(@conn, :info) %>
3 | <%= get_flash(@conn, :error) %>
4 | <%= @inner_content %>
5 |
6 |
--------------------------------------------------------------------------------
/test/live_onnx_web/controllers/page_controller_test.exs:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.PageControllerTest do
2 | use LiveOnnxWeb.ConnCase
3 |
4 | test "GET /", %{conn: conn} do
5 | conn = get(conn, "/")
6 | assert html_response(conn, 200) =~ "Welcome to Phoenix!"
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/lib/live_onnx.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnx do
2 | @moduledoc """
3 | LiveOnnx keeps the contexts that define your domain
4 | and business logic.
5 |
6 | Contexts are also responsible for managing your data, regardless
7 | if it comes from the database, an external API or others.
8 | """
9 | end
10 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/views/layout_view.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.LayoutView do
2 | use LiveOnnxWeb, :view
3 |
4 | # Phoenix LiveDashboard is available only in development by default,
5 | # so we instruct Elixir to not warn if the dashboard route is missing.
6 | @compile {:no_warn_undefined, {Routes, :live_dashboard_path, 2}}
7 | end
8 |
--------------------------------------------------------------------------------
/test/live_onnx_web/views/layout_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.LayoutViewTest do
2 | use LiveOnnxWeb.ConnCase, async: true
3 |
4 | # When testing helpers, you may want to import Phoenix.HTML and
5 | # use functions such as safe_to_string() to convert the helper
6 | # result into an HTML string.
7 | # import Phoenix.HTML
8 | end
9 |
--------------------------------------------------------------------------------
/priv/gettext/en/LC_MESSAGES/errors.po:
--------------------------------------------------------------------------------
1 | ## `msgid`s in this file come from POT (.pot) files.
2 | ##
3 | ## Do not add, change, or remove `msgid`s manually here as
4 | ## they're tied to the ones in the corresponding POT file
5 | ## (with the same domain).
6 | ##
7 | ## Use `mix gettext.extract --merge` or `mix gettext.merge`
8 | ## to merge POT files into PO files.
9 | msgid ""
10 | msgstr ""
11 | "Language: en\n"
12 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/templates/layout/live.html.heex:
--------------------------------------------------------------------------------
1 |
2 | <%= live_flash(@flash, :info) %>
5 |
6 | <%= live_flash(@flash, :error) %>
9 |
10 | <%= @inner_content %>
11 |
12 |
--------------------------------------------------------------------------------
/priv/gettext/errors.pot:
--------------------------------------------------------------------------------
1 | ## This is a PO Template file.
2 | ##
3 | ## `msgid`s here are often extracted from source code.
4 | ## Add new translations manually only if they're dynamic
5 | ## translations that can't be statically extracted.
6 | ##
7 | ## Run `mix gettext.extract` to bring this file up to
8 | ## date. Leave `msgstr`s empty as changing them here has no
9 | ## effect: edit them in PO (`.po`) files instead.
10 |
11 |
--------------------------------------------------------------------------------
/test/live_onnx_web/views/error_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.ErrorViewTest do
2 | use LiveOnnxWeb.ConnCase, async: true
3 |
4 | # Bring render/3 and render_to_string/3 for testing custom views
5 | import Phoenix.View
6 |
7 | test "renders 404.html" do
8 | assert render_to_string(LiveOnnxWeb.ErrorView, "404.html", []) == "Not Found"
9 | end
10 |
11 | test "renders 500.html" do
12 | assert render_to_string(LiveOnnxWeb.ErrorView, "500.html", []) == "Internal Server Error"
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/views/error_view.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.ErrorView do
2 | use LiveOnnxWeb, :view
3 |
4 | # If you want to customize a particular status code
5 | # for a certain format, you may uncomment below.
6 | # def render("500.html", _assigns) do
7 | # "Internal Server Error"
8 | # end
9 |
10 | # By default, Phoenix returns the status message from
11 | # the template name. For example, "404.html" becomes
12 | # "Not Found".
13 | def template_not_found(template, _assigns) do
14 | Phoenix.Controller.status_message_from_template(template)
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/config/test.exs:
--------------------------------------------------------------------------------
1 | import Config
2 |
3 | # We don't run a server during test. If one is required,
4 | # you can enable the server option below.
5 | config :live_onnx, LiveOnnxWeb.Endpoint,
6 | http: [ip: {127, 0, 0, 1}, port: 4002],
7 | secret_key_base: "HZ230zFY0xebxs1J/GwhFcfU4+ceHJSkqbHKtVz0hBpSkrpH71M+ewlhRBTbJUEq",
8 | server: false
9 |
10 | # In test we don't send emails.
11 | config :live_onnx, LiveOnnx.Mailer,
12 | adapter: Swoosh.Adapters.Test
13 |
14 | # Print only warnings and errors during test
15 | config :logger, level: :warn
16 |
17 | # Initialize plugs at runtime for faster test compilation
18 | config :phoenix, :plug_init_mode, :runtime
19 |
--------------------------------------------------------------------------------
/model/resnet18/README.md:
--------------------------------------------------------------------------------
1 | ## resnet18.onnx export
2 | export from torchvision resnet18
3 |
4 | ```
5 | pip install torch torchvision
6 | ```
7 |
8 | ```python
9 | import torchvision
10 | import torch
11 |
12 | net = torchvision.models.resnet18(pretrained = True)
13 |
14 | model_onnx_path = "model/resnet18/model.onnx"
15 | input_names = [ "input" ]
16 | output_names = [ "output" ]
17 |
18 | input_shape = (3, 224, 224)
19 | batch_size = 1
20 | dummy_input = torch.randn(batch_size, *input_shape)
21 |
22 |
23 | output = torch.onnx.export(net, dummy_input, model_onnx_path, \
24 | verbose=False, input_names=input_names, output_names=output_names)
25 |
26 | ```
--------------------------------------------------------------------------------
/model/convnext/README.md:
--------------------------------------------------------------------------------
1 | ## convnext.onnx export
2 | export from torchvision convnext_base
3 |
4 | ```
5 | pip install torch torchvision
6 | ```
7 |
8 | ```python
9 | import torchvision
10 | import torch
11 |
12 | net = torchvision.models.convnext_base(pretrained = True)
13 |
14 | model_onnx_path = "model/convnext/model.onnx"
15 | input_names = [ "input" ]
16 | output_names = [ "output" ]
17 |
18 | input_shape = (3, 224, 224)
19 | batch_size = 1
20 | dummy_input = torch.randn(batch_size, *input_shape)
21 |
22 |
23 | output = torch.onnx.export(net, dummy_input, model_onnx_path, \
24 | verbose=False, input_names=input_names, output_names=output_names)
25 |
26 | ```
--------------------------------------------------------------------------------
/model/squeezenet/README.md:
--------------------------------------------------------------------------------
1 | ## squeeze.onnx export
2 | export from torchvision squeezenet
3 |
4 | ```
5 | pip install torch torchvision
6 | ```
7 |
8 | ```python
9 | import torchvision
10 | import torch
11 |
12 | net = torchvision.models.squeezenet1_0(pretrained = True)
13 |
14 | model_onnx_path = "model/squeezenet/model.onnx"
15 | input_names = [ "input" ]
16 | output_names = [ "output" ]
17 |
18 | input_shape = (3, 224, 224)
19 | batch_size = 1
20 | dummy_input = torch.randn(batch_size, *input_shape)
21 |
22 |
23 | output = torch.onnx.export(net, dummy_input, model_onnx_path, \
24 | verbose=False, input_names=input_names, output_names=output_names)
25 |
26 | ```
--------------------------------------------------------------------------------
/lib/live_onnx_web/gettext.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.Gettext do
2 | @moduledoc """
3 | A module providing Internationalization with a gettext-based API.
4 |
5 | By using [Gettext](https://hexdocs.pm/gettext),
6 | your module gains a set of macros for translations, for example:
7 |
8 | import LiveOnnxWeb.Gettext
9 |
10 | # Simple translation
11 | gettext("Here is the string to translate")
12 |
13 | # Plural translation
14 | ngettext("Here is the string to translate",
15 | "Here are the strings to translate",
16 | 3)
17 |
18 | # Domain-based translation
19 | dgettext("errors", "Here is the error message to translate")
20 |
21 | See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
22 | """
23 | use Gettext, otp_app: :live_onnx
24 | end
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # The directory Mix will write compiled artifacts to.
2 | /_build/
3 |
4 | # If you run "mix test --cover", coverage assets end up here.
5 | /cover/
6 |
7 | # The directory Mix downloads your dependencies sources to.
8 | /deps/
9 |
10 | # Where 3rd-party dependencies like ExDoc output generated docs.
11 | /doc/
12 |
13 | # Ignore .fetch files in case you like to edit your project deps locally.
14 | /.fetch
15 |
16 | # If the VM crashes, it generates a dump, let's ignore it too.
17 | erl_crash.dump
18 |
19 | # Also ignore archive artifacts (built via "mix archive.build").
20 | *.ez
21 |
22 | # Ignore package tarball (built via "mix hex.build").
23 | live_onnx-*.tar
24 |
25 | # Ignore assets that are produced by build tools.
26 | /priv/static/assets/
27 |
28 | # Ignore digested assets cache.
29 | /priv/static/cache_manifest.json
30 |
31 | # In case you use Node.js/npm, you want to ignore these.
32 | npm-debug.log
33 | /assets/node_modules/
34 |
35 | .DS_Store
36 | .cache
37 | model/*/model.*
38 | model/*/model_fail.onnx
--------------------------------------------------------------------------------
/model/vgg16/README.md:
--------------------------------------------------------------------------------
1 | ## vgg16.onnx export
2 | export from torchvision vgg16
3 |
4 | ```
5 | pip install torch torchvision
6 | ```
7 |
8 | ```python
9 | import torchvision
10 | import torch
11 |
12 | net = torchvision.models.vgg16(pretrained = True)
13 |
14 | model_onnx_path = "model/vgg16/model.onnx"
15 | input_names = [ "input" ]
16 | output_names = [ "output" ]
17 |
18 | input_shape = (3, 224, 224)
19 | batch_size = 1
20 | dummy_input = torch.randn(batch_size, *input_shape)
21 |
22 |
23 | output = torch.onnx.export(net, dummy_input, model_onnx_path, \
24 | verbose=False, input_names=input_names, output_names=output_names)
25 |
26 | ```
27 |
28 | ## model.dets create
29 | AxonOnnx import too slow
30 | becasue load from dets
31 |
32 | ```elixir
33 | {model, params} = AxonOnnx.import("model/vgg16/model.onnx")
34 |
35 | # save to dets
36 | :dets.open_file("vgg16", type: :bag, file: 'model/vgg16/model.dets')
37 | :dets.insert("vgg16",{1,{model,params}})
38 | :dets.sync("vgg16")
39 | :dets.stop
40 | ```
41 |
42 |
--------------------------------------------------------------------------------
/model/alexnet/README.md:
--------------------------------------------------------------------------------
1 | ## alexnet.onnx export
2 | export from torchvision alexnet
3 |
4 | ```
5 | pip install torch torchvision
6 | ```
7 |
8 | ```python
9 | import torchvision
10 | import torch
11 |
12 | net = torchvision.models.alexnet(pretrained = True)
13 |
14 | model_onnx_path = "model/alexnet/model.onnx"
15 | input_names = [ "input" ]
16 | output_names = [ "output" ]
17 |
18 | input_shape = (3, 224, 224)
19 | batch_size = 1
20 | dummy_input = torch.randn(batch_size, *input_shape)
21 |
22 |
23 | output = torch.onnx.export(net, dummy_input, model_onnx_path, \
24 | verbose=False, input_names=input_names, output_names=output_names)
25 |
26 | ```
27 |
28 | ## model.dets create
29 | AxonOnnx import too slow
30 | becasue load from dets
31 |
32 | ```elixir
33 | {model, params} = AxonOnnx.import("model/alexnet/model.onnx")
34 |
35 | # save to dets
36 | :dets.open_file("alexnet", type: :bag, file: 'model/alexnet/model.dets')
37 | :dets.insert("alexnet",{1,{model,params}})
38 | :dets.sync("alexnet")
39 | :dets.stop
40 | ```
41 |
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LiveOnnx
2 |
3 | Requirements:
4 |
5 | * Elixir installed
6 |
7 | To start your Phoenix server:
8 |
9 | * Install dependencies with `mix deps.get`
10 | * get supported onnx model
11 | * Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server`
12 |
13 | Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
14 |
15 | Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html).
16 |
17 | ## demo
18 |
19 | https://user-images.githubusercontent.com/91950/172017672-ad98402d-93a7-4d7a-9e94-b69eebc1cea2.mp4
20 |
21 | ## supported model
22 |
23 | * ResNet18
24 | * AlexNet
25 | * SqueezeNet
26 | * Vgg16
27 | * ConvNext
28 |
29 | ## unsupported model
30 |
31 | * densenet -> unsupported "Pad" 2022/06/05
32 | * inception -> unsupported "Pad" 2022/06/05
33 | * shufflenet -> unable to build model from ONNX graph, expected value onnx::Conv_378 to be a graph input, but it was not present in built graphs 2022/06/05
34 |
35 | ## export onnx proccess
36 | see model/model_name directory
37 |
--------------------------------------------------------------------------------
/test/support/channel_case.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.ChannelCase do
2 | @moduledoc """
3 | This module defines the test case to be used by
4 | channel tests.
5 |
6 | Such tests rely on `Phoenix.ChannelTest` and also
7 | import other functionality to make it easier
8 | to build common data structures and query the data layer.
9 |
10 | Finally, if the test case interacts with the database,
11 | we enable the SQL sandbox, so changes done to the database
12 | are reverted at the end of every test. If you are using
13 | PostgreSQL, you can even run database tests asynchronously
14 | by setting `use LiveOnnxWeb.ChannelCase, async: true`, although
15 | this option is not recommended for other databases.
16 | """
17 |
18 | use ExUnit.CaseTemplate
19 |
20 | using do
21 | quote do
22 | # Import conveniences for testing with channels
23 | import Phoenix.ChannelTest
24 | import LiveOnnxWeb.ChannelCase
25 |
26 | # The default endpoint for testing
27 | @endpoint LiveOnnxWeb.Endpoint
28 | end
29 | end
30 |
31 | setup _tags do
32 | :ok
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/lib/live_onnx/application.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnx.Application do
2 | # See https://hexdocs.pm/elixir/Application.html
3 | # for more information on OTP Applications
4 | @moduledoc false
5 |
6 | use Application
7 |
8 | @impl true
9 | def start(_type, _args) do
10 | children = [
11 | # Start the Telemetry supervisor
12 | LiveOnnxWeb.Telemetry,
13 | # Start the PubSub system
14 | {Phoenix.PubSub, name: LiveOnnx.PubSub},
15 | # Start the Endpoint (http/https)
16 | LiveOnnxWeb.Endpoint
17 | # Start a worker by calling: LiveOnnx.Worker.start_link(arg)
18 | # {LiveOnnx.Worker, arg}
19 | ]
20 |
21 | # See https://hexdocs.pm/elixir/Supervisor.html
22 | # for other strategies and supported options
23 | opts = [strategy: :one_for_one, name: LiveOnnx.Supervisor]
24 | Supervisor.start_link(children, opts)
25 | end
26 |
27 | # Tell Phoenix to update the endpoint configuration
28 | # whenever the application is updated.
29 | @impl true
30 | def config_change(changed, _new, removed) do
31 | LiveOnnxWeb.Endpoint.config_change(changed, removed)
32 | :ok
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/test/support/conn_case.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.ConnCase do
2 | @moduledoc """
3 | This module defines the test case to be used by
4 | tests that require setting up a connection.
5 |
6 | Such tests rely on `Phoenix.ConnTest` and also
7 | import other functionality to make it easier
8 | to build common data structures and query the data layer.
9 |
10 | Finally, if the test case interacts with the database,
11 | we enable the SQL sandbox, so changes done to the database
12 | are reverted at the end of every test. If you are using
13 | PostgreSQL, you can even run database tests asynchronously
14 | by setting `use LiveOnnxWeb.ConnCase, async: true`, although
15 | this option is not recommended for other databases.
16 | """
17 |
18 | use ExUnit.CaseTemplate
19 |
20 | using do
21 | quote do
22 | # Import conveniences for testing with connections
23 | import Plug.Conn
24 | import Phoenix.ConnTest
25 | import LiveOnnxWeb.ConnCase
26 |
27 | alias LiveOnnxWeb.Router.Helpers, as: Routes
28 |
29 | # The default endpoint for testing
30 | @endpoint LiveOnnxWeb.Endpoint
31 | end
32 | end
33 |
34 | setup _tags do
35 | {:ok, conn: Phoenix.ConnTest.build_conn()}
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/templates/layout/root.html.heex:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | <%= csrf_meta_tag() %>
8 | <%= live_title_tag assigns[:page_title] || "LiveOnnx", suffix: " · Phoenix Framework" %>
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Get Started
18 | <%= if function_exported?(Routes, :live_dashboard_path, 2) do %>
19 | <%= link "LiveDashboard", to: Routes.live_dashboard_path(@conn, :home) %>
20 | <% end %>
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | <%= @inner_content %>
29 |
30 |
31 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/templates/page/index.html.heex:
--------------------------------------------------------------------------------
1 |
2 | <%= gettext "Welcome to %{name}!", name: "Phoenix" %>
3 | Peace of mind from prototype to production
4 |
5 |
6 |
7 |
8 | Resources
9 |
20 |
21 |
22 | Help
23 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/telemetry.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.Telemetry do
2 | use Supervisor
3 | import Telemetry.Metrics
4 |
5 | def start_link(arg) do
6 | Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
7 | end
8 |
9 | @impl true
10 | def init(_arg) do
11 | children = [
12 | # Telemetry poller will execute the given period measurements
13 | # every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics
14 | {:telemetry_poller, measurements: periodic_measurements(), period: 10_000}
15 | # Add reporters as children of your supervision tree.
16 | # {Telemetry.Metrics.ConsoleReporter, metrics: metrics()}
17 | ]
18 |
19 | Supervisor.init(children, strategy: :one_for_one)
20 | end
21 |
22 | def metrics do
23 | [
24 | # Phoenix Metrics
25 | summary("phoenix.endpoint.stop.duration",
26 | unit: {:native, :millisecond}
27 | ),
28 | summary("phoenix.router_dispatch.stop.duration",
29 | tags: [:route],
30 | unit: {:native, :millisecond}
31 | ),
32 |
33 | # VM Metrics
34 | summary("vm.memory.total", unit: {:byte, :kilobyte}),
35 | summary("vm.total_run_queue_lengths.total"),
36 | summary("vm.total_run_queue_lengths.cpu"),
37 | summary("vm.total_run_queue_lengths.io")
38 | ]
39 | end
40 |
41 | defp periodic_measurements do
42 | [
43 | # A module, function and arguments to be invoked periodically.
44 | # This function must call :telemetry.execute/3 and a metric must be added above.
45 | # {LiveOnnxWeb, :count_users, []}
46 | ]
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/endpoint.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.Endpoint do
2 | use Phoenix.Endpoint, otp_app: :live_onnx
3 |
4 | # The session will be stored in the cookie and signed,
5 | # this means its contents can be read but not tampered with.
6 | # Set :encryption_salt if you would also like to encrypt it.
7 | @session_options [
8 | store: :cookie,
9 | key: "_live_onnx_key",
10 | signing_salt: "pMR1BscD"
11 | ]
12 |
13 | socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]]
14 |
15 | # Serve at "/" the static files from "priv/static" directory.
16 | #
17 | # You should set gzip to true if you are running phx.digest
18 | # when deploying your static files in production.
19 | plug Plug.Static,
20 | at: "/",
21 | from: :live_onnx,
22 | gzip: false,
23 | only: ~w(assets fonts images favicon.ico robots.txt)
24 |
25 | # Code reloading can be explicitly enabled under the
26 | # :code_reloader configuration of your endpoint.
27 | if code_reloading? do
28 | socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
29 | plug Phoenix.LiveReloader
30 | plug Phoenix.CodeReloader
31 | end
32 |
33 | plug Phoenix.LiveDashboard.RequestLogger,
34 | param_key: "request_logger",
35 | cookie_key: "request_logger"
36 |
37 | plug Plug.RequestId
38 | plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
39 |
40 | plug Plug.Parsers,
41 | parsers: [:urlencoded, :multipart, :json],
42 | pass: ["*/*"],
43 | json_decoder: Phoenix.json_library()
44 |
45 | plug Plug.MethodOverride
46 | plug Plug.Head
47 | plug Plug.Session, @session_options
48 | plug LiveOnnxWeb.Router
49 | end
50 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/router.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.Router do
2 | use LiveOnnxWeb, :router
3 |
4 | pipeline :browser do
5 | plug :accepts, ["html"]
6 | plug :fetch_session
7 | plug :fetch_live_flash
8 | plug :put_root_layout, {LiveOnnxWeb.LayoutView, :root}
9 | plug :protect_from_forgery
10 | plug :put_secure_browser_headers
11 | end
12 |
13 | pipeline :api do
14 | plug :accepts, ["json"]
15 | end
16 |
17 | scope "/", LiveOnnxWeb do
18 | pipe_through :browser
19 |
20 | live "/", PageLive
21 | live "/:id", PageLive
22 | end
23 |
24 | # Other scopes may use custom stacks.
25 | # scope "/api", LiveOnnxWeb do
26 | # pipe_through :api
27 | # end
28 |
29 | # Enables LiveDashboard only for development
30 | #
31 | # If you want to use the LiveDashboard in production, you should put
32 | # it behind authentication and allow only admins to access it.
33 | # If your application does not have an admins-only section yet,
34 | # you can use Plug.BasicAuth to set up some basic authentication
35 | # as long as you are also using SSL (which you should anyway).
36 | if Mix.env() in [:dev, :test] do
37 | import Phoenix.LiveDashboard.Router
38 |
39 | scope "/" do
40 | pipe_through :browser
41 |
42 | live_dashboard "/dashboard", metrics: LiveOnnxWeb.Telemetry
43 | end
44 | end
45 |
46 | # Enables the Swoosh mailbox preview in development.
47 | #
48 | # Note that preview only shows emails that were sent by the same
49 | # node running the Phoenix server.
50 | if Mix.env() == :dev do
51 | scope "/dev" do
52 | pipe_through :browser
53 |
54 | forward "/mailbox", Plug.Swoosh.MailboxPreview
55 | end
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/views/error_helpers.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.ErrorHelpers do
2 | @moduledoc """
3 | Conveniences for translating and building error messages.
4 | """
5 |
6 | use Phoenix.HTML
7 |
8 | @doc """
9 | Generates tag for inlined form input errors.
10 | """
11 | def error_tag(form, field) do
12 | Enum.map(Keyword.get_values(form.errors, field), fn error ->
13 | content_tag(:span, translate_error(error),
14 | class: "invalid-feedback",
15 | phx_feedback_for: input_name(form, field)
16 | )
17 | end)
18 | end
19 |
20 | @doc """
21 | Translates an error message using gettext.
22 | """
23 | def translate_error({msg, opts}) do
24 | # When using gettext, we typically pass the strings we want
25 | # to translate as a static argument:
26 | #
27 | # # Translate "is invalid" in the "errors" domain
28 | # dgettext("errors", "is invalid")
29 | #
30 | # # Translate the number of files with plural rules
31 | # dngettext("errors", "1 file", "%{count} files", count)
32 | #
33 | # Because the error messages we show in our forms and APIs
34 | # are defined inside Ecto, we need to translate them dynamically.
35 | # This requires us to call the Gettext module passing our gettext
36 | # backend as first argument.
37 | #
38 | # Note we use the "errors" domain, which means translations
39 | # should be written to the errors.po file. The :count option is
40 | # set by Ecto and indicates we should also apply plural rules.
41 | if count = opts[:count] do
42 | Gettext.dngettext(LiveOnnxWeb.Gettext, "errors", msg, msg, count, opts)
43 | else
44 | Gettext.dgettext(LiveOnnxWeb.Gettext, "errors", msg, opts)
45 | end
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/live/page_live.html.heex:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
16 | <%= for {ans, index} <- Enum.with_index(@ans) do %>
17 | <%= "#{index + 1}: " <> Map.get(@list, to_string(ans)) %>
18 | <% end %>
19 |
20 |
21 |
22 |
23 |
38 | <%= if @upload_file do %>
39 |
40 | <% end %>
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/assets/js/app.js:
--------------------------------------------------------------------------------
1 | // We import the CSS which is extracted to its own file by esbuild.
2 | // Remove this line if you add a your own CSS build pipeline (e.g postcss).
3 | import "../css/app.css"
4 |
5 | // If you want to use Phoenix channels, run `mix help phx.gen.channel`
6 | // to get started and then uncomment the line below.
7 | // import "./user_socket.js"
8 |
9 | // You can include dependencies in two ways.
10 | //
11 | // The simplest option is to put them in assets/vendor and
12 | // import them using relative paths:
13 | //
14 | // import "../vendor/some-package.js"
15 | //
16 | // Alternatively, you can `npm install some-package --prefix assets` and import
17 | // them using a path starting with the package name:
18 | //
19 | // import "some-package"
20 | //
21 |
22 | // Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
23 | import "phoenix_html"
24 | // Establish Phoenix Socket and LiveView configuration.
25 | import {Socket} from "phoenix"
26 | import {LiveSocket} from "phoenix_live_view"
27 | import topbar from "../vendor/topbar"
28 |
29 | let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
30 | let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
31 |
32 | // Show progress bar on live navigation and form submits
33 | topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
34 | window.addEventListener("phx:page-loading-start", info => topbar.show())
35 | window.addEventListener("phx:page-loading-stop", info => topbar.hide())
36 |
37 | // connect if there are any LiveViews on the page
38 | liveSocket.connect()
39 |
40 | // expose liveSocket on window for web console debug logs and latency simulation:
41 | // >> liveSocket.enableDebug()
42 | // >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
43 | // >> liveSocket.disableLatencySim()
44 | window.liveSocket = liveSocket
45 |
46 |
--------------------------------------------------------------------------------
/config/config.exs:
--------------------------------------------------------------------------------
1 | # This file is responsible for configuring your application
2 | # and its dependencies with the aid of the Config module.
3 | #
4 | # This configuration file is loaded before any dependency and
5 | # is restricted to this project.
6 |
7 | # General application configuration
8 | import Config
9 |
10 | config :nx, :default_backend, EXLA.Backend
11 | config :nx, :default_defn_options, compiler: EXLA
12 |
13 | # Configures the endpoint
14 | config :live_onnx, LiveOnnxWeb.Endpoint,
15 | url: [host: "localhost"],
16 | render_errors: [view: LiveOnnxWeb.ErrorView, accepts: ~w(html json), layout: false],
17 | pubsub_server: LiveOnnx.PubSub,
18 | live_view: [signing_salt: "+34hIyL0"]
19 |
20 | # Configures the mailer
21 | #
22 | # By default it uses the "Local" adapter which stores the emails
23 | # locally. You can see the emails in your browser, at "/dev/mailbox".
24 | #
25 | # For production it's recommended to configure a different adapter
26 | # at the `config/runtime.exs`.
27 | config :live_onnx, LiveOnnx.Mailer, adapter: Swoosh.Adapters.Local
28 |
29 | # Swoosh API client is needed for adapters other than SMTP.
30 | config :swoosh, :api_client, false
31 |
32 | # Configure esbuild (the version is required)
33 | config :esbuild,
34 | version: "0.14.0",
35 | default: [
36 | args:
37 | ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
38 | cd: Path.expand("../assets", __DIR__),
39 | env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
40 | ]
41 |
42 | # Configures Elixir's Logger
43 | config :logger, :console,
44 | format: "$time $metadata[$level] $message\n",
45 | metadata: [:request_id]
46 |
47 | # Use Jason for JSON parsing in Phoenix
48 | config :phoenix, :json_library, Jason
49 |
50 | # Import environment specific config. This must remain at the bottom
51 | # of this file so it overrides the configuration defined above.
52 | import_config "#{config_env()}.exs"
53 |
--------------------------------------------------------------------------------
/config/prod.exs:
--------------------------------------------------------------------------------
1 | import Config
2 |
3 | # For production, don't forget to configure the url host
4 | # to something meaningful, Phoenix uses this information
5 | # when generating URLs.
6 | #
7 | # Note we also include the path to a cache manifest
8 | # containing the digested version of static files. This
9 | # manifest is generated by the `mix phx.digest` task,
10 | # which you should run after static files are built and
11 | # before starting your production server.
12 | config :live_onnx, LiveOnnxWeb.Endpoint, cache_static_manifest: "priv/static/cache_manifest.json"
13 |
14 | # Do not print debug messages in production
15 | config :logger, level: :info
16 |
17 | # ## SSL Support
18 | #
19 | # To get SSL working, you will need to add the `https` key
20 | # to the previous section and set your `:url` port to 443:
21 | #
22 | # config :live_onnx, LiveOnnxWeb.Endpoint,
23 | # ...,
24 | # url: [host: "example.com", port: 443],
25 | # https: [
26 | # ...,
27 | # port: 443,
28 | # cipher_suite: :strong,
29 | # keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
30 | # certfile: System.get_env("SOME_APP_SSL_CERT_PATH")
31 | # ]
32 | #
33 | # The `cipher_suite` is set to `:strong` to support only the
34 | # latest and more secure SSL ciphers. This means old browsers
35 | # and clients may not be supported. You can set it to
36 | # `:compatible` for wider support.
37 | #
38 | # `:keyfile` and `:certfile` expect an absolute path to the key
39 | # and cert in disk or a relative path inside priv, for example
40 | # "priv/ssl/server.key". For all supported SSL configuration
41 | # options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1
42 | #
43 | # We also recommend setting `force_ssl` in your endpoint, ensuring
44 | # no data is ever sent via http, always redirecting to https:
45 | #
46 | # config :live_onnx, LiveOnnxWeb.Endpoint,
47 | # force_ssl: [hsts: true]
48 | #
49 | # Check `Plug.SSL` for all available options in `force_ssl`.
50 |
--------------------------------------------------------------------------------
/config/dev.exs:
--------------------------------------------------------------------------------
1 | import Config
2 |
3 | # For development, we disable any cache and enable
4 | # debugging and code reloading.
5 | #
6 | # The watchers configuration can be used to run external
7 | # watchers to your application. For example, we use it
8 | # with esbuild to bundle .js and .css sources.
9 | config :live_onnx, LiveOnnxWeb.Endpoint,
10 | # Binding to loopback ipv4 address prevents access from other machines.
11 | # Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
12 | http: [ip: {127, 0, 0, 1}, port: 4000],
13 | check_origin: false,
14 | code_reloader: true,
15 | debug_errors: true,
16 | secret_key_base: "DnJBaHZRY5EcwnD7AvW4u0uqWtkZpT3+Btmd1bqwrwYwaB4q8/zoWGsiJFxPTueE",
17 | watchers: [
18 | # Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
19 | esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}
20 | ]
21 |
22 | # ## SSL Support
23 | #
24 | # In order to use HTTPS in development, a self-signed
25 | # certificate can be generated by running the following
26 | # Mix task:
27 | #
28 | # mix phx.gen.cert
29 | #
30 | # Note that this task requires Erlang/OTP 20 or later.
31 | # Run `mix help phx.gen.cert` for more information.
32 | #
33 | # The `http:` config above can be replaced with:
34 | #
35 | # https: [
36 | # port: 4001,
37 | # cipher_suite: :strong,
38 | # keyfile: "priv/cert/selfsigned_key.pem",
39 | # certfile: "priv/cert/selfsigned.pem"
40 | # ],
41 | #
42 | # If desired, both `http:` and `https:` keys can be
43 | # configured to run both http and https servers on
44 | # different ports.
45 |
46 | # Watch static and templates for browser reloading.
47 | config :live_onnx, LiveOnnxWeb.Endpoint,
48 | live_reload: [
49 | patterns: [
50 | ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
51 | ~r"priv/gettext/.*(po)$",
52 | ~r"lib/live_onnx_web/(live|views)/.*(ex)$",
53 | ~r"lib/live_onnx_web/templates/.*(eex)$"
54 | ]
55 | ]
56 |
57 | # Do not include metadata nor timestamps in development logs
58 | config :logger, :console, format: "[$level] $message\n"
59 |
60 | # Set a higher stacktrace during development. Avoid configuring such
61 | # in production as building large stacktraces may be expensive.
62 | config :phoenix, :stacktrace_depth, 20
63 |
64 | # Initialize plugs at runtime for faster development compilation
65 | config :phoenix, :plug_init_mode, :runtime
66 |
--------------------------------------------------------------------------------
/mix.exs:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnx.MixProject do
2 | use Mix.Project
3 |
4 | def project do
5 | [
6 | app: :live_onnx,
7 | version: "0.1.0",
8 | elixir: "~> 1.12",
9 | elixirc_paths: elixirc_paths(Mix.env()),
10 | compilers: [:gettext] ++ Mix.compilers(),
11 | start_permanent: Mix.env() == :prod,
12 | aliases: aliases(),
13 | deps: deps()
14 | ]
15 | end
16 |
17 | # Configuration for the OTP application.
18 | #
19 | # Type `mix help compile.app` for more information.
20 | def application do
21 | [
22 | mod: {LiveOnnx.Application, []},
23 | extra_applications: [:logger, :runtime_tools]
24 | ]
25 | end
26 |
27 | # Specifies which paths to compile per environment.
28 | defp elixirc_paths(:test), do: ["lib", "test/support"]
29 | defp elixirc_paths(_), do: ["lib"]
30 |
31 | # Specifies your project dependencies.
32 | #
33 | # Type `mix help deps` for examples and options.
34 | defp deps do
35 | [
36 | {:phoenix, "~> 1.6.6"},
37 | {:phoenix_ecto, "~> 4.4"},
38 | {:ecto_sql, "~> 3.6"},
39 | {:postgrex, ">= 0.0.0"},
40 | {:phoenix_html, "~> 3.0"},
41 | {:phoenix_live_reload, "~> 1.2", only: :dev},
42 | {:phoenix_live_view, "~> 0.17.5"},
43 | {:floki, ">= 0.30.0", only: :test},
44 | {:phoenix_live_dashboard, "~> 0.6"},
45 | {:esbuild, "~> 0.3", runtime: Mix.env() == :dev},
46 | {:swoosh, "~> 1.3"},
47 | {:telemetry_metrics, "~> 0.6"},
48 | {:telemetry_poller, "~> 1.0"},
49 | {:gettext, "~> 0.18"},
50 | {:jason, "~> 1.2"},
51 | {:plug_cowboy, "~> 2.5"},
52 | {:axon_onnx, github: "elixir-nx/axon_onnx"},
53 | {:stb_image, "~> 0.4.0"},
54 | {:exla, "~> 0.3.0-dev", github: "elixir-nx/nx", sparse: "exla"},
55 | {:nx, "~> 0.3.0-dev",
56 | [env: :prod, git: "https://github.com/elixir-nx/nx.git", sparse: "nx", override: true]}
57 | ]
58 | end
59 |
60 | # Aliases are shortcuts or tasks specific to the current project.
61 | # For example, to install project dependencies and perform other setup tasks, run:
62 | #
63 | # $ mix setup
64 | #
65 | # See the documentation for `Mix` for more info on aliases.
66 | defp aliases do
67 | [
68 | setup: ["deps.get", "ecto.setup", "cmd --cd assets npm install"],
69 | "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
70 | "ecto.reset": ["ecto.drop", "ecto.setup"],
71 | test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
72 | "assets.deploy": [
73 | "cmd --cd assets npm run deploy",
74 | "esbuild default --minify",
75 | "phx.digest"
76 | ]
77 | ]
78 | end
79 | end
80 |
--------------------------------------------------------------------------------
/assets/css/app.css:
--------------------------------------------------------------------------------
1 | /* This file is for your main application CSS */
2 | @import "./phoenix.css";
3 | @import "https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css";
4 | /* Alerts and form errors used by phx.new */
5 | .alert {
6 | padding: 15px;
7 | margin-bottom: 20px;
8 | border: 1px solid transparent;
9 | border-radius: 4px;
10 | }
11 | .alert-info {
12 | color: #31708f;
13 | background-color: #d9edf7;
14 | border-color: #bce8f1;
15 | }
16 | .alert-warning {
17 | color: #8a6d3b;
18 | background-color: #fcf8e3;
19 | border-color: #faebcc;
20 | }
21 | .alert-danger {
22 | color: #a94442;
23 | background-color: #f2dede;
24 | border-color: #ebccd1;
25 | }
26 | .alert p {
27 | margin-bottom: 0;
28 | }
29 | .alert:empty {
30 | display: none;
31 | }
32 | .invalid-feedback {
33 | color: #a94442;
34 | display: block;
35 | margin: -1rem 0 2rem;
36 | }
37 |
38 | /* LiveView specific classes for your customization */
39 | .phx-no-feedback.invalid-feedback,
40 | .phx-no-feedback .invalid-feedback {
41 | display: none;
42 | }
43 |
44 | .phx-click-loading {
45 | opacity: 0.5;
46 | transition: opacity 1s ease-out;
47 | }
48 |
49 | .phx-loading{
50 | cursor: wait;
51 | }
52 |
53 | .phx-modal {
54 | opacity: 1!important;
55 | position: fixed;
56 | z-index: 1;
57 | left: 0;
58 | top: 0;
59 | width: 100%;
60 | height: 100%;
61 | overflow: auto;
62 | background-color: rgba(0,0,0,0.4);
63 | }
64 |
65 | .phx-modal-content {
66 | background-color: #fefefe;
67 | margin: 15vh auto;
68 | padding: 20px;
69 | border: 1px solid #888;
70 | width: 80%;
71 | }
72 |
73 | .phx-modal-close {
74 | color: #aaa;
75 | float: right;
76 | font-size: 28px;
77 | font-weight: bold;
78 | }
79 |
80 | .phx-modal-close:hover,
81 | .phx-modal-close:focus {
82 | color: black;
83 | text-decoration: none;
84 | cursor: pointer;
85 | }
86 |
87 | .fade-in-scale {
88 | animation: 0.2s ease-in 0s normal forwards 1 fade-in-scale-keys;
89 | }
90 |
91 | .fade-out-scale {
92 | animation: 0.2s ease-out 0s normal forwards 1 fade-out-scale-keys;
93 | }
94 |
95 | .fade-in {
96 | animation: 0.2s ease-out 0s normal forwards 1 fade-in-keys;
97 | }
98 | .fade-out {
99 | animation: 0.2s ease-out 0s normal forwards 1 fade-out-keys;
100 | }
101 |
102 | @keyframes fade-in-scale-keys{
103 | 0% { scale: 0.95; opacity: 0; }
104 | 100% { scale: 1.0; opacity: 1; }
105 | }
106 |
107 | @keyframes fade-out-scale-keys{
108 | 0% { scale: 1.0; opacity: 1; }
109 | 100% { scale: 0.95; opacity: 0; }
110 | }
111 |
112 | @keyframes fade-in-keys{
113 | 0% { opacity: 0; }
114 | 100% { opacity: 1; }
115 | }
116 |
117 | @keyframes fade-out-keys{
118 | 0% { opacity: 1; }
119 | 100% { opacity: 0; }
120 | }
121 |
--------------------------------------------------------------------------------
/lib/live_onnx_web.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb do
2 | @moduledoc """
3 | The entrypoint for defining your web interface, such
4 | as controllers, views, channels and so on.
5 |
6 | This can be used in your application as:
7 |
8 | use LiveOnnxWeb, :controller
9 | use LiveOnnxWeb, :view
10 |
11 | The definitions below will be executed for every view,
12 | controller, etc, so keep them short and clean, focused
13 | on imports, uses and aliases.
14 |
15 | Do NOT define functions inside the quoted expressions
16 | below. Instead, define any helper function in modules
17 | and import those modules here.
18 | """
19 |
20 | def controller do
21 | quote do
22 | use Phoenix.Controller, namespace: LiveOnnxWeb
23 |
24 | import Plug.Conn
25 | import LiveOnnxWeb.Gettext
26 | alias LiveOnnxWeb.Router.Helpers, as: Routes
27 | end
28 | end
29 |
30 | def view do
31 | quote do
32 | use Phoenix.View,
33 | root: "lib/live_onnx_web/templates",
34 | namespace: LiveOnnxWeb
35 |
36 | # Import convenience functions from controllers
37 | import Phoenix.Controller,
38 | only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
39 |
40 | # Include shared imports and aliases for views
41 | unquote(view_helpers())
42 | end
43 | end
44 |
45 | def live_view do
46 | quote do
47 | use Phoenix.LiveView,
48 | layout: {LiveOnnxWeb.LayoutView, "live.html"}
49 |
50 | unquote(view_helpers())
51 | end
52 | end
53 |
54 | def live_component do
55 | quote do
56 | use Phoenix.LiveComponent
57 |
58 | unquote(view_helpers())
59 | end
60 | end
61 |
62 | def component do
63 | quote do
64 | use Phoenix.Component
65 |
66 | unquote(view_helpers())
67 | end
68 | end
69 |
70 | def router do
71 | quote do
72 | use Phoenix.Router
73 |
74 | import Plug.Conn
75 | import Phoenix.Controller
76 | import Phoenix.LiveView.Router
77 | end
78 | end
79 |
80 | def channel do
81 | quote do
82 | use Phoenix.Channel
83 | import LiveOnnxWeb.Gettext
84 | end
85 | end
86 |
87 | defp view_helpers do
88 | quote do
89 | # Use all HTML functionality (forms, tags, etc)
90 | use Phoenix.HTML
91 |
92 | # Import LiveView and .heex helpers (live_render, live_patch, <.form>, etc)
93 | import Phoenix.LiveView.Helpers
94 |
95 | # Import basic rendering functionality (render, render_layout, etc)
96 | import Phoenix.View
97 |
98 | import LiveOnnxWeb.ErrorHelpers
99 | import LiveOnnxWeb.Gettext
100 | alias LiveOnnxWeb.Router.Helpers, as: Routes
101 | end
102 | end
103 |
104 | @doc """
105 | When used, dispatch to the appropriate controller/view/etc.
106 | """
107 | defmacro __using__(which) when is_atom(which) do
108 | apply(__MODULE__, which, [])
109 | end
110 | end
111 |
--------------------------------------------------------------------------------
/config/runtime.exs:
--------------------------------------------------------------------------------
1 | import Config
2 |
3 | # config/runtime.exs is executed for all environments, including
4 | # during releases. It is executed after compilation and before the
5 | # system starts, so it is typically used to load production configuration
6 | # and secrets from environment variables or elsewhere. Do not define
7 | # any compile-time configuration in here, as it won't be applied.
8 | # The block below contains prod specific runtime configuration.
9 |
10 | # Start the phoenix server if environment is set and running in a release
11 | if System.get_env("PHX_SERVER") && System.get_env("RELEASE_NAME") do
12 | config :live_onnx, LiveOnnxWeb.Endpoint, server: true
13 | end
14 |
15 | if config_env() == :prod do
16 | # The secret key base is used to sign/encrypt cookies and other secrets.
17 | # A default value is used in config/dev.exs and config/test.exs but you
18 | # want to use a different value for prod and you most likely don't want
19 | # to check this value into version control, so we use an environment
20 | # variable instead.
21 | secret_key_base =
22 | System.get_env("SECRET_KEY_BASE") ||
23 | raise """
24 | environment variable SECRET_KEY_BASE is missing.
25 | You can generate one by calling: mix phx.gen.secret
26 | """
27 |
28 | host = System.get_env("PHX_HOST") || "example.com"
29 | port = String.to_integer(System.get_env("PORT") || "4000")
30 |
31 | config :live_onnx, LiveOnnxWeb.Endpoint,
32 | url: [host: host, port: 443],
33 | http: [
34 | # Enable IPv6 and bind on all interfaces.
35 | # Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.
36 | # See the documentation on https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html
37 | # for details about using IPv6 vs IPv4 and loopback vs public addresses.
38 | ip: {0, 0, 0, 0, 0, 0, 0, 0},
39 | port: port
40 | ],
41 | secret_key_base: secret_key_base
42 |
43 | # ## Using releases
44 | #
45 | # If you are doing OTP releases, you need to instruct Phoenix
46 | # to start each relevant endpoint:
47 | #
48 | # config :live_onnx, LiveOnnxWeb.Endpoint, server: true
49 | #
50 | # Then you can assemble a release by calling `mix release`.
51 | # See `mix help release` for more information.
52 |
53 | # ## Configuring the mailer
54 | #
55 | # In production you need to configure the mailer to use a different adapter.
56 | # Also, you may need to configure the Swoosh API client of your choice if you
57 | # are not using SMTP. Here is an example of the configuration:
58 | #
59 | # config :live_onnx, LiveOnnx.Mailer,
60 | # adapter: Swoosh.Adapters.Mailgun,
61 | # api_key: System.get_env("MAILGUN_API_KEY"),
62 | # domain: System.get_env("MAILGUN_DOMAIN")
63 | #
64 | # For this example you need include a HTTP client required by Swoosh API client.
65 | # Swoosh supports Hackney and Finch out of the box:
66 | #
67 | # config :swoosh, :api_client, Swoosh.ApiClient.Hackney
68 | #
69 | # See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details.
70 | end
71 |
--------------------------------------------------------------------------------
/lib/live_onnx_web/live/page_live.ex:
--------------------------------------------------------------------------------
1 | defmodule LiveOnnxWeb.PageLive do
2 | use LiveOnnxWeb, :live_view
3 | require Axon
4 |
5 | @impl true
6 | def mount(params, _session, socket) do
7 | socket =
8 | socket
9 | |> assign_enable_model()
10 | |> assign(:list, File.read!("model/classlist.json") |> Jason.decode!())
11 | |> assign(:upload_file, nil)
12 | |> assign(:tensor, nil)
13 | |> assign(:ans, [])
14 | |> allow_upload(
15 | :image,
16 | accept: :any,
17 | chunk_size: 6400_000,
18 | progress: &handle_progress/3,
19 | auto_upload: true
20 | )
21 |
22 | {:ok, socket}
23 | end
24 |
25 | defp assign_enable_model(socket) do
26 | model_names =
27 | File.ls!("model")
28 | |> Enum.filter(fn name -> File.exists?("model/#{name}/model.onnx") end)
29 |
30 | assign(socket, :enable_model, model_names)
31 | end
32 |
33 | def handle_params(%{"id" => "vgg16"}, _action, socket) do
34 | {:ok, dets} = :dets.open_file('model/vgg16/model.dets')
35 | [{1, {model, params}}] = :dets.lookup(dets, 1)
36 |
37 | {:noreply, assign_model(socket, model, params, "vgg16")}
38 | end
39 |
40 | def handle_params(%{"id" => "alexnet"}, _action, socket) do
41 | {:ok, dets} = :dets.open_file('model/alexnet/model.dets')
42 | [{1, {model, params}}] = :dets.lookup(dets, 1)
43 |
44 | {:noreply, assign_model(socket, model, params, "alexnet")}
45 | end
46 |
47 | def handle_params(%{"id" => model_name}, _action, socket) do
48 | {model, params} = AxonOnnx.import("model/#{model_name}/model.onnx")
49 |
50 | {:noreply, assign_model(socket, model, params, model_name)}
51 | end
52 |
53 | def handle_params(%{}, _action, socket) do
54 | {:noreply, assign(socket, model_name: "None")}
55 | end
56 |
57 | defp assign_model(socket, model, params, model_name) do
58 | socket
59 | |> assign(:model, model)
60 | |> assign(:params, params)
61 | |> assign(:model_name, model_name)
62 | |> assign(:ans, [])
63 | end
64 |
65 | def handle_progress(:image, _entry, socket) do
66 | upload_file =
67 | consume_uploaded_entries(socket, :image, fn %{path: path}, _entry ->
68 | File.read(path)
69 | end)
70 | |> List.first()
71 |
72 | tensor = build_tensor(upload_file)
73 | {:noreply, assign(socket, upload_file: upload_file, tensor: tensor)}
74 | end
75 |
76 | defp build_tensor(data) do
77 | {:ok, image} = StbImage.from_binary(data)
78 | {:ok, image} = StbImage.resize(image, 224, 224)
79 | nx_image = StbImage.to_nx(image)
80 | nx_channels = Nx.axis_size(nx_image, 2)
81 |
82 | case nx_channels do
83 | 3 -> nx_image
84 | 4 -> Nx.slice(nx_image, [0, 0, 0], [224, 224, 3])
85 | end
86 | |> Nx.divide(255)
87 | |> Nx.subtract(Nx.tensor([0.485, 0.456, 0.406]))
88 | |> Nx.divide(Nx.tensor([0.229, 0.224, 0.225]))
89 | |> Nx.transpose()
90 | |> Nx.new_axis(0)
91 | end
92 |
93 | @impl true
94 | def handle_event("validate", _params, socket) do
95 | {:noreply, socket}
96 | end
97 |
98 | @impl true
99 | def handle_event("selected", %{"model" => model}, socket) do
100 | {:noreply, push_patch(socket, to: "/#{model}", replace: true)}
101 | end
102 |
103 | @impl true
104 | def handle_event(
105 | "detect",
106 | _params,
107 | %{assigns: %{tensor: tensor, model: model, params: params}} = socket
108 | ) do
109 | ans =
110 | Axon.predict(model, params, tensor)
111 | |> Nx.flatten()
112 | |> Nx.argsort()
113 | |> Nx.reverse()
114 | |> Nx.slice([0], [5])
115 | |> Nx.to_flat_list()
116 |
117 | {:noreply, assign(socket, :ans, ans)}
118 | end
119 |
120 | @impl true
121 | def handle_event("clear", _params, socket) do
122 | socket =
123 | socket
124 | |> assign(:upload_file, nil)
125 | |> assign(:tensor, nil)
126 | |> assign(:ans, [])
127 |
128 | {:noreply, socket}
129 | end
130 | end
131 |
--------------------------------------------------------------------------------
/assets/vendor/topbar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license MIT
3 | * topbar 1.0.0, 2021-01-06
4 | * https://buunguyen.github.io/topbar
5 | * Copyright (c) 2021 Buu Nguyen
6 | */
7 | (function (window, document) {
8 | "use strict";
9 |
10 | // https://gist.github.com/paulirish/1579671
11 | (function () {
12 | var lastTime = 0;
13 | var vendors = ["ms", "moz", "webkit", "o"];
14 | for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
15 | window.requestAnimationFrame =
16 | window[vendors[x] + "RequestAnimationFrame"];
17 | window.cancelAnimationFrame =
18 | window[vendors[x] + "CancelAnimationFrame"] ||
19 | window[vendors[x] + "CancelRequestAnimationFrame"];
20 | }
21 | if (!window.requestAnimationFrame)
22 | window.requestAnimationFrame = function (callback, element) {
23 | var currTime = new Date().getTime();
24 | var timeToCall = Math.max(0, 16 - (currTime - lastTime));
25 | var id = window.setTimeout(function () {
26 | callback(currTime + timeToCall);
27 | }, timeToCall);
28 | lastTime = currTime + timeToCall;
29 | return id;
30 | };
31 | if (!window.cancelAnimationFrame)
32 | window.cancelAnimationFrame = function (id) {
33 | clearTimeout(id);
34 | };
35 | })();
36 |
37 | var canvas,
38 | progressTimerId,
39 | fadeTimerId,
40 | currentProgress,
41 | showing,
42 | addEvent = function (elem, type, handler) {
43 | if (elem.addEventListener) elem.addEventListener(type, handler, false);
44 | else if (elem.attachEvent) elem.attachEvent("on" + type, handler);
45 | else elem["on" + type] = handler;
46 | },
47 | options = {
48 | autoRun: true,
49 | barThickness: 3,
50 | barColors: {
51 | 0: "rgba(26, 188, 156, .9)",
52 | ".25": "rgba(52, 152, 219, .9)",
53 | ".50": "rgba(241, 196, 15, .9)",
54 | ".75": "rgba(230, 126, 34, .9)",
55 | "1.0": "rgba(211, 84, 0, .9)",
56 | },
57 | shadowBlur: 10,
58 | shadowColor: "rgba(0, 0, 0, .6)",
59 | className: null,
60 | },
61 | repaint = function () {
62 | canvas.width = window.innerWidth;
63 | canvas.height = options.barThickness * 5; // need space for shadow
64 |
65 | var ctx = canvas.getContext("2d");
66 | ctx.shadowBlur = options.shadowBlur;
67 | ctx.shadowColor = options.shadowColor;
68 |
69 | var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
70 | for (var stop in options.barColors)
71 | lineGradient.addColorStop(stop, options.barColors[stop]);
72 | ctx.lineWidth = options.barThickness;
73 | ctx.beginPath();
74 | ctx.moveTo(0, options.barThickness / 2);
75 | ctx.lineTo(
76 | Math.ceil(currentProgress * canvas.width),
77 | options.barThickness / 2
78 | );
79 | ctx.strokeStyle = lineGradient;
80 | ctx.stroke();
81 | },
82 | createCanvas = function () {
83 | canvas = document.createElement("canvas");
84 | var style = canvas.style;
85 | style.position = "fixed";
86 | style.top = style.left = style.right = style.margin = style.padding = 0;
87 | style.zIndex = 100001;
88 | style.display = "none";
89 | if (options.className) canvas.classList.add(options.className);
90 | document.body.appendChild(canvas);
91 | addEvent(window, "resize", repaint);
92 | },
93 | topbar = {
94 | config: function (opts) {
95 | for (var key in opts)
96 | if (options.hasOwnProperty(key)) options[key] = opts[key];
97 | },
98 | show: function () {
99 | if (showing) return;
100 | showing = true;
101 | if (fadeTimerId !== null) window.cancelAnimationFrame(fadeTimerId);
102 | if (!canvas) createCanvas();
103 | canvas.style.opacity = 1;
104 | canvas.style.display = "block";
105 | topbar.progress(0);
106 | if (options.autoRun) {
107 | (function loop() {
108 | progressTimerId = window.requestAnimationFrame(loop);
109 | topbar.progress(
110 | "+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2)
111 | );
112 | })();
113 | }
114 | },
115 | progress: function (to) {
116 | if (typeof to === "undefined") return currentProgress;
117 | if (typeof to === "string") {
118 | to =
119 | (to.indexOf("+") >= 0 || to.indexOf("-") >= 0
120 | ? currentProgress
121 | : 0) + parseFloat(to);
122 | }
123 | currentProgress = to > 1 ? 1 : to;
124 | repaint();
125 | return currentProgress;
126 | },
127 | hide: function () {
128 | if (!showing) return;
129 | showing = false;
130 | if (progressTimerId != null) {
131 | window.cancelAnimationFrame(progressTimerId);
132 | progressTimerId = null;
133 | }
134 | (function loop() {
135 | if (topbar.progress("+.1") >= 1) {
136 | canvas.style.opacity -= 0.05;
137 | if (canvas.style.opacity <= 0.05) {
138 | canvas.style.display = "none";
139 | fadeTimerId = null;
140 | return;
141 | }
142 | }
143 | fadeTimerId = window.requestAnimationFrame(loop);
144 | })();
145 | },
146 | };
147 |
148 | if (typeof module === "object" && typeof module.exports === "object") {
149 | module.exports = topbar;
150 | } else if (typeof define === "function" && define.amd) {
151 | define(function () {
152 | return topbar;
153 | });
154 | } else {
155 | this.topbar = topbar;
156 | }
157 | }.call(this, window, document));
158 |
--------------------------------------------------------------------------------
/assets/css/phoenix.css:
--------------------------------------------------------------------------------
1 | /* Includes some default style for the starter application.
2 | * This can be safely deleted to start fresh.
3 | */
4 |
5 | /* Milligram v1.4.1 https://milligram.github.io
6 | * Copyright (c) 2020 CJ Patoilo Licensed under the MIT license
7 | */
8 |
9 | *,*:after,*:before{box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%}body{color:#000000;font-family:'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;font-size:1.6em;font-weight:300;letter-spacing:.01em;line-height:1.6}blockquote{border-left:0.3rem solid #d1d1d1;margin-left:0;margin-right:0;padding:1rem 1.5rem}blockquote *:last-child{margin-bottom:0}.button,button,input[type='button'],input[type='reset'],input[type='submit']{background-color:#0069d9;border:0.1rem solid #0069d9;border-radius:.4rem;color:#fff;cursor:pointer;display:inline-block;font-size:1.1rem;font-weight:700;height:3.8rem;letter-spacing:.1rem;line-height:3.8rem;padding:0 3.0rem;text-align:center;text-decoration:none;text-transform:uppercase;white-space:nowrap}.button:focus,.button:hover,button:focus,button:hover,input[type='button']:focus,input[type='button']:hover,input[type='reset']:focus,input[type='reset']:hover,input[type='submit']:focus,input[type='submit']:hover{background-color:#606c76;border-color:#606c76;color:#fff;outline:0}.button[disabled],button[disabled],input[type='button'][disabled],input[type='reset'][disabled],input[type='submit'][disabled]{cursor:default;opacity:.5}.button[disabled]:focus,.button[disabled]:hover,button[disabled]:focus,button[disabled]:hover,input[type='button'][disabled]:focus,input[type='button'][disabled]:hover,input[type='reset'][disabled]:focus,input[type='reset'][disabled]:hover,input[type='submit'][disabled]:focus,input[type='submit'][disabled]:hover{background-color:#0069d9;border-color:#0069d9}.button.button-outline,button.button-outline,input[type='button'].button-outline,input[type='reset'].button-outline,input[type='submit'].button-outline{background-color:transparent;color:#0069d9}.button.button-outline:focus,.button.button-outline:hover,button.button-outline:focus,button.button-outline:hover,input[type='button'].button-outline:focus,input[type='button'].button-outline:hover,input[type='reset'].button-outline:focus,input[type='reset'].button-outline:hover,input[type='submit'].button-outline:focus,input[type='submit'].button-outline:hover{background-color:transparent;border-color:#606c76;color:#606c76}.button.button-outline[disabled]:focus,.button.button-outline[disabled]:hover,button.button-outline[disabled]:focus,button.button-outline[disabled]:hover,input[type='button'].button-outline[disabled]:focus,input[type='button'].button-outline[disabled]:hover,input[type='reset'].button-outline[disabled]:focus,input[type='reset'].button-outline[disabled]:hover,input[type='submit'].button-outline[disabled]:focus,input[type='submit'].button-outline[disabled]:hover{border-color:inherit;color:#0069d9}.button.button-clear,button.button-clear,input[type='button'].button-clear,input[type='reset'].button-clear,input[type='submit'].button-clear{background-color:transparent;border-color:transparent;color:#0069d9}.button.button-clear:focus,.button.button-clear:hover,button.button-clear:focus,button.button-clear:hover,input[type='button'].button-clear:focus,input[type='button'].button-clear:hover,input[type='reset'].button-clear:focus,input[type='reset'].button-clear:hover,input[type='submit'].button-clear:focus,input[type='submit'].button-clear:hover{background-color:transparent;border-color:transparent;color:#606c76}.button.button-clear[disabled]:focus,.button.button-clear[disabled]:hover,button.button-clear[disabled]:focus,button.button-clear[disabled]:hover,input[type='button'].button-clear[disabled]:focus,input[type='button'].button-clear[disabled]:hover,input[type='reset'].button-clear[disabled]:focus,input[type='reset'].button-clear[disabled]:hover,input[type='submit'].button-clear[disabled]:focus,input[type='submit'].button-clear[disabled]:hover{color:#0069d9}code{background:#f4f5f6;border-radius:.4rem;font-size:86%;margin:0 .2rem;padding:.2rem .5rem;white-space:nowrap}pre{background:#f4f5f6;border-left:0.3rem solid #0069d9;overflow-y:hidden}pre>code{border-radius:0;display:block;padding:1rem 1.5rem;white-space:pre}hr{border:0;border-top:0.1rem solid #f4f5f6;margin:3.0rem 0}input[type='color'],input[type='date'],input[type='datetime'],input[type='datetime-local'],input[type='email'],input[type='month'],input[type='number'],input[type='password'],input[type='search'],input[type='tel'],input[type='text'],input[type='url'],input[type='week'],input:not([type]),textarea,select{-webkit-appearance:none;background-color:transparent;border:0.1rem solid #d1d1d1;border-radius:.4rem;box-shadow:none;box-sizing:inherit;height:3.8rem;padding:.6rem 1.0rem .7rem;width:100%}input[type='color']:focus,input[type='date']:focus,input[type='datetime']:focus,input[type='datetime-local']:focus,input[type='email']:focus,input[type='month']:focus,input[type='number']:focus,input[type='password']:focus,input[type='search']:focus,input[type='tel']:focus,input[type='text']:focus,input[type='url']:focus,input[type='week']:focus,input:not([type]):focus,textarea:focus,select:focus{border-color:#0069d9;outline:0}select{background:url('data:image/svg+xml;utf8, ') center right no-repeat;padding-right:3.0rem}select:focus{background-image:url('data:image/svg+xml;utf8, ')}select[multiple]{background:none;height:auto}textarea{min-height:6.5rem}label,legend{display:block;font-size:1.6rem;font-weight:700;margin-bottom:.5rem}fieldset{border-width:0;padding:0}input[type='checkbox'],input[type='radio']{display:inline}.label-inline{display:inline-block;font-weight:normal;margin-left:.5rem}.container{margin:0 auto;max-width:112.0rem;padding:0 2.0rem;position:relative;width:100%}.row{display:flex;flex-direction:column;padding:0;width:100%}.row.row-no-padding{padding:0}.row.row-no-padding>.column{padding:0}.row.row-wrap{flex-wrap:wrap}.row.row-top{align-items:flex-start}.row.row-bottom{align-items:flex-end}.row.row-center{align-items:center}.row.row-stretch{align-items:stretch}.row.row-baseline{align-items:baseline}.row .column{display:block;flex:1 1 auto;margin-left:0;max-width:100%;width:100%}.row .column.column-offset-10{margin-left:10%}.row .column.column-offset-20{margin-left:20%}.row .column.column-offset-25{margin-left:25%}.row .column.column-offset-33,.row .column.column-offset-34{margin-left:33.3333%}.row .column.column-offset-40{margin-left:40%}.row .column.column-offset-50{margin-left:50%}.row .column.column-offset-60{margin-left:60%}.row .column.column-offset-66,.row .column.column-offset-67{margin-left:66.6666%}.row .column.column-offset-75{margin-left:75%}.row .column.column-offset-80{margin-left:80%}.row .column.column-offset-90{margin-left:90%}.row .column.column-10{flex:0 0 10%;max-width:10%}.row .column.column-20{flex:0 0 20%;max-width:20%}.row .column.column-25{flex:0 0 25%;max-width:25%}.row .column.column-33,.row .column.column-34{flex:0 0 33.3333%;max-width:33.3333%}.row .column.column-40{flex:0 0 40%;max-width:40%}.row .column.column-50{flex:0 0 50%;max-width:50%}.row .column.column-60{flex:0 0 60%;max-width:60%}.row .column.column-66,.row .column.column-67{flex:0 0 66.6666%;max-width:66.6666%}.row .column.column-75{flex:0 0 75%;max-width:75%}.row .column.column-80{flex:0 0 80%;max-width:80%}.row .column.column-90{flex:0 0 90%;max-width:90%}.row .column .column-top{align-self:flex-start}.row .column .column-bottom{align-self:flex-end}.row .column .column-center{align-self:center}@media (min-width: 40rem){.row{flex-direction:row;margin-left:-1.0rem;width:calc(100% + 2.0rem)}.row .column{margin-bottom:inherit;padding:0 1.0rem}}a{color:#0069d9;text-decoration:none}a:focus,a:hover{color:#606c76}dl,ol,ul{list-style:none;margin-top:0;padding-left:0}dl dl,dl ol,dl ul,ol dl,ol ol,ol ul,ul dl,ul ol,ul ul{font-size:90%;margin:1.5rem 0 1.5rem 3.0rem}ol{list-style:decimal inside}ul{list-style:circle inside}.button,button,dd,dt,li{margin-bottom:1.0rem}fieldset,input,select,textarea{margin-bottom:1.5rem}blockquote,dl,figure,form,ol,p,pre,table,ul{margin-bottom:2.5rem}table{border-spacing:0;display:block;overflow-x:auto;text-align:left;width:100%}td,th{border-bottom:0.1rem solid #e1e1e1;padding:1.2rem 1.5rem}td:first-child,th:first-child{padding-left:0}td:last-child,th:last-child{padding-right:0}@media (min-width: 40rem){table{display:table;overflow-x:initial}}b,strong{font-weight:bold}p{margin-top:0}h1,h2,h3,h4,h5,h6{font-weight:300;letter-spacing:-.1rem;margin-bottom:2.0rem;margin-top:0}h1{font-size:4.6rem;line-height:1.2}h2{font-size:3.6rem;line-height:1.25}h3{font-size:2.8rem;line-height:1.3}h4{font-size:2.2rem;letter-spacing:-.08rem;line-height:1.35}h5{font-size:1.8rem;letter-spacing:-.05rem;line-height:1.5}h6{font-size:1.6rem;letter-spacing:0;line-height:1.4}img{max-width:100%}.clearfix:after{clear:both;content:' ';display:table}.float-left{float:left}.float-right{float:right}
10 |
11 | /* General style */
12 | h1{font-size: 3.6rem; line-height: 1.25}
13 | h2{font-size: 2.8rem; line-height: 1.3}
14 | h3{font-size: 2.2rem; letter-spacing: -.08rem; line-height: 1.35}
15 | h4{font-size: 1.8rem; letter-spacing: -.05rem; line-height: 1.5}
16 | h5{font-size: 1.6rem; letter-spacing: 0; line-height: 1.4}
17 | h6{font-size: 1.4rem; letter-spacing: 0; line-height: 1.2}
18 | pre{padding: 1em;}
19 |
20 | .container{
21 | margin: 0 auto;
22 | max-width: 80.0rem;
23 | padding: 0 2.0rem;
24 | position: relative;
25 | width: 100%
26 | }
27 | select {
28 | width: auto;
29 | }
30 |
31 | /* Phoenix promo and logo */
32 | .phx-hero {
33 | text-align: center;
34 | border-bottom: 1px solid #e3e3e3;
35 | background: #eee;
36 | border-radius: 6px;
37 | padding: 3em 3em 1em;
38 | margin-bottom: 3rem;
39 | font-weight: 200;
40 | font-size: 120%;
41 | }
42 | .phx-hero input {
43 | background: #ffffff;
44 | }
45 | .phx-logo {
46 | min-width: 300px;
47 | margin: 1rem;
48 | display: block;
49 | }
50 | .phx-logo img {
51 | width: auto;
52 | display: block;
53 | }
54 |
55 | /* Headers */
56 | header {
57 | width: 100%;
58 | background: #fdfdfd;
59 | border-bottom: 1px solid #eaeaea;
60 | margin-bottom: 2rem;
61 | }
62 | header section {
63 | align-items: center;
64 | display: flex;
65 | flex-direction: column;
66 | justify-content: space-between;
67 | }
68 | header section :first-child {
69 | order: 2;
70 | }
71 | header section :last-child {
72 | order: 1;
73 | }
74 | header nav ul,
75 | header nav li {
76 | margin: 0;
77 | padding: 0;
78 | display: block;
79 | text-align: right;
80 | white-space: nowrap;
81 | }
82 | header nav ul {
83 | margin: 1rem;
84 | margin-top: 0;
85 | }
86 | header nav a {
87 | display: block;
88 | }
89 |
90 | @media (min-width: 40.0rem) { /* Small devices (landscape phones, 576px and up) */
91 | header section {
92 | flex-direction: row;
93 | }
94 | header nav ul {
95 | margin: 1rem;
96 | }
97 | .phx-logo {
98 | flex-basis: 527px;
99 | margin: 2rem 1rem;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/mix.lock:
--------------------------------------------------------------------------------
1 | %{
2 | "axon": {:git, "https://github.com/elixir-nx/axon.git", "d59221193a80efde0c6268aab8338840bae2f04a", []},
3 | "axon_onnx": {:git, "https://github.com/elixir-nx/axon_onnx.git", "a1c6bf6dce6ca25520941c62aa6e5ec083fe2848", []},
4 | "castore": {:hex, :castore, "0.1.17", "ba672681de4e51ed8ec1f74ed624d104c0db72742ea1a5e74edbc770c815182f", [:mix], [], "hexpm", "d9844227ed52d26e7519224525cb6868650c272d4a3d327ce3ca5570c12163f9"},
5 | "complex": {:hex, :complex, "0.4.1", "5d5a7bdbec13428c05824bac550b7d2b14ec395cd64663eca3cb0d3359aa22c5", [:mix], [], "hexpm", "6a813529dddba9bdfc17dffdd1aeda7b3d6891b76c8d4c1ae902ec74eb496a32"},
6 | "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
7 | "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
8 | "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
9 | "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
10 | "db_connection": {:hex, :db_connection, "2.4.2", "f92e79aff2375299a16bcb069a14ee8615c3414863a6fef93156aee8e86c2ff3", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4fe53ca91b99f55ea249693a0229356a08f4d1a7931d8ffa79289b145fe83668"},
11 | "decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
12 | "ecto": {:hex, :ecto, "3.8.4", "e06b8b87e62b27fea17fd2ff6041572ddd10339fd16cdf58446e402c6c90a74b", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f9244288b8d42db40515463a008cf3f4e0e564bb9c249fe87bf28a6d79fe82d4"},
13 | "ecto_sql": {:hex, :ecto_sql, "3.8.3", "a7d22c624202546a39d615ed7a6b784580391e65723f2d24f65941b4dd73d471", [:mix], [{:db_connection, "~> 2.5 or ~> 2.4.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.8.4", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "348cb17fb9e6daf6f251a87049eafcb57805e2892e5e6a0f5dea0985d367329b"},
14 | "elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"},
15 | "esbuild": {:hex, :esbuild, "0.5.0", "d5bb08ff049d7880ee3609ed5c4b864bd2f46445ea40b16b4acead724fb4c4a3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "f183a0b332d963c4cfaf585477695ea59eef9a6f2204fdd0efa00e099694ffe5"},
16 | "exla": {:git, "https://github.com/elixir-nx/nx.git", "8eadd775cf08b871c364794b231924170ff06e3d", [sparse: "exla"]},
17 | "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
18 | "floki": {:hex, :floki, "0.33.1", "f20f1eb471e726342b45ccb68edb9486729e7df94da403936ea94a794f072781", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "461035fd125f13fdf30f243c85a0b1e50afbec876cbf1ceefe6fddd2e6d712c6"},
19 | "gettext": {:hex, :gettext, "0.19.1", "564953fd21f29358e68b91634799d9d26989f8d039d7512622efb3c3b1c97892", [:mix], [], "hexpm", "10c656c0912b8299adba9b061c06947511e3f109ab0d18b44a866a4498e77222"},
20 | "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
21 | "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
22 | "mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"},
23 | "nx": {:git, "https://github.com/elixir-nx/nx.git", "8eadd775cf08b871c364794b231924170ff06e3d", [sparse: "nx"]},
24 | "phoenix": {:hex, :phoenix, "1.6.11", "29f3c0fd12fa1fc4d4b05e341578e55bc78d96ea83a022587a7e276884d397e4", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1664e34f80c25ea4918fbadd957f491225ef601c0e00b4e644b1a772864bfbc2"},
25 | "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"},
26 | "phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"},
27 | "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.6.5", "1495bb014be12c9a9252eca04b9af54246f6b5c1e4cd1f30210cd00ec540cf8e", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.3", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.17.7", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "ef4fa50dd78364409039c99cf6f98ab5209b4c5f8796c17f4db118324f0db852"},
28 | "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.3", "3a53772a6118d5679bf50fc1670505a290e32a1d195df9e069d8c53ab040c054", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "766796676e5f558dbae5d1bdb066849673e956005e3730dfd5affd7a6da4abac"},
29 | "phoenix_live_view": {:hex, :phoenix_live_view, "0.17.11", "205f6aa5405648c76f2abcd57716f42fc07d8f21dd8ea7b262dd12b324b50c95", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7177791944b7f90ed18f5935a6a5f07f760b36f7b3bdfb9d28c57440a3c43f99"},
30 | "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"},
31 | "phoenix_view": {:hex, :phoenix_view, "1.1.2", "1b82764a065fb41051637872c7bd07ed2fdb6f5c3bd89684d4dca6e10115c95a", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "7ae90ad27b09091266f6adbb61e1d2516a7c3d7062c6789d46a7554ec40f3a56"},
32 | "plug": {:hex, :plug, "1.13.6", "187beb6b67c6cec50503e940f0434ea4692b19384d47e5fdfd701e93cadb4cc2", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02b9c6b9955bce92c829f31d6284bf53c591ca63c4fb9ff81dfd0418667a34ff"},
33 | "plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"},
34 | "plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"},
35 | "postgrex": {:hex, :postgrex, "0.16.3", "fac79a81a9a234b11c44235a4494d8565303fa4b9147acf57e48978a074971db", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "aeaae1d2d1322da4e5fe90d241b0a564ce03a3add09d7270fb85362166194590"},
36 | "protox": {:hex, :protox, "1.6.10", "41d0b0c5b9190e7d5e6a2b1a03a09257ead6f3d95e6a0cf8b81430b526126908", [:mix], [{:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "9769fca26ae7abfc5cc61308a1e8d9e2400ff89a799599cee7930d21132832d9"},
37 | "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
38 | "stb_image": {:hex, :stb_image, "0.4.0", "0f5cf6b3a3a91fccdd712be44c4651689edb2b5ec22c418833126e349254b3f2", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nx, "~> 0.1", [hex: :nx, repo: "hexpm", optional: true]}], "hexpm", "0f2abad7f863bf0efcb15da4852471641864ab4cea36733eda0a7da0536ed67a"},
39 | "swoosh": {:hex, :swoosh, "1.7.3", "febb47c8c3ce76747eb9e3ea25ed694c815f72069127e3bb039b7724082ec670", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "76abac313f95b6825baa8ceec269d597e8395950c928742fc6451d3456ca256d"},
40 | "table_rex": {:hex, :table_rex, "3.1.1", "0c67164d1714b5e806d5067c1e96ff098ba7ae79413cc075973e17c38a587caa", [:mix], [], "hexpm", "678a23aba4d670419c23c17790f9dcd635a4a89022040df7d5d772cb21012490"},
41 | "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"},
42 | "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
43 | "telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"},
44 | "xla": {:hex, :xla, "0.3.0", "7f40d3d799447bd745e6e61985c922821e355eca37c25754bac299d11f137f2e", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "0de304f5624ea2f2ae1afdcbd72d33855364be36fed2cc5de8d6d2ec8950926e"},
45 | }
46 |
--------------------------------------------------------------------------------
/model/classlist.json:
--------------------------------------------------------------------------------
1 | {
2 | "0": "tench, Tinca tinca",
3 | "1": "goldfish, Carassius auratus",
4 | "2": "great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias",
5 | "3": "tiger shark, Galeocerdo cuvieri",
6 | "4": "hammerhead, hammerhead shark",
7 | "5": "electric ray, crampfish, numbfish, torpedo",
8 | "6": "stingray",
9 | "7": "cock",
10 | "8": "hen",
11 | "9": "ostrich, Struthio camelus",
12 | "10": "brambling, Fringilla montifringilla",
13 | "11": "goldfinch, Carduelis carduelis",
14 | "12": "house finch, linnet, Carpodacus mexicanus",
15 | "13": "junco, snowbird",
16 | "14": "indigo bunting, indigo finch, indigo bird, Passerina cyanea",
17 | "15": "robin, American robin, Turdus migratorius",
18 | "16": "bulbul",
19 | "17": "jay",
20 | "18": "magpie",
21 | "19": "chickadee",
22 | "20": "water ouzel, dipper",
23 | "21": "kite",
24 | "22": "bald eagle, American eagle, Haliaeetus leucocephalus",
25 | "23": "vulture",
26 | "24": "great grey owl, great gray owl, Strix nebulosa",
27 | "25": "European fire salamander, Salamandra salamandra",
28 | "26": "common newt, Triturus vulgaris",
29 | "27": "eft",
30 | "28": "spotted salamander, Ambystoma maculatum",
31 | "29": "axolotl, mud puppy, Ambystoma mexicanum",
32 | "30": "bullfrog, Rana catesbeiana",
33 | "31": "tree frog, tree-frog",
34 | "32": "tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui",
35 | "33": "loggerhead, loggerhead turtle, Caretta caretta",
36 | "34": "leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea",
37 | "35": "mud turtle",
38 | "36": "terrapin",
39 | "37": "box turtle, box tortoise",
40 | "38": "banded gecko",
41 | "39": "common iguana, iguana, Iguana iguana",
42 | "40": "American chameleon, anole, Anolis carolinensis",
43 | "41": "whiptail, whiptail lizard",
44 | "42": "agama",
45 | "43": "frilled lizard, Chlamydosaurus kingi",
46 | "44": "alligator lizard",
47 | "45": "Gila monster, Heloderma suspectum",
48 | "46": "green lizard, Lacerta viridis",
49 | "47": "African chameleon, Chamaeleo chamaeleon",
50 | "48": "Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis",
51 | "49": "African crocodile, Nile crocodile, Crocodylus niloticus",
52 | "50": "American alligator, Alligator mississipiensis",
53 | "51": "triceratops",
54 | "52": "thunder snake, worm snake, Carphophis amoenus",
55 | "53": "ringneck snake, ring-necked snake, ring snake",
56 | "54": "hognose snake, puff adder, sand viper",
57 | "55": "green snake, grass snake",
58 | "56": "king snake, kingsnake",
59 | "57": "garter snake, grass snake",
60 | "58": "water snake",
61 | "59": "vine snake",
62 | "60": "night snake, Hypsiglena torquata",
63 | "61": "boa constrictor, Constrictor constrictor",
64 | "62": "rock python, rock snake, Python sebae",
65 | "63": "Indian cobra, Naja naja",
66 | "64": "green mamba",
67 | "65": "sea snake",
68 | "66": "horned viper, cerastes, sand viper, horned asp, Cerastes cornutus",
69 | "67": "diamondback, diamondback rattlesnake, Crotalus adamanteus",
70 | "68": "sidewinder, horned rattlesnake, Crotalus cerastes",
71 | "69": "trilobite",
72 | "70": "harvestman, daddy longlegs, Phalangium opilio",
73 | "71": "scorpion",
74 | "72": "black and gold garden spider, Argiope aurantia",
75 | "73": "barn spider, Araneus cavaticus",
76 | "74": "garden spider, Aranea diademata",
77 | "75": "black widow, Latrodectus mactans",
78 | "76": "tarantula",
79 | "77": "wolf spider, hunting spider",
80 | "78": "tick",
81 | "79": "centipede",
82 | "80": "black grouse",
83 | "81": "ptarmigan",
84 | "82": "ruffed grouse, partridge, Bonasa umbellus",
85 | "83": "prairie chicken, prairie grouse, prairie fowl",
86 | "84": "peacock",
87 | "85": "quail",
88 | "86": "partridge",
89 | "87": "African grey, African gray, Psittacus erithacus",
90 | "88": "macaw",
91 | "89": "sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita",
92 | "90": "lorikeet",
93 | "91": "coucal",
94 | "92": "bee eater",
95 | "93": "hornbill",
96 | "94": "hummingbird",
97 | "95": "jacamar",
98 | "96": "toucan",
99 | "97": "drake",
100 | "98": "red-breasted merganser, Mergus serrator",
101 | "99": "goose",
102 | "100": "black swan, Cygnus atratus",
103 | "101": "tusker",
104 | "102": "echidna, spiny anteater, anteater",
105 | "103": "platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus",
106 | "104": "wallaby, brush kangaroo",
107 | "105": "koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus",
108 | "106": "wombat",
109 | "107": "jellyfish",
110 | "108": "sea anemone, anemone",
111 | "109": "brain coral",
112 | "110": "flatworm, platyhelminth",
113 | "111": "nematode, nematode worm, roundworm",
114 | "112": "conch",
115 | "113": "snail",
116 | "114": "slug",
117 | "115": "sea slug, nudibranch",
118 | "116": "chiton, coat-of-mail shell, sea cradle, polyplacophore",
119 | "117": "chambered nautilus, pearly nautilus, nautilus",
120 | "118": "Dungeness crab, Cancer magister",
121 | "119": "rock crab, Cancer irroratus",
122 | "120": "fiddler crab",
123 | "121": "king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica",
124 | "122": "American lobster, Northern lobster, Maine lobster, Homarus americanus",
125 | "123": "spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish",
126 | "124": "crayfish, crawfish, crawdad, crawdaddy",
127 | "125": "hermit crab",
128 | "126": "isopod",
129 | "127": "white stork, Ciconia ciconia",
130 | "128": "black stork, Ciconia nigra",
131 | "129": "spoonbill",
132 | "130": "flamingo",
133 | "131": "little blue heron, Egretta caerulea",
134 | "132": "American egret, great white heron, Egretta albus",
135 | "133": "bittern",
136 | "134": "crane",
137 | "135": "limpkin, Aramus pictus",
138 | "136": "European gallinule, Porphyrio porphyrio",
139 | "137": "American coot, marsh hen, mud hen, water hen, Fulica americana",
140 | "138": "bustard",
141 | "139": "ruddy turnstone, Arenaria interpres",
142 | "140": "red-backed sandpiper, dunlin, Erolia alpina",
143 | "141": "redshank, Tringa totanus",
144 | "142": "dowitcher",
145 | "143": "oystercatcher, oyster catcher",
146 | "144": "pelican",
147 | "145": "king penguin, Aptenodytes patagonica",
148 | "146": "albatross, mollymawk",
149 | "147": "grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus",
150 | "148": "killer whale, killer, orca, grampus, sea wolf, Orcinus orca",
151 | "149": "dugong, Dugong dugon",
152 | "150": "sea lion",
153 | "151": "Chihuahua",
154 | "152": "Japanese spaniel",
155 | "153": "Maltese dog, Maltese terrier, Maltese",
156 | "154": "Pekinese, Pekingese, Peke",
157 | "155": "Shih-Tzu",
158 | "156": "Blenheim spaniel",
159 | "157": "papillon",
160 | "158": "toy terrier",
161 | "159": "Rhodesian ridgeback",
162 | "160": "Afghan hound, Afghan",
163 | "161": "basset, basset hound",
164 | "162": "beagle",
165 | "163": "bloodhound, sleuthhound",
166 | "164": "bluetick",
167 | "165": "black-and-tan coonhound",
168 | "166": "Walker hound, Walker foxhound",
169 | "167": "English foxhound",
170 | "168": "redbone",
171 | "169": "borzoi, Russian wolfhound",
172 | "170": "Irish wolfhound",
173 | "171": "Italian greyhound",
174 | "172": "whippet",
175 | "173": "Ibizan hound, Ibizan Podenco",
176 | "174": "Norwegian elkhound, elkhound",
177 | "175": "otterhound, otter hound",
178 | "176": "Saluki, gazelle hound",
179 | "177": "Scottish deerhound, deerhound",
180 | "178": "Weimaraner",
181 | "179": "Staffordshire bullterrier, Staffordshire bull terrier",
182 | "180": "American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier",
183 | "181": "Bedlington terrier",
184 | "182": "Border terrier",
185 | "183": "Kerry blue terrier",
186 | "184": "Irish terrier",
187 | "185": "Norfolk terrier",
188 | "186": "Norwich terrier",
189 | "187": "Yorkshire terrier",
190 | "188": "wire-haired fox terrier",
191 | "189": "Lakeland terrier",
192 | "190": "Sealyham terrier, Sealyham",
193 | "191": "Airedale, Airedale terrier",
194 | "192": "cairn, cairn terrier",
195 | "193": "Australian terrier",
196 | "194": "Dandie Dinmont, Dandie Dinmont terrier",
197 | "195": "Boston bull, Boston terrier",
198 | "196": "miniature schnauzer",
199 | "197": "giant schnauzer",
200 | "198": "standard schnauzer",
201 | "199": "Scotch terrier, Scottish terrier, Scottie",
202 | "200": "Tibetan terrier, chrysanthemum dog",
203 | "201": "silky terrier, Sydney silky",
204 | "202": "soft-coated wheaten terrier",
205 | "203": "West Highland white terrier",
206 | "204": "Lhasa, Lhasa apso",
207 | "205": "flat-coated retriever",
208 | "206": "curly-coated retriever",
209 | "207": "golden retriever",
210 | "208": "Labrador retriever",
211 | "209": "Chesapeake Bay retriever",
212 | "210": "German short-haired pointer",
213 | "211": "vizsla, Hungarian pointer",
214 | "212": "English setter",
215 | "213": "Irish setter, red setter",
216 | "214": "Gordon setter",
217 | "215": "Brittany spaniel",
218 | "216": "clumber, clumber spaniel",
219 | "217": "English springer, English springer spaniel",
220 | "218": "Welsh springer spaniel",
221 | "219": "cocker spaniel, English cocker spaniel, cocker",
222 | "220": "Sussex spaniel",
223 | "221": "Irish water spaniel",
224 | "222": "kuvasz",
225 | "223": "schipperke",
226 | "224": "groenendael",
227 | "225": "malinois",
228 | "226": "briard",
229 | "227": "kelpie",
230 | "228": "komondor",
231 | "229": "Old English sheepdog, bobtail",
232 | "230": "Shetland sheepdog, Shetland sheep dog, Shetland",
233 | "231": "collie",
234 | "232": "Border collie",
235 | "233": "Bouvier des Flandres, Bouviers des Flandres",
236 | "234": "Rottweiler",
237 | "235": "German shepherd, German shepherd dog, German police dog, alsatian",
238 | "236": "Doberman, Doberman pinscher",
239 | "237": "miniature pinscher",
240 | "238": "Greater Swiss Mountain dog",
241 | "239": "Bernese mountain dog",
242 | "240": "Appenzeller",
243 | "241": "EntleBucher",
244 | "242": "boxer",
245 | "243": "bull mastiff",
246 | "244": "Tibetan mastiff",
247 | "245": "French bulldog",
248 | "246": "Great Dane",
249 | "247": "Saint Bernard, St Bernard",
250 | "248": "Eskimo dog, husky",
251 | "249": "malamute, malemute, Alaskan malamute",
252 | "250": "Siberian husky",
253 | "251": "dalmatian, coach dog, carriage dog",
254 | "252": "affenpinscher, monkey pinscher, monkey dog",
255 | "253": "basenji",
256 | "254": "pug, pug-dog",
257 | "255": "Leonberg",
258 | "256": "Newfoundland, Newfoundland dog",
259 | "257": "Great Pyrenees",
260 | "258": "Samoyed, Samoyede",
261 | "259": "Pomeranian",
262 | "260": "chow, chow chow",
263 | "261": "keeshond",
264 | "262": "Brabancon griffon",
265 | "263": "Pembroke, Pembroke Welsh corgi",
266 | "264": "Cardigan, Cardigan Welsh corgi",
267 | "265": "toy poodle",
268 | "266": "miniature poodle",
269 | "267": "standard poodle",
270 | "268": "Mexican hairless",
271 | "269": "timber wolf, grey wolf, gray wolf, Canis lupus",
272 | "270": "white wolf, Arctic wolf, Canis lupus tundrarum",
273 | "271": "red wolf, maned wolf, Canis rufus, Canis niger",
274 | "272": "coyote, prairie wolf, brush wolf, Canis latrans",
275 | "273": "dingo, warrigal, warragal, Canis dingo",
276 | "274": "dhole, Cuon alpinus",
277 | "275": "African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus",
278 | "276": "hyena, hyaena",
279 | "277": "red fox, Vulpes vulpes",
280 | "278": "kit fox, Vulpes macrotis",
281 | "279": "Arctic fox, white fox, Alopex lagopus",
282 | "280": "grey fox, gray fox, Urocyon cinereoargenteus",
283 | "281": "tabby, tabby cat",
284 | "282": "tiger cat",
285 | "283": "Persian cat",
286 | "284": "Siamese cat, Siamese",
287 | "285": "Egyptian cat",
288 | "286": "cougar, puma, catamount, mountain lion, painter, panther, Felis concolor",
289 | "287": "lynx, catamount",
290 | "288": "leopard, Panthera pardus",
291 | "289": "snow leopard, ounce, Panthera uncia",
292 | "290": "jaguar, panther, Panthera onca, Felis onca",
293 | "291": "lion, king of beasts, Panthera leo",
294 | "292": "tiger, Panthera tigris",
295 | "293": "cheetah, chetah, Acinonyx jubatus",
296 | "294": "brown bear, bruin, Ursus arctos",
297 | "295": "American black bear, black bear, Ursus americanus, Euarctos americanus",
298 | "296": "ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus",
299 | "297": "sloth bear, Melursus ursinus, Ursus ursinus",
300 | "298": "mongoose",
301 | "299": "meerkat, mierkat",
302 | "300": "tiger beetle",
303 | "301": "ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle",
304 | "302": "ground beetle, carabid beetle",
305 | "303": "long-horned beetle, longicorn, longicorn beetle",
306 | "304": "leaf beetle, chrysomelid",
307 | "305": "dung beetle",
308 | "306": "rhinoceros beetle",
309 | "307": "weevil",
310 | "308": "fly",
311 | "309": "bee",
312 | "310": "ant, emmet, pismire",
313 | "311": "grasshopper, hopper",
314 | "312": "cricket",
315 | "313": "walking stick, walkingstick, stick insect",
316 | "314": "cockroach, roach",
317 | "315": "mantis, mantid",
318 | "316": "cicada, cicala",
319 | "317": "leafhopper",
320 | "318": "lacewing, lacewing fly",
321 | "319": "dragonfly, darning needle, devil's darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk",
322 | "320": "damselfly",
323 | "321": "admiral",
324 | "322": "ringlet, ringlet butterfly",
325 | "323": "monarch, monarch butterfly, milkweed butterfly, Danaus plexippus",
326 | "324": "cabbage butterfly",
327 | "325": "sulphur butterfly, sulfur butterfly",
328 | "326": "lycaenid, lycaenid butterfly",
329 | "327": "starfish, sea star",
330 | "328": "sea urchin",
331 | "329": "sea cucumber, holothurian",
332 | "330": "wood rabbit, cottontail, cottontail rabbit",
333 | "331": "hare",
334 | "332": "Angora, Angora rabbit",
335 | "333": "hamster",
336 | "334": "porcupine, hedgehog",
337 | "335": "fox squirrel, eastern fox squirrel, Sciurus niger",
338 | "336": "marmot",
339 | "337": "beaver",
340 | "338": "guinea pig, Cavia cobaya",
341 | "339": "sorrel",
342 | "340": "zebra",
343 | "341": "hog, pig, grunter, squealer, Sus scrofa",
344 | "342": "wild boar, boar, Sus scrofa",
345 | "343": "warthog",
346 | "344": "hippopotamus, hippo, river horse, Hippopotamus amphibius",
347 | "345": "ox",
348 | "346": "water buffalo, water ox, Asiatic buffalo, Bubalus bubalis",
349 | "347": "bison",
350 | "348": "ram, tup",
351 | "349": "bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis",
352 | "350": "ibex, Capra ibex",
353 | "351": "hartebeest",
354 | "352": "impala, Aepyceros melampus",
355 | "353": "gazelle",
356 | "354": "Arabian camel, dromedary, Camelus dromedarius",
357 | "355": "llama",
358 | "356": "weasel",
359 | "357": "mink",
360 | "358": "polecat, fitch, foulmart, foumart, Mustela putorius",
361 | "359": "black-footed ferret, ferret, Mustela nigripes",
362 | "360": "otter",
363 | "361": "skunk, polecat, wood pussy",
364 | "362": "badger",
365 | "363": "armadillo",
366 | "364": "three-toed sloth, ai, Bradypus tridactylus",
367 | "365": "orangutan, orang, orangutang, Pongo pygmaeus",
368 | "366": "gorilla, Gorilla gorilla",
369 | "367": "chimpanzee, chimp, Pan troglodytes",
370 | "368": "gibbon, Hylobates lar",
371 | "369": "siamang, Hylobates syndactylus, Symphalangus syndactylus",
372 | "370": "guenon, guenon monkey",
373 | "371": "patas, hussar monkey, Erythrocebus patas",
374 | "372": "baboon",
375 | "373": "macaque",
376 | "374": "langur",
377 | "375": "colobus, colobus monkey",
378 | "376": "proboscis monkey, Nasalis larvatus",
379 | "377": "marmoset",
380 | "378": "capuchin, ringtail, Cebus capucinus",
381 | "379": "howler monkey, howler",
382 | "380": "titi, titi monkey",
383 | "381": "spider monkey, Ateles geoffroyi",
384 | "382": "squirrel monkey, Saimiri sciureus",
385 | "383": "Madagascar cat, ring-tailed lemur, Lemur catta",
386 | "384": "indri, indris, Indri indri, Indri brevicaudatus",
387 | "385": "Indian elephant, Elephas maximus",
388 | "386": "African elephant, Loxodonta africana",
389 | "387": "lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens",
390 | "388": "giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca",
391 | "389": "barracouta, snoek",
392 | "390": "eel",
393 | "391": "coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch",
394 | "392": "rock beauty, Holocanthus tricolor",
395 | "393": "anemone fish",
396 | "394": "sturgeon",
397 | "395": "gar, garfish, garpike, billfish, Lepisosteus osseus",
398 | "396": "lionfish",
399 | "397": "puffer, pufferfish, blowfish, globefish",
400 | "398": "abacus",
401 | "399": "abaya",
402 | "400": "academic gown, academic robe, judge's robe",
403 | "401": "accordion, piano accordion, squeeze box",
404 | "402": "acoustic guitar",
405 | "403": "aircraft carrier, carrier, flattop, attack aircraft carrier",
406 | "404": "airliner",
407 | "405": "airship, dirigible",
408 | "406": "altar",
409 | "407": "ambulance",
410 | "408": "amphibian, amphibious vehicle",
411 | "409": "analog clock",
412 | "410": "apiary, bee house",
413 | "411": "apron",
414 | "412": "ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin",
415 | "413": "assault rifle, assault gun",
416 | "414": "backpack, back pack, knapsack, packsack, rucksack, haversack",
417 | "415": "bakery, bakeshop, bakehouse",
418 | "416": "balance beam, beam",
419 | "417": "balloon",
420 | "418": "ballpoint, ballpoint pen, ballpen, Biro",
421 | "419": "Band Aid",
422 | "420": "banjo",
423 | "421": "bannister, banister, balustrade, balusters, handrail",
424 | "422": "barbell",
425 | "423": "barber chair",
426 | "424": "barbershop",
427 | "425": "barn",
428 | "426": "barometer",
429 | "427": "barrel, cask",
430 | "428": "barrow, garden cart, lawn cart, wheelbarrow",
431 | "429": "baseball",
432 | "430": "basketball",
433 | "431": "bassinet",
434 | "432": "bassoon",
435 | "433": "bathing cap, swimming cap",
436 | "434": "bath towel",
437 | "435": "bathtub, bathing tub, bath, tub",
438 | "436": "beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon",
439 | "437": "beacon, lighthouse, beacon light, pharos",
440 | "438": "beaker",
441 | "439": "bearskin, busby, shako",
442 | "440": "beer bottle",
443 | "441": "beer glass",
444 | "442": "bell cote, bell cot",
445 | "443": "bib",
446 | "444": "bicycle-built-for-two, tandem bicycle, tandem",
447 | "445": "bikini, two-piece",
448 | "446": "binder, ring-binder",
449 | "447": "binoculars, field glasses, opera glasses",
450 | "448": "birdhouse",
451 | "449": "boathouse",
452 | "450": "bobsled, bobsleigh, bob",
453 | "451": "bolo tie, bolo, bola tie, bola",
454 | "452": "bonnet, poke bonnet",
455 | "453": "bookcase",
456 | "454": "bookshop, bookstore, bookstall",
457 | "455": "bottlecap",
458 | "456": "bow",
459 | "457": "bow tie, bow-tie, bowtie",
460 | "458": "brass, memorial tablet, plaque",
461 | "459": "brassiere, bra, bandeau",
462 | "460": "breakwater, groin, groyne, mole, bulwark, seawall, jetty",
463 | "461": "breastplate, aegis, egis",
464 | "462": "broom",
465 | "463": "bucket, pail",
466 | "464": "buckle",
467 | "465": "bulletproof vest",
468 | "466": "bullet train, bullet",
469 | "467": "butcher shop, meat market",
470 | "468": "cab, hack, taxi, taxicab",
471 | "469": "caldron, cauldron",
472 | "470": "candle, taper, wax light",
473 | "471": "cannon",
474 | "472": "canoe",
475 | "473": "can opener, tin opener",
476 | "474": "cardigan",
477 | "475": "car mirror",
478 | "476": "carousel, carrousel, merry-go-round, roundabout, whirligig",
479 | "477": "carpenter's kit, tool kit",
480 | "478": "carton",
481 | "479": "car wheel",
482 | "480": "cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM",
483 | "481": "cassette",
484 | "482": "cassette player",
485 | "483": "castle",
486 | "484": "catamaran",
487 | "485": "CD player",
488 | "486": "cello, violoncello",
489 | "487": "cellular telephone, cellular phone, cellphone, cell, mobile phone",
490 | "488": "chain",
491 | "489": "chainlink fence",
492 | "490": "chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour",
493 | "491": "chain saw, chainsaw",
494 | "492": "chest",
495 | "493": "chiffonier, commode",
496 | "494": "chime, bell, gong",
497 | "495": "china cabinet, china closet",
498 | "496": "Christmas stocking",
499 | "497": "church, church building",
500 | "498": "cinema, movie theater, movie theatre, movie house, picture palace",
501 | "499": "cleaver, meat cleaver, chopper",
502 | "500": "cliff dwelling",
503 | "501": "cloak",
504 | "502": "clog, geta, patten, sabot",
505 | "503": "cocktail shaker",
506 | "504": "coffee mug",
507 | "505": "coffeepot",
508 | "506": "coil, spiral, volute, whorl, helix",
509 | "507": "combination lock",
510 | "508": "computer keyboard, keypad",
511 | "509": "confectionery, confectionary, candy store",
512 | "510": "container ship, containership, container vessel",
513 | "511": "convertible",
514 | "512": "corkscrew, bottle screw",
515 | "513": "cornet, horn, trumpet, trump",
516 | "514": "cowboy boot",
517 | "515": "cowboy hat, ten-gallon hat",
518 | "516": "cradle",
519 | "517": "crane",
520 | "518": "crash helmet",
521 | "519": "crate",
522 | "520": "crib, cot",
523 | "521": "Crock Pot",
524 | "522": "croquet ball",
525 | "523": "crutch",
526 | "524": "cuirass",
527 | "525": "dam, dike, dyke",
528 | "526": "desk",
529 | "527": "desktop computer",
530 | "528": "dial telephone, dial phone",
531 | "529": "diaper, nappy, napkin",
532 | "530": "digital clock",
533 | "531": "digital watch",
534 | "532": "dining table, board",
535 | "533": "dishrag, dishcloth",
536 | "534": "dishwasher, dish washer, dishwashing machine",
537 | "535": "disk brake, disc brake",
538 | "536": "dock, dockage, docking facility",
539 | "537": "dogsled, dog sled, dog sleigh",
540 | "538": "dome",
541 | "539": "doormat, welcome mat",
542 | "540": "drilling platform, offshore rig",
543 | "541": "drum, membranophone, tympan",
544 | "542": "drumstick",
545 | "543": "dumbbell",
546 | "544": "Dutch oven",
547 | "545": "electric fan, blower",
548 | "546": "electric guitar",
549 | "547": "electric locomotive",
550 | "548": "entertainment center",
551 | "549": "envelope",
552 | "550": "espresso maker",
553 | "551": "face powder",
554 | "552": "feather boa, boa",
555 | "553": "file, file cabinet, filing cabinet",
556 | "554": "fireboat",
557 | "555": "fire engine, fire truck",
558 | "556": "fire screen, fireguard",
559 | "557": "flagpole, flagstaff",
560 | "558": "flute, transverse flute",
561 | "559": "folding chair",
562 | "560": "football helmet",
563 | "561": "forklift",
564 | "562": "fountain",
565 | "563": "fountain pen",
566 | "564": "four-poster",
567 | "565": "freight car",
568 | "566": "French horn, horn",
569 | "567": "frying pan, frypan, skillet",
570 | "568": "fur coat",
571 | "569": "garbage truck, dustcart",
572 | "570": "gasmask, respirator, gas helmet",
573 | "571": "gas pump, gasoline pump, petrol pump, island dispenser",
574 | "572": "goblet",
575 | "573": "go-kart",
576 | "574": "golf ball",
577 | "575": "golfcart, golf cart",
578 | "576": "gondola",
579 | "577": "gong, tam-tam",
580 | "578": "gown",
581 | "579": "grand piano, grand",
582 | "580": "greenhouse, nursery, glasshouse",
583 | "581": "grille, radiator grille",
584 | "582": "grocery store, grocery, food market, market",
585 | "583": "guillotine",
586 | "584": "hair slide",
587 | "585": "hair spray",
588 | "586": "half track",
589 | "587": "hammer",
590 | "588": "hamper",
591 | "589": "hand blower, blow dryer, blow drier, hair dryer, hair drier",
592 | "590": "hand-held computer, hand-held microcomputer",
593 | "591": "handkerchief, hankie, hanky, hankey",
594 | "592": "hard disc, hard disk, fixed disk",
595 | "593": "harmonica, mouth organ, harp, mouth harp",
596 | "594": "harp",
597 | "595": "harvester, reaper",
598 | "596": "hatchet",
599 | "597": "holster",
600 | "598": "home theater, home theatre",
601 | "599": "honeycomb",
602 | "600": "hook, claw",
603 | "601": "hoopskirt, crinoline",
604 | "602": "horizontal bar, high bar",
605 | "603": "horse cart, horse-cart",
606 | "604": "hourglass",
607 | "605": "iPod",
608 | "606": "iron, smoothing iron",
609 | "607": "jack-o'-lantern",
610 | "608": "jean, blue jean, denim",
611 | "609": "jeep, landrover",
612 | "610": "jersey, T-shirt, tee shirt",
613 | "611": "jigsaw puzzle",
614 | "612": "jinrikisha, ricksha, rickshaw",
615 | "613": "joystick",
616 | "614": "kimono",
617 | "615": "knee pad",
618 | "616": "knot",
619 | "617": "lab coat, laboratory coat",
620 | "618": "ladle",
621 | "619": "lampshade, lamp shade",
622 | "620": "laptop, laptop computer",
623 | "621": "lawn mower, mower",
624 | "622": "lens cap, lens cover",
625 | "623": "letter opener, paper knife, paperknife",
626 | "624": "library",
627 | "625": "lifeboat",
628 | "626": "lighter, light, igniter, ignitor",
629 | "627": "limousine, limo",
630 | "628": "liner, ocean liner",
631 | "629": "lipstick, lip rouge",
632 | "630": "Loafer",
633 | "631": "lotion",
634 | "632": "loudspeaker, speaker, speaker unit, loudspeaker system, speaker system",
635 | "633": "loupe, jeweler's loupe",
636 | "634": "lumbermill, sawmill",
637 | "635": "magnetic compass",
638 | "636": "mailbag, postbag",
639 | "637": "mailbox, letter box",
640 | "638": "maillot",
641 | "639": "maillot, tank suit",
642 | "640": "manhole cover",
643 | "641": "maraca",
644 | "642": "marimba, xylophone",
645 | "643": "mask",
646 | "644": "matchstick",
647 | "645": "maypole",
648 | "646": "maze, labyrinth",
649 | "647": "measuring cup",
650 | "648": "medicine chest, medicine cabinet",
651 | "649": "megalith, megalithic structure",
652 | "650": "microphone, mike",
653 | "651": "microwave, microwave oven",
654 | "652": "military uniform",
655 | "653": "milk can",
656 | "654": "minibus",
657 | "655": "miniskirt, mini",
658 | "656": "minivan",
659 | "657": "missile",
660 | "658": "mitten",
661 | "659": "mixing bowl",
662 | "660": "mobile home, manufactured home",
663 | "661": "Model T",
664 | "662": "modem",
665 | "663": "monastery",
666 | "664": "monitor",
667 | "665": "moped",
668 | "666": "mortar",
669 | "667": "mortarboard",
670 | "668": "mosque",
671 | "669": "mosquito net",
672 | "670": "motor scooter, scooter",
673 | "671": "mountain bike, all-terrain bike, off-roader",
674 | "672": "mountain tent",
675 | "673": "mouse, computer mouse",
676 | "674": "mousetrap",
677 | "675": "moving van",
678 | "676": "muzzle",
679 | "677": "nail",
680 | "678": "neck brace",
681 | "679": "necklace",
682 | "680": "nipple",
683 | "681": "notebook, notebook computer",
684 | "682": "obelisk",
685 | "683": "oboe, hautboy, hautbois",
686 | "684": "ocarina, sweet potato",
687 | "685": "odometer, hodometer, mileometer, milometer",
688 | "686": "oil filter",
689 | "687": "organ, pipe organ",
690 | "688": "oscilloscope, scope, cathode-ray oscilloscope, CRO",
691 | "689": "overskirt",
692 | "690": "oxcart",
693 | "691": "oxygen mask",
694 | "692": "packet",
695 | "693": "paddle, boat paddle",
696 | "694": "paddlewheel, paddle wheel",
697 | "695": "padlock",
698 | "696": "paintbrush",
699 | "697": "pajama, pyjama, pj's, jammies",
700 | "698": "palace",
701 | "699": "panpipe, pandean pipe, syrinx",
702 | "700": "paper towel",
703 | "701": "parachute, chute",
704 | "702": "parallel bars, bars",
705 | "703": "park bench",
706 | "704": "parking meter",
707 | "705": "passenger car, coach, carriage",
708 | "706": "patio, terrace",
709 | "707": "pay-phone, pay-station",
710 | "708": "pedestal, plinth, footstall",
711 | "709": "pencil box, pencil case",
712 | "710": "pencil sharpener",
713 | "711": "perfume, essence",
714 | "712": "Petri dish",
715 | "713": "photocopier",
716 | "714": "pick, plectrum, plectron",
717 | "715": "pickelhaube",
718 | "716": "picket fence, paling",
719 | "717": "pickup, pickup truck",
720 | "718": "pier",
721 | "719": "piggy bank, penny bank",
722 | "720": "pill bottle",
723 | "721": "pillow",
724 | "722": "ping-pong ball",
725 | "723": "pinwheel",
726 | "724": "pirate, pirate ship",
727 | "725": "pitcher, ewer",
728 | "726": "plane, carpenter's plane, woodworking plane",
729 | "727": "planetarium",
730 | "728": "plastic bag",
731 | "729": "plate rack",
732 | "730": "plow, plough",
733 | "731": "plunger, plumber's helper",
734 | "732": "Polaroid camera, Polaroid Land camera",
735 | "733": "pole",
736 | "734": "police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria",
737 | "735": "poncho",
738 | "736": "pool table, billiard table, snooker table",
739 | "737": "pop bottle, soda bottle",
740 | "738": "pot, flowerpot",
741 | "739": "potter's wheel",
742 | "740": "power drill",
743 | "741": "prayer rug, prayer mat",
744 | "742": "printer",
745 | "743": "prison, prison house",
746 | "744": "projectile, missile",
747 | "745": "projector",
748 | "746": "puck, hockey puck",
749 | "747": "punching bag, punch bag, punching ball, punchball",
750 | "748": "purse",
751 | "749": "quill, quill pen",
752 | "750": "quilt, comforter, comfort, puff",
753 | "751": "racer, race car, racing car",
754 | "752": "racket, racquet",
755 | "753": "radiator",
756 | "754": "radio, wireless",
757 | "755": "radio telescope, radio reflector",
758 | "756": "rain barrel",
759 | "757": "recreational vehicle, RV, R.V.",
760 | "758": "reel",
761 | "759": "reflex camera",
762 | "760": "refrigerator, icebox",
763 | "761": "remote control, remote",
764 | "762": "restaurant, eating house, eating place, eatery",
765 | "763": "revolver, six-gun, six-shooter",
766 | "764": "rifle",
767 | "765": "rocking chair, rocker",
768 | "766": "rotisserie",
769 | "767": "rubber eraser, rubber, pencil eraser",
770 | "768": "rugby ball",
771 | "769": "rule, ruler",
772 | "770": "running shoe",
773 | "771": "safe",
774 | "772": "safety pin",
775 | "773": "saltshaker, salt shaker",
776 | "774": "sandal",
777 | "775": "sarong",
778 | "776": "sax, saxophone",
779 | "777": "scabbard",
780 | "778": "scale, weighing machine",
781 | "779": "school bus",
782 | "780": "schooner",
783 | "781": "scoreboard",
784 | "782": "screen, CRT screen",
785 | "783": "screw",
786 | "784": "screwdriver",
787 | "785": "seat belt, seatbelt",
788 | "786": "sewing machine",
789 | "787": "shield, buckler",
790 | "788": "shoe shop, shoe-shop, shoe store",
791 | "789": "shoji",
792 | "790": "shopping basket",
793 | "791": "shopping cart",
794 | "792": "shovel",
795 | "793": "shower cap",
796 | "794": "shower curtain",
797 | "795": "ski",
798 | "796": "ski mask",
799 | "797": "sleeping bag",
800 | "798": "slide rule, slipstick",
801 | "799": "sliding door",
802 | "800": "slot, one-armed bandit",
803 | "801": "snorkel",
804 | "802": "snowmobile",
805 | "803": "snowplow, snowplough",
806 | "804": "soap dispenser",
807 | "805": "soccer ball",
808 | "806": "sock",
809 | "807": "solar dish, solar collector, solar furnace",
810 | "808": "sombrero",
811 | "809": "soup bowl",
812 | "810": "space bar",
813 | "811": "space heater",
814 | "812": "space shuttle",
815 | "813": "spatula",
816 | "814": "speedboat",
817 | "815": "spider web, spider's web",
818 | "816": "spindle",
819 | "817": "sports car, sport car",
820 | "818": "spotlight, spot",
821 | "819": "stage",
822 | "820": "steam locomotive",
823 | "821": "steel arch bridge",
824 | "822": "steel drum",
825 | "823": "stethoscope",
826 | "824": "stole",
827 | "825": "stone wall",
828 | "826": "stopwatch, stop watch",
829 | "827": "stove",
830 | "828": "strainer",
831 | "829": "streetcar, tram, tramcar, trolley, trolley car",
832 | "830": "stretcher",
833 | "831": "studio couch, day bed",
834 | "832": "stupa, tope",
835 | "833": "submarine, pigboat, sub, U-boat",
836 | "834": "suit, suit of clothes",
837 | "835": "sundial",
838 | "836": "sunglass",
839 | "837": "sunglasses, dark glasses, shades",
840 | "838": "sunscreen, sunblock, sun blocker",
841 | "839": "suspension bridge",
842 | "840": "swab, swob, mop",
843 | "841": "sweatshirt",
844 | "842": "swimming trunks, bathing trunks",
845 | "843": "swing",
846 | "844": "switch, electric switch, electrical switch",
847 | "845": "syringe",
848 | "846": "table lamp",
849 | "847": "tank, army tank, armored combat vehicle, armoured combat vehicle",
850 | "848": "tape player",
851 | "849": "teapot",
852 | "850": "teddy, teddy bear",
853 | "851": "television, television system",
854 | "852": "tennis ball",
855 | "853": "thatch, thatched roof",
856 | "854": "theater curtain, theatre curtain",
857 | "855": "thimble",
858 | "856": "thresher, thrasher, threshing machine",
859 | "857": "throne",
860 | "858": "tile roof",
861 | "859": "toaster",
862 | "860": "tobacco shop, tobacconist shop, tobacconist",
863 | "861": "toilet seat",
864 | "862": "torch",
865 | "863": "totem pole",
866 | "864": "tow truck, tow car, wrecker",
867 | "865": "toyshop",
868 | "866": "tractor",
869 | "867": "trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi",
870 | "868": "tray",
871 | "869": "trench coat",
872 | "870": "tricycle, trike, velocipede",
873 | "871": "trimaran",
874 | "872": "tripod",
875 | "873": "triumphal arch",
876 | "874": "trolleybus, trolley coach, trackless trolley",
877 | "875": "trombone",
878 | "876": "tub, vat",
879 | "877": "turnstile",
880 | "878": "typewriter keyboard",
881 | "879": "umbrella",
882 | "880": "unicycle, monocycle",
883 | "881": "upright, upright piano",
884 | "882": "vacuum, vacuum cleaner",
885 | "883": "vase",
886 | "884": "vault",
887 | "885": "velvet",
888 | "886": "vending machine",
889 | "887": "vestment",
890 | "888": "viaduct",
891 | "889": "violin, fiddle",
892 | "890": "volleyball",
893 | "891": "waffle iron",
894 | "892": "wall clock",
895 | "893": "wallet, billfold, notecase, pocketbook",
896 | "894": "wardrobe, closet, press",
897 | "895": "warplane, military plane",
898 | "896": "washbasin, handbasin, washbowl, lavabo, wash-hand basin",
899 | "897": "washer, automatic washer, washing machine",
900 | "898": "water bottle",
901 | "899": "water jug",
902 | "900": "water tower",
903 | "901": "whiskey jug",
904 | "902": "whistle",
905 | "903": "wig",
906 | "904": "window screen",
907 | "905": "window shade",
908 | "906": "Windsor tie",
909 | "907": "wine bottle",
910 | "908": "wing",
911 | "909": "wok",
912 | "910": "wooden spoon",
913 | "911": "wool, woolen, woollen",
914 | "912": "worm fence, snake fence, snake-rail fence, Virginia fence",
915 | "913": "wreck",
916 | "914": "yawl",
917 | "915": "yurt",
918 | "916": "web site, website, internet site, site",
919 | "917": "comic book",
920 | "918": "crossword puzzle, crossword",
921 | "919": "street sign",
922 | "920": "traffic light, traffic signal, stoplight",
923 | "921": "book jacket, dust cover, dust jacket, dust wrapper",
924 | "922": "menu",
925 | "923": "plate",
926 | "924": "guacamole",
927 | "925": "consomme",
928 | "926": "hot pot, hotpot",
929 | "927": "trifle",
930 | "928": "ice cream, icecream",
931 | "929": "ice lolly, lolly, lollipop, popsicle",
932 | "930": "French loaf",
933 | "931": "bagel, beigel",
934 | "932": "pretzel",
935 | "933": "cheeseburger",
936 | "934": "hotdog, hot dog, red hot",
937 | "935": "mashed potato",
938 | "936": "head cabbage",
939 | "937": "broccoli",
940 | "938": "cauliflower",
941 | "939": "zucchini, courgette",
942 | "940": "spaghetti squash",
943 | "941": "acorn squash",
944 | "942": "butternut squash",
945 | "943": "cucumber, cuke",
946 | "944": "artichoke, globe artichoke",
947 | "945": "bell pepper",
948 | "946": "cardoon",
949 | "947": "mushroom",
950 | "948": "Granny Smith",
951 | "949": "strawberry",
952 | "950": "orange",
953 | "951": "lemon",
954 | "952": "fig",
955 | "953": "pineapple, ananas",
956 | "954": "banana",
957 | "955": "jackfruit, jak, jack",
958 | "956": "custard apple",
959 | "957": "pomegranate",
960 | "958": "hay",
961 | "959": "carbonara",
962 | "960": "chocolate sauce, chocolate syrup",
963 | "961": "dough",
964 | "962": "meat loaf, meatloaf",
965 | "963": "pizza, pizza pie",
966 | "964": "potpie",
967 | "965": "burrito",
968 | "966": "red wine",
969 | "967": "espresso",
970 | "968": "cup",
971 | "969": "eggnog",
972 | "970": "alp",
973 | "971": "bubble",
974 | "972": "cliff, drop, drop-off",
975 | "973": "coral reef",
976 | "974": "geyser",
977 | "975": "lakeside, lakeshore",
978 | "976": "promontory, headland, head, foreland",
979 | "977": "sandbar, sand bar",
980 | "978": "seashore, coast, seacoast, sea-coast",
981 | "979": "valley, vale",
982 | "980": "volcano",
983 | "981": "ballplayer, baseball player",
984 | "982": "groom, bridegroom",
985 | "983": "scuba diver",
986 | "984": "rapeseed",
987 | "985": "daisy",
988 | "986": "yellow lady's slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum",
989 | "987": "corn",
990 | "988": "acorn",
991 | "989": "hip, rose hip, rosehip",
992 | "990": "buckeye, horse chestnut, conker",
993 | "991": "coral fungus",
994 | "992": "agaric",
995 | "993": "gyromitra",
996 | "994": "stinkhorn, carrion fungus",
997 | "995": "earthstar",
998 | "996": "hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa",
999 | "997": "bolete",
1000 | "998": "ear, spike, capitulum",
1001 | "999": "toilet tissue, toilet paper, bathroom tissue"
1002 | }
--------------------------------------------------------------------------------