diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..2fcf1c6d00 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..bbcbbe7d61 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/CHANGELOG.md b/CHANGELOG.md index c3416d88cc..610b0bf22f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,26 @@ +# [2.1.0](https://github.com/Microsoft/VoTT/compare/v2.0.0...v2.1.0) (04-29-2019) +[GitHub Release](https://github.com/Microsoft/VoTT/releases/tag/v2.1.0) + +- fix: Updates backwards compat & fixes cntk export image bug (#789) +- fix: Updates export options for pascalVOC rename (#788) +- fix: change method for alloc string to buffer (#777) +- feat: Add CSV Exporter (#757) +- fix: Fix display of tag color picker (#782) +- feat: Active Learning Updates (#778) +- doc: updates to readme and changelog (#781) +- doc: Adds CODE_OF_CONDUCT.md (#779) +- doc: Add bug & feature templates (#780) +- fix: Refactored project tag/delete updates (#764) +- fix: Enables selection of azure region for custom vision export (#765) +- feat: CNTK Export Provider (#771) +- feat: Save partial project progress during project creation (#769) +- fix: Fixes ymax and rename Tensorflow nama everywhere (#763) + # [2.0.0](https://github.com/Microsoft/VoTT/compare/v2.0.0-preview.3...v2.0.0) (04-12-2019) -[GitHub Release](https://github.com/Microsoft/VoTT/releases/tag/2.0.0) +[GitHub Release](https://github.com/Microsoft/VoTT/releases/tag/v2.0.0) - doc: update v1/master reference (#748) - ci: update pipeline for v2 flipover to master (#747) @@ -36,7 +54,7 @@ - ci: update pipelines to work for all branches with prefix dev (#700) # [2.0.0-preview.3](https://github.com/Microsoft/VoTT/compare/v2.0.0-preview.2...v2.0.0-preview.3) (03-20-2019) -[GitHub Release](https://github.com/Microsoft/VoTT/releases/tag/2.0.0-preview.3) +[GitHub Release](https://github.com/Microsoft/VoTT/releases/tag/v2.0.0-preview.3) - ci: Clean up sonar cloud issues - Remove height from root style (#694) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..c2ffc8ea13 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at opensource@microsoft.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/README.md b/README.md index 0973011ba9..6f071fe6fb 100644 --- a/README.md +++ b/README.md @@ -28,34 +28,37 @@ VoTT helps facilitate an end-to-end machine learning pipeline: -* [Getting Started](#getting-started) - * [Download and install a release package for your platform (recommended)](#download-and-install-a-release-package-for-your-platform-recommended) - * [Build and run from source](#build-and-run-from-source) -* [V1 & V2](#v1--v2) - * [Where is V1](#where-is-v1) - * [V1 releases](#v1-releases) - * [Can I use my V1 project in V2](#can-i-use-my-v1-project-in-v2) -* [Using VoTT](#using-vott) - * [Creating Connections](#creating-connections) - * [Creating a New Project](#creating-a-new-project) - * [Project Settings](#project-settings) - * [Security Tokens](#security-tokens) - * [Labeling an Image](#labeling-an-image) - * [Labeling a Video](#labeling-a-video) - * [Exporting Labels](#exporting-labels) - * [Keyboard Shortcuts](#keyboard-shortcuts) - * [Tag Shortcuts](#tag-shortcuts) - * [Tag Ordering](#tag-ordering) - * [Tag Locking](#tag-locking) - * [Editor Shortcuts](#editor-shortcuts) -* [Collaborators](#collaborators) -* [Contributing to VoTT](#contributing-to-vott) +- [VoTT (Visual Object Tagging Tool)](#vott-visual-object-tagging-tool) + - [Table of Contents](#table-of-contents) + - [Getting Started](#getting-started) + - [Download and install a release package for your platform (recommended)](#download-and-install-a-release-package-for-your-platform-recommended) + - [Build and run from source](#build-and-run-from-source) + - [Run as Web Application](#run-as-web-application) + - [V1 & V2](#v1--v2) + - [Where is V1](#where-is-v1) + - [V1 releases](#v1-releases) + - [V1 projects in V2](#v1-projects-in-v2) + - [Using VoTT](#using-vott) + - [Creating Connections](#creating-connections) + - [Creating a New Project](#creating-a-new-project) + - [Project Settings](#project-settings) + - [Security Tokens](#security-tokens) + - [Labeling an Image](#labeling-an-image) + - [Labeling a Video](#labeling-a-video) + - [Exporting Labels](#exporting-labels) + - [Keyboard Shortcuts](#keyboard-shortcuts) + - [Tag Ordering](#tag-ordering) + - [Tag Locking](#tag-locking) + - [Editor Shortcuts](#editor-shortcuts) + - [Mouse Controls](#mouse-controls) + - [Collaborators](#collaborators) + - [Contributing to VoTT](#contributing-to-vott) ## Getting Started -VoTT can be installed as a native application or run from source. +VoTT can be installed as a native application or run from source. VoTT is also available as a [stand-alone Web application](https://vott.z5.web.core.windows.net) and can be used in any modern Web browser. ### Download and install a release package for your platform (recommended) @@ -71,11 +74,16 @@ VoTT requires [NodeJS (>= 10.x, Dubnium) and NPM](https://github.com/nodejs/Rele npm ci npm start ``` - > **IMPORTANT** > > When running locally with `npm`, both the electron and the browser versions of the application will start. One major difference is that the electron version can access the local file system. +### Run as Web Application + +Using a modern Web browser, VoTT can be loaded from: [https://vott.z5.web.core.windows.net](https://vott.z5.web.core.windows.net) + +As noted above, the Web version of VoTT *cannot* access the local file system; all assets must be imported/exported through a Cloud project. + ## V1 & V2 VoTT V2 is a refactor and refresh of the original Electron-based application. As the usage and demand for VoTT grew, `V2` was started as an initiative to improve and make VoTT more extensible and maintainable. In addition, `V2` uses more modern development frameworks and patterns (React, Redux) and is authored in TypeScript. @@ -187,8 +195,10 @@ Tagging and drawing regions is not possible while the video is playing. Once assets have been labeled, they can be exported into a variety of formats: * [Azure Custom Vision Service](https://azure.microsoft.com/en-us/services/cognitive-services/custom-vision-service/) +* [Microsoft Cognitive Toolkit (CNTK)](https://github.com/Microsoft/CNTK) * TensorFlow (Pascal VOC and TFRecords) * VoTT (generic JSON schema) +* Comma Separated Values (CSV) In addition, users may choose to export @@ -238,7 +248,7 @@ VOTT allows you to fine tune the bounding boxes using the arrow keys in a few di * Ctrl + Alt + Arrowkey - Shrink Region * Ctrl + Shift + Arrowkey - Expand Region -The slide viewer can be navigated from the keyboard as follows: +The slide viewer can be navigated from the keyboard as follows: * W or ArrowUp - Previous Asset * S or ArrowDown - Next Asset diff --git a/cocoSSDModel/classes.json b/cocoSSDModel/classes.json new file mode 100644 index 0000000000..af8423983c --- /dev/null +++ b/cocoSSDModel/classes.json @@ -0,0 +1 @@ +[{"name":"/m/01g317","id":1,"displayName":"person"},{"name":"/m/0199g","id":2,"displayName":"bicycle"},{"name":"/m/0k4j","id":3,"displayName":"car"},{"name":"/m/04_sv","id":4,"displayName":"motorcycle"},{"name":"/m/05czz6l","id":5,"displayName":"airplane"},{"name":"/m/01bjv","id":6,"displayName":"bus"},{"name":"/m/07jdr","id":7,"displayName":"train"},{"name":"/m/07r04","id":8,"displayName":"truck"},{"name":"/m/019jd","id":9,"displayName":"boat"},{"name":"/m/015qff","id":10,"displayName":"traffic light"},{"name":"/m/01pns0","id":11,"displayName":"fire hydrant"},{"name":"/m/02pv19","id":13,"displayName":"stop sign"},{"name":"/m/015qbp","id":14,"displayName":"parking meter"},{"name":"/m/0cvnqh","id":15,"displayName":"bench"},{"name":"/m/015p6","id":16,"displayName":"bird"},{"name":"/m/01yrx","id":17,"displayName":"cat"},{"name":"/m/0bt9lr","id":18,"displayName":"dog"},{"name":"/m/03k3r","id":19,"displayName":"horse"},{"name":"/m/07bgp","id":20,"displayName":"sheep"},{"name":"/m/01xq0k1","id":21,"displayName":"cow"},{"name":"/m/0bwd_0j","id":22,"displayName":"elephant"},{"name":"/m/01dws","id":23,"displayName":"bear"},{"name":"/m/0898b","id":24,"displayName":"zebra"},{"name":"/m/03bk1","id":25,"displayName":"giraffe"},{"name":"/m/01940j","id":27,"displayName":"backpack"},{"name":"/m/0hnnb","id":28,"displayName":"umbrella"},{"name":"/m/080hkjn","id":31,"displayName":"handbag"},{"name":"/m/01rkbr","id":32,"displayName":"tie"},{"name":"/m/01s55n","id":33,"displayName":"suitcase"},{"name":"/m/02wmf","id":34,"displayName":"frisbee"},{"name":"/m/071p9","id":35,"displayName":"skis"},{"name":"/m/06__v","id":36,"displayName":"snowboard"},{"name":"/m/018xm","id":37,"displayName":"sports ball"},{"name":"/m/02zt3","id":38,"displayName":"kite"},{"name":"/m/03g8mr","id":39,"displayName":"baseball bat"},{"name":"/m/03grzl","id":40,"displayName":"baseball glove"},{"name":"/m/06_fw","id":41,"displayName":"skateboard"},{"name":"/m/019w40","id":42,"displayName":"surfboard"},{"name":"/m/0dv9c","id":43,"displayName":"tennis racket"},{"name":"/m/04dr76w","id":44,"displayName":"bottle"},{"name":"/m/09tvcd","id":46,"displayName":"wine glass"},{"name":"/m/08gqpm","id":47,"displayName":"cup"},{"name":"/m/0dt3t","id":48,"displayName":"fork"},{"name":"/m/04ctx","id":49,"displayName":"knife"},{"name":"/m/0cmx8","id":50,"displayName":"spoon"},{"name":"/m/04kkgm","id":51,"displayName":"bowl"},{"name":"/m/09qck","id":52,"displayName":"banana"},{"name":"/m/014j1m","id":53,"displayName":"apple"},{"name":"/m/0l515","id":54,"displayName":"sandwich"},{"name":"/m/0cyhj_","id":55,"displayName":"orange"},{"name":"/m/0hkxq","id":56,"displayName":"broccoli"},{"name":"/m/0fj52s","id":57,"displayName":"carrot"},{"name":"/m/01b9xk","id":58,"displayName":"hot dog"},{"name":"/m/0663v","id":59,"displayName":"pizza"},{"name":"/m/0jy4k","id":60,"displayName":"donut"},{"name":"/m/0fszt","id":61,"displayName":"cake"},{"name":"/m/01mzpv","id":62,"displayName":"chair"},{"name":"/m/02crq1","id":63,"displayName":"couch"},{"name":"/m/03fp41","id":64,"displayName":"potted plant"},{"name":"/m/03ssj5","id":65,"displayName":"bed"},{"name":"/m/04bcr3","id":67,"displayName":"dining table"},{"name":"/m/09g1w","id":70,"displayName":"toilet"},{"name":"/m/07c52","id":72,"displayName":"tv"},{"name":"/m/01c648","id":73,"displayName":"laptop"},{"name":"/m/020lf","id":74,"displayName":"mouse"},{"name":"/m/0qjjc","id":75,"displayName":"remote"},{"name":"/m/01m2v","id":76,"displayName":"keyboard"},{"name":"/m/050k8","id":77,"displayName":"cell phone"},{"name":"/m/0fx9l","id":78,"displayName":"microwave"},{"name":"/m/029bxz","id":79,"displayName":"oven"},{"name":"/m/01k6s3","id":80,"displayName":"toaster"},{"name":"/m/0130jx","id":81,"displayName":"sink"},{"name":"/m/040b_t","id":82,"displayName":"refrigerator"},{"name":"/m/0bt_c3","id":84,"displayName":"book"},{"name":"/m/01x3z","id":85,"displayName":"clock"},{"name":"/m/02s195","id":86,"displayName":"vase"},{"name":"/m/01lsmm","id":87,"displayName":"scissors"},{"name":"/m/0kmg4","id":88,"displayName":"teddy bear"},{"name":"/m/03wvsk","id":89,"displayName":"hair drier"},{"name":"/m/012xff","id":90,"displayName":"toothbrush"}] \ No newline at end of file diff --git a/cocoSSDModel/group1-shard1of5 b/cocoSSDModel/group1-shard1of5 new file mode 100644 index 0000000000..1752229434 Binary files /dev/null and b/cocoSSDModel/group1-shard1of5 differ diff --git a/cocoSSDModel/group1-shard2of5 b/cocoSSDModel/group1-shard2of5 new file mode 100644 index 0000000000..d04bc12267 Binary files /dev/null and b/cocoSSDModel/group1-shard2of5 differ diff --git a/cocoSSDModel/group1-shard3of5 b/cocoSSDModel/group1-shard3of5 new file mode 100644 index 0000000000..243a13e5f0 Binary files /dev/null and b/cocoSSDModel/group1-shard3of5 differ diff --git a/cocoSSDModel/group1-shard4of5 b/cocoSSDModel/group1-shard4of5 new file mode 100644 index 0000000000..5ddf602e67 Binary files /dev/null and b/cocoSSDModel/group1-shard4of5 differ diff --git a/cocoSSDModel/group1-shard5of5 b/cocoSSDModel/group1-shard5of5 new file mode 100644 index 0000000000..613e32cec4 Binary files /dev/null and b/cocoSSDModel/group1-shard5of5 differ diff --git a/cocoSSDModel/model.json b/cocoSSDModel/model.json new file mode 100644 index 0000000000..80158f3514 --- /dev/null +++ b/cocoSSDModel/model.json @@ -0,0 +1,21549 @@ +{ + "modelTopology": { + "node": [ + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "ConstantFolding/Postprocessor/Decode/div_recip", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1917" + }, + { + "size": "4" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "Postprocessor/ExpandDims", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "ConstantFolding/Postprocessor/Decode/div_4_recip", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 3 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [ + { + "size": "2" + } + ] + } + } + } + }, + "name": "Postprocessor/Reshape_1/shape", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "ConstantFolding/Postprocessor/Decode/div_2_recip", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "576" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "576" + }, + { + "size": "12" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "12" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "1280" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1280" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1280" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1280" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1280" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "1280" + }, + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "512" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "512" + } + ] + } + } + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "512" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "512" + } + ] + } + } + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "512" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "512" + }, + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "256" + }, + { + "size": "1" + } + ] + } + } + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "256" + }, + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "256" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "256" + }, + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "128" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "128" + }, + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 1917 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "MultipleGridAnchorGenerator/assert_equal/x", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 4 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "BoxPredictor_0/stack/3", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 2 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Postprocessor/ExpandDims_1/dim", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "576" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/ClassPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + } + }, + "name": "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + } + }, + "name": "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "576" + }, + { + "size": "273" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_0/ClassPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "273" + } + ] + } + } + } + }, + "name": "BoxPredictor_0/ClassPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 1083 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "BoxPredictor_0/stack/1", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "1280" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/ClassPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1280" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1280" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1280" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1280" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "1280" + }, + { + "size": "546" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/ClassPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "546" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_1/ClassPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 600 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "BoxPredictor_1/stack/1", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "512" + }, + { + "size": "1" + } + ] + } + } + } + }, + "name": "BoxPredictor_2/ClassPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "512" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "512" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "512" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "512" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "512" + }, + { + "size": "546" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/ClassPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "546" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_2/ClassPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 150 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "BoxPredictor_2/stack/1", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "256" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/ClassPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "256" + }, + { + "size": "546" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/ClassPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "546" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_3/ClassPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 54 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "BoxPredictor_3/stack/1", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "256" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/ClassPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + } + }, + "name": "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "256" + }, + { + "size": "546" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/ClassPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "546" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_4/ClassPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 24 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "BoxPredictor_4/stack/1", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "128" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/ClassPredictor_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/gamma", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/beta", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/moving_mean", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/moving_variance", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "128" + }, + { + "size": "546" + } + ] + } + } + } + }, + "name": "BoxPredictor_5/ClassPredictor/weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "546" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "BoxPredictor_5/ClassPredictor/biases", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "160" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "160" + }, + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "960" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "960" + }, + { + "size": "160" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "160" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "160" + }, + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "960" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "960" + }, + { + "size": "160" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "96" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "96" + }, + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "576" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "576" + }, + { + "size": "96" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "96" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "96" + }, + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "576" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "576" + }, + { + "size": "96" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "64" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "64" + }, + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "384" + }, + { + "size": "1" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "384" + }, + { + "size": "64" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "64" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "64" + }, + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "384" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "384" + }, + { + "size": "64" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "64" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "64" + }, + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "384" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "384" + }, + { + "size": "64" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "32" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "32" + }, + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "192" + }, + { + "size": "1" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "192" + }, + { + "size": "32" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "32" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "32" + }, + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "192" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "192" + }, + { + "size": "32" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "24" + }, + { + "size": "144" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "144" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "144" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "144" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "144" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "144" + }, + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [] + } + } + } + }, + "name": "Preprocessor/mul/x", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 0 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Preprocessor/map/TensorArrayStack/range/start", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "Preprocessor/sub/y", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "32" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/Conv/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "32" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/Conv/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "32" + }, + { + "size": "1" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "32" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "32" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "32" + }, + { + "size": "16" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "16" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "16" + }, + { + "size": "96" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "96" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "96" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "96" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "96" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "96" + }, + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "24" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "24" + }, + { + "size": "144" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "144" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "144" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "144" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "144" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "144" + }, + { + "size": "32" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "32" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "32" + }, + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "192" + }, + { + "size": "1" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "192" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "192" + }, + { + "size": "64" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "64" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "64" + }, + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "384" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "384" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "384" + }, + { + "size": "96" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "96" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "96" + }, + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "576" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "576" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "576" + }, + { + "size": "160" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "160" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "160" + }, + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "960" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "960" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "960" + }, + { + "size": "320" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/project/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "320" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/project/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "320" + }, + { + "size": "1280" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/Conv_1/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1280" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/Conv_1/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "1280" + }, + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "256" + }, + { + "size": "1" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "256" + }, + { + "size": "512" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "512" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "512" + }, + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "128" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "128" + }, + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "256" + }, + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "128" + }, + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "128" + }, + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "256" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "256" + }, + { + "size": "64" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "64" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "3" + }, + { + "size": "3" + }, + { + "size": "64" + }, + { + "size": "1" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/depthwise_weights", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 1 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "64" + } + ] + } + } + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/BatchNorm/batchnorm/mul", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "64" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "1" + }, + { + "size": "1" + }, + { + "size": "64" + }, + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/Conv2D/merged_input", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 1, + "tensorShape": { + "dim": [ + { + "size": "128" + } + ] + } + } + }, + "dtype": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/BatchNorm/batchnorm/sub", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 0 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [ + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Postprocessor/strided_slice/stack", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 1 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [ + { + "size": "1" + } + ] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Postprocessor/strided_slice/stack_1", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 6 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "BoxPredictor_5/stack/1", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 91 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "BoxPredictor_0/stack_1/2", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 3 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 1 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + } + }, + "name": "Postprocessor/Tile/multiples/1", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [ + { + "size": "3" + } + ] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Postprocessor/Slice/begin", + "op": "Const" + }, + { + "input": [], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [ + { + "size": "3" + } + ] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Postprocessor/Slice/size", + "op": "Const" + }, + { + "input": [], + "attr": { + "dtype": { + "type": 4 + }, + "shape": { + "shape": { + "dim": [ + { + "size": "-1" + }, + { + "size": "-1" + }, + { + "size": "-1" + }, + { + "size": "3" + } + ] + } + } + }, + "name": "image_tensor", + "op": "Placeholder" + }, + { + "input": [ + "Preprocessor/map/TensorArrayStack/range/start" + ], + "attr": { + "T": { + "type": 3 + }, + "is_constant": { + "b": false + }, + "parallel_iterations": { + "i": "32" + }, + "frame_name": { + "s": [ + 80, + 114, + 101, + 112, + 114, + 111, + 99, + 101, + 115, + 115, + 111, + 114, + 47, + 109, + 97, + 112, + 47, + 119, + 104, + 105, + 108, + 101, + 47, + 119, + 104, + 105, + 108, + 101, + 95, + 99, + 111, + 110, + 116, + 101, + 120, + 116 + ] + } + }, + "name": "Preprocessor/map/while/Enter", + "op": "Enter" + }, + { + "input": [ + "image_tensor" + ], + "attr": { + "SrcT": { + "type": 4 + }, + "DstT": { + "type": 1 + } + }, + "name": "ToFloat", + "op": "Cast" + }, + { + "input": [ + "Preprocessor/map/while/Enter", + "Preprocessor/map/while/NextIteration" + ], + "attr": { + "T": { + "type": 3 + }, + "N": { + "i": "2" + } + }, + "name": "Preprocessor/map/while/Merge", + "op": "Merge" + }, + { + "input": [ + "ToFloat" + ], + "attr": { + "T": { + "type": 1 + }, + "out_type": { + "type": 3 + } + }, + "name": "Preprocessor/map/TensorArrayUnstack/Shape", + "op": "Shape" + }, + { + "input": [ + "Preprocessor/map/TensorArrayUnstack/Shape", + "Postprocessor/strided_slice/stack", + "Postprocessor/strided_slice/stack_1", + "Postprocessor/strided_slice/stack_1" + ], + "attr": { + "T": { + "type": 3 + }, + "Index": { + "type": 3 + }, + "shrink_axis_mask": { + "i": "1" + }, + "begin_mask": { + "i": "0" + }, + "ellipsis_mask": { + "i": "0" + }, + "new_axis_mask": { + "i": "0" + }, + "end_mask": { + "i": "0" + } + }, + "name": "Preprocessor/map/TensorArrayUnstack/strided_slice", + "op": "StridedSlice" + }, + { + "input": [ + "Preprocessor/map/TensorArrayUnstack/strided_slice" + ], + "attr": { + "dtype": { + "type": 1 + }, + "element_shape": { + "shape": { + "dim": [], + "unknownRank": true + } + }, + "dynamic_size": { + "b": false + }, + "clear_after_read": { + "b": true + }, + "identical_element_shapes": { + "b": false + }, + "tensor_array_name": { + "s": [] + } + }, + "name": "Preprocessor/map/TensorArray_1", + "op": "TensorArrayV3" + }, + { + "input": [ + "Preprocessor/map/TensorArrayStack/range/start", + "Preprocessor/map/TensorArrayUnstack/strided_slice", + "Postprocessor/Tile/multiples/1" + ], + "attr": { + "Tidx": { + "type": 3 + } + }, + "name": "Preprocessor/map/TensorArrayUnstack/range", + "op": "Range" + }, + { + "input": [ + "Preprocessor/map/TensorArrayUnstack/strided_slice" + ], + "attr": { + "tensor_array_name": { + "s": [] + }, + "dtype": { + "type": 1 + }, + "element_shape": { + "shape": { + "dim": [], + "unknownRank": true + } + }, + "dynamic_size": { + "b": false + }, + "clear_after_read": { + "b": true + }, + "identical_element_shapes": { + "b": false + } + }, + "name": "Preprocessor/map/TensorArray", + "op": "TensorArrayV3" + }, + { + "input": [ + "Preprocessor/map/TensorArrayUnstack/strided_slice" + ], + "attr": { + "T": { + "type": 3 + }, + "is_constant": { + "b": true + }, + "parallel_iterations": { + "i": "32" + }, + "frame_name": { + "s": [ + 80, + 114, + 101, + 112, + 114, + 111, + 99, + 101, + 115, + 115, + 111, + 114, + 47, + 109, + 97, + 112, + 47, + 119, + 104, + 105, + 108, + 101, + 47, + 119, + 104, + 105, + 108, + 101, + 95, + 99, + 111, + 110, + 116, + 101, + 120, + 116 + ] + } + }, + "name": "Preprocessor/map/while/Less/Enter", + "op": "Enter" + }, + { + "input": [ + "Preprocessor/map/TensorArray_1:1" + ], + "attr": { + "is_constant": { + "b": false + }, + "parallel_iterations": { + "i": "32" + }, + "frame_name": { + "s": [ + 80, + 114, + 101, + 112, + 114, + 111, + 99, + 101, + 115, + 115, + 111, + 114, + 47, + 109, + 97, + 112, + 47, + 119, + 104, + 105, + 108, + 101, + 47, + 119, + 104, + 105, + 108, + 101, + 95, + 99, + 111, + 110, + 116, + 101, + 120, + 116 + ] + }, + "T": { + "type": 1 + } + }, + "name": "Preprocessor/map/while/Enter_1", + "op": "Enter" + }, + { + "input": [ + "Preprocessor/map/TensorArray_1" + ], + "attr": { + "frame_name": { + "s": [ + 80, + 114, + 101, + 112, + 114, + 111, + 99, + 101, + 115, + 115, + 111, + 114, + 47, + 109, + 97, + 112, + 47, + 119, + 104, + 105, + 108, + 101, + 47, + 119, + 104, + 105, + 108, + 101, + 95, + 99, + 111, + 110, + 116, + 101, + 120, + 116 + ] + }, + "T": { + "type": 20 + }, + "is_constant": { + "b": true + }, + "parallel_iterations": { + "i": "32" + } + }, + "name": "Preprocessor/map/while/TensorArrayWrite/TensorArrayWriteV3/Enter", + "op": "Enter" + }, + { + "input": [ + "Preprocessor/map/TensorArray" + ], + "attr": { + "T": { + "type": 20 + }, + "is_constant": { + "b": true + }, + "parallel_iterations": { + "i": "32" + }, + "frame_name": { + "s": [ + 80, + 114, + 101, + 112, + 114, + 111, + 99, + 101, + 115, + 115, + 111, + 114, + 47, + 109, + 97, + 112, + 47, + 119, + 104, + 105, + 108, + 101, + 47, + 119, + 104, + 105, + 108, + 101, + 95, + 99, + 111, + 110, + 116, + 101, + 120, + 116 + ] + } + }, + "name": "Preprocessor/map/while/TensorArrayReadV3/Enter", + "op": "Enter" + }, + { + "input": [ + "Preprocessor/map/TensorArray", + "Preprocessor/map/TensorArrayUnstack/range", + "ToFloat", + "Preprocessor/map/TensorArray:1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Preprocessor/map/TensorArrayUnstack/TensorArrayScatter/TensorArrayScatterV3", + "op": "TensorArrayScatterV3" + }, + { + "input": [ + "Preprocessor/map/while/Merge", + "Preprocessor/map/while/Less/Enter" + ], + "attr": { + "T": { + "type": 3 + } + }, + "name": "Preprocessor/map/while/Less", + "op": "Less" + }, + { + "input": [ + "Preprocessor/map/while/Enter_1", + "Preprocessor/map/while/NextIteration_1" + ], + "attr": { + "T": { + "type": 1 + }, + "N": { + "i": "2" + } + }, + "name": "Preprocessor/map/while/Merge_1", + "op": "Merge" + }, + { + "input": [ + "Preprocessor/map/TensorArrayUnstack/TensorArrayScatter/TensorArrayScatterV3" + ], + "attr": { + "T": { + "type": 1 + }, + "is_constant": { + "b": true + }, + "parallel_iterations": { + "i": "32" + }, + "frame_name": { + "s": [ + 80, + 114, + 101, + 112, + 114, + 111, + 99, + 101, + 115, + 115, + 111, + 114, + 47, + 109, + 97, + 112, + 47, + 119, + 104, + 105, + 108, + 101, + 47, + 119, + 104, + 105, + 108, + 101, + 95, + 99, + 111, + 110, + 116, + 101, + 120, + 116 + ] + } + }, + "name": "Preprocessor/map/while/TensorArrayReadV3/Enter_1", + "op": "Enter" + }, + { + "input": [ + "Preprocessor/map/while/Less" + ], + "attr": {}, + "name": "Preprocessor/map/while/LoopCond", + "op": "LoopCond" + }, + { + "input": [ + "Preprocessor/map/while/Merge", + "Preprocessor/map/while/LoopCond" + ], + "attr": { + "T": { + "type": 3 + } + }, + "name": "Preprocessor/map/while/Switch", + "op": "Switch" + }, + { + "input": [ + "Preprocessor/map/while/Merge_1", + "Preprocessor/map/while/LoopCond" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Preprocessor/map/while/Switch_1", + "op": "Switch" + }, + { + "input": [ + "Preprocessor/map/while/Switch:1" + ], + "attr": { + "T": { + "type": 3 + } + }, + "name": "Preprocessor/map/while/Identity", + "op": "Identity" + }, + { + "input": [ + "Preprocessor/map/while/Switch_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Preprocessor/map/while/Exit_1", + "op": "Exit" + }, + { + "input": [ + "Preprocessor/map/while/TensorArrayReadV3/Enter", + "Preprocessor/map/while/Identity", + "Preprocessor/map/while/TensorArrayReadV3/Enter_1" + ], + "attr": { + "dtype": { + "type": 1 + } + }, + "name": "Preprocessor/map/while/TensorArrayReadV3", + "op": "TensorArrayReadV3" + }, + { + "input": [ + "^Preprocessor/map/while/Identity" + ], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 0 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Preprocessor/map/while/ResizeImage/ExpandDims/dim", + "op": "Const" + }, + { + "input": [ + "^Preprocessor/map/while/Identity" + ], + "attr": { + "dtype": { + "type": 3 + }, + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [ + { + "size": "2" + } + ] + } + } + } + }, + "name": "Preprocessor/map/while/ResizeImage/stack", + "op": "Const" + }, + { + "input": [ + "^Preprocessor/map/while/Identity" + ], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [ + 1 + ], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Preprocessor/map/while/add/y", + "op": "Const" + }, + { + "input": [ + "Preprocessor/map/TensorArray_1", + "Preprocessor/map/while/Exit_1" + ], + "attr": {}, + "name": "Preprocessor/map/TensorArrayStack/TensorArraySizeV3", + "op": "TensorArraySizeV3" + }, + { + "input": [ + "Preprocessor/map/while/TensorArrayReadV3", + "Preprocessor/map/while/ResizeImage/ExpandDims/dim" + ], + "attr": { + "Tdim": { + "type": 3 + }, + "T": { + "type": 1 + } + }, + "name": "Preprocessor/map/while/ResizeImage/ExpandDims", + "op": "ExpandDims" + }, + { + "input": [ + "Preprocessor/map/while/Identity", + "Preprocessor/map/while/add/y" + ], + "attr": { + "T": { + "type": 3 + } + }, + "name": "Preprocessor/map/while/add", + "op": "Add" + }, + { + "input": [ + "Preprocessor/map/TensorArrayStack/range/start", + "Preprocessor/map/TensorArrayStack/TensorArraySizeV3", + "Postprocessor/Tile/multiples/1" + ], + "attr": { + "Tidx": { + "type": 3 + } + }, + "name": "Preprocessor/map/TensorArrayStack/range", + "op": "Range" + }, + { + "input": [ + "Preprocessor/map/while/ResizeImage/ExpandDims", + "Preprocessor/map/while/ResizeImage/stack" + ], + "attr": { + "align_corners": { + "b": false + }, + "T": { + "type": 1 + } + }, + "name": "Preprocessor/map/while/ResizeImage/ResizeBilinear", + "op": "ResizeBilinear" + }, + { + "input": [ + "Preprocessor/map/while/add" + ], + "attr": { + "T": { + "type": 3 + } + }, + "name": "Preprocessor/map/while/NextIteration", + "op": "NextIteration" + }, + { + "input": [ + "Preprocessor/map/TensorArray_1", + "Preprocessor/map/TensorArrayStack/range", + "Preprocessor/map/while/Exit_1" + ], + "attr": { + "element_shape": { + "shape": { + "dim": [ + { + "size": "300" + }, + { + "size": "300" + }, + { + "size": "3" + } + ] + } + }, + "dtype": { + "type": 1 + } + }, + "name": "Preprocessor/map/TensorArrayStack/TensorArrayGatherV3", + "op": "TensorArrayGatherV3" + }, + { + "input": [ + "Preprocessor/map/while/ResizeImage/ResizeBilinear" + ], + "attr": { + "T": { + "type": 1 + }, + "squeeze_dims": { + "list": { + "s": [], + "i": [ + "0" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "Preprocessor/map/while/ResizeImage/Squeeze", + "op": "Squeeze" + }, + { + "input": [ + "Preprocessor/mul/x", + "Preprocessor/map/TensorArrayStack/TensorArrayGatherV3" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Preprocessor/mul", + "op": "Mul" + }, + { + "input": [ + "Preprocessor/map/while/TensorArrayWrite/TensorArrayWriteV3/Enter", + "Preprocessor/map/while/Identity", + "Preprocessor/map/while/ResizeImage/Squeeze", + "Preprocessor/map/while/Switch_1:1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Preprocessor/map/while/TensorArrayWrite/TensorArrayWriteV3", + "op": "TensorArrayWriteV3" + }, + { + "input": [ + "Preprocessor/mul", + "Preprocessor/sub/y" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Preprocessor/sub", + "op": "Sub" + }, + { + "input": [ + "Preprocessor/map/while/TensorArrayWrite/TensorArrayWriteV3" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Preprocessor/map/while/NextIteration_1", + "op": "NextIteration" + }, + { + "input": [ + "Preprocessor/sub", + "FeatureExtractor/MobilenetV2/Conv/Conv2D/merged_input" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "2", + "2", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/Conv/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/Conv/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/Conv/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/Conv/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/Conv/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/Conv/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/Conv/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/depthwise_weights" + ], + "attr": { + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv/project/Conv2D/merged_input" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv/project/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv/project/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv/project/BatchNorm/batchnorm/add_1", + "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/Conv2D/merged_input" + ], + "attr": { + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/depthwise_weights" + ], + "attr": { + "strides": { + "list": { + "s": [], + "i": [ + "1", + "2", + "2", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_1/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_1/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_1/project/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/project/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_1/project/BatchNorm/batchnorm/add_1", + "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/depthwise_weights" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_2/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_2/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_1/project/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "N": { + "i": "2" + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add", + "op": "AddN" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_2/project/BatchNorm/batchnorm/sub", + "FeatureExtractor/MobilenetV2/expanded_conv_2/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add" + ], + "attr": { + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/ArithmeticOptimizer/AddOpsRewrite_add", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_2/ArithmeticOptimizer/AddOpsRewrite_add", + "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/depthwise_weights" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "2", + "2", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_3/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_3/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_3/project/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/project/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_3/project/BatchNorm/batchnorm/add_1", + "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/Conv2D/merged_input" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/depthwise_weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_4/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_4/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_3/project/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "N": { + "i": "2" + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add", + "op": "AddN" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_4/project/BatchNorm/batchnorm/sub", + "FeatureExtractor/MobilenetV2/expanded_conv_4/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/ArithmeticOptimizer/AddOpsRewrite_add", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_4/ArithmeticOptimizer/AddOpsRewrite_add", + "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/depthwise_weights" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_5/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_5/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_4/ArithmeticOptimizer/AddOpsRewrite_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "N": { + "i": "2" + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add", + "op": "AddN" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_5/project/BatchNorm/batchnorm/sub", + "FeatureExtractor/MobilenetV2/expanded_conv_5/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/ArithmeticOptimizer/AddOpsRewrite_add", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_5/ArithmeticOptimizer/AddOpsRewrite_add", + "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/depthwise_weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "2", + "2", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_6/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_6/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_6/project/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/project/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_6/project/BatchNorm/batchnorm/add_1", + "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/depthwise_weights" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_7/project/Conv2D/merged_input" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_7/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_6/project/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "N": { + "i": "2" + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add", + "op": "AddN" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_7/project/BatchNorm/batchnorm/sub", + "FeatureExtractor/MobilenetV2/expanded_conv_7/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/ArithmeticOptimizer/AddOpsRewrite_add", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_7/ArithmeticOptimizer/AddOpsRewrite_add", + "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/Conv2D/merged_input" + ], + "attr": { + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/depthwise_weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_8/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_8/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_7/ArithmeticOptimizer/AddOpsRewrite_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "N": { + "i": "2" + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add", + "op": "AddN" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_8/project/BatchNorm/batchnorm/sub", + "FeatureExtractor/MobilenetV2/expanded_conv_8/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/ArithmeticOptimizer/AddOpsRewrite_add", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_8/ArithmeticOptimizer/AddOpsRewrite_add", + "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/depthwise_weights" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_9/project/Conv2D/merged_input" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_9/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_8/ArithmeticOptimizer/AddOpsRewrite_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "N": { + "i": "2" + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add", + "op": "AddN" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_9/project/BatchNorm/batchnorm/sub", + "FeatureExtractor/MobilenetV2/expanded_conv_9/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/ArithmeticOptimizer/AddOpsRewrite_add", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_9/ArithmeticOptimizer/AddOpsRewrite_add", + "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/Conv2D/merged_input" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/depthwise_weights" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_10/project/Conv2D/merged_input" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_10/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_10/project/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/project/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_10/project/BatchNorm/batchnorm/add_1", + "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/depthwise_weights" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_11/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_11/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_10/project/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "N": { + "i": "2" + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add", + "op": "AddN" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_11/project/BatchNorm/batchnorm/sub", + "FeatureExtractor/MobilenetV2/expanded_conv_11/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/ArithmeticOptimizer/AddOpsRewrite_add", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_11/ArithmeticOptimizer/AddOpsRewrite_add", + "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/depthwise_weights" + ], + "attr": { + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_12/project/Conv2D/merged_input" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_12/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_11/ArithmeticOptimizer/AddOpsRewrite_add" + ], + "attr": { + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "N": { + "i": "2" + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add", + "op": "AddN" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_12/project/BatchNorm/batchnorm/sub", + "FeatureExtractor/MobilenetV2/expanded_conv_12/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/ArithmeticOptimizer/AddOpsRewrite_add", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_12/ArithmeticOptimizer/AddOpsRewrite_add", + "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/Conv2D/merged_input" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/Relu6", + "BoxPredictor_0/BoxEncodingPredictor_depthwise/depthwise_weights" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/Relu6", + "BoxPredictor_0/ClassPredictor_depthwise/depthwise_weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_0/ClassPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/Relu6" + ], + "attr": { + "T": { + "type": 1 + }, + "out_type": { + "type": 3 + } + }, + "name": "BoxPredictor_0/Shape", + "op": "Shape" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/depthwise_weights" + ], + "attr": { + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "2", + "2", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "BoxPredictor_0/BoxEncodingPredictor_depthwise/depthwise", + "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "epsilon": { + "f": 0.0010000000474974513 + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "is_training": { + "b": false + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_0/ClassPredictor_depthwise/depthwise", + "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "is_training": { + "b": false + }, + "epsilon": { + "f": 0.0010000000474974513 + } + }, + "name": "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_0/Shape", + "Postprocessor/strided_slice/stack", + "Postprocessor/strided_slice/stack_1", + "Postprocessor/strided_slice/stack_1" + ], + "attr": { + "T": { + "type": 3 + }, + "Index": { + "type": 3 + }, + "shrink_axis_mask": { + "i": "1" + }, + "ellipsis_mask": { + "i": "0" + }, + "begin_mask": { + "i": "0" + }, + "new_axis_mask": { + "i": "0" + }, + "end_mask": { + "i": "0" + } + }, + "name": "BoxPredictor_0/strided_slice", + "op": "StridedSlice" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_0/ClassPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_0/strided_slice", + "BoxPredictor_0/stack/1", + "Postprocessor/Tile/multiples/1", + "BoxPredictor_0/stack/3" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "4" + } + }, + "name": "BoxPredictor_0/stack", + "op": "Pack" + }, + { + "input": [ + "BoxPredictor_0/strided_slice", + "BoxPredictor_0/stack/1", + "BoxPredictor_0/stack_1/2" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "3" + } + }, + "name": "BoxPredictor_0/stack_1", + "op": "Pack" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "BoxPredictor_0/BoxEncodingPredictor_depthwise/Relu6", + "BoxPredictor_0/BoxEncodingPredictor/weights" + ], + "attr": { + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_0/ClassPredictor_depthwise/Relu6", + "BoxPredictor_0/ClassPredictor/weights" + ], + "attr": { + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_0/ClassPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_0/BoxEncodingPredictor/Conv2D", + "BoxPredictor_0/BoxEncodingPredictor/biases" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_0/BoxEncodingPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "BoxPredictor_0/ClassPredictor/Conv2D", + "BoxPredictor_0/ClassPredictor/biases" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_0/ClassPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_13/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_0/BoxEncodingPredictor/BiasAdd", + "BoxPredictor_0/stack" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_0/Reshape", + "op": "Reshape" + }, + { + "input": [ + "BoxPredictor_0/ClassPredictor/BiasAdd", + "BoxPredictor_0/stack_1" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_0/Reshape_1", + "op": "Reshape" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_13/project/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/project/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_13/project/BatchNorm/batchnorm/add_1", + "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/Conv2D/merged_input" + ], + "attr": { + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/depthwise_weights" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_14/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_14/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_13/project/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "N": { + "i": "2" + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add", + "op": "AddN" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_14/project/BatchNorm/batchnorm/sub", + "FeatureExtractor/MobilenetV2/expanded_conv_14/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/ArithmeticOptimizer/AddOpsRewrite_add", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_14/ArithmeticOptimizer/AddOpsRewrite_add", + "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/depthwise_weights" + ], + "attr": { + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_15/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_15/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_14/ArithmeticOptimizer/AddOpsRewrite_add" + ], + "attr": { + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + }, + "N": { + "i": "2" + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add", + "op": "AddN" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_15/project/BatchNorm/batchnorm/sub", + "FeatureExtractor/MobilenetV2/expanded_conv_15/ArithmeticOptimizer/AddOpsRewrite_Leaf_1_add" + ], + "attr": { + "T": { + "type": 1 + }, + "_grappler:ArithmeticOptimizer:AddOpsRewriteStage": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/ArithmeticOptimizer/AddOpsRewrite_add", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_15/ArithmeticOptimizer/AddOpsRewrite_add", + "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/Conv2D/merged_input" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/depthwise_weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/depthwise", + "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/Relu6", + "FeatureExtractor/MobilenetV2/expanded_conv_16/project/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/project/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_16/project/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/expanded_conv_16/project/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/project/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/expanded_conv_16/project/BatchNorm/batchnorm/add_1", + "FeatureExtractor/MobilenetV2/Conv_1/Conv2D/merged_input" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/Conv_1/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/Conv_1/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/Conv_1/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/Conv_1/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/Conv_1/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/Conv_1/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/Conv_1/Relu6", + "BoxPredictor_1/BoxEncodingPredictor_depthwise/depthwise_weights" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/Conv_1/Relu6", + "BoxPredictor_1/ClassPredictor_depthwise/depthwise_weights" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_1/ClassPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/Conv_1/Relu6" + ], + "attr": { + "T": { + "type": 1 + }, + "out_type": { + "type": 3 + } + }, + "name": "BoxPredictor_1/Shape", + "op": "Shape" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/Conv_1/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/Conv2D/merged_input" + ], + "attr": { + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_1/BoxEncodingPredictor_depthwise/depthwise", + "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "is_training": { + "b": false + }, + "epsilon": { + "f": 0.0010000000474974513 + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_1/ClassPredictor_depthwise/depthwise", + "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "is_training": { + "b": false + }, + "epsilon": { + "f": 0.0010000000474974513 + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_1/Shape", + "Postprocessor/strided_slice/stack", + "Postprocessor/strided_slice/stack_1", + "Postprocessor/strided_slice/stack_1" + ], + "attr": { + "begin_mask": { + "i": "0" + }, + "ellipsis_mask": { + "i": "0" + }, + "new_axis_mask": { + "i": "0" + }, + "end_mask": { + "i": "0" + }, + "T": { + "type": 3 + }, + "Index": { + "type": 3 + }, + "shrink_axis_mask": { + "i": "1" + } + }, + "name": "BoxPredictor_1/strided_slice", + "op": "StridedSlice" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_1/ClassPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_1/strided_slice", + "BoxPredictor_1/stack/1", + "Postprocessor/Tile/multiples/1", + "BoxPredictor_0/stack/3" + ], + "attr": { + "axis": { + "i": "0" + }, + "N": { + "i": "4" + }, + "T": { + "type": 3 + } + }, + "name": "BoxPredictor_1/stack", + "op": "Pack" + }, + { + "input": [ + "BoxPredictor_1/strided_slice", + "BoxPredictor_1/stack/1", + "BoxPredictor_0/stack_1/2" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "3" + } + }, + "name": "BoxPredictor_1/stack_1", + "op": "Pack" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_1/BoxEncodingPredictor_depthwise/Relu6", + "BoxPredictor_1/BoxEncodingPredictor/weights" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_1/ClassPredictor_depthwise/Relu6", + "BoxPredictor_1/ClassPredictor/weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "BoxPredictor_1/ClassPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/depthwise_weights" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "2", + "2", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "BoxPredictor_1/BoxEncodingPredictor/Conv2D", + "BoxPredictor_1/BoxEncodingPredictor/biases" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_1/BoxEncodingPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "BoxPredictor_1/ClassPredictor/Conv2D", + "BoxPredictor_1/ClassPredictor/biases" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_1/ClassPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/depthwise", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "BoxPredictor_1/BoxEncodingPredictor/BiasAdd", + "BoxPredictor_1/stack" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_1/Reshape", + "op": "Reshape" + }, + { + "input": [ + "BoxPredictor_1/ClassPredictor/BiasAdd", + "BoxPredictor_1/stack_1" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_1/Reshape_1", + "op": "Reshape" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/Conv2D/merged_input" + ], + "attr": { + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/Relu6", + "BoxPredictor_2/BoxEncodingPredictor_depthwise/depthwise_weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/Relu6", + "BoxPredictor_2/ClassPredictor_depthwise/depthwise_weights" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "BoxPredictor_2/ClassPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/Relu6" + ], + "attr": { + "T": { + "type": 1 + }, + "out_type": { + "type": 3 + } + }, + "name": "BoxPredictor_2/Shape", + "op": "Shape" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_2/BoxEncodingPredictor_depthwise/depthwise", + "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "is_training": { + "b": false + }, + "epsilon": { + "f": 0.0010000000474974513 + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_2/ClassPredictor_depthwise/depthwise", + "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "epsilon": { + "f": 0.0010000000474974513 + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "is_training": { + "b": false + } + }, + "name": "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_2/Shape", + "Postprocessor/strided_slice/stack", + "Postprocessor/strided_slice/stack_1", + "Postprocessor/strided_slice/stack_1" + ], + "attr": { + "T": { + "type": 3 + }, + "Index": { + "type": 3 + }, + "shrink_axis_mask": { + "i": "1" + }, + "begin_mask": { + "i": "0" + }, + "ellipsis_mask": { + "i": "0" + }, + "new_axis_mask": { + "i": "0" + }, + "end_mask": { + "i": "0" + } + }, + "name": "BoxPredictor_2/strided_slice", + "op": "StridedSlice" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_2/ClassPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_2/strided_slice", + "BoxPredictor_2/stack/1", + "Postprocessor/Tile/multiples/1", + "BoxPredictor_0/stack/3" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "4" + } + }, + "name": "BoxPredictor_2/stack", + "op": "Pack" + }, + { + "input": [ + "BoxPredictor_2/strided_slice", + "BoxPredictor_2/stack/1", + "BoxPredictor_0/stack_1/2" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "3" + } + }, + "name": "BoxPredictor_2/stack_1", + "op": "Pack" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_2/BoxEncodingPredictor_depthwise/Relu6", + "BoxPredictor_2/BoxEncodingPredictor/weights" + ], + "attr": { + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_2/ClassPredictor_depthwise/Relu6", + "BoxPredictor_2/ClassPredictor/weights" + ], + "attr": { + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_2/ClassPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/depthwise_weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "2", + "2", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "BoxPredictor_2/BoxEncodingPredictor/Conv2D", + "BoxPredictor_2/BoxEncodingPredictor/biases" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_2/BoxEncodingPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "BoxPredictor_2/ClassPredictor/Conv2D", + "BoxPredictor_2/ClassPredictor/biases" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_2/ClassPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/depthwise", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "BoxPredictor_2/BoxEncodingPredictor/BiasAdd", + "BoxPredictor_2/stack" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_2/Reshape", + "op": "Reshape" + }, + { + "input": [ + "BoxPredictor_2/ClassPredictor/BiasAdd", + "BoxPredictor_2/stack_1" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_2/Reshape_1", + "op": "Reshape" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/Conv2D/merged_input" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/Relu6", + "BoxPredictor_3/BoxEncodingPredictor_depthwise/depthwise_weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/Relu6", + "BoxPredictor_3/ClassPredictor_depthwise/depthwise_weights" + ], + "attr": { + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_3/ClassPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/Relu6" + ], + "attr": { + "T": { + "type": 1 + }, + "out_type": { + "type": 3 + } + }, + "name": "BoxPredictor_3/Shape", + "op": "Shape" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_3/BoxEncodingPredictor_depthwise/depthwise", + "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "is_training": { + "b": false + }, + "epsilon": { + "f": 0.0010000000474974513 + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_3/ClassPredictor_depthwise/depthwise", + "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "is_training": { + "b": false + }, + "epsilon": { + "f": 0.0010000000474974513 + } + }, + "name": "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_3/Shape", + "Postprocessor/strided_slice/stack", + "Postprocessor/strided_slice/stack_1", + "Postprocessor/strided_slice/stack_1" + ], + "attr": { + "shrink_axis_mask": { + "i": "1" + }, + "begin_mask": { + "i": "0" + }, + "ellipsis_mask": { + "i": "0" + }, + "new_axis_mask": { + "i": "0" + }, + "end_mask": { + "i": "0" + }, + "Index": { + "type": 3 + }, + "T": { + "type": 3 + } + }, + "name": "BoxPredictor_3/strided_slice", + "op": "StridedSlice" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_3/ClassPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_3/strided_slice", + "BoxPredictor_3/stack/1", + "Postprocessor/Tile/multiples/1", + "BoxPredictor_0/stack/3" + ], + "attr": { + "axis": { + "i": "0" + }, + "N": { + "i": "4" + }, + "T": { + "type": 3 + } + }, + "name": "BoxPredictor_3/stack", + "op": "Pack" + }, + { + "input": [ + "BoxPredictor_3/strided_slice", + "BoxPredictor_3/stack/1", + "BoxPredictor_0/stack_1/2" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "3" + } + }, + "name": "BoxPredictor_3/stack_1", + "op": "Pack" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_3/BoxEncodingPredictor_depthwise/Relu6", + "BoxPredictor_3/BoxEncodingPredictor/weights" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_3/ClassPredictor_depthwise/Relu6", + "BoxPredictor_3/ClassPredictor/weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "BoxPredictor_3/ClassPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/depthwise_weights" + ], + "attr": { + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "2", + "2", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "BoxPredictor_3/BoxEncodingPredictor/Conv2D", + "BoxPredictor_3/BoxEncodingPredictor/biases" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_3/BoxEncodingPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "BoxPredictor_3/ClassPredictor/Conv2D", + "BoxPredictor_3/ClassPredictor/biases" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_3/ClassPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/depthwise", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "BoxPredictor_3/BoxEncodingPredictor/BiasAdd", + "BoxPredictor_3/stack" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_3/Reshape", + "op": "Reshape" + }, + { + "input": [ + "BoxPredictor_3/ClassPredictor/BiasAdd", + "BoxPredictor_3/stack_1" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_3/Reshape_1", + "op": "Reshape" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/Conv2D/merged_input" + ], + "attr": { + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/Relu6", + "BoxPredictor_4/BoxEncodingPredictor_depthwise/depthwise_weights" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/Relu6", + "BoxPredictor_4/ClassPredictor_depthwise/depthwise_weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "BoxPredictor_4/ClassPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/Relu6" + ], + "attr": { + "T": { + "type": 1 + }, + "out_type": { + "type": 3 + } + }, + "name": "BoxPredictor_4/Shape", + "op": "Shape" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/Conv2D/merged_input" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_4/BoxEncodingPredictor_depthwise/depthwise", + "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "is_training": { + "b": false + }, + "epsilon": { + "f": 0.0010000000474974513 + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_4/ClassPredictor_depthwise/depthwise", + "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "epsilon": { + "f": 0.0010000000474974513 + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "is_training": { + "b": false + } + }, + "name": "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_4/Shape", + "Postprocessor/strided_slice/stack", + "Postprocessor/strided_slice/stack_1", + "Postprocessor/strided_slice/stack_1" + ], + "attr": { + "shrink_axis_mask": { + "i": "1" + }, + "ellipsis_mask": { + "i": "0" + }, + "begin_mask": { + "i": "0" + }, + "new_axis_mask": { + "i": "0" + }, + "end_mask": { + "i": "0" + }, + "Index": { + "type": 3 + }, + "T": { + "type": 3 + } + }, + "name": "BoxPredictor_4/strided_slice", + "op": "StridedSlice" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_4/ClassPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_4/strided_slice", + "BoxPredictor_4/stack/1", + "Postprocessor/Tile/multiples/1", + "BoxPredictor_0/stack/3" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "4" + } + }, + "name": "BoxPredictor_4/stack", + "op": "Pack" + }, + { + "input": [ + "BoxPredictor_4/strided_slice", + "BoxPredictor_4/stack/1", + "BoxPredictor_0/stack_1/2" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "3" + } + }, + "name": "BoxPredictor_4/stack_1", + "op": "Pack" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_4/BoxEncodingPredictor_depthwise/Relu6", + "BoxPredictor_4/BoxEncodingPredictor/weights" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_4/ClassPredictor_depthwise/Relu6", + "BoxPredictor_4/ClassPredictor/weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "BoxPredictor_4/ClassPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/depthwise_weights" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "2", + "2", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "BoxPredictor_4/BoxEncodingPredictor/Conv2D", + "BoxPredictor_4/BoxEncodingPredictor/biases" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_4/BoxEncodingPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "BoxPredictor_4/ClassPredictor/Conv2D", + "BoxPredictor_4/ClassPredictor/biases" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_4/ClassPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/depthwise", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/BatchNorm/batchnorm/mul" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/BatchNorm/batchnorm/mul_1", + "op": "Mul" + }, + { + "input": [ + "BoxPredictor_4/BoxEncodingPredictor/BiasAdd", + "BoxPredictor_4/stack" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_4/Reshape", + "op": "Reshape" + }, + { + "input": [ + "BoxPredictor_4/ClassPredictor/BiasAdd", + "BoxPredictor_4/stack_1" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_4/Reshape_1", + "op": "Reshape" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/Relu6", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/Conv2D/merged_input" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/BatchNorm/batchnorm/mul_1", + "op": "Conv2D" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/BatchNorm/batchnorm/mul_1", + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/BatchNorm/batchnorm/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/BatchNorm/batchnorm/add_1", + "op": "Add" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/BatchNorm/batchnorm/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/Relu6", + "op": "Relu6" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/Relu6", + "BoxPredictor_5/BoxEncodingPredictor_depthwise/depthwise_weights" + ], + "attr": { + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/Relu6", + "BoxPredictor_5/ClassPredictor_depthwise/depthwise_weights" + ], + "attr": { + "T": { + "type": 1 + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + } + }, + "name": "BoxPredictor_5/ClassPredictor_depthwise/depthwise", + "op": "DepthwiseConv2dNative" + }, + { + "input": [ + "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/Relu6" + ], + "attr": { + "T": { + "type": 1 + }, + "out_type": { + "type": 3 + } + }, + "name": "BoxPredictor_5/Shape", + "op": "Shape" + }, + { + "input": [ + "BoxPredictor_5/BoxEncodingPredictor_depthwise/depthwise", + "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "is_training": { + "b": false + }, + "epsilon": { + "f": 0.0010000000474974513 + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_5/ClassPredictor_depthwise/depthwise", + "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/gamma", + "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/beta", + "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/moving_mean", + "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/moving_variance" + ], + "attr": { + "epsilon": { + "f": 0.0010000000474974513 + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "is_training": { + "b": false + } + }, + "name": "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm", + "op": "FusedBatchNorm" + }, + { + "input": [ + "BoxPredictor_5/Shape", + "Postprocessor/strided_slice/stack", + "Postprocessor/strided_slice/stack_1", + "Postprocessor/strided_slice/stack_1" + ], + "attr": { + "new_axis_mask": { + "i": "0" + }, + "end_mask": { + "i": "0" + }, + "Index": { + "type": 3 + }, + "T": { + "type": 3 + }, + "shrink_axis_mask": { + "i": "1" + }, + "ellipsis_mask": { + "i": "0" + }, + "begin_mask": { + "i": "0" + } + }, + "name": "BoxPredictor_5/strided_slice", + "op": "StridedSlice" + }, + { + "input": [ + "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/FusedBatchNorm" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_5/ClassPredictor_depthwise/Relu6", + "op": "Relu6" + }, + { + "input": [ + "BoxPredictor_5/strided_slice", + "BoxPredictor_5/stack/1", + "Postprocessor/Tile/multiples/1", + "BoxPredictor_0/stack/3" + ], + "attr": { + "axis": { + "i": "0" + }, + "N": { + "i": "4" + }, + "T": { + "type": 3 + } + }, + "name": "BoxPredictor_5/stack", + "op": "Pack" + }, + { + "input": [ + "BoxPredictor_5/strided_slice", + "BoxPredictor_5/stack/1", + "BoxPredictor_0/stack_1/2" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "3" + } + }, + "name": "BoxPredictor_5/stack_1", + "op": "Pack" + }, + { + "input": [ + "BoxPredictor_5/BoxEncodingPredictor_depthwise/Relu6", + "BoxPredictor_5/BoxEncodingPredictor/weights" + ], + "attr": { + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + }, + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_5/ClassPredictor_depthwise/Relu6", + "BoxPredictor_5/ClassPredictor/weights" + ], + "attr": { + "padding": { + "s": [ + 83, + 65, + 77, + 69 + ] + }, + "dilations": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + }, + "strides": { + "list": { + "s": [], + "i": [ + "1", + "1", + "1", + "1" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + }, + "use_cudnn_on_gpu": { + "b": true + } + }, + "name": "BoxPredictor_5/ClassPredictor/Conv2D", + "op": "Conv2D" + }, + { + "input": [ + "BoxPredictor_5/BoxEncodingPredictor/Conv2D", + "BoxPredictor_5/BoxEncodingPredictor/biases" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_5/BoxEncodingPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "BoxPredictor_5/ClassPredictor/Conv2D", + "BoxPredictor_5/ClassPredictor/biases" + ], + "attr": { + "T": { + "type": 1 + }, + "data_format": { + "s": [ + 78, + 72, + 87, + 67 + ] + } + }, + "name": "BoxPredictor_5/ClassPredictor/BiasAdd", + "op": "BiasAdd" + }, + { + "input": [ + "BoxPredictor_5/BoxEncodingPredictor/BiasAdd", + "BoxPredictor_5/stack" + ], + "attr": { + "Tshape": { + "type": 3 + }, + "T": { + "type": 1 + } + }, + "name": "BoxPredictor_5/Reshape", + "op": "Reshape" + }, + { + "input": [ + "BoxPredictor_5/ClassPredictor/BiasAdd", + "BoxPredictor_5/stack_1" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "BoxPredictor_5/Reshape_1", + "op": "Reshape" + }, + { + "input": [ + "BoxPredictor_0/Reshape", + "BoxPredictor_1/Reshape", + "BoxPredictor_2/Reshape", + "BoxPredictor_3/Reshape", + "BoxPredictor_4/Reshape", + "BoxPredictor_5/Reshape", + "Postprocessor/Tile/multiples/1" + ], + "attr": { + "T": { + "type": 1 + }, + "N": { + "i": "6" + }, + "Tidx": { + "type": 3 + } + }, + "name": "concat", + "op": "ConcatV2" + }, + { + "input": [ + "BoxPredictor_0/Reshape_1", + "BoxPredictor_1/Reshape_1", + "BoxPredictor_2/Reshape_1", + "BoxPredictor_3/Reshape_1", + "BoxPredictor_4/Reshape_1", + "BoxPredictor_5/Reshape_1", + "Postprocessor/Tile/multiples/1" + ], + "attr": { + "T": { + "type": 1 + }, + "N": { + "i": "6" + }, + "Tidx": { + "type": 3 + } + }, + "name": "concat_1", + "op": "ConcatV2" + }, + { + "input": [ + "concat" + ], + "attr": { + "T": { + "type": 1 + }, + "squeeze_dims": { + "list": { + "s": [], + "i": [ + "2" + ], + "f": [], + "b": [], + "type": [], + "shape": [], + "tensor": [], + "func": [] + } + } + }, + "name": "Squeeze", + "op": "Squeeze" + }, + { + "input": [ + "concat_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/convert_scores", + "op": "Sigmoid" + }, + { + "input": [ + "Squeeze", + "Postprocessor/Reshape_1/shape" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "Postprocessor/Reshape_1", + "op": "Reshape" + }, + { + "input": [ + "Squeeze" + ], + "attr": { + "out_type": { + "type": 3 + }, + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Shape", + "op": "Shape" + }, + { + "input": [ + "Postprocessor/convert_scores", + "Postprocessor/Slice/begin", + "Postprocessor/Slice/size" + ], + "attr": { + "Index": { + "type": 3 + }, + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Slice", + "op": "Slice" + }, + { + "input": [ + "^Postprocessor/Reshape_1" + ], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [ + { + "size": "2" + } + ] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Postprocessor/Decode/transpose/sub_1", + "op": "Const" + }, + { + "input": [ + "Postprocessor/Shape", + "Postprocessor/strided_slice/stack", + "Postprocessor/strided_slice/stack_1", + "Postprocessor/strided_slice/stack_1" + ], + "attr": { + "end_mask": { + "i": "0" + }, + "T": { + "type": 3 + }, + "Index": { + "type": 3 + }, + "shrink_axis_mask": { + "i": "1" + }, + "ellipsis_mask": { + "i": "0" + }, + "begin_mask": { + "i": "0" + }, + "new_axis_mask": { + "i": "0" + } + }, + "name": "Postprocessor/strided_slice", + "op": "StridedSlice" + }, + { + "input": [ + "Postprocessor/Reshape_1", + "Postprocessor/Decode/transpose/sub_1" + ], + "attr": { + "T": { + "type": 1 + }, + "Tperm": { + "type": 3 + } + }, + "name": "Postprocessor/Decode/transpose", + "op": "Transpose" + }, + { + "input": [ + "Postprocessor/strided_slice", + "Postprocessor/Tile/multiples/1", + "Postprocessor/Tile/multiples/1" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "3" + } + }, + "name": "Postprocessor/Tile/multiples", + "op": "Pack" + }, + { + "input": [ + "Postprocessor/strided_slice", + "MultipleGridAnchorGenerator/assert_equal/x", + "BoxPredictor_0/stack/3" + ], + "attr": { + "T": { + "type": 3 + }, + "axis": { + "i": "0" + }, + "N": { + "i": "3" + } + }, + "name": "Postprocessor/stack", + "op": "Pack" + }, + { + "input": [ + "Postprocessor/Decode/transpose" + ], + "attr": { + "T": { + "type": 1 + }, + "num": { + "i": "4" + }, + "axis": { + "i": "0" + } + }, + "name": "Postprocessor/Decode/unstack", + "op": "Unpack" + }, + { + "input": [ + "Postprocessor/ExpandDims", + "Postprocessor/Tile/multiples" + ], + "attr": { + "Tmultiples": { + "type": 3 + }, + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Tile", + "op": "Tile" + }, + { + "input": [ + "Postprocessor/Decode/unstack", + "ConstantFolding/Postprocessor/Decode/div_recip" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/div", + "op": "Mul" + }, + { + "input": [ + "Postprocessor/Decode/unstack:2", + "ConstantFolding/Postprocessor/Decode/div_2_recip" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/div_2", + "op": "Mul" + }, + { + "input": [ + "Postprocessor/Decode/unstack:1", + "ConstantFolding/Postprocessor/Decode/div_recip" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/div_1", + "op": "Mul" + }, + { + "input": [ + "Postprocessor/Decode/unstack:3", + "ConstantFolding/Postprocessor/Decode/div_2_recip" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/div_3", + "op": "Mul" + }, + { + "input": [ + "Postprocessor/Tile", + "Postprocessor/Reshape_1/shape" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "Postprocessor/Reshape", + "op": "Reshape" + }, + { + "input": [ + "Postprocessor/Decode/div_2" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/Exp_1", + "op": "Exp" + }, + { + "input": [ + "Postprocessor/Decode/div_3" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/Exp", + "op": "Exp" + }, + { + "input": [ + "^Postprocessor/Reshape" + ], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [ + { + "size": "2" + } + ] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Postprocessor/Decode/get_center_coordinates_and_sizes/transpose/sub_1", + "op": "Const" + }, + { + "input": [ + "Postprocessor/Reshape", + "Postprocessor/Decode/get_center_coordinates_and_sizes/transpose/sub_1" + ], + "attr": { + "Tperm": { + "type": 3 + }, + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/get_center_coordinates_and_sizes/transpose", + "op": "Transpose" + }, + { + "input": [ + "Postprocessor/Decode/get_center_coordinates_and_sizes/transpose" + ], + "attr": { + "T": { + "type": 1 + }, + "num": { + "i": "4" + }, + "axis": { + "i": "0" + } + }, + "name": "Postprocessor/Decode/get_center_coordinates_and_sizes/unstack", + "op": "Unpack" + }, + { + "input": [ + "Postprocessor/Decode/get_center_coordinates_and_sizes/unstack:2", + "Postprocessor/Decode/get_center_coordinates_and_sizes/unstack" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/get_center_coordinates_and_sizes/sub_1", + "op": "Sub" + }, + { + "input": [ + "Postprocessor/Decode/get_center_coordinates_and_sizes/unstack:3", + "Postprocessor/Decode/get_center_coordinates_and_sizes/unstack:1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/get_center_coordinates_and_sizes/sub", + "op": "Sub" + }, + { + "input": [ + "Postprocessor/Decode/div", + "Postprocessor/Decode/get_center_coordinates_and_sizes/sub_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/mul_2", + "op": "Mul" + }, + { + "input": [ + "Postprocessor/Decode/get_center_coordinates_and_sizes/sub_1", + "ConstantFolding/Postprocessor/Decode/div_4_recip" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/get_center_coordinates_and_sizes/div", + "op": "Mul" + }, + { + "input": [ + "Postprocessor/Decode/div_1", + "Postprocessor/Decode/get_center_coordinates_and_sizes/sub" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/mul_3", + "op": "Mul" + }, + { + "input": [ + "Postprocessor/Decode/get_center_coordinates_and_sizes/sub", + "ConstantFolding/Postprocessor/Decode/div_4_recip" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/get_center_coordinates_and_sizes/div_1", + "op": "Mul" + }, + { + "input": [ + "Postprocessor/Decode/get_center_coordinates_and_sizes/unstack", + "Postprocessor/Decode/get_center_coordinates_and_sizes/div" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/get_center_coordinates_and_sizes/add", + "op": "Add" + }, + { + "input": [ + "Postprocessor/Decode/get_center_coordinates_and_sizes/div", + "Postprocessor/Decode/Exp_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/div_4", + "op": "Mul" + }, + { + "input": [ + "Postprocessor/Decode/get_center_coordinates_and_sizes/unstack:1", + "Postprocessor/Decode/get_center_coordinates_and_sizes/div_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/get_center_coordinates_and_sizes/add_1", + "op": "Add" + }, + { + "input": [ + "Postprocessor/Decode/get_center_coordinates_and_sizes/div_1", + "Postprocessor/Decode/Exp" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/div_5", + "op": "Mul" + }, + { + "input": [ + "Postprocessor/Decode/mul_2", + "Postprocessor/Decode/get_center_coordinates_and_sizes/add" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/add", + "op": "Add" + }, + { + "input": [ + "Postprocessor/Decode/mul_3", + "Postprocessor/Decode/get_center_coordinates_and_sizes/add_1" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/add_1", + "op": "Add" + }, + { + "input": [ + "Postprocessor/Decode/add", + "Postprocessor/Decode/div_4" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/sub", + "op": "Sub" + }, + { + "input": [ + "Postprocessor/Decode/add", + "Postprocessor/Decode/div_4" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/add_2", + "op": "Add" + }, + { + "input": [ + "Postprocessor/Decode/add_1", + "Postprocessor/Decode/div_5" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/sub_1", + "op": "Sub" + }, + { + "input": [ + "Postprocessor/Decode/add_1", + "Postprocessor/Decode/div_5" + ], + "attr": { + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/add_3", + "op": "Add" + }, + { + "input": [ + "Postprocessor/Decode/sub", + "Postprocessor/Decode/sub_1", + "Postprocessor/Decode/add_2", + "Postprocessor/Decode/add_3" + ], + "attr": { + "axis": { + "i": "0" + }, + "N": { + "i": "4" + }, + "T": { + "type": 1 + } + }, + "name": "Postprocessor/Decode/stack", + "op": "Pack" + }, + { + "input": [ + "^Postprocessor/Decode/stack" + ], + "attr": { + "value": { + "tensor": { + "floatVal": [], + "doubleVal": [], + "intVal": [], + "stringVal": [], + "scomplexVal": [], + "int64Val": [], + "boolVal": [], + "uint32Val": [], + "uint64Val": [], + "dtype": 3, + "tensorShape": { + "dim": [ + { + "size": "2" + } + ] + } + } + }, + "dtype": { + "type": 3 + } + }, + "name": "Postprocessor/Decode/transpose_1/sub_1", + "op": "Const" + }, + { + "input": [ + "Postprocessor/Decode/stack", + "Postprocessor/Decode/transpose_1/sub_1" + ], + "attr": { + "T": { + "type": 1 + }, + "Tperm": { + "type": 3 + } + }, + "name": "Postprocessor/Decode/transpose_1", + "op": "Transpose" + }, + { + "input": [ + "Postprocessor/Decode/transpose_1", + "Postprocessor/stack" + ], + "attr": { + "T": { + "type": 1 + }, + "Tshape": { + "type": 3 + } + }, + "name": "Postprocessor/Reshape_2", + "op": "Reshape" + }, + { + "input": [ + "Postprocessor/Reshape_2", + "Postprocessor/ExpandDims_1/dim" + ], + "attr": { + "Tdim": { + "type": 3 + }, + "T": { + "type": 1 + } + }, + "name": "Postprocessor/ExpandDims_1", + "op": "ExpandDims" + } + ], + "library": { + "function": [], + "gradient": [] + }, + "versions": { + "badConsumers": [] + } + }, + "weightsManifest": [ + { + "weights": [ + { + "shape": [], + "dtype": "float32", + "name": "ConstantFolding/Postprocessor/Decode/div_recip" + }, + { + "shape": [ + 1, + 1917, + 4 + ], + "dtype": "float32", + "name": "Postprocessor/ExpandDims" + }, + { + "shape": [], + "dtype": "float32", + "name": "ConstantFolding/Postprocessor/Decode/div_4_recip" + }, + { + "shape": [ + 2 + ], + "dtype": "int32", + "name": "Postprocessor/Reshape_1/shape" + }, + { + "shape": [], + "dtype": "float32", + "name": "ConstantFolding/Postprocessor/Decode/div_2_recip" + }, + { + "shape": [ + 3, + 3, + 576, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "BoxPredictor_0/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 576, + 12 + ], + "dtype": "float32", + "name": "BoxPredictor_0/BoxEncodingPredictor/weights" + }, + { + "shape": [ + 12 + ], + "dtype": "float32", + "name": "BoxPredictor_0/BoxEncodingPredictor/biases" + }, + { + "shape": [ + 3, + 3, + 1280, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 1280 + ], + "dtype": "float32", + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 1280 + ], + "dtype": "float32", + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 1280 + ], + "dtype": "float32", + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 1280 + ], + "dtype": "float32", + "name": "BoxPredictor_1/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 1280, + 24 + ], + "dtype": "float32", + "name": "BoxPredictor_1/BoxEncodingPredictor/weights" + }, + { + "shape": [ + 24 + ], + "dtype": "float32", + "name": "BoxPredictor_1/BoxEncodingPredictor/biases" + }, + { + "shape": [ + 3, + 3, + 512, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 512 + ], + "dtype": "float32", + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 512 + ], + "dtype": "float32", + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 512 + ], + "dtype": "float32", + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 512 + ], + "dtype": "float32", + "name": "BoxPredictor_2/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 512, + 24 + ], + "dtype": "float32", + "name": "BoxPredictor_2/BoxEncodingPredictor/weights" + }, + { + "shape": [ + 24 + ], + "dtype": "float32", + "name": "BoxPredictor_2/BoxEncodingPredictor/biases" + }, + { + "shape": [ + 3, + 3, + 256, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_3/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 256, + 24 + ], + "dtype": "float32", + "name": "BoxPredictor_3/BoxEncodingPredictor/weights" + }, + { + "shape": [ + 24 + ], + "dtype": "float32", + "name": "BoxPredictor_3/BoxEncodingPredictor/biases" + }, + { + "shape": [ + 3, + 3, + 256, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_4/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 256, + 24 + ], + "dtype": "float32", + "name": "BoxPredictor_4/BoxEncodingPredictor/weights" + }, + { + "shape": [ + 24 + ], + "dtype": "float32", + "name": "BoxPredictor_4/BoxEncodingPredictor/biases" + }, + { + "shape": [ + 3, + 3, + 128, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "BoxPredictor_5/BoxEncodingPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 128, + 24 + ], + "dtype": "float32", + "name": "BoxPredictor_5/BoxEncodingPredictor/weights" + }, + { + "shape": [ + 24 + ], + "dtype": "float32", + "name": "BoxPredictor_5/BoxEncodingPredictor/biases" + }, + { + "shape": [], + "dtype": "int32", + "name": "MultipleGridAnchorGenerator/assert_equal/x" + }, + { + "shape": [], + "dtype": "int32", + "name": "BoxPredictor_0/stack/3" + }, + { + "shape": [], + "dtype": "int32", + "name": "Postprocessor/ExpandDims_1/dim" + }, + { + "shape": [ + 3, + 3, + 576, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_0/ClassPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "BoxPredictor_0/ClassPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 576, + 273 + ], + "dtype": "float32", + "name": "BoxPredictor_0/ClassPredictor/weights" + }, + { + "shape": [ + 273 + ], + "dtype": "float32", + "name": "BoxPredictor_0/ClassPredictor/biases" + }, + { + "shape": [], + "dtype": "int32", + "name": "BoxPredictor_0/stack/1" + }, + { + "shape": [ + 3, + 3, + 1280, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_1/ClassPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 1280 + ], + "dtype": "float32", + "name": "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 1280 + ], + "dtype": "float32", + "name": "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 1280 + ], + "dtype": "float32", + "name": "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 1280 + ], + "dtype": "float32", + "name": "BoxPredictor_1/ClassPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 1280, + 546 + ], + "dtype": "float32", + "name": "BoxPredictor_1/ClassPredictor/weights" + }, + { + "shape": [ + 546 + ], + "dtype": "float32", + "name": "BoxPredictor_1/ClassPredictor/biases" + }, + { + "shape": [], + "dtype": "int32", + "name": "BoxPredictor_1/stack/1" + }, + { + "shape": [ + 3, + 3, + 512, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_2/ClassPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 512 + ], + "dtype": "float32", + "name": "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 512 + ], + "dtype": "float32", + "name": "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 512 + ], + "dtype": "float32", + "name": "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 512 + ], + "dtype": "float32", + "name": "BoxPredictor_2/ClassPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 512, + 546 + ], + "dtype": "float32", + "name": "BoxPredictor_2/ClassPredictor/weights" + }, + { + "shape": [ + 546 + ], + "dtype": "float32", + "name": "BoxPredictor_2/ClassPredictor/biases" + }, + { + "shape": [], + "dtype": "int32", + "name": "BoxPredictor_2/stack/1" + }, + { + "shape": [ + 3, + 3, + 256, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_3/ClassPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_3/ClassPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 256, + 546 + ], + "dtype": "float32", + "name": "BoxPredictor_3/ClassPredictor/weights" + }, + { + "shape": [ + 546 + ], + "dtype": "float32", + "name": "BoxPredictor_3/ClassPredictor/biases" + }, + { + "shape": [], + "dtype": "int32", + "name": "BoxPredictor_3/stack/1" + }, + { + "shape": [ + 3, + 3, + 256, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_4/ClassPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "BoxPredictor_4/ClassPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 256, + 546 + ], + "dtype": "float32", + "name": "BoxPredictor_4/ClassPredictor/weights" + }, + { + "shape": [ + 546 + ], + "dtype": "float32", + "name": "BoxPredictor_4/ClassPredictor/biases" + }, + { + "shape": [], + "dtype": "int32", + "name": "BoxPredictor_4/stack/1" + }, + { + "shape": [ + 3, + 3, + 128, + 1 + ], + "dtype": "float32", + "name": "BoxPredictor_5/ClassPredictor_depthwise/depthwise_weights" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/gamma" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/beta" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/moving_mean" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "BoxPredictor_5/ClassPredictor_depthwise/BatchNorm/moving_variance" + }, + { + "shape": [ + 1, + 1, + 128, + 546 + ], + "dtype": "float32", + "name": "BoxPredictor_5/ClassPredictor/weights" + }, + { + "shape": [ + 546 + ], + "dtype": "float32", + "name": "BoxPredictor_5/ClassPredictor/biases" + }, + { + "shape": [ + 160 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 160, + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/Conv2D/merged_input" + }, + { + "shape": [ + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 960, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/depthwise_weights" + }, + { + "shape": [ + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 960, + 160 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_15/project/Conv2D/merged_input" + }, + { + "shape": [ + 160 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 160, + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/Conv2D/merged_input" + }, + { + "shape": [ + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 960, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/depthwise_weights" + }, + { + "shape": [ + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 960, + 160 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_14/project/Conv2D/merged_input" + }, + { + "shape": [ + 96 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 96, + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/Conv2D/merged_input" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 576, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/depthwise_weights" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 576, + 96 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_12/project/Conv2D/merged_input" + }, + { + "shape": [ + 96 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 96, + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/Conv2D/merged_input" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 576, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/depthwise_weights" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 576, + 96 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_11/project/Conv2D/merged_input" + }, + { + "shape": [ + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 64, + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/Conv2D/merged_input" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 384, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/depthwise_weights" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 384, + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_9/project/Conv2D/merged_input" + }, + { + "shape": [ + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 64, + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/Conv2D/merged_input" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 384, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/depthwise_weights" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 384, + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_8/project/Conv2D/merged_input" + }, + { + "shape": [ + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 64, + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/Conv2D/merged_input" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 384, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/depthwise_weights" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 384, + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_7/project/Conv2D/merged_input" + }, + { + "shape": [ + 32 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 32, + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/Conv2D/merged_input" + }, + { + "shape": [ + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 192, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/depthwise_weights" + }, + { + "shape": [ + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 192, + 32 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_5/project/Conv2D/merged_input" + }, + { + "shape": [ + 32 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 32, + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/Conv2D/merged_input" + }, + { + "shape": [ + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 192, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/depthwise_weights" + }, + { + "shape": [ + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 192, + 32 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_4/project/Conv2D/merged_input" + }, + { + "shape": [ + 24 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 24, + 144 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/Conv2D/merged_input" + }, + { + "shape": [ + 144 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 144, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/depthwise_weights" + }, + { + "shape": [ + 144 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 144 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 144, + 24 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_2/project/Conv2D/merged_input" + }, + { + "shape": [], + "dtype": "float32", + "name": "Preprocessor/mul/x" + }, + { + "shape": [], + "dtype": "int32", + "name": "Preprocessor/map/TensorArrayStack/range/start" + }, + { + "shape": [], + "dtype": "float32", + "name": "Preprocessor/sub/y" + }, + { + "shape": [ + 3, + 3, + 3, + 32 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/Conv/Conv2D/merged_input" + }, + { + "shape": [ + 32 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/Conv/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 32, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/depthwise_weights" + }, + { + "shape": [ + 32 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 32 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 32, + 16 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv/project/Conv2D/merged_input" + }, + { + "shape": [ + 16 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 16, + 96 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/Conv2D/merged_input" + }, + { + "shape": [ + 96 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 96, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/depthwise_weights" + }, + { + "shape": [ + 96 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 96 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 96, + 24 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/project/Conv2D/merged_input" + }, + { + "shape": [ + 24 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_1/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 24, + 144 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/Conv2D/merged_input" + }, + { + "shape": [ + 144 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 144, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/depthwise_weights" + }, + { + "shape": [ + 144 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 144 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 144, + 32 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/project/Conv2D/merged_input" + }, + { + "shape": [ + 32 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_3/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 32, + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/Conv2D/merged_input" + }, + { + "shape": [ + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 192, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/depthwise_weights" + }, + { + "shape": [ + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 192 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 192, + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/project/Conv2D/merged_input" + }, + { + "shape": [ + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_6/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 64, + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/Conv2D/merged_input" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 384, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/depthwise_weights" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 384 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 384, + 96 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/project/Conv2D/merged_input" + }, + { + "shape": [ + 96 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_10/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 96, + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/Conv2D/merged_input" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 576, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/depthwise_weights" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 576 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 576, + 160 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/project/Conv2D/merged_input" + }, + { + "shape": [ + 160 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_13/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 160, + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/Conv2D/merged_input" + }, + { + "shape": [ + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/expand/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 960, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/depthwise_weights" + }, + { + "shape": [ + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 960 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 960, + 320 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/project/Conv2D/merged_input" + }, + { + "shape": [ + 320 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/expanded_conv_16/project/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 320, + 1280 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/Conv_1/Conv2D/merged_input" + }, + { + "shape": [ + 1280 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/Conv_1/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 1280, + 256 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/Conv2D/merged_input" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_2_1x1_256/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 256, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/depthwise_weights" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512_depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 256, + 512 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/Conv2D/merged_input" + }, + { + "shape": [ + 512 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_2_3x3_s2_512/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 512, + 128 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/Conv2D/merged_input" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_3_1x1_128/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 128, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/depthwise_weights" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256_depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 128, + 256 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/Conv2D/merged_input" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_3_3x3_s2_256/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 256, + 128 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/Conv2D/merged_input" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_4_1x1_128/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 128, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/depthwise_weights" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256_depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 128, + 256 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/Conv2D/merged_input" + }, + { + "shape": [ + 256 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_4_3x3_s2_256/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 256, + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/Conv2D/merged_input" + }, + { + "shape": [ + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_1_Conv2d_5_1x1_64/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 3, + 3, + 64, + 1 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/depthwise_weights" + }, + { + "shape": [ + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/BatchNorm/batchnorm/mul" + }, + { + "shape": [ + 64 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128_depthwise/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1, + 1, + 64, + 128 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/Conv2D/merged_input" + }, + { + "shape": [ + 128 + ], + "dtype": "float32", + "name": "FeatureExtractor/MobilenetV2/layer_19_2_Conv2d_5_3x3_s2_128/BatchNorm/batchnorm/sub" + }, + { + "shape": [ + 1 + ], + "dtype": "int32", + "name": "Postprocessor/strided_slice/stack" + }, + { + "shape": [ + 1 + ], + "dtype": "int32", + "name": "Postprocessor/strided_slice/stack_1" + }, + { + "shape": [], + "dtype": "int32", + "name": "BoxPredictor_5/stack/1" + }, + { + "shape": [], + "dtype": "int32", + "name": "BoxPredictor_0/stack_1/2" + }, + { + "shape": [], + "dtype": "int32", + "name": "Postprocessor/Tile/multiples/1" + }, + { + "shape": [ + 3 + ], + "dtype": "int32", + "name": "Postprocessor/Slice/begin" + }, + { + "shape": [ + 3 + ], + "dtype": "int32", + "name": "Postprocessor/Slice/size" + }, + { + "shape": [], + "dtype": "int32", + "name": "Preprocessor/map/while/ResizeImage/ExpandDims/dim" + }, + { + "shape": [ + 2 + ], + "dtype": "int32", + "name": "Preprocessor/map/while/ResizeImage/stack" + }, + { + "shape": [], + "dtype": "int32", + "name": "Preprocessor/map/while/add/y" + }, + { + "shape": [ + 2 + ], + "dtype": "int32", + "name": "Postprocessor/Decode/transpose/sub_1" + }, + { + "shape": [ + 2 + ], + "dtype": "int32", + "name": "Postprocessor/Decode/get_center_coordinates_and_sizes/transpose/sub_1" + }, + { + "shape": [ + 2 + ], + "dtype": "int32", + "name": "Postprocessor/Decode/transpose_1/sub_1" + } + ], + "paths": [ + "group1-shard1of5", + "group1-shard2of5", + "group1-shard3of5", + "group1-shard4of5", + "group1-shard5of5" + ] + } + ] +} \ No newline at end of file diff --git a/electron-builder.yml b/electron-builder.yml index f67de1d781..d2cfd01234 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -20,3 +20,5 @@ linux: - snap publish: null electronVersion: 3.0.13 +extraFiles: + - "cocoSSDModel" diff --git a/package-lock.json b/package-lock.json index d633f4d85a..55cc08d4e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vott", - "version": "2.0.0", + "version": "2.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1017,6 +1017,55 @@ "loader-utils": "^1.1.0" } }, + "@tensorflow/tfjs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-1.0.3.tgz", + "integrity": "sha512-tF6GcjO2KBYlPPiS7o4X+D3oASXJcWAYaZA13GCYp5cXAui0ncHxpC85kmNQlp2HEVmcE82BJz/1uUtkNxxQpw==", + "requires": { + "@tensorflow/tfjs-converter": "1.0.3", + "@tensorflow/tfjs-core": "1.0.3", + "@tensorflow/tfjs-data": "1.0.3", + "@tensorflow/tfjs-layers": "1.0.3" + } + }, + "@tensorflow/tfjs-converter": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-1.0.3.tgz", + "integrity": "sha512-vrGvVrPekhTOwMGsomcpcjw0ZUep6xhI8DQQoFXHjBcprt9bFO2hHMdAmYpqafcJ7KVMylbK4h2LJrsBI2zDgQ==" + }, + "@tensorflow/tfjs-core": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-1.0.3.tgz", + "integrity": "sha512-2UbjMQkmrykIIZuoRfmDPrtWm+6fdQRlYLCUJdiOIooeu/q4nye587HM1qKcdZosGPZTW6VvX+4VIVieYn5i0A==", + "requires": { + "@types/seedrandom": "2.4.27", + "@types/webgl-ext": "0.0.30", + "@types/webgl2": "0.0.4", + "seedrandom": "2.4.3" + } + }, + "@tensorflow/tfjs-data": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-1.0.3.tgz", + "integrity": "sha512-WFjYU2pWNZ0TZaJ7rN18GD/wOTVe6rBGxvSwZxIhEVIbwKXaKXFa9V4aGp4QBG9AXHIA89SjmGSGPxfsC015hQ==", + "requires": { + "@types/node-fetch": "^2.1.2", + "node-fetch": "~2.1.2", + "seedrandom": "~2.4.3" + }, + "dependencies": { + "node-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=" + } + } + }, + "@tensorflow/tfjs-layers": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-1.0.3.tgz", + "integrity": "sha512-7VdvQb0ft7TrWAbBy7HI+p420KX9rblYYACZ7/BzvzsikfEOdEL90WxrZDjZ167rYN/KvqC/haGcmhW/dYU3MA==" + }, "@types/axios": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz", @@ -1074,6 +1123,15 @@ "integrity": "sha512-NVQEMviDWjuen3UW+mU1J6fZ0WhOfG1yRce/2OTcbaz+fgmTw2cahx6N2wh0Yl+a+hg2UZj/oElZmtULWyGIsA==", "dev": true }, + "@types/json2csv": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@types/json2csv/-/json2csv-4.4.0.tgz", + "integrity": "sha512-24S6hQGGsOZxTXbRyKvNaV5k882XTo9RX/LH6+RtVtimFNE2J0T/LWlru6BeEssByVA9/ZLif1PLk/8X8/qPCQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/lodash": { "version": "4.14.120", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.120.tgz", @@ -1087,8 +1145,15 @@ "@types/node": { "version": "10.12.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.7.tgz", - "integrity": "sha512-Zh5Z4kACfbeE8aAOYh9mqotRxaZMro8MbBQtR8vEXOMiZo2rGEh2LayJijKdlu48YnS6y2EFU/oo2NCe5P6jGw==", - "dev": true + "integrity": "sha512-Zh5Z4kACfbeE8aAOYh9mqotRxaZMro8MbBQtR8vEXOMiZo2rGEh2LayJijKdlu48YnS6y2EFU/oo2NCe5P6jGw==" + }, + "@types/node-fetch": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.1.7.tgz", + "integrity": "sha512-TZozHCDVrs0Aj1B9ZR5F4Q9MknDNcVd+hO5lxXOCzz07ELBey6s1gMUSZHUYHlPfRFKJFXiTnNuD7ePiI6S4/g==", + "requires": { + "@types/node": "*" + } }, "@types/prop-types": { "version": "15.5.8", @@ -1230,6 +1295,11 @@ "redux": "^4.0.0" } }, + "@types/seedrandom": { + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.27.tgz", + "integrity": "sha1-nbVjk33YaRX2kJK8QyWdL0hXjkE=" + }, "@types/snapsvg": { "version": "0.4.35", "resolved": "https://registry.npmjs.org/@types/snapsvg/-/snapsvg-0.4.35.tgz", @@ -1243,6 +1313,16 @@ "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz", "integrity": "sha512-42zEJkBpNfMEAvWR5WlwtTH22oDzcMjFsL9gDGExwF8X8WvAiw7Vwop7hPw03QT8TKfec83LwbHj6SvpqM4ELQ==" }, + "@types/webgl-ext": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/webgl-ext/-/webgl-ext-0.0.30.tgz", + "integrity": "sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==" + }, + "@types/webgl2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.4.tgz", + "integrity": "sha512-PACt1xdErJbMUOUweSrbVM7gSIYm1vTncW2hF6Os/EeWi6TXYAYMPp+8v6rzHmypE5gHrxaxZNXgMkJVIdZpHw==" + }, "@webassemblyjs/ast": { "version": "1.7.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.6.tgz", @@ -7239,7 +7319,8 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "optional": true }, "aproba": { "version": "1.2.0", @@ -7282,7 +7363,8 @@ "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "optional": true }, "concat-map": { "version": "0.0.1", @@ -7293,7 +7375,8 @@ "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -7423,6 +7506,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -7552,7 +7636,8 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "optional": true }, "object-assign": { "version": "4.1.1", @@ -7650,7 +7735,8 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -7686,6 +7772,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7705,6 +7792,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7748,12 +7836,14 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "optional": true }, "yallist": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "optional": true } } }, @@ -9372,6 +9462,17 @@ "requires": { "node-fetch": "^1.0.1", "whatwg-fetch": ">=0.10.0" + }, + "dependencies": { + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + } } }, "isstream": { @@ -10142,6 +10243,11 @@ "topo": "2.x.x" } }, + "jpeg-js": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.4.tgz", + "integrity": "sha512-6IzjQxvnlT8UlklNmDXIJMWxijULjqGrzgqc0OG7YadZdvm7KPQ1j0ehmQQHckgEWOfgpptzcnWgESovxudpTA==" + }, "jquery": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", @@ -10260,6 +10366,16 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "json2csv": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-4.5.0.tgz", + "integrity": "sha512-SfWprYRawoBsEHZyb1NvZz2qJpuLRDlSexHqtnHxFEFvzK83zgm7Bftq2miBODjRQG0O7PaHC5271Hfbu10P+w==", + "requires": { + "commander": "^2.15.1", + "jsonparse": "^1.3.1", + "lodash.get": "^4.4.2" + } + }, "json3": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", @@ -10283,6 +10399,11 @@ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -10518,6 +10639,11 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, "lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -11253,13 +11379,9 @@ } }, "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", + "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" }, "node-forge": { "version": "0.7.5", @@ -16369,6 +16491,11 @@ } } }, + "seedrandom": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.3.tgz", + "integrity": "sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw=" + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", diff --git a/package.json b/package.json index 5dde953633..cdbc91a468 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vott", - "version": "2.0.0", + "version": "2.1.0", "author": { "name": "Microsoft", "url": "https://github.com/Microsoft/VoTT" @@ -16,6 +16,7 @@ "main": "build/main.js", "dependencies": { "@azure/storage-blob": "^10.3.0", + "@tensorflow/tfjs": "^1.0.3", "@types/snapsvg": "^0.4.35", "axios": "^0.18.0", "bootstrap": "^4.1.3", @@ -23,8 +24,11 @@ "crypto-js": "^3.1.9-1", "dotenv": "^7.0.0", "google-protobuf": "^3.6.1", + "jpeg-js": "^0.3.4", + "json2csv": "^4.5.0", "lodash": "^4.17.11", "md5.js": "^1.3.5", + "node-fetch": "^2.3.0", "node-int64": "^0.4.0", "rc-align": "^2.4.5", "rc-checkbox": "^2.1.6", @@ -95,6 +99,7 @@ "@types/dotenv": "^6.1.0", "@types/enzyme": "^3.1.15", "@types/jest": "23.3.9", + "@types/json2csv": "^4.4.0", "@types/node": "10.12.7", "@types/react": "16.7.6", "@types/react-dom": "16.0.9", diff --git a/src/common/htmlFileReader.test.ts b/src/common/htmlFileReader.test.ts index 7f9e40f6aa..be8c189d69 100644 --- a/src/common/htmlFileReader.test.ts +++ b/src/common/htmlFileReader.test.ts @@ -10,17 +10,7 @@ describe("Html File Reader", () => { beforeEach(() => { assetTestCache.clear(); - - document.createElement = jest.fn((elementType) => { - switch (elementType) { - case "img": - return mockImage(); - case "video": - return mockVideo(); - case "canvas": - return mockCanvas(); - } - }); + MockFactory.mockElement(assetTestCache); }); it("Resolves promise after successfully reading file", async () => { @@ -234,67 +224,4 @@ describe("Html File Reader", () => { await expect(HtmlFileReader.getAssetFrameImage(videoErrorFrame)).rejects.not.toBeNull(); }); }); - - const mockImage = jest.fn(() => { - const element: any = { - naturalWidth: 0, - naturalHeight: 0, - onload: jest.fn(), - }; - - setImmediate(() => { - const asset = assetTestCache.get(element.src); - element.naturalWidth = asset.size.width; - element.naturalHeight = asset.size.height; - - element.onload(); - }); - - return element; - }); - - const mockVideo = jest.fn(() => { - const element: any = { - src: "", - duration: 0, - currentTime: 0, - videoWidth: 0, - videoHeight: 0, - onloadedmetadata: jest.fn(), - onseeked: jest.fn(), - onerror: jest.fn(), - }; - - setImmediate(() => { - const asset = assetTestCache.get(element.src); - if (asset.name.toLowerCase().indexOf("error") > -1) { - element.onerror("An error occurred loading the video"); - } else { - element.videoWidth = asset.size.width; - element.videoHeight = asset.size.height; - element.currentTime = asset.timestamp; - element.onloadedmetadata(); - element.onseeked(); - } - }); - - return element; - }); - - const mockCanvas = jest.fn(() => { - const canvas: any = { - width: 0, - height: 0, - getContext: jest.fn(() => { - return { - drawImage: jest.fn(), - }; - }), - toBlob: jest.fn((callback) => { - callback(new Blob(["Binary image data"])); - }), - }; - - return canvas; - }); }); diff --git a/src/common/localization/en-us.ts b/src/common/localization/en-us.ts index 8b302d2b28..cd5b7a81f7 100644 --- a/src/common/localization/en-us.ts +++ b/src/common/localization/en-us.ts @@ -143,6 +143,7 @@ export const english: IAppStrings = { warnings: { existingName: "Tag name already exists. Choose another name", emptyName: "Cannot have an empty tag name", + unknownTagName: "Unknown", }, toolbar: { add: "Add new tag", @@ -231,6 +232,7 @@ export const english: IAppStrings = { nextAsset: "Next Asset", saveProject: "Save Project", exportProject: "Export Project", + activeLearning: "Active Learning", }, videoPlayer: { previousTaggedFrame: { @@ -256,6 +258,15 @@ export const english: IAppStrings = { apply: "Apply Tag with Hot Key", lock: "Lock Tag with Hot Key", }, + rename: { + title: "Rename Tag", + confirmation: "Are you sure you want to rename this tag? It will be renamed throughout all assets", + }, + delete: { + title: "Delete Tag", + confirmation: "Are you sure you want to delete this tag? It will be deleted throughout all assets \ + and any regions where this is the only tag will also be deleted", + }, }, canvas: { removeAllRegions: { @@ -266,8 +277,8 @@ export const english: IAppStrings = { messages: { enforceTaggedRegions: { title: "Invalid region(s) detected", - // tslint:disable-next-line:max-line-length - description: "1 or more regions have not been tagged. Ensure all regions are tagged before continuing to next asset.", + description: "1 or more regions have not been tagged. Ensure all regions are tagged before \ + continuing to next asset.", }, }, }, @@ -287,23 +298,43 @@ export const english: IAppStrings = { tagged: "Only tagged Assets", }, }, - }, - }, - vottJson: { - displayName: "VoTT JSON", - properties: { + testTrainSplit: { + title: "Test / Train Split", + description: "The test train split to use for exported data", + }, includeImages: { title: "Include Images", description: "Whether or not to include binary image assets in target connection", }, }, }, + vottJson: { + displayName: "VoTT JSON", + }, azureCV: { displayName: "Azure Custom Vision Service", + regions: { + australiaEast: "Australia East", + centralIndia: "Central India", + eastUs: "East US", + eastUs2: "East US 2", + japanEast: "Japan East", + northCentralUs: "North Central US", + northEurope: "North Europe", + southCentralUs: "South Central US", + southeastAsia: "Southeast Asia", + ukSouth: "UK South", + westUs2: "West US 2", + westEurope: "West Europe", + }, properties: { apiKey: { title: "API Key", }, + region: { + title: "Region", + description: "The Azure region where your service is deployed", + }, classificationType: { title: "Classification Type", options: { @@ -342,17 +373,19 @@ export const english: IAppStrings = { tfRecords: { displayName: "Tensorflow Records", }, - tfPascalVoc: { - displayName: "Tensorflow Pascal VOC", - testTrainSplit: { - title: "Test / Train Split", - description: "The test train split to use for exported data", - }, + pascalVoc: { + displayName: "Pascal VOC", exportUnassigned: { title: "Export Unassigned", description: "Whether or not to include unassigned tags in exported data", }, }, + cntk: { + displayName: "Microsoft Cognitive Toolkit (CNTK)", + }, + csv: { + displayName: "Comma Separated Values (CSV)", + }, }, messages: { saveSuccess: "Successfully saved export settings", @@ -360,6 +393,40 @@ export const english: IAppStrings = { }, activeLearning: { title: "Active Learning", + form: { + properties: { + modelPathType: { + title: "Model Provider", + description: "Where to load the training model from", + options: { + preTrained: "Pre-trained Coco SSD", + customFilePath: "Custom (File path)", + customWebUrl: "Custom (Url)", + }, + }, + autoDetect: { + title: "Auto Detect", + description: "Whether or not to automatically make predictions as you navigate between assets", + }, + modelPath: { + title: "Model path", + description: "Select a model from your local file system", + }, + modelUrl: { + title: "Model URL", + description: "Load your model from a public web URL", + }, + predictTag: { + title: "Predict Tag", + description: "Whether or not to automatically include tags in predictions", + }, + }, + }, + messages: { + loadingModel: "Loading active learning model...", + errorLoadModel: "Error loading active learning model", + saveSuccess: "Successfully saved active learning settings", + }, }, profile: { settings: "Profile Settings", @@ -413,5 +480,10 @@ export const english: IAppStrings = { title: "Error exporting project", message: "Project is missing export format. Please select an export format in the export setting page.", }, + activeLearningPredictionError: { + title: "Active Learning Error", + message: "An error occurred while predicting regions in the current asset. \ + Please verify your active learning configuration and try again", + }, }, }; diff --git a/src/common/localization/es-cl.ts b/src/common/localization/es-cl.ts index 80d2dbf5a6..5f6f7857a1 100644 --- a/src/common/localization/es-cl.ts +++ b/src/common/localization/es-cl.ts @@ -60,8 +60,8 @@ export const spanish: IAppStrings = { }, securityTokens: { title: "Tokens de seguridad", - // tslint:disable-next-line:max-line-length - description: "Los tokens de seguridad se utilizan para cifrar datos confidenciales dentro de la configuración del proyecto", + description: "Los tokens de seguridad se utilizan para cifrar datos confidenciales \ + dentro de la configuración del proyecto", }, version: { description: "Versión:", @@ -144,6 +144,7 @@ export const spanish: IAppStrings = { warnings: { existingName: "Nombre de etiqueta ya existe. Elige otro nombre", emptyName: "El nombre de etiqueta no puede ser vacío", + unknownTagName: "Desconocido", }, toolbar: { add: "Agregar nueva etiqueta", @@ -233,6 +234,7 @@ export const spanish: IAppStrings = { nextAsset: "Siguiente activo", saveProject: "Guardar Proyecto", exportProject: "Exprtar Proyecto", + activeLearning: "Aprendizaje Activo", }, videoPlayer: { previousTaggedFrame: { @@ -258,6 +260,16 @@ export const spanish: IAppStrings = { apply: "Aplicar etiqueta con tecla de acceso rápido", lock: "Bloquear etiqueta con tecla de acceso rápido", }, + rename: { + title: "Cambiar el nombre de la etiqueta", + confirmation: "¿Está seguro que quiere cambiar el nombre de esta etiqueta? \ + Será cambiada en todos los activos", + }, + delete: { + title: "Delete Tag", + confirmation: "¿Está seguro que quiere borrar esta etiqueta? Será borrada en todos \ + los activos y en las regiones donde esta etiqueta sea la única, la region también será borrada", + }, }, canvas: { removeAllRegions: { @@ -268,8 +280,8 @@ export const spanish: IAppStrings = { messages: { enforceTaggedRegions: { title: "Las regiones no válidas detectadas", - // tslint:disable-next-line:max-line-length - description: "1 o más regiones no se han etiquetado. Por favor, etiquete todas las regiones antes de continuar con el siguiente activo.", + description: "1 o más regiones no se han etiquetado. \ + Por favor, etiquete todas las regiones antes de continuar con el siguiente activo.", }, }, }, @@ -289,23 +301,43 @@ export const spanish: IAppStrings = { tagged: "Solo activos etiquetados", }, }, - }, - }, - vottJson: { - displayName: "VoTT JSON", - properties: { + testTrainSplit: { + title: "La división para entrenar y comprobar", + description: "La división de datos para utilizar entre el entrenamiento y la comprobación", + }, includeImages: { title: "Incluir imágenes", description: "Si desea o no incluir activos de imagen binaria en la conexión de destino", }, }, }, + vottJson: { + displayName: "VoTT JSON", + }, azureCV: { displayName: "Servicio de Visión Personalizada Azure", + regions: { + australiaEast: "Australia este", + centralIndia: "Centro de la India", + eastUs: "Este de EE.", + eastUs2: "Este US 2", + japanEast: "Japón este", + northCentralUs: "Centro norte de EE.", + northEurope: "Europa del norte", + southCentralUs: "Centro sur de EE.", + southeastAsia: "Sudeste asiático", + ukSouth: "UK sur", + westUs2: "West US 2", + westEurope: "Europa occidental", + }, properties: { apiKey: { title: "Clave de API", }, + region: { + title: "Región", + description: "La región de Azure donde se implementa el servicio", + }, classificationType: { title: "Tipo de clasificación", options: { @@ -344,17 +376,19 @@ export const spanish: IAppStrings = { tfRecords: { displayName: "Registros de Tensorflow", }, - tfPascalVoc: { - displayName: "Tensorflow Pascal VOC", - testTrainSplit: { - title: "Prueba/tren Split", - description: "La división del tren de prueba que se utilizará para los datos exportados", - }, + pascalVoc: { + displayName: "Pascal VOC", exportUnassigned: { title: "Exportar sin asignar", description: "Si se incluyen o no etiquetas no asignadas en los datos exportados", }, }, + cntk: { + displayName: "Microsoft Cognitive Toolkit (CNTK)", + }, + csv: { + displayName: "Los valores separados por comas (CSV)", + }, }, messages: { saveSuccess: "Configuración de exportación guardada correctamente", @@ -362,6 +396,41 @@ export const spanish: IAppStrings = { }, activeLearning: { title: "Aprendizaje Activo", + form: { + properties: { + modelPathType: { + title: "Proveedor del modelo", + description: "Fuente desde la cual cargar el modelo", + options: { + preTrained: "SSD de coco pre-entrenado", + customFilePath: "Personalizado (ruta de archivo)", + customWebUrl: "Personalizado (URL)", + }, + }, + autoDetect: { + title: "Detección automática", + description: "Si desea o no realizar automáticamente predicciones a \ + medida que navega entre activos", + }, + modelPath: { + title: "Ruta de modelo", + description: "Seleccione un modelo de su sistema de archivos local", + }, + modelUrl: { + title: "URL del modelo", + description: "Cargue el modelo desde una URL web pública", + }, + predictTag: { + title: "Predecir etiqueta", + description: "Si se incluirán o no automáticamente las etiquetas en las predicciones", + }, + }, + }, + messages: { + loadingModel: "Cargando modelo...", + errorLoadModel: "Error al cargar el modelo", + saveSuccess: "La configuración de aprendizaje activa se ha guardada correctamente", + }, }, profile: { settings: "Configuración de Perfíl", @@ -417,5 +486,10 @@ export const spanish: IAppStrings = { message: `Proyecto falta el formato de exportación. Seleccione un formato de exportación en la página de configuración de exportación.`, }, + activeLearningPredictionError: { + title: "Error de aprendizaje", + message: "Se ha producido un error al predecir regiones en el activo actual. \ + Compruebe la configuración de aprendizaje activa y vuelva a intentarlo", + }, }, }; diff --git a/src/common/mockFactory.ts b/src/common/mockFactory.ts index a808b71677..f3902f0bcb 100644 --- a/src/common/mockFactory.ts +++ b/src/common/mockFactory.ts @@ -3,7 +3,7 @@ import { AssetState, AssetType, IApplicationState, IAppSettings, IAsset, IAssetMetadata, IConnection, IExportFormat, IProject, ITag, StorageType, ISecurityToken, EditorMode, IAppError, IProjectVideoSettings, ErrorCode, - IPoint, IRegion, RegionType, + IPoint, IRegion, RegionType, ModelPathType, } from "../models/applicationState"; import { IV1Project, IV1Region } from "../models/v1Models"; import { ExportAssetState } from "../providers/export/exportProvider"; @@ -33,6 +33,7 @@ import { SelectionMode } from "vott-ct/lib/js/CanvasTools/Interface/ISelectorSet import { IKeyboardBindingProps } from "../react/components/common/keyboardBinding/keyboardBinding"; import { KeyEventType } from "../react/components/common/keyboardManager/keyboardManager"; import { IKeyboardRegistrations } from "../react/components/common/keyboardManager/keyboardRegistrationManager"; +import { IActiveLearningPageProps } from "../react/components/pages/activeLearning/activeLearningPage"; export default class MockFactory { @@ -283,6 +284,13 @@ export default class MockFactory { targetConnection: connection, tags: MockFactory.createTestTags(tagCount), videoSettings: MockFactory.createVideoSettings(), + activeLearningSettings: { + modelPathType: ModelPathType.Coco, + modelPath: "", + modelUrl: "", + autoDetect: false, + predictTag: false, + }, autoSave: true, }; } @@ -630,14 +638,14 @@ export default class MockFactory { /** * Creates array of IExportProviderRegistrationOptions for the different providers - * vottJson, tensorFlowPascalVOC, azureCustomVision + * vottJson, PascalVOC, azureCustomVision, csv */ public static createExportProviderRegistrations(): IExportProviderRegistrationOptions[] { const registrations: IExportProviderRegistrationOptions[] = []; registrations.push(MockFactory.createExportProviderRegistration("vottJson")); - registrations.push(MockFactory.createExportProviderRegistration("tensorFlowPascalVOC")); + registrations.push(MockFactory.createExportProviderRegistration("pascalVOC")); registrations.push(MockFactory.createExportProviderRegistration("azureCustomVision")); - + registrations.push(MockFactory.createExportProviderRegistration("csv")); return registrations; } @@ -810,14 +818,16 @@ export default class MockFactory { */ public static projectActions(): IProjectActions { return { - loadProject: jest.fn((project: IProject) => Promise.resolve()), - saveProject: jest.fn((project: IProject) => Promise.resolve()), - deleteProject: jest.fn((project: IProject) => Promise.resolve()), + loadProject: jest.fn(() => Promise.resolve()), + saveProject: jest.fn(() => Promise.resolve()), + deleteProject: jest.fn(() => Promise.resolve()), closeProject: jest.fn(() => Promise.resolve()), - loadAssets: jest.fn((project: IProject) => Promise.resolve()), - exportProject: jest.fn((project: IProject) => Promise.resolve()), - loadAssetMetadata: jest.fn((project: IProject, asset: IAsset) => Promise.resolve()), - saveAssetMetadata: jest.fn((project: IProject, assetMetadata: IAssetMetadata) => Promise.resolve()), + loadAssets: jest.fn(() => Promise.resolve()), + exportProject: jest.fn(() => Promise.resolve()), + loadAssetMetadata: jest.fn(() => Promise.resolve()), + saveAssetMetadata: jest.fn(() => Promise.resolve()), + updateProjectTag: jest.fn(() => Promise.resolve()), + deleteProjectTag: jest.fn(() => Promise.resolve()), }; } @@ -884,6 +894,21 @@ export default class MockFactory { }; } + /** + * Creates fake IActiveLearningPageProps + * @param projectId Current project ID + */ + public static activeLearningProps(projectId?: string): IActiveLearningPageProps { + return { + actions: (projectActions as any) as IProjectActions, + history: MockFactory.history(), + location: MockFactory.location(), + match: MockFactory.match(projectId, "active-learning"), + project: null, + recentProjects: MockFactory.createTestProjects(), + }; + } + /** * Creates fake IEditorPageProps * @param projectId Current project ID @@ -1010,6 +1035,93 @@ export default class MockFactory { }; } + public static mockElement(assetTestCache: Map) { + document.createElement = jest.fn((elementType) => { + switch (elementType) { + case "img": + const mockImage = MockFactory.mockImage(assetTestCache); + return mockImage(); + case "video": + const mockVideo = MockFactory.mockVideo(assetTestCache); + return mockVideo(); + case "canvas": + const mockCanvas = MockFactory.mockCanvas(); + return mockCanvas(); + } + }); + } + + public static mockImage(assetTestCache: Map) { + return jest.fn(() => { + const element: any = { + naturalWidth: 0, + naturalHeight: 0, + onload: jest.fn(), + }; + + setImmediate(() => { + const asset = assetTestCache.get(element.src); + if (asset) { + element.naturalWidth = asset.size.width; + element.naturalHeight = asset.size.height; + } + + element.onload(); + }); + + return element; + }); + } + + public static mockVideo(assetTestCache: Map) { + return jest.fn(() => { + const element: any = { + src: "", + duration: 0, + currentTime: 0, + videoWidth: 0, + videoHeight: 0, + onloadedmetadata: jest.fn(), + onseeked: jest.fn(), + onerror: jest.fn(), + }; + + setImmediate(() => { + const asset = assetTestCache.get(element.src); + if (asset.name.toLowerCase().indexOf("error") > -1) { + element.onerror("An error occurred loading the video"); + } else { + element.videoWidth = asset.size.width; + element.videoHeight = asset.size.height; + element.currentTime = asset.timestamp; + element.onloadedmetadata(); + element.onseeked(); + } + }); + + return element; + }); + } + + public static mockCanvas() { + return jest.fn(() => { + const canvas: any = { + width: 800, + height: 600, + getContext: jest.fn(() => { + return { + drawImage: jest.fn(), + }; + }), + toBlob: jest.fn((callback) => { + callback(new Blob(["Binary image data"])); + }), + }; + + return canvas; + }); + } + private static pageProps(projectId: string, method: string) { return { project: null, @@ -1091,5 +1203,4 @@ export default class MockFactory { return StorageType.Other; } } - } diff --git a/src/common/strings.ts b/src/common/strings.ts index 566b7acd20..ff760878ae 100644 --- a/src/common/strings.ts +++ b/src/common/strings.ts @@ -154,6 +154,7 @@ export interface IAppStrings { warnings: { existingName: string; emptyName: string; + unknownTagName: string; } }; connections: { @@ -230,6 +231,7 @@ export interface IAppStrings { nextAsset: string; saveProject: string; exportProject: string; + activeLearning: string; } videoPlayer: { nextTaggedFrame: { @@ -255,6 +257,14 @@ export interface IAppStrings { apply: string; lock: string; }, + rename: { + title: string; + confirmation: string; + }, + delete: { + title: string; + confirmation: string; + }, } canvas: { removeAllRegions: { @@ -285,23 +295,43 @@ export interface IAppStrings { tagged: string, }, }, - }, - }, - vottJson: { - displayName: string, - properties: { + testTrainSplit: { + title: string, + description: string, + }, includeImages: { title: string, description: string, }, }, }, + vottJson: { + displayName: string, + }, azureCV: { displayName: string, + regions: { + eastUs: string, + eastUs2: string, + northCentralUs: string, + southCentralUs: string, + westUs2: string, + westEurope: string, + northEurope: string, + southeastAsia: string, + australiaEast: string, + centralIndia: string, + ukSouth: string, + japanEast: string, + }, properties: { apiKey: { title: string, }, + region: { + title: string, + description: string, + }, newOrExisting: { title: string, options: { @@ -340,17 +370,19 @@ export interface IAppStrings { tfRecords: { displayName: string, }, - tfPascalVoc: { + pascalVoc: { displayName: string, - testTrainSplit: { - title: string, - description: string, - }, exportUnassigned: { title: string, description: string, }, }, + cntk: { + displayName: string, + }, + csv: { + displayName: string, + }, }, messages: { saveSuccess: string; @@ -358,6 +390,40 @@ export interface IAppStrings { }; activeLearning: { title: string; + form: { + properties: { + modelPathType: { + title: string, + description: string, + options: { + preTrained: string, + customFilePath: string, + customWebUrl: string, + }, + }, + autoDetect: { + title: string, + description: string, + }, + predictTag: { + title: string, + description: string, + }, + modelPath: { + title: string, + description: string, + }, + modelUrl: { + title: string, + description: string, + }, + }, + } + messages: { + loadingModel: string; + errorLoadModel: string; + saveSuccess: string; + } }; profile: { settings: string; @@ -374,6 +440,7 @@ export interface IAppStrings { importError: IErrorMetadata, pasteRegionTooBigError: IErrorMetadata, exportFormatNotFound: IErrorMetadata, + activeLearningPredictionError: IErrorMetadata, }; } diff --git a/src/electron/providers/storage/localFileSystem.test.ts b/src/electron/providers/storage/localFileSystem.test.ts index adf00e7fe1..4e3a901506 100644 --- a/src/electron/providers/storage/localFileSystem.test.ts +++ b/src/electron/providers/storage/localFileSystem.test.ts @@ -23,6 +23,7 @@ describe("LocalFileSystem Storage Provider", () => { a: 1, b: 2, c: 3, + d: "한글 中國 にほんご", }; await localFileSystem.writeText(filePath, JSON.stringify(contents, null, 4)); diff --git a/src/electron/providers/storage/localFileSystem.ts b/src/electron/providers/storage/localFileSystem.ts index 1c09a4122b..0367cc82b1 100644 --- a/src/electron/providers/storage/localFileSystem.ts +++ b/src/electron/providers/storage/localFileSystem.ts @@ -71,7 +71,7 @@ export default class LocalFileSystem implements IStorageProvider { } public writeText(filePath: string, contents: string): Promise { - const buffer = Buffer.alloc(contents.length, contents); + const buffer = Buffer.from(contents); return this.writeBinary(filePath, buffer); } diff --git a/src/models/applicationState.ts b/src/models/applicationState.ts index c8ad04a967..41b11bbd33 100644 --- a/src/models/applicationState.ts +++ b/src/models/applicationState.ts @@ -1,4 +1,5 @@ import { ExportAssetState } from "../providers/export/exportProvider"; +import { IAssetPreviewSettings } from "../react/components/common/assetPreview/assetPreview"; /** * @name - Application State @@ -49,6 +50,7 @@ export enum ErrorCode { ExportFormatNotFound = "exportFormatNotFound", PasteRegionTooBig = "pasteRegionTooBig", OverloadedKeyBinding = "overloadedKeyBinding", + ActiveLearningPredictionError = "activeLearningPredictionError", } /** @@ -112,6 +114,7 @@ export interface IProject { targetConnection: IConnection; exportFormat: IExportFormat; videoSettings: IProjectVideoSettings; + activeLearningSettings: IActiveLearningSettings; autoSave: boolean; assets?: { [index: string]: IAsset }; lastVisitedAssetId?: string; @@ -198,6 +201,44 @@ export interface IProjectVideoSettings { frameExtractionRate: number; } +/** + * @name - Model Path Type + * @description - Defines the mechanism to load the TF.js model for Active Learning + * @member Coco - Specifies the default/generic pre-trained Coco-SSD model + * @member File - Specifies to load a custom model from filesystem + * @member Url - Specifies to load a custom model from a web server + */ +export enum ModelPathType { + Coco = "coco", + File = "file", + Url = "url", +} + +/** + * Properties for additional project settings + * @member activeLearningSettings - Active Learning settings + */ +export interface IAdditionalPageSettings extends IAssetPreviewSettings { + activeLearningSettings: IActiveLearningSettings; +} + +/** + * @name - Active Learning Settings for the project + * @description - Defines the active learning settings within a VoTT project + * @member modelPathType - Model loading type ["coco", "file", "url"] + * @member modelPath - Local filesystem path to the TF.js model + * @member modelUrl - Web url to the TF.js model + * @member autoDetect - Flag for automatically call the model while opening a new asset + * @member predictTag - Flag to predict also the tag name other than the rectangle coordinates only + */ +export interface IActiveLearningSettings { + modelPathType: ModelPathType; + modelPath?: string; + modelUrl?: string; + autoDetect: boolean; + predictTag: boolean; +} + /** * @name - Asset Video Settings * @description - Defines the settings for video assets @@ -231,6 +272,7 @@ export interface IAsset { format?: string; timestamp?: number; parent?: IAsset; + predicted?: boolean; } /** diff --git a/src/providers/activeLearning/electronProxyHandler.test.ts b/src/providers/activeLearning/electronProxyHandler.test.ts new file mode 100644 index 0000000000..17eade6e2e --- /dev/null +++ b/src/providers/activeLearning/electronProxyHandler.test.ts @@ -0,0 +1,33 @@ +jest.mock("../storage/localFileSystemProxy"); +import { LocalFileSystemProxy } from "../storage/localFileSystemProxy"; +import { ElectronProxyHandler } from "./electronProxyHandler"; +import * as tf from "@tensorflow/tfjs"; +// tslint:disable-next-line:no-var-requires +const modelJson = require("../../../cocoSSDModel/model.json"); + +describe("Load default model from filesystem with TF io.IOHandler", () => { + it("Check file system proxy is correctly called", async () => { + const storageProviderMock = LocalFileSystemProxy as jest.Mock; + storageProviderMock.mockClear(); + + storageProviderMock.prototype.readText = jest.fn((fileName) => { + return Promise.resolve(JSON.stringify(modelJson)); + }); + + storageProviderMock.prototype.readBinary = jest.fn((fileName) => { + return Promise.resolve([]); + }); + + const handler = new ElectronProxyHandler("folder"); + try { + const model = await tf.loadGraphModel(handler); + } catch (_) { + // fully loading TF model fails as it has to load also weights + } + + expect(LocalFileSystemProxy.prototype.readText).toBeCalledWith("/model.json"); + + // Coco SSD Lite default embedded model has 5 weights matrix + expect(LocalFileSystemProxy.prototype.readBinary).toBeCalledTimes(5); + }); +}); diff --git a/src/providers/activeLearning/electronProxyHandler.ts b/src/providers/activeLearning/electronProxyHandler.ts new file mode 100644 index 0000000000..cbda70f59b --- /dev/null +++ b/src/providers/activeLearning/electronProxyHandler.ts @@ -0,0 +1,76 @@ +import * as tfc from "@tensorflow/tfjs-core"; +import { LocalFileSystemProxy, ILocalFileSystemProxyOptions } from "../../providers/storage/localFileSystemProxy"; + +export class ElectronProxyHandler implements tfc.io.IOHandler { + protected readonly provider: LocalFileSystemProxy; + + constructor(folderPath: string) { + const options: ILocalFileSystemProxyOptions = { folderPath }; + this.provider = new LocalFileSystemProxy(options); + } + + public async load(): Promise { + const modelJSON = JSON.parse(await this.provider.readText("/model.json")); + + const modelArtifacts: tfc.io.ModelArtifacts = { + modelTopology: modelJSON.modelTopology, + }; + + if (modelJSON.weightsManifest != null) { + const [weightSpecs, weightData] = + await this.loadWeights(modelJSON.weightsManifest); + modelArtifacts.weightSpecs = weightSpecs; + modelArtifacts.weightData = weightData; + } + + return modelArtifacts; + } + + public async loadClasses(): Promise { + const json = await this.provider.readText("/classes.json"); + return json ? JSON.parse(json) : null; + } + + private async loadWeights(weightsManifest: tfc.io.WeightsManifestConfig) + : Promise<[tfc.io.WeightsManifestEntry[], ArrayBuffer]> { + const buffers: Buffer[] = []; + const weightSpecs: tfc.io.WeightsManifestEntry[] = []; + + for (const group of weightsManifest) { + for (const shardName of group.paths) { + const buffer = await this.provider.readBinary("/" + shardName); + buffers.push(buffer); + } + weightSpecs.push(...group.weights); + } + + return [weightSpecs, this.toArrayBuffer(buffers)]; + } + + /** + * Convert a Buffer or an Array of Buffers to an ArrayBuffer. + * + * If the input is an Array of Buffers, they will be concatenated in the + * specified order to form the output ArrayBuffer. + */ + private toArrayBuffer(buf: Buffer | Buffer[]): ArrayBuffer { + if (Array.isArray(buf)) { + // An Array of Buffers. + let totalLength = 0; + for (const buffer of buf) { + totalLength += buffer.length; + } + + const ab = new ArrayBuffer(totalLength); + const view = new Uint8Array(ab); + let pos = 0; + for (const buffer of buf) { + pos += buffer.copy(view, pos); + } + return ab; + } else { + // A single Buffer. Return a copy of the underlying ArrayBuffer slice. + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + } + } +} diff --git a/src/providers/activeLearning/objectDetection.test.ts b/src/providers/activeLearning/objectDetection.test.ts new file mode 100644 index 0000000000..ed9e97dec9 --- /dev/null +++ b/src/providers/activeLearning/objectDetection.test.ts @@ -0,0 +1,123 @@ +import * as tf from "@tensorflow/tfjs"; +jest.mock("../storage/localFileSystemProxy"); +import { LocalFileSystemProxy } from "../storage/localFileSystemProxy"; +import { ObjectDetection, DetectedObject } from "./objectDetection"; +import { strings } from "../../common/strings"; +// tslint:disable-next-line:no-var-requires +const modelJson = require("../../../cocoSSDModel/model.json"); + +describe("Load an Object Detection model", () => { + it("Load model from file system using proxy", async () => { + const storageProviderMock = LocalFileSystemProxy as jest.Mock; + storageProviderMock.mockClear(); + + storageProviderMock.prototype.readText = jest.fn((fileName) => { + return Promise.resolve(JSON.stringify(modelJson)); + }); + + storageProviderMock.prototype.readBinary = jest.fn((fileName) => { + return Promise.resolve([]); + }); + + const model = new ObjectDetection(); + + try { + await model.load("path"); + } catch (_) { + // fully loading TF model fails has it has to load also weights + } + + expect(LocalFileSystemProxy.prototype.readText).toBeCalledWith("/model.json"); + + // Coco SSD Lite default embedded model has 5 weights matrix + expect(LocalFileSystemProxy.prototype.readBinary).toBeCalledTimes(5); + + // Modal not properly loaded as readBinary mock is not really loading the weights + expect(model.loaded).toBeFalsy(); + + const noDetection = await model.detect(null); + expect(noDetection.length).toEqual(0); + + model.dispose(); + }); + + it("Load model from http url", async () => { + window.fetch = jest.fn().mockImplementation((url, o) => { + if (url === "http://url/model.json") { + return Promise.resolve({ + ok: true, + json: () => modelJson, + }); + } else { + return Promise.resolve({ + ok: true, + data: () => [], + }); + } + }); + + const model = new ObjectDetection(); + + expect(model.load("http://url")).rejects.not.toBeNull(); + expect(window.fetch).toBeCalledTimes(1); + + // Modal not properly loaded as readBinary mock is not really loading the weights + expect(model.loaded).toBeFalsy(); + + const noDetection = await model.detect(null); + expect(noDetection.length).toEqual(0); + + model.dispose(); + }); +}); + +describe("Test Detection on Fake Model", () => { + beforeEach(() => { + spyOn(tf, "loadGraphModel").and.callFake(() => { + const model = { + executeAsync: + (x: tf.Tensor) => [tf.ones([1, 1917, 90]), tf.ones([1, 1917, 1, 4])], + }; + + return model; + }); + }); + + it("ObjectDetection detect method should generate output", async () => { + const model = new ObjectDetection(); + await model.load("path"); + + const x = tf.zeros([227, 227, 3]) as tf.Tensor3D; + + const data = await model.detect(x, 1); + + expect(data).toEqual([{bbox: [227, 227, 0, 0], class: strings.tags.warnings.unknownTagName, score: 1}]); + }); +}); + +describe("Test predictImage on Fake Model", () => { + beforeEach(() => { + spyOn(tf, "loadGraphModel").and.callFake(() => { + const model = { + executeAsync: + (x: tf.Tensor) => [tf.ones([1, 1917, 90]), tf.ones([1, 1917, 1, 4])], + }; + + return model; + }); + }); + + it("predictImage on a fake image", async () => { + const model = new ObjectDetection(); + await model.load("path"); + + const x = tf.zeros([227, 227, 3]) as tf.Tensor3D; + const regions = await model.predictImage(x, false, 1, 1); + + expect(regions.length).toEqual(20); + expect(regions[0].boundingBox.left).toEqual(227); + expect(regions[0].boundingBox.top).toEqual(227); + expect(regions[0].boundingBox.width).toEqual(0); + expect(regions[0].boundingBox.height).toEqual(0); + }); +}); diff --git a/src/providers/activeLearning/objectDetection.ts b/src/providers/activeLearning/objectDetection.ts new file mode 100755 index 0000000000..196db45aed --- /dev/null +++ b/src/providers/activeLearning/objectDetection.ts @@ -0,0 +1,253 @@ +import axios from "axios"; +import * as shortid from "shortid"; +import * as tf from "@tensorflow/tfjs"; +import { ElectronProxyHandler } from "./electronProxyHandler"; +import { IRegion, RegionType } from "../../models/applicationState"; +import { strings } from "../../common/strings"; + +// tslint:disable-next-line:interface-over-type-literal +export type DetectedObject = { + bbox: [number, number, number, number]; // [x, y, width, height] + class: string; + score: number; +}; + +/** + * Defines supported data types supported by Tensorflow JS + */ +export type ImageObject = tf.Tensor3D | ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement; + +/** + * Object Dectection loads active learning models and predicts regions + */ +export class ObjectDetection { + private modelLoaded: boolean = false; + + get loaded(): boolean { + return this.modelLoaded; + } + + private model: tf.GraphModel; + private jsonClasses: JSON; + + /** + * Dispose the tensors allocated by the model. You should call this when you + * are done with the model. + */ + public dispose() { + if (this.model) { + this.model.dispose(); + } + } + + /** + * Load a TensorFlow.js Object Detection model from file: or http URL. + * @param modelFolderPath file: or http URL to the model + */ + public async load(modelFolderPath: string) { + try { + if (modelFolderPath.toLowerCase().startsWith("http://") || + modelFolderPath.toLowerCase().startsWith("https://")) { + this.model = await tf.loadGraphModel(modelFolderPath + "/model.json"); + + const response = await axios.get(modelFolderPath + "/classes.json"); + this.jsonClasses = JSON.parse(JSON.stringify(response.data)); + } else { + const handler = new ElectronProxyHandler(modelFolderPath); + this.model = await tf.loadGraphModel(handler); + this.jsonClasses = await handler.loadClasses(); + } + + // Warmup the model. + const result = await this.model.executeAsync(tf.zeros([1, 300, 300, 3])) as tf.Tensor[]; + result.forEach(async (t) => await t.data()); + result.forEach(async (t) => t.dispose()); + this.modelLoaded = true; + } catch (err) { + this.modelLoaded = false; + throw err; + } + } + + /** + * Predict Regions from an HTMLImageElement returning list of IRegion. + * @param image ImageObject to be used for prediction + * @param predictTag Flag indicates if predict only region bounding box of tag too. + * @param xRatio Width compression ratio between the HTMLImageElement and the original image. + * @param yRatio Height compression ratio between the HTMLImageElement and the original image. + */ + public async predictImage(image: ImageObject, predictTag: boolean, xRatio: number, yRatio: number) + : Promise { + const regions: IRegion[] = []; + + const predictions = await this.detect(image); + predictions.forEach((prediction) => { + const left = Math.max(0, prediction.bbox[0] * xRatio); + const top = Math.max(0, prediction.bbox[1] * yRatio); + const width = Math.max(0, prediction.bbox[2] * xRatio); + const height = Math.max(0, prediction.bbox[3] * yRatio); + + regions.push({ + id: shortid.generate(), + type: RegionType.Rectangle, + tags: predictTag ? [prediction.class] : [], + boundingBox: { + left, + top, + width, + height, + }, + points: [{ + x: left, + y: top, + }, + { + x: left + width, + y: top, + }, + { + x: left + width, + y: top + height, + }, + { + x: left, + y: top + height, + }], + }); + }); + + return regions; + } + + /** + * Detect objects for an image returning a list of bounding boxes with + * associated class and score. + * + * @param img The image to detect objects from. Can be a tensor or a DOM + * element image, video, or canvas. + * @param maxNumBoxes The maximum number of bounding boxes of detected + * objects. There can be multiple objects of the same class, but at different + * locations. Defaults to 20. + * + */ + public async detect(img: ImageObject, maxNumBoxes: number = 20): Promise { + if (this.model) { + return this.infer(img, maxNumBoxes); + } + + return []; + } + + /** + * Infers through the model. + * + * @param img The image to classify. Can be a tensor or a DOM element image, + * video, or canvas. + * @param maxNumBoxes The maximum number of bounding boxes of detected + * objects. There can be multiple objects of the same class, but at different + * locations. Defaults to 20. + */ + private async infer(img: ImageObject, maxNumBoxes: number = 20): Promise { + const batched = tf.tidy(() => { + if (!(img instanceof tf.Tensor)) { + img = tf.browser.fromPixels(img); + } + // Reshape to a single-element batch so we can pass it to executeAsync. + return img.expandDims(0); + }); + const height = batched.shape[1]; + const width = batched.shape[2]; + + // model returns two tensors: + // 1. box classification score with shape of [1, 1917, 90] + // 2. box location with shape of [1, 1917, 1, 4] + // where 1917 is the number of box detectors, 90 is the number of classes. + // and 4 is the four coordinates of the box. + const result = await this.model.executeAsync(batched) as tf.Tensor[]; + + const scores = result[0].dataSync() as Float32Array; + const boxes = result[1].dataSync() as Float32Array; + + // clean the webgl tensors + batched.dispose(); + tf.dispose(result); + + const [maxScores, classes] = this.calculateMaxScores(scores, result[0].shape[1], result[0].shape[2]); + + const prevBackend = tf.getBackend(); + // run post process in cpu + tf.setBackend("cpu"); + const indexTensor = tf.tidy(() => { + const boxes2 = tf.tensor2d(boxes, [result[1].shape[1], result[1].shape[3]]); + return tf.image.nonMaxSuppression(boxes2, maxScores, maxNumBoxes, 0.5, 0.5); + }); + + const indexes = indexTensor.dataSync() as Float32Array; + indexTensor.dispose(); + + // restore previous backend + tf.setBackend(prevBackend); + + return this.buildDetectedObjects(width, height, boxes, maxScores, indexes, classes); + } + + private buildDetectedObjects( + width: number, height: number, boxes: Float32Array, scores: number[], + indexes: Float32Array, classes: number[]): DetectedObject[] { + const count = indexes.length; + const objects: DetectedObject[] = []; + + for (let i = 0; i < count; i++) { + const bbox = []; + for (let j = 0; j < 4; j++) { + bbox[j] = boxes[indexes[i] * 4 + j]; + } + const minY = bbox[0] * height; + const minX = bbox[1] * width; + const maxY = bbox[2] * height; + const maxX = bbox[3] * width; + bbox[0] = minX; + bbox[1] = minY; + bbox[2] = maxX - minX; + bbox[3] = maxY - minY; + objects.push({ + bbox: bbox as [number, number, number, number], + class: this.getClass(i, indexes, classes), + score: scores[indexes[i]], + }); + } + + return objects; + } + + private getClass(index: number, indexes: Float32Array, classes: number[]): string { + if (this.jsonClasses && index < indexes.length && indexes[index] < classes.length) { + const classId = classes[indexes[index]] - 1; + const classObject = this.jsonClasses[classId]; + + return classObject ? classObject.displayName : strings.tags.warnings.unknownTagName; + } + + return ""; + } + + private calculateMaxScores( + scores: Float32Array, numBoxes: number, + numClasses: number): [number[], number[]] { + const maxes = []; + const classes = []; + for (let i = 0; i < numBoxes; i++) { + let max = Number.MIN_VALUE; + let index = -1; + for (let j = 0; j < numClasses; j++) { + if (scores[i * numClasses + j] > max) { + max = scores[i * numClasses + j]; + index = j; + } + } + maxes[i] = max; + classes[i] = index; + } + return [maxes, classes]; + } +} diff --git a/src/providers/export/azureCustomVision.json b/src/providers/export/azureCustomVision.json index a657b4f5dc..fd130fda41 100644 --- a/src/providers/export/azureCustomVision.json +++ b/src/providers/export/azureCustomVision.json @@ -3,7 +3,8 @@ "title": "${strings.export.providers.azureCV.displayName}", "required": [ "assetState", - "apiKey" + "apiKey", + "region" ], "properties": { "assetState": { @@ -22,6 +23,40 @@ "${strings.export.providers.common.properties.assetState.options.tagged}" ] }, + "region": { + "type": "string", + "title": "${strings.export.providers.azureCV.properties.region.title}", + "description": "${strings.export.providers.azureCV.properties.region.description}", + "default": "southcentralus", + "enum": [ + "australiaeast", + "centralindia", + "eastus", + "eastus2", + "japaneast", + "northcentralus", + "northeurope", + "southcentralus", + "southeastasia", + "uksouth", + "westus2", + "westeurope" + ], + "enumNames": [ + "${strings.export.providers.azureCV.regions.australiaEast}", + "${strings.export.providers.azureCV.regions.centralIndia}", + "${strings.export.providers.azureCV.regions.eastUs}", + "${strings.export.providers.azureCV.regions.eastUs2}", + "${strings.export.providers.azureCV.regions.japanEast}", + "${strings.export.providers.azureCV.regions.northCentralUs}", + "${strings.export.providers.azureCV.regions.northEurope}", + "${strings.export.providers.azureCV.regions.southCentralUs}", + "${strings.export.providers.azureCV.regions.southeastAsia}", + "${strings.export.providers.azureCV.regions.ukSouth}", + "${strings.export.providers.azureCV.regions.westUs2}", + "${strings.export.providers.azureCV.regions.westEurope}" + ] + }, "apiKey": { "type": "string", "title": "${strings.export.providers.azureCV.properties.apiKey.title}" @@ -61,19 +96,20 @@ "projectType": { "type": "string", "title": "${strings.export.providers.azureCV.properties.projectType.title}", + "default": "Classification", "enum": [ "Classification", - "Object Detection" + "ObjectDetection" ], "enumNames": [ "${strings.export.providers.azureCV.properties.projectType.options.classification}", "${strings.export.providers.azureCV.properties.projectType.options.objectDetection}" - ], - "default": "Classification" + ] }, "classificationType": { "type": "string", "title": "${strings.export.providers.azureCV.properties.classificationType.title}", + "default": "Multilabel", "enum": [ "Multilabel", "Multiclass" @@ -81,8 +117,7 @@ "enumNames": [ "${strings.export.providers.azureCV.properties.classificationType.options.multiLabel}", "${strings.export.providers.azureCV.properties.classificationType.options.multiClass}" - ], - "default": "Multilabel" + ] }, "domainId": { "type": "string", @@ -91,6 +126,8 @@ }, "required": [ "name", + "projectType", + "classificationType", "domainId" ] }, diff --git a/src/providers/export/azureCustomVision.test.ts b/src/providers/export/azureCustomVision.test.ts index 3a4f23bfac..e83e834cd5 100644 --- a/src/providers/export/azureCustomVision.test.ts +++ b/src/providers/export/azureCustomVision.test.ts @@ -1,12 +1,15 @@ import shortid from "shortid"; import _ from "lodash"; -import { AzureCustomVisionProvider, IAzureCustomVisionExportOptions, NewOrExisting } from "./azureCustomVision"; +import { + AzureCustomVisionProvider, IAzureCustomVisionExportOptions, + NewOrExisting, AzureRegion, +} from "./azureCustomVision"; import registerProviders from "../../registerProviders"; import { ExportProviderFactory } from "./exportProviderFactory"; import MockFactory from "../../common/mockFactory"; import { IProject, AssetState, IAsset, IAssetMetadata, - RegionType, IRegion, IExportProviderOptions, AssetType, + RegionType, IRegion, IExportProviderOptions, } from "../../models/applicationState"; import { ExportAssetState } from "./exportProvider"; jest.mock("./azureCustomVision/azureCustomVisionService"); @@ -29,6 +32,7 @@ describe("Azure Custom Vision Export Provider", () => { let testProject: IProject = null; const defaultOptions: IAzureCustomVisionExportOptions = { apiKey: expect.any(String), + region: AzureRegion.SouthCentralUS, assetState: ExportAssetState.All, newOrExisting: NewOrExisting.New, projectId: expect.any(String), @@ -64,6 +68,7 @@ describe("Azure Custom Vision Export Provider", () => { assetState: ExportAssetState.All, projectId: "azure-custom-vision-project-1", apiKey: "ABC123", + region: AzureRegion.SouthCentralUS, }, }, }; @@ -81,6 +86,18 @@ describe("Azure Custom Vision Export Provider", () => { expect(provider).toBeInstanceOf(AzureCustomVisionProvider); }); + it("Constructs custom vision service with correct options", () => { + const customVisionMock = AzureCustomVisionService as jest.Mocked; + const providerOptions = testProject.exportFormat.providerOptions as IAzureCustomVisionExportOptions; + providerOptions.region = AzureRegion.WestEurope; + createProvider(testProject); + + expect(customVisionMock).toBeCalledWith({ + apiKey: providerOptions.apiKey, + baseUrl: `https://${providerOptions.region}.api.cognitive.microsoft.com/customvision/v2.2/Training`, + }); + }); + it("Calling save with New project creates Azure Custom Vision project", async () => { const customVisionMock = AzureCustomVisionService as jest.Mocked; customVisionMock.prototype.create = jest.fn((project) => { diff --git a/src/providers/export/azureCustomVision.ts b/src/providers/export/azureCustomVision.ts index 832e21a106..99ff10fbb3 100644 --- a/src/providers/export/azureCustomVision.ts +++ b/src/providers/export/azureCustomVision.ts @@ -17,6 +17,7 @@ import HtmlFileReader from "../../common/htmlFileReader"; export interface IAzureCustomVisionExportOptions extends IExportProviderOptions { assetState: ExportAssetState; newOrExisting: NewOrExisting; + region: AzureRegion; apiKey: string; projectId?: string; name?: string; @@ -38,6 +39,24 @@ export enum NewOrExisting { Existing = "existing", } +/** + * Azure regions + */ +export enum AzureRegion { + EastUS = "eastus", + EastUS2 = "eastus2", + NorthCentralUS = "northcentralus", + SouthCentralUS = "southcentralus", + WestUS2 = "westus2", + WestEurope = "westeurope", + NorthEurope = "northeurope", + SoutheastAsia = "southeastasia", + AustraliaEast = "australiaeast", + CentralIndia = "centralindia", + UKSouth = "uksouth", + JapanEast = "japaneast", +} + /** * @name - Azure Custom Vision Provider * @description - Exports a VoTT project into an Azure custom vision project @@ -49,9 +68,13 @@ export class AzureCustomVisionProvider extends ExportProvider { + const testAssets = MockFactory.createTestAssets(10, 1); + let testProject: IProject = null; + + const defaultOptions: ICntkExportProviderOptions = { + assetState: ExportAssetState.Tagged, + testTrainSplit: 80, + }; + + function createProvider(project: IProject): CntkExportProvider { + return new CntkExportProvider( + project, + project.exportFormat.providerOptions as ICntkExportProviderOptions, + ); + } + + beforeAll(() => { + registerMixins(); + registerProviders(); + + HtmlFileReader.getAssetBlob = jest.fn(() => { + return Promise.resolve(new Blob(["Some binary data"])); + }); + }); + + beforeEach(() => { + jest.resetAllMocks(); + + testAssets.forEach((asset) => { + asset.state = AssetState.Tagged; + }); + + testProject = { + ...MockFactory.createTestProject("TestProject"), + assets: _.keyBy(testAssets, (a) => a.id), + exportFormat: { + providerType: "cntk", + providerOptions: defaultOptions, + }, + }; + + AssetProviderFactory.create = jest.fn(() => { + return { + getAssets: jest.fn(() => Promise.resolve(testAssets)), + }; + }); + + const assetServiceMock = AssetService as jest.Mocked; + assetServiceMock.prototype.getAssetMetadata = jest.fn((asset) => { + const assetMetadata = { + asset: { ...asset }, + regions: [ + MockFactory.createTestRegion("region-1", ["tag1"]), + MockFactory.createTestRegion("region-2", ["tag1"]), + ], + version: appInfo.version, + }; + + return Promise.resolve(assetMetadata); + }); + }); + + it("Is defined", () => { + expect(CntkExportProvider).toBeDefined(); + }); + + it("Can be instantiated through the factory", () => { + const options: ICntkExportProviderOptions = { + assetState: ExportAssetState.All, + testTrainSplit: 80, + }; + const exportProvider = ExportProviderFactory.create("cntk", testProject, options); + expect(exportProvider).not.toBeNull(); + expect(exportProvider).toBeInstanceOf(CntkExportProvider); + }); + + it("Creates correct folder structure", async () => { + const provider = createProvider(testProject); + await provider.export(); + + const storageProviderMock = LocalFileSystemProxy as any; + const createContainerCalls = storageProviderMock.mock.instances[0].createContainer.mock.calls; + const createContainerArgs = createContainerCalls.map((args) => args[0]); + + const expectedFolderPath = "Project-TestProject-CNTK-export"; + expect(createContainerArgs).toContain(expectedFolderPath); + expect(createContainerArgs).toContain(`${expectedFolderPath}/positive`); + expect(createContainerArgs).toContain(`${expectedFolderPath}/negative`); + expect(createContainerArgs).toContain(`${expectedFolderPath}/testImages`); + }); + + it("Writes export files to storage provider", async () => { + const provider = createProvider(testProject); + const getAssetsSpy = jest.spyOn(provider, "getAssetsForExport"); + + await provider.export(); + + const assetsToExport = await getAssetsSpy.mock.results[0].value; + const testSplit = (100 - (defaultOptions.testTrainSplit || 80)) / 100; + const testCount = Math.ceil(assetsToExport.length * testSplit); + const testArray = assetsToExport.slice(0, testCount); + const trainArray = assetsToExport.slice(testCount, assetsToExport.length); + + const storageProviderMock = LocalFileSystemProxy as any; + const writeBinaryCalls = storageProviderMock.mock.instances[0].writeBinary.mock.calls; + const writeTextFileCalls = storageProviderMock.mock.instances[0].writeText.mock.calls; + + expect(writeBinaryCalls).toHaveLength(testAssets.length); + expect(writeTextFileCalls).toHaveLength(testAssets.length * 2); + + testArray.forEach((assetMetadata) => { + const testFolderPath = "Project-TestProject-CNTK-export/testImages"; + assertExportedAsset(testFolderPath, assetMetadata); + }); + + trainArray.forEach((assetMetadata) => { + const trainFolderPath = "Project-TestProject-CNTK-export/positive"; + assertExportedAsset(trainFolderPath, assetMetadata); + }); + }); + + function assertExportedAsset(folderPath: string, assetMetadata: IAssetMetadata) { + const storageProviderMock = LocalFileSystemProxy as any; + const writeBinaryCalls = storageProviderMock.mock.instances[0].writeBinary.mock.calls; + const writeBinaryFilenameArgs = writeBinaryCalls.map((args) => args[0]); + const writeTextFileCalls = storageProviderMock.mock.instances[0].writeText.mock.calls; + const writeTextFilenameArgs = writeTextFileCalls.map((args) => args[0]); + + expect(writeBinaryFilenameArgs).toContain(`${folderPath}/${assetMetadata.asset.name}`); + expect(writeTextFilenameArgs).toContain(`${folderPath}/${assetMetadata.asset.name}.bboxes.labels.tsv`); + expect(writeTextFilenameArgs).toContain(`${folderPath}/${assetMetadata.asset.name}.bboxes.tsv`); + + const writeLabelsCall = writeTextFileCalls + .find((args: string[]) => args[0].indexOf(`${assetMetadata.asset.name}.bboxes.labels.tsv`) >= 0); + + const writeBoxesCall = writeTextFileCalls + .find((args: string[]) => args[0].indexOf(`${assetMetadata.asset.name}.bboxes.tsv`) >= 0); + + const expectedLabelData = `${assetMetadata.regions[0].tags[0]}${os.EOL}${assetMetadata.regions[1].tags[0]}`; + expect(writeLabelsCall[1]).toEqual(expectedLabelData); + + const expectedBoxData = []; + // tslint:disable-next-line:max-line-length + expectedBoxData.push(`${assetMetadata.regions[0].boundingBox.left}\t${assetMetadata.regions[0].boundingBox.left + assetMetadata.regions[0].boundingBox.width}\t${assetMetadata.regions[0].boundingBox.top}\t${assetMetadata.regions[0].boundingBox.top + assetMetadata.regions[0].boundingBox.height}`); + // tslint:disable-next-line:max-line-length + expectedBoxData.push(`${assetMetadata.regions[1].boundingBox.left}\t${assetMetadata.regions[1].boundingBox.left + assetMetadata.regions[1].boundingBox.width}\t${assetMetadata.regions[1].boundingBox.top}\t${assetMetadata.regions[1].boundingBox.top + assetMetadata.regions[1].boundingBox.height}`); + expect(writeBoxesCall[1]).toEqual(expectedBoxData.join(os.EOL)); + } +}); diff --git a/src/providers/export/cntk.ts b/src/providers/export/cntk.ts new file mode 100644 index 0000000000..767f1a1641 --- /dev/null +++ b/src/providers/export/cntk.ts @@ -0,0 +1,104 @@ +import os from "os"; +import { ExportProvider, IExportResults } from "./exportProvider"; +import { IAssetMetadata, IExportProviderOptions, IProject } from "../../models/applicationState"; +import HtmlFileReader from "../../common/htmlFileReader"; +import Guard from "../../common/guard"; + +enum ExportSplit { + Test, + Train, +} + +/** + * Export options for CNTK export provider + */ +export interface ICntkExportProviderOptions extends IExportProviderOptions { + /** The test / train split ratio for exporting data */ + testTrainSplit?: number; +} + +/** + * CNTK Export provider + */ +export class CntkExportProvider extends ExportProvider { + private exportFolderName: string; + + constructor(project: IProject, options: ICntkExportProviderOptions) { + super(project, options); + Guard.null(options); + + this.exportFolderName = `${this.project.name.replace(/\s/g, "-")}-CNTK-export`; + } + + public async export(): Promise { + await this.createFolderStructure(); + const assetsToExport = await this.getAssetsForExport(); + const testSplit = (100 - (this.options.testTrainSplit || 80)) / 100; + const testCount = Math.ceil(assetsToExport.length * testSplit); + const testArray = assetsToExport.slice(0, testCount); + + const results = await assetsToExport.mapAsync(async (assetMetadata) => { + try { + const exportSplit = testArray.find((am) => am.asset.id === assetMetadata.asset.id) + ? ExportSplit.Test + : ExportSplit.Train; + + await this.exportAssetFrame(assetMetadata, exportSplit); + return { + asset: assetMetadata, + success: true, + }; + } catch (e) { + return { + asset: assetMetadata, + success: false, + error: e, + }; + } + }); + + return { + completed: results.filter((r) => r.success), + errors: results.filter((r) => !r.success), + count: results.length, + }; + } + + private async exportAssetFrame(assetMetadata: IAssetMetadata, exportSplit: ExportSplit) { + const labelData = []; + const boundingBoxData = []; + + assetMetadata.regions.forEach((region) => { + region.tags.forEach((tagName) => { + labelData.push(tagName); + // tslint:disable-next-line:max-line-length + boundingBoxData.push(`${region.boundingBox.left}\t${region.boundingBox.left + region.boundingBox.width}\t${region.boundingBox.top}\t${region.boundingBox.top + region.boundingBox.height}`); + }); + }); + + const buffer = await HtmlFileReader.getAssetArray(assetMetadata.asset); + const folderName = exportSplit === ExportSplit.Train ? "positive" : "testImages"; + const labelsPath = `${this.exportFolderName}/${folderName}/${assetMetadata.asset.name}.bboxes.labels.tsv`; + const boundingBoxPath = `${this.exportFolderName}/${folderName}/${assetMetadata.asset.name}.bboxes.tsv`; + const binaryPath = `${this.exportFolderName}/${folderName}/${assetMetadata.asset.name}`; + + await Promise.all([ + this.storageProvider.writeText(labelsPath, labelData.join(os.EOL)), + this.storageProvider.writeText(boundingBoxPath, boundingBoxData.join(os.EOL)), + this.storageProvider.writeBinary(binaryPath, Buffer.from(buffer)), + ]); + } + + private async createFolderStructure(): Promise { + const positiveFolder = `${this.exportFolderName}/positive`; + const negativeFolder = `${this.exportFolderName}/negative`; + const testImagesFolder = `${this.exportFolderName}/testImages`; + + await this.storageProvider.createContainer(this.exportFolderName); + + await [positiveFolder, negativeFolder, testImagesFolder] + .forEachAsync(async (folderPath) => { + await this.storageProvider.createContainer(folderPath); + }); + } +} diff --git a/src/providers/export/cntk.ui.json b/src/providers/export/cntk.ui.json new file mode 100644 index 0000000000..24dffa9463 --- /dev/null +++ b/src/providers/export/cntk.ui.json @@ -0,0 +1,5 @@ +{ + "testTrainSplit": { + "ui:widget": "slider" + } +} diff --git a/src/providers/export/csv.json b/src/providers/export/csv.json new file mode 100644 index 0000000000..45d6ae0cd6 --- /dev/null +++ b/src/providers/export/csv.json @@ -0,0 +1,28 @@ +{ + "type": "object", + "title": "${strings.export.providers.csv.displayName}", + "properties": { + "assetState": { + "type": "string", + "title": "${strings.export.providers.common.properties.assetState.title}", + "description": "${strings.export.providers.common.properties.assetState.description}", + "enum": [ + "all", + "visited", + "tagged" + ], + "default": "visited", + "enumNames": [ + "${strings.export.providers.common.properties.assetState.options.all}", + "${strings.export.providers.common.properties.assetState.options.visited}", + "${strings.export.providers.common.properties.assetState.options.tagged}" + ] + }, + "includeImages": { + "type": "boolean", + "default": true, + "title": "${strings.export.providers.common.properties.includeImages.title}", + "description": "${strings.export.providers.common.properties.includeImages.description}" + } + } +} diff --git a/src/providers/export/csv.test.ts b/src/providers/export/csv.test.ts new file mode 100644 index 0000000000..bdb8f3bf9c --- /dev/null +++ b/src/providers/export/csv.test.ts @@ -0,0 +1,159 @@ +import _ from "lodash"; +import { CsvExportProvider, ICsvExportProviderOptions } from "./csv"; +import registerProviders from "../../registerProviders"; +import { ExportAssetState } from "./exportProvider"; +import { ExportProviderFactory } from "./exportProviderFactory"; +import { + IProject, IAssetMetadata, AssetState, IExportProviderOptions, + RegionType, +} from "../../models/applicationState"; +import MockFactory from "../../common/mockFactory"; + +jest.mock("../../services/assetService"); +import { AssetService } from "../../services/assetService"; + +jest.mock("../storage/localFileSystemProxy"); +import { LocalFileSystemProxy } from "../storage/localFileSystemProxy"; +import registerMixins from "../../registerMixins"; +import HtmlFileReader from "../../common/htmlFileReader"; +import { appInfo } from "../../common/appInfo"; +import { AssetProviderFactory } from "../storage/assetProviderFactory"; +import os from "os"; + +registerMixins(); + +describe("CSV Format Export Provider", () => { + const testAssets = MockFactory.createTestAssets(10, 1); + const testProject: IProject = { + ...MockFactory.createTestProject(), + assets: { + "asset-1": MockFactory.createTestAsset("1", AssetState.Tagged), + "asset-2": MockFactory.createTestAsset("2", AssetState.Tagged), + "asset-3": MockFactory.createTestAsset("3", AssetState.Visited), + "asset-4": MockFactory.createTestAsset("4", AssetState.NotVisited), + }, + exportFormat: { + providerType: "csv", + providerOptions: { + assetState: ExportAssetState.All, + }, + }, + }; + + const expectedFileName = "vott-csv-export/" + testProject.name.replace(" ", "-") + "-export.csv"; + + beforeAll(() => { + HtmlFileReader.getAssetBlob = jest.fn(() => { + return Promise.resolve(new Blob(["Some binary data"])); + }); + + AssetProviderFactory.create = jest.fn(() => { + return { + getAssets: jest.fn(() => Promise.resolve(testAssets)), + }; + }); + }); + + beforeEach(() => { + registerProviders(); + }); + + it("Is defined", () => { + expect(CsvExportProvider).toBeDefined(); + }); + + it("Can be instantiated through the factory", () => { + const options: IExportProviderOptions = { + assetState: ExportAssetState.All, + }; + const exportProvider = ExportProviderFactory.create("csv", testProject, options); + expect(exportProvider).not.toBeNull(); + expect(exportProvider).toBeInstanceOf(CsvExportProvider); + }); + + describe("Export variations", () => { + beforeEach(() => { + const assetServiceMock = AssetService as jest.Mocked; + assetServiceMock.prototype.getAssetMetadata = jest.fn((asset) => { + const assetMetadata: IAssetMetadata = { + asset, + regions: [ + { + id: "1", + type: RegionType.Rectangle, + tags: ["a", "b"], + boundingBox: { + left: 1, + top: 2, + width: 3, + height: 4, + }, + }, + ], + version: appInfo.version, + }; + + return Promise.resolve(assetMetadata); + }); + + const storageProviderMock = LocalFileSystemProxy as jest.Mock; + storageProviderMock.prototype.writeText.mockClear(); + storageProviderMock.prototype.writeBinary.mockClear(); + storageProviderMock.mockClear(); + }); + + it("Exports all assets", async () => { + const options: ICsvExportProviderOptions = { + assetState: ExportAssetState.All, + includeImages: false, + }; + + const exportProvider = new CsvExportProvider(testProject, options); + await exportProvider.export(); + + const storageProviderMock = LocalFileSystemProxy as any; + const exportCsv = storageProviderMock.mock.instances[0].writeText.mock.calls[0][1]; + const records = exportCsv.split(os.EOL); + + // 10 assets - Each with 1 region and 2 tags + expect(records.length).toEqual(testAssets.length * 2 + 1); + + expect(LocalFileSystemProxy.prototype.writeText) + .toBeCalledWith(expectedFileName, expect.any(String)); + }); + + it("Exports only visited assets (includes tagged)", async () => { + const options: ICsvExportProviderOptions = { + assetState: ExportAssetState.Visited, + includeImages: false, + }; + + const exportProvider = new CsvExportProvider(testProject, options); + await exportProvider.export(); + + const storageProviderMock = LocalFileSystemProxy as any; + const exportCsv = storageProviderMock.mock.instances[0].writeText.mock.calls[0][1]; + const records = exportCsv.split(os.EOL); + + // 2 tagged / 1 visited assets - Each with 1 region and 2 tags + expect(records.length).toEqual(7); + }); + + it("Exports only tagged assets", async () => { + const options: ICsvExportProviderOptions = { + assetState: ExportAssetState.Tagged, + includeImages: false, + }; + + const exportProvider = new CsvExportProvider(testProject, options); + await exportProvider.export(); + + const storageProviderMock = LocalFileSystemProxy as any; + const exportCsv = storageProviderMock.mock.instances[0].writeText.mock.calls[0][1]; + const records = exportCsv.split(os.EOL); + + // 2 tagged - Each with 1 region and 2 tags + expect(records.length).toEqual(5); + }); + }); +}); diff --git a/src/providers/export/csv.ts b/src/providers/export/csv.ts new file mode 100644 index 0000000000..17c30e4b34 --- /dev/null +++ b/src/providers/export/csv.ts @@ -0,0 +1,73 @@ +import _ from "lodash"; +import { ExportProvider } from "./exportProvider"; +import { IProject, IExportProviderOptions } from "../../models/applicationState"; +import Guard from "../../common/guard"; +import HtmlFileReader from "../../common/htmlFileReader"; +import json2csv, { Parser } from "json2csv"; + +/** + * Options for CSV Export Provider + */ +export interface ICsvExportProviderOptions extends IExportProviderOptions { + /** Whether or not to include binary assets in target connection */ + includeImages: boolean; +} + +/** + * @name - CSV Format Export Provider + * @description - Exports a project into a single CSV file that include all configured assets + */ +export class CsvExportProvider extends ExportProvider { + constructor(project: IProject, options: ICsvExportProviderOptions) { + super(project, options); + Guard.null(options); + } + + /** + * Export project to CSV + */ + public async export(): Promise { + const results = await this.getAssetsForExport(); + const dataItems = []; + + await results.forEachAsync(async (assetMetadata) => { + if (this.options.includeImages) { + // Write Image + const arrayBuffer = await HtmlFileReader.getAssetArray(assetMetadata.asset); + const assetFilePath = `vott-csv-export/${assetMetadata.asset.name}`; + await this.storageProvider.writeBinary(assetFilePath, Buffer.from(arrayBuffer)); + } + + // Push CSV Records + // The CSV file itself must have the following format:: + // image,xmin,ymin,xmax,ymax,label + // image_1.jpg,26,594,86,617,cat + // image_1.jpg,599,528,612,541,car + // image_2.jpg,393,477,430,552,dog + assetMetadata.regions.forEach((region) => { + region.tags.forEach((tag) => { + const dataItem = { + image: assetMetadata.asset.name, + xmin: region.boundingBox.left, + ymin: region.boundingBox.top, + xmax: region.boundingBox.left + region.boundingBox.width, + ymax: region.boundingBox.top + region.boundingBox.height, + label: tag, + }; + dataItems.push(dataItem); + }); + }); + }); + + // Configure CSV options + const csvOptions: json2csv.Options<{}> = { + fields: ["image", "xmin", "ymin", "xmax", "ymax", "label"], + }; + const csvParser = new Parser(csvOptions); + const csvData = csvParser.parse(dataItems); + + // Save CSV + const fileName = `vott-csv-export/${this.project.name.replace(/\s/g, "-")}-export.csv`; + await this.storageProvider.writeText(fileName, csvData); + } +} diff --git a/src/providers/export/csv.ui.json b/src/providers/export/csv.ui.json new file mode 100644 index 0000000000..0e2963f969 --- /dev/null +++ b/src/providers/export/csv.ui.json @@ -0,0 +1,5 @@ +{ + "includeImages": { + "ui:widget": "checkbox" + } +} diff --git a/src/providers/export/tensorFlowPascalVOC.json b/src/providers/export/pascalVOC.json similarity index 68% rename from src/providers/export/tensorFlowPascalVOC.json rename to src/providers/export/pascalVOC.json index e9f9ba19de..0a5924ac89 100644 --- a/src/providers/export/tensorFlowPascalVOC.json +++ b/src/providers/export/pascalVOC.json @@ -1,6 +1,6 @@ { "type": "object", - "title": "${strings.export.providers.tfPascalVoc.displayName}", + "title": "${strings.export.providers.pascalVoc.displayName}", "properties": { "assetState": { "type": "string", @@ -19,14 +19,14 @@ ] }, "testTrainSplit": { - "title": "${strings.export.providers.tfPascalVoc.testTrainSplit.title}", - "description": "${strings.export.providers.tfPascalVoc.testTrainSplit.description}", + "title": "${strings.export.providers.common.properties.testTrainSplit.title}", + "description": "${strings.export.providers.common.properties.testTrainSplit.description}", "type": "number", "default": 80 }, "exportUnassigned": { - "title": "${strings.export.providers.tfPascalVoc.exportUnassigned.title}", - "description": "${strings.export.providers.tfPascalVoc.exportUnassigned.description}", + "title": "${strings.export.providers.pascalVoc.exportUnassigned.title}", + "description": "${strings.export.providers.pascalVoc.exportUnassigned.description}", "type": "boolean", "default": true } diff --git a/src/providers/export/tensorFlowPascalVOC.test.ts b/src/providers/export/pascalVOC.test.ts similarity index 92% rename from src/providers/export/tensorFlowPascalVOC.test.ts rename to src/providers/export/pascalVOC.test.ts index da0f0d6af9..a5131a3cf7 100644 --- a/src/providers/export/tensorFlowPascalVOC.test.ts +++ b/src/providers/export/pascalVOC.test.ts @@ -1,5 +1,5 @@ import _ from "lodash"; -import { TFPascalVOCExportProvider, ITFPascalVOCExportProviderOptions } from "./tensorFlowPascalVOC"; +import { PascalVOCExportProvider, IPascalVOCExportProviderOptions } from "./pascalVOC"; import { ExportAssetState } from "./exportProvider"; import registerProviders from "../../registerProviders"; import { ExportProviderFactory } from "./exportProviderFactory"; @@ -21,7 +21,7 @@ import { AssetProviderFactory } from "../storage/assetProviderFactory"; registerMixins(); -describe("TFPascalVOC Json Export Provider", () => { +describe("PascalVOC Json Export Provider", () => { const testAssets = MockFactory.createTestAssets(10, 1); const baseTestProject = MockFactory.createTestProject("Test Project"); baseTestProject.assets = { @@ -51,18 +51,18 @@ describe("TFPascalVOC Json Export Provider", () => { }); it("Is defined", () => { - expect(TFPascalVOCExportProvider).toBeDefined(); + expect(PascalVOCExportProvider).toBeDefined(); }); it("Can be instantiated through the factory", () => { - const options: ITFPascalVOCExportProviderOptions = { + const options: IPascalVOCExportProviderOptions = { assetState: ExportAssetState.All, exportUnassigned: true, testTrainSplit: 80, }; - const exportProvider = ExportProviderFactory.create("tensorFlowPascalVOC", baseTestProject, options); + const exportProvider = ExportProviderFactory.create("pascalVOC", baseTestProject, options); expect(exportProvider).not.toBeNull(); - expect(exportProvider).toBeInstanceOf(TFPascalVOCExportProvider); + expect(exportProvider).toBeInstanceOf(PascalVOCExportProvider); }); describe("Export variations", () => { @@ -87,7 +87,7 @@ describe("TFPascalVOC Json Export Provider", () => { }); it("Exports all assets", async () => { - const options: ITFPascalVOCExportProviderOptions = { + const options: IPascalVOCExportProviderOptions = { assetState: ExportAssetState.All, exportUnassigned: true, testTrainSplit: 80, @@ -96,7 +96,7 @@ describe("TFPascalVOC Json Export Provider", () => { const testProject = { ...baseTestProject }; testProject.tags = MockFactory.createTestTags(3); - const exportProvider = new TFPascalVOCExportProvider(testProject, options); + const exportProvider = new PascalVOCExportProvider(testProject, options); await exportProvider.export(); const storageProviderMock = LocalFileSystemProxy as any; @@ -145,7 +145,7 @@ describe("TFPascalVOC Json Export Provider", () => { }); it("Exports only visited assets (includes tagged)", async () => { - const options: ITFPascalVOCExportProviderOptions = { + const options: IPascalVOCExportProviderOptions = { assetState: ExportAssetState.Visited, exportUnassigned: true, testTrainSplit: 80, @@ -154,7 +154,7 @@ describe("TFPascalVOC Json Export Provider", () => { const testProject = { ...baseTestProject }; testProject.tags = MockFactory.createTestTags(1); - const exportProvider = new TFPascalVOCExportProvider(testProject, options); + const exportProvider = new PascalVOCExportProvider(testProject, options); await exportProvider.export(); const storageProviderMock = LocalFileSystemProxy as any; @@ -191,7 +191,7 @@ describe("TFPascalVOC Json Export Provider", () => { }); it("Exports only tagged assets", async () => { - const options: ITFPascalVOCExportProviderOptions = { + const options: IPascalVOCExportProviderOptions = { assetState: ExportAssetState.Tagged, exportUnassigned: true, testTrainSplit: 80, @@ -200,7 +200,7 @@ describe("TFPascalVOC Json Export Provider", () => { const testProject = { ...baseTestProject }; testProject.tags = MockFactory.createTestTags(3); - const exportProvider = new TFPascalVOCExportProvider(testProject, options); + const exportProvider = new PascalVOCExportProvider(testProject, options); await exportProvider.export(); const storageProviderMock = LocalFileSystemProxy as any; @@ -242,7 +242,7 @@ describe("TFPascalVOC Json Export Provider", () => { }); it("Export includes unassigned tags", async () => { - const options: ITFPascalVOCExportProviderOptions = { + const options: IPascalVOCExportProviderOptions = { assetState: ExportAssetState.Tagged, exportUnassigned: true, testTrainSplit: 80, @@ -254,7 +254,7 @@ describe("TFPascalVOC Json Export Provider", () => { testProject.assets = _.keyBy(testAssets, (asset) => asset.id); testProject.tags = MockFactory.createTestTags(3); - const exportProvider = new TFPascalVOCExportProvider(testProject, options); + const exportProvider = new PascalVOCExportProvider(testProject, options); await exportProvider.export(); const storageProviderMock = LocalFileSystemProxy as any; @@ -275,7 +275,7 @@ describe("TFPascalVOC Json Export Provider", () => { }); it("Export does not include unassigned tags", async () => { - const options: ITFPascalVOCExportProviderOptions = { + const options: IPascalVOCExportProviderOptions = { assetState: ExportAssetState.Tagged, exportUnassigned: false, testTrainSplit: 80, @@ -287,7 +287,7 @@ describe("TFPascalVOC Json Export Provider", () => { testProject.assets = _.keyBy(testAssets, (asset) => asset.id); testProject.tags = MockFactory.createTestTags(3); - const exportProvider = new TFPascalVOCExportProvider(testProject, options); + const exportProvider = new PascalVOCExportProvider(testProject, options); await exportProvider.export(); const storageProviderMock = LocalFileSystemProxy as any; @@ -309,7 +309,7 @@ describe("TFPascalVOC Json Export Provider", () => { describe("Annotations", () => { it("contains expected XML", async () => { - const options: ITFPascalVOCExportProviderOptions = { + const options: IPascalVOCExportProviderOptions = { assetState: ExportAssetState.Tagged, exportUnassigned: false, testTrainSplit: 80, @@ -321,7 +321,7 @@ describe("TFPascalVOC Json Export Provider", () => { testProject.assets = _.keyBy(testAssets, (asset) => asset.id); testProject.tags = [MockFactory.createTestTag("1")]; - const exportProvider = new TFPascalVOCExportProvider(testProject, options); + const exportProvider = new PascalVOCExportProvider(testProject, options); await exportProvider.export(); const storageProviderMock = LocalFileSystemProxy as any; @@ -345,7 +345,7 @@ describe("TFPascalVOC Json Export Provider", () => { describe("Test Train Splits", () => { async function testTestTrainSplit(testTrainSplit: number): Promise { - const options: ITFPascalVOCExportProviderOptions = { + const options: IPascalVOCExportProviderOptions = { assetState: ExportAssetState.Tagged, exportUnassigned: true, testTrainSplit, @@ -357,7 +357,7 @@ describe("TFPascalVOC Json Export Provider", () => { testProject.assets = _.keyBy(testAssets, (asset) => asset.id); testProject.tags = [MockFactory.createTestTag("1")]; - const exportProvider = new TFPascalVOCExportProvider(testProject, options); + const exportProvider = new PascalVOCExportProvider(testProject, options); await exportProvider.export(); const storageProviderMock = LocalFileSystemProxy as any; diff --git a/src/providers/export/tensorFlowPascalVOC.ts b/src/providers/export/pascalVOC.ts similarity index 92% rename from src/providers/export/tensorFlowPascalVOC.ts rename to src/providers/export/pascalVOC.ts index 9fd449793b..26efff9ca0 100644 --- a/src/providers/export/tensorFlowPascalVOC.ts +++ b/src/providers/export/pascalVOC.ts @@ -1,11 +1,10 @@ import _ from "lodash"; import { ExportProvider } from "./exportProvider"; -import { IProject, IAssetMetadata, RegionType, ITag, IExportProviderOptions } from "../../models/applicationState"; +import { IProject, IAssetMetadata, ITag, IExportProviderOptions } from "../../models/applicationState"; import Guard from "../../common/guard"; import HtmlFileReader from "../../common/htmlFileReader"; -import { itemTemplate, annotationTemplate, objectTemplate } from "./tensorFlowPascalVOC/tensorFlowPascalVOCTemplates"; +import { itemTemplate, annotationTemplate, objectTemplate } from "./pascalVOC/pascalVOCTemplates"; import { interpolate } from "../../common/strings"; -import { PlatformType } from "../../common/hostProcess"; import os from "os"; interface IObjectInfo { @@ -23,9 +22,9 @@ interface IImageInfo { } /** - * Export options for TensorFlow Pascal VOC Export Provider + * Export options for Pascal VOC Export Provider */ -export interface ITFPascalVOCExportProviderOptions extends IExportProviderOptions { +export interface IPascalVOCExportProviderOptions extends IExportProviderOptions { /** The test / train split ratio for exporting data */ testTrainSplit?: number; /** Whether or not to include unassigned tags in exported data */ @@ -33,19 +32,19 @@ export interface ITFPascalVOCExportProviderOptions extends IExportProviderOption } /** - * @name - TFPascalVOC Json Export Provider - * @description - Exports a project into a single JSON file that include all configured assets + * @name - PascalVOC Export Provider + * @description - Exports a project into a Pascal VOC */ -export class TFPascalVOCExportProvider extends ExportProvider { +export class PascalVOCExportProvider extends ExportProvider { private imagesInfo = new Map(); - constructor(project: IProject, options: ITFPascalVOCExportProviderOptions) { + constructor(project: IProject, options: IPascalVOCExportProviderOptions) { super(project, options); Guard.null(options); } /** - * Export project to TensorFlow PascalVOC + * Export project to PascalVOC */ public async export(): Promise { const allAssets = await this.getAssetsForExport(); @@ -53,7 +52,7 @@ export class TFPascalVOCExportProvider extends ExportProvider assetMetadata.asset.id); // Create Export Folder - const exportFolderName = `${this.project.name.replace(" ", "-")}-TFPascalVOC-export`; + const exportFolderName = `${this.project.name.replace(/\s/g, "-")}-PascalVOC-export`; await this.storageProvider.createContainer(exportFolderName); await this.exportImages(exportFolderName, allAssets); diff --git a/src/providers/export/tensorFlowPascalVOC.ui.json b/src/providers/export/pascalVOC.ui.json similarity index 100% rename from src/providers/export/tensorFlowPascalVOC.ui.json rename to src/providers/export/pascalVOC.ui.json diff --git a/src/providers/export/tensorFlowPascalVOC/tensorFlowPascalVOCTemplates.ts b/src/providers/export/pascalVOC/pascalVOCTemplates.ts similarity index 96% rename from src/providers/export/tensorFlowPascalVOC/tensorFlowPascalVOCTemplates.ts rename to src/providers/export/pascalVOC/pascalVOCTemplates.ts index ec4c6ce19b..c62c166ec3 100644 --- a/src/providers/export/tensorFlowPascalVOC/tensorFlowPascalVOCTemplates.ts +++ b/src/providers/export/pascalVOC/pascalVOCTemplates.ts @@ -31,6 +31,6 @@ export const objectTemplate = "\ ${xmin}\n\ ${ymin}\n\ ${xmax}\n\ - ${xmin}\n\ + ${ymax}\n\ \n\ "; diff --git a/src/providers/export/tensorFlowRecords.ts b/src/providers/export/tensorFlowRecords.ts index 359a5a675f..56dd5eacb9 100644 --- a/src/providers/export/tensorFlowRecords.ts +++ b/src/providers/export/tensorFlowRecords.ts @@ -4,7 +4,7 @@ import { ExportProvider } from "./exportProvider"; import { IProject, IAssetMetadata, IExportProviderOptions } from "../../models/applicationState"; import Guard from "../../common/guard"; import HtmlFileReader from "../../common/htmlFileReader"; -import { itemTemplate } from "./tensorFlowPascalVOC/tensorFlowPascalVOCTemplates"; +import { itemTemplate } from "./pascalVOC/pascalVOCTemplates"; import { interpolate } from "../../common/strings"; import { TFRecordsBuilder, FeatureType } from "./tensorFlowRecords/tensorFlowBuilder"; @@ -41,7 +41,7 @@ export class TFRecordsExportProvider extends ExportProvider { exportObject.assets = _.keyBy(allAssets, (assetMetadata) => assetMetadata.asset.id); // Create Export Folder - const exportFolderName = `${this.project.name.replace(" ", "-")}-TFRecords-export`; + const exportFolderName = `${this.project.name.replace(/\s/g, "-")}-TFRecords-export`; await this.storageProvider.createContainer(exportFolderName); await this.exportPBTXT(exportFolderName, this.project); diff --git a/src/providers/export/vottJson.json b/src/providers/export/vottJson.json index 744da3194d..fd4fb136ad 100644 --- a/src/providers/export/vottJson.json +++ b/src/providers/export/vottJson.json @@ -21,8 +21,8 @@ "includeImages": { "type": "boolean", "default": true, - "title": "${strings.export.providers.vottJson.properties.includeImages.title}", - "description": "${strings.export.providers.vottJson.properties.includeImages.description}" + "title": "${strings.export.providers.common.properties.includeImages.title}", + "description": "${strings.export.providers.common.properties.includeImages.description}" } } } diff --git a/src/providers/export/vottJson.test.ts b/src/providers/export/vottJson.test.ts index da23e3e020..bd556c2e9c 100644 --- a/src/providers/export/vottJson.test.ts +++ b/src/providers/export/vottJson.test.ts @@ -3,7 +3,7 @@ import { VottJsonExportProvider, IVottJsonExportProviderOptions } from "./vottJs import registerProviders from "../../registerProviders"; import { ExportAssetState } from "./exportProvider"; import { ExportProviderFactory } from "./exportProviderFactory"; -import { IProject, IAssetMetadata, AssetState, IExportProviderOptions } from "../../models/applicationState"; +import { IProject, IAssetMetadata, AssetState } from "../../models/applicationState"; import MockFactory from "../../common/mockFactory"; jest.mock("../../services/assetService"); diff --git a/src/providers/export/vottJson.ts b/src/providers/export/vottJson.ts index 2505746f22..eda2113548 100644 --- a/src/providers/export/vottJson.ts +++ b/src/providers/export/vottJson.ts @@ -1,6 +1,6 @@ import _ from "lodash"; import { ExportProvider } from "./exportProvider"; -import { IProject, IExportProviderOptions, IAssetMetadata } from "../../models/applicationState"; +import { IProject, IExportProviderOptions } from "../../models/applicationState"; import Guard from "../../common/guard"; import { constants } from "../../common/constants"; import HtmlFileReader from "../../common/htmlFileReader"; @@ -31,17 +31,9 @@ export class VottJsonExportProvider extends ExportProvider { - return new Promise(async (resolve) => { - const blob = await HtmlFileReader.getAssetBlob(assetMetadata.asset); - const assetFilePath = `vott-json-export/${assetMetadata.asset.name}`; - const fileReader = new FileReader(); - fileReader.onload = async () => { - const buffer = Buffer.from(fileReader.result as ArrayBuffer); - await this.storageProvider.writeBinary(assetFilePath, buffer); - resolve(); - }; - fileReader.readAsArrayBuffer(blob); - }); + const arrayBuffer = await HtmlFileReader.getAssetArray(assetMetadata.asset); + const assetFilePath = `vott-json-export/${assetMetadata.asset.name}`; + await this.storageProvider.writeBinary(assetFilePath, Buffer.from(arrayBuffer)); }); } @@ -53,7 +45,7 @@ export class VottJsonExportProvider extends ExportProvider { ); + onError={this.props.onError} + crossOrigin="anonymous" />); } private onLoad = () => { diff --git a/src/react/components/common/assetPreview/tfrecordAsset.tsx b/src/react/components/common/assetPreview/tfrecordAsset.tsx index 774d0e63d1..8eeafe47f5 100644 --- a/src/react/components/common/assetPreview/tfrecordAsset.tsx +++ b/src/react/components/common/assetPreview/tfrecordAsset.tsx @@ -31,7 +31,8 @@ export class TFRecordAsset extends React.Component + onError={this.onError} + crossOrigin="anonymous" /> ); } diff --git a/src/react/components/common/assetPreview/videoAsset.tsx b/src/react/components/common/assetPreview/videoAsset.tsx index 7d445634f9..501c8dc289 100644 --- a/src/react/components/common/assetPreview/videoAsset.tsx +++ b/src/react/components/common/assetPreview/videoAsset.tsx @@ -73,7 +73,8 @@ export class VideoAsset extends React.Component { height="100%" autoPlay={autoPlay} src={videoPath} - onError={this.props.onError}> + onError={this.props.onError} + crossOrigin="anonymous"> {autoPlay && diff --git a/src/react/components/common/colorPicker.tsx b/src/react/components/common/colorPicker.tsx index 6d4bae1afb..77c6418178 100644 --- a/src/react/components/common/colorPicker.tsx +++ b/src/react/components/common/colorPicker.tsx @@ -25,20 +25,22 @@ export class ColorPicker extends React.Component { private GithubPicker = () => { return ( - + + }} + triangle={"hide"} + /> + ); } diff --git a/src/react/components/common/externalPicker/externalPicker.test.tsx b/src/react/components/common/externalPicker/externalPicker.test.tsx index 31cb5a3ba0..4d3da6bf7a 100644 --- a/src/react/components/common/externalPicker/externalPicker.test.tsx +++ b/src/react/components/common/externalPicker/externalPicker.test.tsx @@ -1,11 +1,10 @@ import React from "react"; import { mount, ReactWrapper } from "enzyme"; import axios from "axios"; -import ExternalPicker, { IExternalPickerProps, IExternalPickerState } from "./externalPicker"; +import ExternalPicker, { IExternalPickerProps, IExternalPickerState, FilterOperator } from "./externalPicker"; import MockFactory from "../../../../common/mockFactory"; describe("External Picker", () => { - let wrapper: ReactWrapper = null; const onChangeHandler = jest.fn(); const defaultProps = createProps({ id: "my-custom-control", @@ -16,12 +15,13 @@ describe("External Picker", () => { formContext: { providerOptions: { apiKey: "", + region: "", }, }, onChange: onChangeHandler, options: { method: "GET", - url: "https://myserver/api", + url: "https://${props.formContext.providerOptions.region}.server.com/api", keySelector: "${item.key}", valueSelector: "${item.value}", authHeaderName: "Authorization", @@ -48,32 +48,34 @@ describe("External Picker", () => { }); }); - beforeEach(() => { - wrapper = createComponent(defaultProps as IExternalPickerProps); - }); - it("Renders select element with default option", () => { + const wrapper = createComponent(defaultProps); expect(wrapper.find("select").length).toEqual(1); expect(wrapper.find("option").length).toEqual(1); }); it("Does not bind external data if authorization is missing", () => { + createComponent(defaultProps); expect(axios.request).not.toBeCalled(); }); it("Renders items bound from external data when formContext rebinds", async () => { const expectedApiKey = "ABC123"; - - await MockFactory.flushUi(() => { - wrapper.setProps({ - formContext: { - providerOptions: { - apiKey: expectedApiKey, - }, + const expectedRegion = "southcentralus"; + + const props = { + ...defaultProps, + formContext: { + providerOptions: { + apiKey: expectedApiKey, + region: expectedRegion, }, - }); - }); + }, + }; + const wrapper = createComponent(props); + + await MockFactory.flushUi(); wrapper.update(); const expectedHeaders = {}; @@ -81,7 +83,7 @@ describe("External Picker", () => { expect(axios.request).toBeCalledWith({ method: defaultProps.options.method, - url: defaultProps.options.url, + url: `https://${expectedRegion}.server.com/api`, headers: expectedHeaders, }); @@ -93,19 +95,81 @@ describe("External Picker", () => { }); it("Calls onChange event handler on option selection", () => { - wrapper.setProps({ - formContext: {}, - }); + const wrapper = createComponent(defaultProps); wrapper.find("select").simulate("change", { target: { value: testResponse[0].key } }); expect(onChangeHandler).toBeCalledWith(testResponse[0].key); }); - function createProps(otherProps: any): IExternalPickerProps { + it("Clears items when HTTP request fails", async () => { + const requestMock = axios.request as jest.Mock; + requestMock.mockImplementationOnce(() => Promise.reject({ status: 400 })); + + const expectedApiKey = "ABC123"; + const expectedRegion = "southcentralus"; + const props: IExternalPickerProps = { - ...otherProps, + ...defaultProps, + formContext: { + providerOptions: { + apiKey: expectedApiKey, + region: expectedRegion, + }, + }, }; - return props; + const wrapper = createComponent(props); + await MockFactory.flushUi(); + + expect(wrapper.state().items).toEqual([]); + expect(onChangeHandler).toBeCalledWith(undefined); + }); + + describe("Filters items", () => { + it("Applies a filter to the item when defined", async () => { + const requestMock = axios.request as jest.Mock; + requestMock.mockImplementationOnce(() => Promise.resolve({ + data: [ + { id: "1", name: "Object Detection 1", type: "ObjectDetection" }, + { id: "2", name: "Object Detection 2", type: "ObjectDetection" }, + { id: "3", name: "Classification 1", type: "Classification" }, + { id: "4", name: "Classification 2", type: "Classification" }, + ], + status: 200, + })); + + const props: IExternalPickerProps = { + ...defaultProps, + formContext: { + providerOptions: { + apiKey: "ABC123", + region: "southcentralus", + projectType: "Classification", + }, + }, + }; + + props.options.keySelector = "${item.id}"; + props.options.valueSelector = "${item.name}"; + props.options.filter = { + left: "${item.type}", + right: "${props.formContext.providerOptions.projectType}", + operator: FilterOperator.Equals, + }; + + const wrapper = createComponent(props); + await MockFactory.flushUi(); + + expect(wrapper.state().items).toEqual([ + { key: "3", value: "Classification 1" }, + { key: "4", value: "Classification 2" }, + ]); + }); + }); + + function createProps(otherProps: any): IExternalPickerProps { + return { + ...otherProps, + }; } }); diff --git a/src/react/components/common/externalPicker/externalPicker.tsx b/src/react/components/common/externalPicker/externalPicker.tsx index b719bc7935..acad549253 100644 --- a/src/react/components/common/externalPicker/externalPicker.tsx +++ b/src/react/components/common/externalPicker/externalPicker.tsx @@ -24,6 +24,19 @@ export interface IExternalPickerUiOptions { valueSelector: string; authHeaderName?: string; authHeaderValue?: string; + filter?: IExternalPickerFilter; +} + +export interface IExternalPickerFilter { + left: string; + right: string; + operator: FilterOperator; +} + +export enum FilterOperator { + Equals = "eq", + GreaterThan = "gt", + LessThan = "lt", } /** @@ -46,15 +59,9 @@ export interface IExternalPickerState { * Dropdown that provides options from an external HTTP source */ export default class ExternalPicker extends React.Component { - constructor(props, context) { - super(props, context); - - this.state = { - items: [], - }; - - this.onChange = this.onChange.bind(this); - } + public state: IExternalPickerState = { + items: [], + }; public render() { return ( @@ -78,12 +85,12 @@ export default class ExternalPicker extends React.Component { const target = e.target as HTMLSelectElement; this.props.onChange(target.value === "" ? undefined : target.value); } - private async bindExternalData() { + private bindExternalData = async (): Promise => { const uiOptions = this.props.options; const customHeaders: any = {}; const authHeaderValue = interpolate(uiOptions.authHeaderValue, { @@ -98,24 +105,52 @@ export default class ExternalPicker extends React.Component { + + let rawItems: any[] = response.data; + + // Optionally filter results if a filter has been defined + if (uiOptions.filter) { + rawItems = rawItems.filter((item) => this.filterPredicate(item, uiOptions.filter)); + } + + const items: IKeyValuePair[] = rawItems.map((item) => { return { key: interpolate(uiOptions.keySelector, { item }), value: interpolate(uiOptions.valueSelector, { item }), }; }); - this.setState({ - items, - }); + this.setState({ items }); } catch (e) { - return; + this.setState({ items: [] }); + this.props.onChange(undefined); + } + } + + /** + * Determines if the specified item will return as part of the filter + * @param item The item to evaluate + * @param filter The filter expression to evaluate against + */ + private filterPredicate(item: any, filter: IExternalPickerFilter): boolean { + const left = interpolate(filter.left, { item, props: this.props }); + const right = interpolate(filter.right, { item, props: this.props }); + + switch (filter.operator) { + case FilterOperator.Equals: + return left === right; + case FilterOperator.GreaterThan: + return left > right; + case FilterOperator.LessThan: + return left < right; + default: + throw new Error("Invalid filter operator"); } } } diff --git a/src/react/components/common/protectedInput/protectedInput.tsx b/src/react/components/common/protectedInput/protectedInput.tsx index 514303051e..ff2224efe6 100644 --- a/src/react/components/common/protectedInput/protectedInput.tsx +++ b/src/react/components/common/protectedInput/protectedInput.tsx @@ -33,7 +33,7 @@ export class ProtectedInput extends React.Component { @@ -40,6 +41,31 @@ describe("Tag Input Component", () => { expect(props.onCtrlTagClick).not.toBeCalled(); }); + it("Edits tag name when alt clicked", () => { + const props = createProps(); + const wrapper = createComponent(props); + wrapper.find("div.tag-name-container").first().simulate("click", { altKey: true } ); + expect(wrapper.state().editingTag).toEqual(props.tags[0]); + expect(wrapper.exists("input.tag-name-editor")).toBe(true); + }); + + it("Edits tag color when alt clicked", () => { + const props = createProps(); + const wrapper = createComponent(props); + expect(wrapper.state().clickedColor).toBe(false); + expect(wrapper.exists("div.color-picker")).toBe(false); + wrapper.find("div.tag-color").first().simulate("click", { altKey: true } ); + expect(wrapper.state().clickedColor).toBe(true); + expect(wrapper.state().showColorPicker).toBe(true); + expect(wrapper.state().editingTag).toEqual(props.tags[0]); + expect(wrapper.exists("div.color-picker")).toBe(true); + // Get color picker and call onEditColor function + const picker = wrapper.find(ColorPicker).instance() as ColorPicker; + picker.props.onEditColor("#000000"); + expect(props.onChange).toBeCalled(); + expect(true).toBeTruthy(); + }); + it("Calls onClick handler when clicking text", () => { const props: ITagInputProps = createProps(); const wrapper = createComponent(props); @@ -101,6 +127,34 @@ describe("Tag Input Component", () => { expect(wrapper.state().searchTags).toBe(true); }); + it("Add tag box closed with escape key", () => { + const wrapper = createComponent(); + expect(wrapper.exists(".tag-input-box")).toBe(false); + expect(wrapper.state().addTags).toBeFalsy(); + wrapper.find("div.tag-input-toolbar-item.plus").simulate("click"); + expect(wrapper.exists(".tag-input-box")).toBe(true); + expect(wrapper.state().addTags).toBe(true); + + wrapper.find(".tag-input-box").simulate("keydown", { key: "Escape" }); + expect(wrapper.exists(".tag-input-box")).toBe(false); + expect(wrapper.state().addTags).toBe(false); + }); + + it("Tag search box closed with escape key", async () => { + const wrapper = createComponent(); + expect(wrapper.exists(".tag-search-box")).toBe(false); + expect(wrapper.state().searchTags).toBeFalsy(); + wrapper.find("div.tag-input-toolbar-item.search").simulate("click"); + expect(wrapper.exists(".tag-search-box")).toBe(true); + expect(wrapper.state().searchTags).toBe(true); + + wrapper.find(".tag-search-box").simulate("keydown", { key: "Escape" }); + await MockFactory.flushUi(); + expect(wrapper.state().searchTags).toBe(false); + + expect(wrapper.exists(".tag-search-box")).toBe(false); + }); + it("Tag can be locked from toolbar", () => { const tags = MockFactory.createTestTags(); const props = createProps(tags); @@ -110,7 +164,7 @@ describe("Tag Input Component", () => { expect(props.onLockedTagsChange).toBeCalledWith([tags[0].name]); }); - it("Tag can be edited from toolbar", () => { + it("Tag name can be edited from toolbar", () => { const tags = MockFactory.createTestTags(); const props = createProps(tags); const wrapper = createComponent(props); @@ -120,6 +174,25 @@ describe("Tag Input Component", () => { expect(wrapper.exists("input.tag-name-editor")).toBe(true); }); + it("Tag color can be edited from toolbar", () => { + const tags = MockFactory.createTestTags(); + const props = createProps(tags); + const wrapper = createComponent(props); + expect(wrapper.state().clickedColor).toBe(false); + expect(wrapper.exists("div.color-picker")).toBe(false); + wrapper.find("div.tag-color").first().simulate("click"); + expect(wrapper.state().clickedColor).toBe(true); + wrapper.find("div.tag-input-toolbar-item.edit").simulate("click"); + expect(wrapper.state().showColorPicker).toBe(true); + expect(wrapper.state().editingTag).toEqual(tags[0]); + expect(wrapper.exists("div.color-picker")).toBe(true); + // Get color picker and call onEditColor function + const picker = wrapper.find(ColorPicker).instance() as ColorPicker; + picker.props.onEditColor("#000000"); + expect(props.onChange).toBeCalled(); + expect(true).toBeTruthy(); + }); + it("Tag can be moved up from toolbar", () => { const tags = MockFactory.createTestTags(); const lastTag = tags[tags.length - 1]; @@ -169,6 +242,16 @@ describe("Tag Input Component", () => { expect(props.onChange).not.toBeCalled(); }); + it("Does not try to add tag with same name as existing tag", () => { + const props: ITagInputProps = { + ...createProps(), + showTagInputBox: true, + }; + const wrapper = createComponent(props); + wrapper.find(".tag-input-box").simulate("keydown", { key: "Enter", target: { value: props.tags[0].name } }); + expect(props.onChange).not.toBeCalled(); + }); + it("Selects a tag", () => { const tags = MockFactory.createTestTags(); const onChange = jest.fn(); @@ -230,6 +313,54 @@ describe("Tag Input Component", () => { expect(onChange).toBeCalledWith(expectedTags); }); + it("Does not edit tag name with empty string", () => { + const tags = MockFactory.createTestTags(); + const onChange = jest.fn(); + const onTagNameChange = jest.fn(); + const props = { + ...createProps(tags, onChange), + onTagNameChange, + }; + const wrapper = createComponent(props); + wrapper.find(".tag-content").first().simulate("click"); + wrapper.find("i.tag-input-toolbar-icon.fas.fa-edit").simulate("click"); + wrapper.find("input.tag-name-editor").simulate("keydown", { key: "Enter", target: { value: "" } }); + expect(wrapper.state().tags).toEqual(tags); + expect(onChange).not.toBeCalled(); + }); + + it("Does not call onChange when edited tag name is the same", () => { + const tags = MockFactory.createTestTags(); + const onChange = jest.fn(); + const onTagNameChange = jest.fn(); + const props = { + ...createProps(tags, onChange), + onTagNameChange, + }; + const wrapper = createComponent(props); + wrapper.find(".tag-content").first().simulate("click"); + wrapper.find("i.tag-input-toolbar-icon.fas.fa-edit").simulate("click"); + wrapper.find("input.tag-name-editor").simulate("keydown", { key: "Enter", target: { value: tags[0].name } }); + expect(wrapper.state().tags).toEqual(tags); + expect(onChange).not.toBeCalled(); + }); + + it("Does not change tag name to name of other existing tag", () => { + const tags = MockFactory.createTestTags(); + const onChange = jest.fn(); + const onTagNameChange = jest.fn(); + const props = { + ...createProps(tags, onChange), + onTagNameChange, + }; + const wrapper = createComponent(props); + wrapper.find(".tag-content").first().simulate("click"); + wrapper.find("i.tag-input-toolbar-icon.fas.fa-edit").simulate("click"); + wrapper.find("input.tag-name-editor").simulate("keydown", { key: "Enter", target: { value: tags[1].name } }); + expect(wrapper.state().tags).toEqual(tags); + expect(onChange).not.toBeCalled(); + }); + it("Reorders a tag", () => { const tags = MockFactory.createTestTags(); const onChange = jest.fn(); @@ -247,7 +378,20 @@ describe("Tag Input Component", () => { expect(wrapper.state().tags.indexOf(firstTag)).toEqual(0); }); - it("set's applied tags when selected regions are available", () => { + it("Searches for a tag", () => { + const props: ITagInputProps = { + ...createProps(), + showSearchBox: true, + }; + const wrapper = createComponent(props); + expect(wrapper.find(".tag-item-block").length).toBeGreaterThan(1); + wrapper.find(".tag-search-box").simulate("change", { target: { value: "1" } }); + expect(wrapper.state().searchQuery).toEqual("1"); + expect(wrapper.find(".tag-item-block")).toHaveLength(1); + expect(wrapper.find(".tag-name-body").first().text()).toEqual("Tag 1"); + }); + + it("sets applied tags when selected regions are available", () => { const tags = MockFactory.createTestTags(); const onChange = jest.fn(); const props = createProps(tags, onChange); diff --git a/src/react/components/common/tagInput/tagInput.tsx b/src/react/components/common/tagInput/tagInput.tsx index 7291ad16f9..107489024d 100644 --- a/src/react/components/common/tagInput/tagInput.tsx +++ b/src/react/components/common/tagInput/tagInput.tsx @@ -1,4 +1,4 @@ -import React, { KeyboardEvent } from "react"; +import React, { KeyboardEvent, RefObject } from "react"; import ReactDOM from "react-dom"; import Align from "rc-align"; import { randomIntInRange } from "../../../../common/utils"; @@ -31,9 +31,9 @@ export interface ITagInputProps { /** Function to call on clicking individual tag while holding CTRL key */ onCtrlTagClick?: (tag: ITag) => void; /** Function to call when tag is renamed */ - onTagRenamed?: (oldTag: string, newTag: string) => void; + onTagRenamed?: (tagName: string, newTagName: string) => void; /** Function to call when tag is deleted */ - onTagDeleted?: (tag: ITag) => void; + onTagDeleted?: (tagName: string) => void; /** Always show tag input box */ showTagInputBox?: boolean; /** Always show tag search box */ @@ -72,7 +72,7 @@ export class TagInput extends React.Component { portalElement: defaultDOMNode(), }; - private tagItemRefs: { [id: string]: TagInputItem } = {}; + private tagItemRefs: Map = new Map(); private portalDiv = document.createElement("div"); public render() { @@ -98,6 +98,7 @@ export class TagInput extends React.Component { this.state.searchTags &&
this.setState({ searchQuery: e.target.value })} @@ -109,7 +110,7 @@ export class TagInput extends React.Component { } {this.getColorPickerPortal()}
- {this.getTagItems()} + {this.renderTagItems()}
{ this.state.addTags && @@ -154,21 +155,17 @@ export class TagInput extends React.Component { } } - private getTagNode = (tag: ITag) => { - if (!tag) { - return defaultDOMNode(); - } - return ReactDOM.findDOMNode(this.tagItemRefs[tag.name]) as Element; + private getTagNode = (tag: ITag): Element => { + const itemRef = tag ? this.tagItemRefs.get(tag.name) : null; + return (itemRef ? ReactDOM.findDOMNode(itemRef) : defaultDOMNode()) as Element; } private onEditTag = (tag: ITag) => { - if (!tag) { - return; - } const { editingTag } = this.state; const newEditingTag = (editingTag && editingTag.name === tag.name) ? null : tag; this.setState({ editingTag: newEditingTag, + editingTagNode: this.getTagNode(newEditingTag), }); if (this.state.clickedColor) { this.setState({ @@ -219,20 +216,25 @@ export class TagInput extends React.Component { }, () => this.props.onChange(tags)); } - private updateTag = (oldTag: ITag, newTag: ITag) => { - if (oldTag === newTag) { + private updateTag = (tag: ITag, newTag: ITag) => { + if (tag.name === newTag.name && tag.color === newTag.color) { return; } if (!newTag.name.length) { toast.warn(strings.tags.warnings.emptyName); return; } - if (newTag.name !== oldTag.name && this.state.tags.some((t) => t.name === newTag.name)) { + const nameChange = tag.name !== newTag.name; + if (nameChange && this.state.tags.some((t) => t.name === newTag.name)) { toast.warn(strings.tags.warnings.existingName); return; } + if (nameChange && this.props.onTagRenamed) { + this.props.onTagRenamed(tag.name, newTag.name); + return; + } const tags = this.state.tags.map((t) => { - return (t.name === oldTag.name) ? newTag : t; + return (t.name === tag.name) ? newTag : t; }); this.setState({ tags, @@ -293,12 +295,15 @@ export class TagInput extends React.Component { return this.state.editingTagNode || document; } - private getTagItems = () => { - let props = this.getTagItemProps(); + private renderTagItems = () => { + let props = this.createTagItemProps(); const query = this.state.searchQuery; + this.tagItemRefs.clear(); + if (query.length) { props = props.filter((prop) => prop.tag.name.toLowerCase().includes(query.toLowerCase())); } + return props.map((prop) => { />); } - private setTagItemRef = (item, tag) => { - if (item) { - this.tagItemRefs[tag.name] = item; - } + private setTagItemRef = (item: TagInputItem, tag: ITag) => { + this.tagItemRefs.set(tag.name, item); + return item; } - private getTagItemProps = (): ITagInputItemProps[] => { + private createTagItemProps = (): ITagInputItemProps[] => { const tags = this.state.tags; const selectedRegionTagSet = this.getSelectedRegionTagSet(); - return tags.map((tag) => { - const item: ITagInputItemProps = { + + return tags.map((tag) => ( + { tag, index: tags.findIndex((t) => t.name === tag.name), isLocked: this.props.lockedTags && this.props.lockedTags.findIndex((t) => t === tag.name) > -1, @@ -326,9 +331,8 @@ export class TagInput extends React.Component { appliedToSelectedRegions: selectedRegionTagSet.has(tag.name), onClick: this.handleClick, onChange: this.updateTag, - }; - return item; - }); + } as ITagInputItemProps + )); } private getSelectedRegionTagSet = (): Set => { @@ -346,6 +350,7 @@ export class TagInput extends React.Component { private onAltClick = (tag: ITag, clickedColor: boolean) => { const { editingTag } = this.state; const newEditingTag = editingTag && editingTag.name === tag.name ? null : tag; + this.setState({ editingTag: newEditingTag, editingTagNode: this.getTagNode(newEditingTag), @@ -355,16 +360,16 @@ export class TagInput extends React.Component { } private handleClick = (tag: ITag, props: ITagClickProps) => { + // Lock tags if (props.ctrlKey && this.props.onCtrlTagClick) { this.props.onCtrlTagClick(tag); this.setState({ clickedColor: props.clickedColor }); - } else if (props.altKey) { + } else if (props.altKey) { // Edit tag this.onAltClick(tag, props.clickedColor); - } else { + } else { // Select tag const { editingTag, selectedTag } = this.state; const inEditMode = editingTag && tag.name === editingTag.name; const alreadySelected = selectedTag && selectedTag.name === tag.name; - const newEditingTag = inEditMode ? null : editingTag; this.setState({ @@ -389,12 +394,19 @@ export class TagInput extends React.Component { if (!tag) { return; } + if (this.props.onTagDeleted) { + this.props.onTagDeleted(tag.name); + return; + } + const index = this.state.tags.indexOf(tag); const tags = this.state.tags.filter((t) => t.name !== tag.name); + this.setState({ tags, selectedTag: this.getNewSelectedTag(tags, index), }, () => this.props.onChange(tags)); + if (this.props.lockedTags.find((l) => l === tag.name)) { this.props.onLockedTagsChange( this.props.lockedTags.filter((lockedTag) => lockedTag !== tag.name), diff --git a/src/react/components/pages/activeLearning/activeLearningForm.json b/src/react/components/pages/activeLearning/activeLearningForm.json new file mode 100644 index 0000000000..c8729d338e --- /dev/null +++ b/src/react/components/pages/activeLearning/activeLearningForm.json @@ -0,0 +1,82 @@ +{ + "type": "object", + "properties": { + "modelPathType": { + "type": "string", + "title": "${strings.activeLearning.form.properties.modelPathType.title}", + "description": "${strings.activeLearning.form.properties.modelPathType.description}", + "enum": [ + "coco", + "file", + "url" + ], + "default": "coco", + "enumNames": [ + "${strings.activeLearning.form.properties.modelPathType.options.preTrained}", + "${strings.activeLearning.form.properties.modelPathType.options.customFilePath}", + "${strings.activeLearning.form.properties.modelPathType.options.customWebUrl}" + ] + }, + "autoDetect": { + "title": "${strings.activeLearning.form.properties.autoDetect.title}", + "description": "${strings.activeLearning.form.properties.autoDetect.description}", + "type": "boolean" + }, + "predictTag": { + "title": " ${strings.activeLearning.form.properties.predictTag.title}", + "description": "${strings.activeLearning.form.properties.predictTag.description}", + "type": "boolean" + } + }, + "dependencies": { + "modelPathType": { + "oneOf": [ + { + "properties": { + "modelPathType": { + "enum": [ + "coco" + ] + } + } + }, + { + "required": [ + "modelPath" + ], + "properties": { + "modelPathType": { + "enum": [ + "file" + ] + }, + "modelPath": { + "title": "${strings.activeLearning.form.properties.modelPath.title}", + "description": "${strings.activeLearning.form.properties.modelPath.description}", + "type": "string" + } + } + }, + { + "required": [ + "modelUrl" + ], + "properties": { + "modelPathType": { + "enum": [ + "url" + ] + }, + "modelUrl": { + "title": "${strings.activeLearning.form.properties.modelUrl.title}", + "description": "${strings.activeLearning.form.properties.modelUrl.description}", + "default": "http://", + "pattern": "^https?\\\\://[a-zA-Z0-9\\\\-\\\\.]+\\\\.[a-zA-Z]{2,3}(/\\\\S*)?$", + "type": "string" + } + } + } + ] + } + } +} diff --git a/src/react/components/pages/activeLearning/activeLearningForm.test.tsx b/src/react/components/pages/activeLearning/activeLearningForm.test.tsx new file mode 100644 index 0000000000..e517c31dfb --- /dev/null +++ b/src/react/components/pages/activeLearning/activeLearningForm.test.tsx @@ -0,0 +1,95 @@ +import React from "react"; +import { IActiveLearningFormProps, ActiveLearningForm, IActiveLearningFormState } from "./activeLearningForm"; +import { ReactWrapper, mount } from "enzyme"; +import { ModelPathType, IActiveLearningSettings } from "../../../../models/applicationState"; +import Form from "react-jsonschema-form"; + +describe("Active Learning Form", () => { + const onChangeHandler = jest.fn(); + const onSubmitHandler = jest.fn(); + const onCancelHandler = jest.fn(); + const defaultProps: IActiveLearningFormProps = { + settings: { + modelPathType: ModelPathType.Coco, + modelPath: null, + modelUrl: null, + autoDetect: false, + predictTag: true, + }, + onChange: onChangeHandler, + onSubmit: onSubmitHandler, + onCancel: onCancelHandler, + }; + + function createComponent(props?: IActiveLearningFormProps) + : ReactWrapper { + props = props || defaultProps; + return mount(); + } + + it("renders a dynamic json schema form with default props", () => { + const wrapper = createComponent(); + expect(wrapper.find(Form).exists()).toBe(true); + expect(wrapper.state().formData).toEqual(defaultProps.settings); + }); + + it("sets formData state when loaded with different props", () => { + const props: IActiveLearningFormProps = { + ...defaultProps, + settings: { + modelPathType: ModelPathType.Url, + modelUrl: "https://myserver.com/myModel", + autoDetect: true, + predictTag: true, + }, + }; + + const wrapper = createComponent(props); + expect(wrapper.state().formData).toEqual(props.settings); + }); + + it("updates form data when the props change", () => { + const wrapper = createComponent(); + + const newSettings: IActiveLearningSettings = { + modelPathType: ModelPathType.Url, + modelUrl: "https://myserver.com/myModel", + autoDetect: true, + predictTag: true, + }; + + wrapper.setProps({ settings: newSettings }); + expect(wrapper.state().formData).toEqual(newSettings); + }); + + it("sets formData state when form changes", () => { + const wrapper = createComponent(); + const formData: IActiveLearningSettings = { + modelPathType: ModelPathType.Url, + modelUrl: "https://myserver.com/myModel", + autoDetect: true, + predictTag: true, + }; + + // Set type to URL + wrapper.find(Form).props().onChange({ formData: { modelPathType: ModelPathType.Url } }); + // Set the remaining settings + wrapper.find(Form).props().onChange({ formData }); + expect(wrapper.state().formData).toEqual(formData); + expect(onChangeHandler).toBeCalledWith(formData); + }); + + it("submits form data to the registered submit handler", () => { + const wrapper = createComponent(); + wrapper.find(Form).props().onSubmit({ formData: defaultProps.settings }); + + expect(onSubmitHandler).toBeCalledWith(defaultProps.settings); + }); + + it("raises the cancel event and called registered handler", () => { + const wrapper = createComponent(); + wrapper.find(".btn-cancel").simulate("click"); + + expect(onCancelHandler).toBeCalled(); + }); +}); diff --git a/src/react/components/pages/activeLearning/activeLearningForm.tsx b/src/react/components/pages/activeLearning/activeLearningForm.tsx new file mode 100644 index 0000000000..ab5f9579ad --- /dev/null +++ b/src/react/components/pages/activeLearning/activeLearningForm.tsx @@ -0,0 +1,112 @@ +import React from "react"; +import Form, { ISubmitEvent, IChangeEvent, Widget } from "react-jsonschema-form"; +import { IActiveLearningSettings, ModelPathType } from "../../../../models/applicationState"; +import { strings, addLocValues } from "../../../../common/strings"; +import CustomFieldTemplate from "../../common/customField/customFieldTemplate"; +import LocalFolderPicker from "../../common/localFolderPicker/localFolderPicker"; +import { CustomWidget } from "../../common/customField/customField"; +import Checkbox from "rc-checkbox"; + +// tslint:disable-next-line:no-var-requires +const formSchema = addLocValues(require("./activeLearningForm.json")); +// tslint:disable-next-line:no-var-requires +const uiSchema = addLocValues(require("./activeLearningForm.ui.json")); + +export interface IActiveLearningFormProps extends React.Props { + settings: IActiveLearningSettings; + onSubmit: (settings: IActiveLearningSettings) => void; + onChange?: (settings: IActiveLearningSettings) => void; + onCancel?: () => void; +} + +export interface IActiveLearningFormState { + classNames: string[]; + formData: IActiveLearningSettings; + uiSchema: any; + formSchema: any; +} + +export class ActiveLearningForm extends React.Component { + public state: IActiveLearningFormState = { + classNames: ["needs-validation"], + uiSchema: { ...uiSchema }, + formSchema: { ...formSchema }, + formData: { + ...this.props.settings, + }, + }; + + private widgets = { + localFolderPicker: (LocalFolderPicker as any) as Widget, + checkbox: CustomWidget(Checkbox, (props) => ({ + checked: props.value, + onChange: (value) => props.onChange(value.target.checked), + disabled: props.disabled, + })), + }; + + public componentDidUpdate(prevProps: Readonly) { + if (this.props.settings !== prevProps.settings) { + this.setState({ formData: this.props.settings }); + } + } + + public render() { + return ( +
+
+ + +
+
+ ); + } + + private onFormChange = (changeEvent: IChangeEvent): void => { + let updatedSettings = changeEvent.formData; + + if (changeEvent.formData.modelPathType !== this.state.formData.modelPathType) { + updatedSettings = { + ...changeEvent.formData, + modelPath: null, + modelUrl: null, + }; + } + + this.setState({ + formData: updatedSettings, + }, () => { + if (this.props.onChange) { + this.props.onChange(updatedSettings); + } + }); + } + + private onFormSubmit = (args: ISubmitEvent): void => { + const settings: IActiveLearningSettings = { + ...args.formData, + }; + + this.setState({ formData: settings }); + this.props.onSubmit(settings); + } + + private onFormCancel = (): void => { + if (this.props.onCancel) { + this.props.onCancel(); + } + } +} diff --git a/src/react/components/pages/activeLearning/activeLearningForm.ui.json b/src/react/components/pages/activeLearning/activeLearningForm.ui.json new file mode 100644 index 0000000000..3608b14c16 --- /dev/null +++ b/src/react/components/pages/activeLearning/activeLearningForm.ui.json @@ -0,0 +1,17 @@ +{ + "modelPath": { + "ui:widget": "localFolderPicker" + }, + "predictTag": { + "ui:widget": "checkbox" + }, + "autoDetect": { + "ui:widget": "checkbox" + }, + "ui:order": [ + "modelPathType", + "*", + "predictTag", + "autoDetect" + ] +} diff --git a/src/react/components/pages/activeLearning/activeLearningPage.test.tsx b/src/react/components/pages/activeLearning/activeLearningPage.test.tsx new file mode 100644 index 0000000000..9bc1679eb2 --- /dev/null +++ b/src/react/components/pages/activeLearning/activeLearningPage.test.tsx @@ -0,0 +1,118 @@ +import React from "react"; +import ActiveLearningPage, { IActiveLearningPageProps, IActiveLearningPageState } from "./activeLearningPage"; +import { ReactWrapper, mount } from "enzyme"; +import { Provider } from "react-redux"; +import { BrowserRouter as Router } from "react-router-dom"; +import createReduxStore from "../../../../redux/store/store"; +import MockFactory from "../../../../common/mockFactory"; +import { ActiveLearningForm } from "./activeLearningForm"; +import { IActiveLearningSettings, ModelPathType } from "../../../../models/applicationState"; +jest.mock("../../../../services/projectService"); +import ProjectService from "../../../../services/projectService"; +import { toast } from "react-toastify"; +import { strings } from "../../../../common/strings"; + +describe("Active Learning Page", () => { + function createComponent(store, props: IActiveLearningPageProps): ReactWrapper { + return mount( + + + + + , + ); + } + + beforeAll(() => { + toast.success = jest.fn(() => 2); + }); + + it("renders and loads settings from props", () => { + const testProject = MockFactory.createTestProject("TestProject"); + const store = createReduxStore(MockFactory.initialState({ + currentProject: testProject, + })); + + const props = MockFactory.activeLearningProps(); + const wrapper = createComponent(store, props); + + const activeLearningPage = wrapper + .find(ActiveLearningPage) + .childAt(0) as ReactWrapper; + + expect(activeLearningPage.state().settings).toEqual(testProject.activeLearningSettings); + expect(wrapper.find(ActiveLearningForm).props().settings).toEqual(testProject.activeLearningSettings); + }); + + it("updates active learning settings if project changes", () => { + const store = createReduxStore(MockFactory.initialState()); + const props = MockFactory.activeLearningProps(); + + const testProject = props.recentProjects[0]; + const wrapper = createComponent(store, props); + + const activeLearningPage = wrapper + .find(ActiveLearningPage) + .childAt(0) as ReactWrapper; + + expect(activeLearningPage.state().settings).toEqual(testProject.activeLearningSettings); + expect(wrapper.find(ActiveLearningForm).props().settings).toEqual(testProject.activeLearningSettings); + }); + + it("saves the active learning settings when the form is submitted", async () => { + const testProject = MockFactory.createTestProject("TestProject"); + const activeLearningSettings: IActiveLearningSettings = { + ...testProject.activeLearningSettings, + modelPathType: ModelPathType.Url, + modelUrl: "http://myserver.com/custommodel", + autoDetect: true, + predictTag: true, + }; + + const store = createReduxStore(MockFactory.initialState({ + currentProject: testProject, + })); + + const projectServiceMock = ProjectService as jest.Mocked; + projectServiceMock.prototype.load = jest.fn((project) => Promise.resolve(project)); + projectServiceMock.prototype.save = jest.fn((project) => Promise.resolve(project)); + + const props = MockFactory.activeLearningProps(); + const saveProjectSpy = jest.spyOn(props.actions, "saveProject"); + saveProjectSpy.mockClear(); + + const wrapper = createComponent(store, props); + + const activeLearningForm = wrapper.find(ActiveLearningForm); + activeLearningForm.props().onSubmit(activeLearningSettings); + + await MockFactory.flushUi(); + + expect(saveProjectSpy).toBeCalledWith(expect.objectContaining({ + ...testProject, + activeLearningSettings, + })); + + expect(toast.success).toBeCalledWith(strings.activeLearning.messages.saveSuccess); + expect(props.history.goBack).toBeCalled(); + }); + + it("returns to the previous page when the form is cancelled", async () => { + const testProject = MockFactory.createTestProject("TestProject"); + const store = createReduxStore(MockFactory.initialState({ + currentProject: testProject, + })); + + const props = MockFactory.activeLearningProps(); + const saveProjectSpy = jest.spyOn(props.actions, "saveProject"); + saveProjectSpy.mockClear(); + + const wrapper = createComponent(store, props); + + wrapper.find(ActiveLearningForm).props().onCancel(); + + await MockFactory.flushUi(); + expect(props.history.goBack).toBeCalled(); + expect(saveProjectSpy).not.toBeCalled(); + }); +}); diff --git a/src/react/components/pages/activeLearning/activeLearningPage.tsx b/src/react/components/pages/activeLearning/activeLearningPage.tsx new file mode 100644 index 0000000000..eefab2c3a7 --- /dev/null +++ b/src/react/components/pages/activeLearning/activeLearningPage.tsx @@ -0,0 +1,93 @@ +import React from "react"; +import { connect } from "react-redux"; +import { RouteComponentProps } from "react-router"; +import { bindActionCreators } from "redux"; +import { IActiveLearningSettings, IProject, IApplicationState } from "../../../../models/applicationState"; +import IProjectActions, * as projectActions from "../../../../redux/actions/projectActions"; +import { strings } from "../../../../common/strings"; +import { ActiveLearningForm } from "./activeLearningForm"; +import { toast } from "react-toastify"; + +export interface IActiveLearningPageProps extends RouteComponentProps, React.Props { + project: IProject; + recentProjects: IProject[]; + actions: IProjectActions; +} + +export interface IActiveLearningPageState { + settings: IActiveLearningSettings; +} + +function mapStateToProps(state: IApplicationState) { + return { + project: state.currentProject, + recentProjects: state.recentProjects, + }; +} + +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators(projectActions, dispatch), + }; +} + +@connect(mapStateToProps, mapDispatchToProps) +export default class ActiveLearningPage extends React.Component { + public state: IActiveLearningPageState = { + settings: this.props.project ? this.props.project.activeLearningSettings : null, + }; + + public async componentDidMount() { + const projectId = this.props.match.params["projectId"]; + // If we are creating a new project check to see if there is a partial + // project already created in local storage + if (!this.props.project && projectId) { + const projectToLoad = this.props.recentProjects.find((project) => project.id === projectId); + if (projectToLoad) { + await this.props.actions.loadProject(projectToLoad); + } + } + } + + public componentDidUpdate(prevProps: Readonly) { + if (prevProps.project !== this.props.project) { + this.setState({ settings: this.props.project.activeLearningSettings }); + } + } + + public render() { + return ( +
+
+

+ + + {strings.activeLearning.title} + +

+
+ +
+
+
+ ); + } + + private onFormSubmit = async (settings: IActiveLearningSettings): Promise => { + const updatedProject: IProject = { + ...this.props.project, + activeLearningSettings: settings, + }; + + await this.props.actions.saveProject(updatedProject); + toast.success(strings.activeLearning.messages.saveSuccess); + this.props.history.goBack(); + } + + private onFormCancel = (): void => { + this.props.history.goBack(); + } +} diff --git a/src/react/components/pages/activeLearningPage.tsx b/src/react/components/pages/activeLearningPage.tsx deleted file mode 100644 index cf36ae08e1..0000000000 --- a/src/react/components/pages/activeLearningPage.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from "react"; - -export default class ActiveLearningPage extends React.Component { - public render() { - return ( -
ActiveLearningPage
- ); - } -} diff --git a/src/react/components/pages/editorPage/canvas.test.tsx b/src/react/components/pages/editorPage/canvas.test.tsx index d4ca52d109..a028f2dc22 100644 --- a/src/react/components/pages/editorPage/canvas.test.tsx +++ b/src/react/components/pages/editorPage/canvas.test.tsx @@ -45,6 +45,7 @@ describe("Editor Canvas", () => { const canvasProps: ICanvasProps = { selectedAsset: getAssetMetadata(), onAssetMetadataChanged: jest.fn(), + onCanvasRendered: jest.fn(), editorMode: EditorMode.Rectangle, selectionMode: SelectionMode.RECT, project: MockFactory.createTestProject(), @@ -179,7 +180,7 @@ describe("Editor Canvas", () => { }); const canvas = wrapper.instance() as Canvas; expect(wrapper.state().currentAsset).toEqual(assetMetadata); - expect(() => canvas.updateCanvasToolsRegions()).not.toThrowError(); + expect(() => canvas.updateCanvasToolsRegionTags()).not.toThrowError(); }); it("canvas content source is updated when asset is deactivated", () => { diff --git a/src/react/components/pages/editorPage/canvas.tsx b/src/react/components/pages/editorPage/canvas.tsx index 33d9dc5f6a..ef2f86827c 100644 --- a/src/react/components/pages/editorPage/canvas.tsx +++ b/src/react/components/pages/editorPage/canvas.tsx @@ -4,7 +4,7 @@ import { CanvasTools } from "vott-ct"; import { RegionData } from "vott-ct/lib/js/CanvasTools/Core/RegionData"; import { EditorMode, IAssetMetadata, - IProject, IRegion, RegionType, IBoundingBox, ISize, + IProject, IRegion, RegionType, } from "../../../../models/applicationState"; import CanvasHelpers from "./canvasHelpers"; import { AssetPreview, ContentSource } from "../../common/assetPreview/assetPreview"; @@ -25,6 +25,7 @@ export interface ICanvasProps extends React.Props { children?: ReactElement; onAssetMetadataChanged?: (assetMetadata: IAssetMetadata) => void; onSelectedRegionsChanged?: (regions: IRegion[]) => void; + onCanvasRendered?: (canvas: HTMLCanvasElement) => void; } export interface ICanvasState { @@ -73,7 +74,8 @@ export default class Canvas extends React.Component } public componentDidUpdate = async (prevProps: Readonly, prevState: Readonly) => { - if (this.props.selectedAsset.asset.id !== prevProps.selectedAsset.asset.id) { + // Handles asset changing + if (this.props.selectedAsset !== prevProps.selectedAsset) { this.setState({ currentAsset: this.props.selectedAsset }); } @@ -83,9 +85,16 @@ export default class Canvas extends React.Component this.editor.AS.setSelectionMode({ mode: this.props.selectionMode, template: options }); } + const assetIdChanged = this.state.currentAsset.asset.id !== prevState.currentAsset.asset.id; + + // When the selected asset has changed but is still the same asset id + if (!assetIdChanged && this.state.currentAsset !== prevState.currentAsset) { + this.refreshCanvasToolsRegions(); + } + // When the project tags change re-apply tags to regions if (this.props.project.tags !== prevProps.project.tags) { - this.updateCanvasToolsRegions(); + this.updateCanvasToolsRegionTags(); } // Handles when the canvas is enabled & disabled @@ -192,7 +201,7 @@ export default class Canvas extends React.Component return this.state.currentAsset.regions.filter((r) => selectedRegions.find((id) => r.id === id)); } - public updateCanvasToolsRegions = (): void => { + public updateCanvasToolsRegionTags = (): void => { for (const region of this.state.currentAsset.regions) { this.editor.RM.updateTagsById( region.id, @@ -447,6 +456,11 @@ export default class Canvas extends React.Component private setContentSource = async (contentSource: ContentSource) => { try { await this.editor.addContentSource(contentSource as any); + + if (this.props.onCanvasRendered) { + const canvas = this.canvasZone.current.querySelector("canvas"); + this.props.onCanvasRendered(canvas); + } } catch (e) { console.warn(e); } @@ -493,7 +507,7 @@ export default class Canvas extends React.Component this.editor.RM.updateTagsById(update.id, CanvasHelpers.getTagsDescriptor(this.props.project.tags, update)); } this.updateAssetRegions(updatedRegions); - this.updateCanvasToolsRegions(); + this.updateCanvasToolsRegionTags(); } /** diff --git a/src/react/components/pages/editorPage/editorFooter.test.tsx b/src/react/components/pages/editorPage/editorFooter.test.tsx deleted file mode 100644 index fdb54a7fe7..0000000000 --- a/src/react/components/pages/editorPage/editorFooter.test.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import { mount, ReactWrapper } from "enzyme"; -import React from "react"; -import EditorFooter, { IEditorFooterProps, IEditorFooterState } from "./editorFooter"; -import MockFactory from "../../../../common/mockFactory"; - -describe("Footer Component", () => { - - const originalTags = MockFactory.createTestTags(); - - function createComponent(props: IEditorFooterProps): ReactWrapper { - return mount( - , - ); - } - - it("tags are initialized correctly", () => { - const wrapper = createComponent({ - tags: originalTags, - lockedTags: [], - }); - const stateTags = wrapper.state().tags; - expect(stateTags).toEqual(originalTags); - }); - - it("tags are empty", () => { - const wrapper = createComponent({ - tags: [], - lockedTags: [], - }); - const stateTags = wrapper.state()["tags"]; - expect(stateTags).toEqual([]); - }); - - it("create a new tag from text box", () => { - const onChangeHandler = jest.fn(); - const wrapper = createComponent({ - tags: originalTags, - lockedTags: [], - onTagsChanged: onChangeHandler, - }); - const newTagName = "My new tag"; - wrapper.find("input").simulate("change", { target: { value: newTagName } }); - wrapper.find("input").simulate("keyDown", { keyCode: 13 }); - expect(onChangeHandler).toBeCalled(); - - const tags = wrapper.state().tags; - expect(tags).toHaveLength(originalTags.length + 1); - expect(tags[tags.length - 1].name).toEqual(newTagName); - }); - - it("create a new tag when no tags exist", () => { - const onChangeHandler = jest.fn(); - const wrapper = createComponent({ - tags: null, - lockedTags: [], - onTagsChanged: onChangeHandler, - }); - const newTagName = "My new tag"; - wrapper.find("input").simulate("change", { target: { value: newTagName } }); - wrapper.find("input").simulate("keyDown", { keyCode: 13 }); - expect(onChangeHandler).toBeCalled(); - - const tags = wrapper.state().tags; - expect(tags).toHaveLength(1); - expect(tags[0].name).toEqual(newTagName); - }); - - it("remove a tag", () => { - const onChangeHandler = jest.fn(); - const wrapper = createComponent({ - tags: originalTags, - lockedTags: [], - onTagsChanged: onChangeHandler, - }); - expect(wrapper.state().tags).toHaveLength(originalTags.length); - wrapper.find("a.ReactTags__remove") - .last().simulate("click"); - expect(onChangeHandler).toBeCalled(); - const tags = wrapper.state().tags; - expect(tags).toHaveLength(originalTags.length - 1); - expect(tags[0].name).toEqual(originalTags[0].name); - expect(tags[0].color).toEqual(originalTags[0].color); - }); - - it("clicking 'ok' in modal closes and calls onChangeHandler", () => { - const onChangeHandler = jest.fn(); - const wrapper = createComponent({ - tags: originalTags, - lockedTags: [], - onTagsChanged: onChangeHandler, - }); - wrapper.find("div.tag") - .first() - .simulate("click", { target: { innerText: originalTags[0].name }, shiftKey: true}); - wrapper.find("button.btn.btn-success").simulate("click"); - expect(onChangeHandler).toBeCalled(); - }); - - it("clicking 'cancel' in modal closes and does not call onChangeHandler", () => { - const onChangeHandler = jest.fn(); - const wrapper = createComponent({ - tags: originalTags, - lockedTags: [], - onTagsChanged: onChangeHandler, - }); - wrapper.find("div.tag") - .first() - .simulate("click", { target: { innerText: originalTags[0].name }, shiftKey: true}); - wrapper.find("button.btn.btn-secondary").simulate("click"); - - expect(onChangeHandler).not.toBeCalled(); - }); - - it("clicking tag calls onTagClickHandler ", () => { - const onChangeHandler = jest.fn(); - const onTagClickHandler = jest.fn(); - const wrapper = createComponent({ - tags: originalTags, - lockedTags: [], - onTagsChanged: onChangeHandler, - onTagClicked: onTagClickHandler, - }); - wrapper.find("div.tag") - .first() - .simulate("click", { target: { innerText: originalTags[0].name }}); - - expect(onTagClickHandler).toBeCalledWith(originalTags[0]); - }); - - it("clicking tag with ctrl does not call onTagClickHandler ", () => { - const onChangeHandler = jest.fn(); - const onTagClickHandler = jest.fn(); - const wrapper = createComponent({ - tags: originalTags, - lockedTags: [], - onTagsChanged: onChangeHandler, - onTagClicked: onTagClickHandler, - }); - wrapper.find("div.tag") - .first() - .simulate("click", { target: { innerText: originalTags[0].name }, shiftKey: true}); - - expect(onTagClickHandler).not.toBeCalled(); - }); - - it("componentDidUpdate check", async () => { - const onChangeHandler = jest.fn(); - const onTagClickHandler = jest.fn(); - const wrapper = createComponent({ - tags: originalTags, - lockedTags: [], - onTagsChanged: onChangeHandler, - onTagClicked: onTagClickHandler, - }); - - wrapper.setProps({tags: [...originalTags, {color: "#808000", name: "NEWTAG"}]}); - - await MockFactory.flushUi(); - wrapper.update(); - - const tagChild = wrapper.find("div.tag"); - - expect(tagChild.length).toEqual(originalTags.length + 1); - expect(tagChild.last().text()).toMatch("NEWTAG"); - }); -}); diff --git a/src/react/components/pages/editorPage/editorFooter.tsx b/src/react/components/pages/editorPage/editorFooter.tsx deleted file mode 100644 index 5078e429a5..0000000000 --- a/src/react/components/pages/editorPage/editorFooter.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import React from "react"; -import { TagEditorModal, TagsInput } from "vott-react"; -import { strings } from "../../../../common/strings"; -import { ITag } from "../../../../models/applicationState"; - -/** - * Properties for Editor Footer - * @member tags - Array of tags for TagsInput component - * @member lockedTags - Tags currently locked for applying to regions - * @member displayHotKeys - Determines whether indices for first 10 tags are shown on tag buttons - * @member onTagsChanged - Function to call when tags are changed - * @member onTagClicked - Function to call when tags are clicked - */ -export interface IEditorFooterProps { - tags: ITag[]; - lockedTags: string[]; - onTagsChanged?: (value) => void; - onTagClicked?: (value) => void; - onCtrlTagClicked?: (value) => void; - onCtrlShiftTagClicked?: (value) => void; -} - -/** - * State for Editor Footer - * @member tags - Array of tags for TagsInput component - */ -export interface IEditorFooterState { - tags: ITag[]; - selectedTag: ITag; -} - -/** - * @name - Editor Footer - * @description - Footer of the editor page. Contains EditorTagsInput component - */ -export default class EditorFooter extends React.Component { - - public state = { - tags: this.props.tags, - selectedTag: null, - }; - - private tagsInput: React.RefObject = React.createRef(); - private tagEditorModal: React.RefObject = React.createRef(); - - public componentDidUpdate(prevProp: IEditorFooterProps) { - if (prevProp.tags !== this.props.tags) { - this.setState({ - tags: this.props.tags, - }); - } - } - - public render() { - return ( -
- - -
- ); - } - - private onTagClicked = (tag: ITag) => { - this.props.onTagClicked(tag); - this.blurTagsInput(); - } - - private onShiftTagClicked = (tag: ITag) => { - this.setState({ - selectedTag: tag, - }, () => { - this.tagEditorModal.current.open(tag); - }); - } - - private onTagModalOk = (oldTag: ITag, newTag: ITag) => { - this.tagsInput.current.updateTag(oldTag, newTag); - this.tagEditorModal.current.close(); - } - - private onTagsChanged = (tags) => { - this.setState({ - tags, - }, () => { - this.props.onTagsChanged(this.state); - this.blurTagsInput(); - }); - } - - /** - * Shows the display index of the tag in the span of the first 10 tags - * Also adds necessary stylings to all locked tags - * @param name Name of tag - * @param index Index of tag - */ - private getTagSpan = (name: string, index: number) => { - let className = "tag-span"; - let displayName = name; - if (index < 10) { - const displayIndex = (index === 9) ? 0 : index + 1; - displayName = `[${displayIndex}] ` + name; - className += " tag-span-index"; - } - if (this.props.lockedTags.find((t) => t === name)) { - className += " locked-tag"; - } - return ( - {displayName} - ); - } - - private blurTagsInput() { - const inputElement: HTMLElement = document.querySelector(".ReactTags__tagInputField"); - if (inputElement) { - setImmediate(() => inputElement.blur()); - } - } -} diff --git a/src/react/components/pages/editorPage/editorPage.test.tsx b/src/react/components/pages/editorPage/editorPage.test.tsx index 786375aba5..8baa7631bc 100644 --- a/src/react/components/pages/editorPage/editorPage.test.tsx +++ b/src/react/components/pages/editorPage/editorPage.test.tsx @@ -8,7 +8,7 @@ import EditorPage, { IEditorPageProps, IEditorPageState } from "./editorPage"; import MockFactory from "../../../../common/mockFactory"; import { IApplicationState, IAssetMetadata, IProject, - EditorMode, IAsset, AssetState, AssetType, ISize, + EditorMode, IAsset, AssetState, ISize, IActiveLearningSettings, ModelPathType, } from "../../../../models/applicationState"; import { AssetProviderFactory } from "../../../../providers/storage/assetProviderFactory"; import createReduxStore from "../../../../redux/store/store"; @@ -29,6 +29,11 @@ import { appInfo } from "../../../../common/appInfo"; import SplitPane from "react-split-pane"; import EditorSideBar from "./editorSideBar"; import Alert from "../../common/alert/alert"; +import registerMixins from "../../../../registerMixins"; +import { TagInput } from "../../common/tagInput/tagInput"; +import { EditorToolbar } from "./editorToolbar"; +import { ToolbarItem } from "../../toolbar/toolbarItem"; +import { ActiveLearningService } from "../../../../services/activeLearningService"; function createComponent(store, props: IEditorPageProps): ReactWrapper { return mount( @@ -58,9 +63,20 @@ describe("Editor Page Component", () => { let assetServiceMock: jest.Mocked = null; let projectServiceMock: jest.Mocked = null; + const electronMock = { + remote: { + app: { + getAppPath: jest.fn(() => ""), + }, + }, + }; + const testAssets: IAsset[] = MockFactory.createTestAssets(5); beforeAll(() => { + registerToolbar(); + window["require"] = jest.fn(() => electronMock); + const editorMock = Editor as any; editorMock.prototype.addContentSource = jest.fn(() => Promise.resolve()); editorMock.prototype.scaleRegionToSourceSize = jest.fn((regionData: any) => regionData); @@ -125,12 +141,10 @@ describe("Editor Page Component", () => { const wrapper = createComponent(store, props); const editorPage = wrapper.find(EditorPage).childAt(0); - expect(getState(wrapper).project).toBeNull(); editorPage.props().project = testProject; await MockFactory.flushUi(); expect(editorPage.props().project).toEqual(testProject); - expect(getState(wrapper).project).toEqual(testProject); }); it("Loads and merges project assets with asset provider assets when state changes", async () => { @@ -163,7 +177,7 @@ describe("Editor Page Component", () => { }); }); - it("Raises onAssetSelected handler when an asset is selected from the sidebar", async () => { + it("Default asset is loaded and saved during initial page rendering", async () => { // create test project and asset const testProject = MockFactory.createTestProject("TestProject"); const defaultAsset = testAssets[0]; @@ -181,6 +195,7 @@ describe("Editor Page Component", () => { const editorPage = wrapper.find(EditorPage).childAt(0) as ReactWrapper; await MockFactory.flushUi(); + wrapper.update(); const expectedAsset = editorPage.state().assets[0]; const partialProject = { @@ -333,45 +348,6 @@ describe("Editor Page Component", () => { expect(saveProjectSpy).toBeCalledWith(expect.objectContaining(partialProject)); }); - describe("Editor Page Component Forcing Tag Scenario", () => { - it("Detect new Tag from asset metadata when selecting the Asset", async () => { - const getAssetMetadataMock = assetServiceMock.prototype.getAssetMetadata as jest.Mock; - getAssetMetadataMock.mockImplementationOnce((asset) => { - const assetMetadata: IAssetMetadata = { - asset: { ...asset }, - regions: [{ ...MockFactory.createTestRegion(), tags: ["NEWTAG"] }], - version: appInfo.version, - }; - return Promise.resolve(assetMetadata); - }); - - // create test project and asset - const testProject = MockFactory.createTestProject("TestProject"); - - // mock store and props - const store = createStore(testProject, true); - const props = MockFactory.editorPageProps(testProject.id); - - const saveProjectSpy = jest.spyOn(props.actions, "saveProject"); - - // create mock editor page - createComponent(store, props); - - const partialProjectToBeSaved = { - id: testProject.id, - name: testProject.name, - tags: expect.arrayContaining([{ - name: "NEWTAG", - color: expect.any(String), - }]), - }; - - await MockFactory.flushUi(); - - expect(saveProjectSpy).toBeCalledWith(expect.objectContaining(partialProjectToBeSaved)); - }); - }); - it("When an image is updated the asset metadata is updated", async () => { const testProject = MockFactory.createTestProject("TestProject"); const store = createStore(testProject, true); @@ -497,7 +473,6 @@ describe("Editor Page Component", () => { const removeAllRegionsConfirm = jest.fn(); beforeAll(() => { - registerToolbar(); const clipboard = (navigator as any).clipboard; if (!(clipboard && clipboard.writeText)) { (navigator as any).clipboard = { @@ -657,6 +632,11 @@ describe("Editor Page Component", () => { }); describe("Basic tag interaction tests", () => { + + beforeAll(() => { + registerMixins(); + }); + it("tags are initialized correctly", () => { const project = MockFactory.createTestProject(); const store = createReduxStore({ @@ -665,26 +645,31 @@ describe("Editor Page Component", () => { }); const wrapper = createComponent(store, MockFactory.editorPageProps()); - expect(getState(wrapper).project.tags).toEqual(project.tags); + expect(wrapper.find(TagInput).props().tags).toEqual(project.tags); }); - it("create a new tag from text box", () => { + it("create a new tag updates project tags", async () => { const project = MockFactory.createTestProject(); const store = createReduxStore({ ...MockFactory.initialState(), currentProject: project, }); + const wrapper = createComponent(store, MockFactory.editorPageProps()); - expect(getState(wrapper).project.tags).toEqual(project.tags); + await waitForSelectedAsset(wrapper); - const newTagName = "My new tag"; - wrapper.find("div.tag-input-toolbar-item.plus").simulate("click"); - wrapper.find(".tag-input-box").simulate("keydown", { key: "Enter", target: { value: newTagName } }); + const newTag = MockFactory.createTestTag("NewTag"); + const updatedTags = [...project.tags, newTag]; + wrapper.find(TagInput).props().onChange(updatedTags); - const stateTags = getState(wrapper).project.tags; + await MockFactory.flushUi(); + wrapper.update(); - expect(stateTags).toHaveLength(project.tags.length + 1); - expect(stateTags[stateTags.length - 1].name).toEqual(newTagName); + const editorPage = wrapper.find(EditorPage).childAt(0) as ReactWrapper; + const projectTags = editorPage.props().project.tags; + + expect(projectTags).toHaveLength(updatedTags.length); + expect(projectTags[projectTags.length - 1].name).toEqual(newTag.name); }); it("Remove a tag", async () => { @@ -697,12 +682,20 @@ describe("Editor Page Component", () => { const wrapper = createComponent(store, MockFactory.editorPageProps()); await waitForSelectedAsset(wrapper); - expect(getState(wrapper).project.tags).toEqual(project.tags); - wrapper.find(".tag-content").last().simulate("click"); - wrapper.find("i.tag-input-toolbar-icon.fas.fa-trash").simulate("click"); + const tagToDelete = project.tags[project.tags.length - 1]; + wrapper.find(TagInput).props().onTagDeleted(tagToDelete.name); + + // Accept the modal delete warning + wrapper.update(); + wrapper.find(".modal-footer button").first().simulate("click"); - const stateTags = getState(wrapper).project.tags; - expect(stateTags).toHaveLength(project.tags.length - 1); + await MockFactory.flushUi(); + wrapper.update(); + + const editorPage = wrapper.find(EditorPage).childAt(0) as ReactWrapper; + const projectTags = editorPage.props().project.tags; + + expect(projectTags).toHaveLength(project.tags.length - 1); }); it("Adds tag to locked tags when CmdOrCtrl clicked", async () => { @@ -807,6 +800,72 @@ describe("Editor Page Component", () => { })); }); }); + + describe("Active Learning", async () => { + let wrapper: ReactWrapper; + let editorPage: ReactWrapper; + const activeLearningMock = ActiveLearningService as jest.Mocked; + + async function beforeActiveLearningTest(activeLearningSettings?: IActiveLearningSettings) { + document.querySelector = MockFactory.mockCanvas(); + activeLearningMock.prototype.isModelLoaded = jest.fn(() => true); + activeLearningMock.prototype.predictRegions = jest.fn((canvas, assetMetadtata) => { + return Promise.resolve({ + ...assetMetadtata, + predicted: true, + }); + }); + const project = MockFactory.createTestProject(); + + if (activeLearningSettings) { + project.activeLearningSettings = activeLearningSettings; + } + + const store = createReduxStore({ + ...MockFactory.initialState(), + currentProject: project, + }); + + wrapper = createComponent(store, MockFactory.editorPageProps()); + await waitForSelectedAsset(wrapper); + wrapper.update(); + editorPage = wrapper.find(EditorPage).childAt(0); + } + + it("predicts regions when auto detect has been enabled", async () => { + const activeLearningSettings: IActiveLearningSettings = { + modelPathType: ModelPathType.Coco, + autoDetect: true, + predictTag: true, + }; + + await beforeActiveLearningTest(activeLearningSettings); + + editorPage.find(Canvas).props().onCanvasRendered(document.createElement("canvas")); + expect(activeLearningMock.prototype.predictRegions).toBeCalled(); + }); + + it("predicts regions when toolbar item is selected", async () => { + await beforeActiveLearningTest(); + + const toolbarItem = { + props: { + name: ToolbarItemName.ActiveLearning, + }, + }; + + const selectedAsset = editorPage.state().selectedAsset; + wrapper.find(EditorToolbar).props().onToolbarItemSelected(toolbarItem as ToolbarItem); + + await MockFactory.flushUi(); + + expect(activeLearningMock.prototype.predictRegions).toBeCalledWith(expect.anything(), selectedAsset); + expect(assetServiceMock.prototype.save).toBeCalledWith({ + ...selectedAsset, + predicted: true, + }); + }); + }); }); function createStore(project: IProject, setCurrentProject: boolean = false): Store { diff --git a/src/react/components/pages/editorPage/editorPage.tsx b/src/react/components/pages/editorPage/editorPage.tsx index 86d4719838..4cb52f0607 100644 --- a/src/react/components/pages/editorPage/editorPage.tsx +++ b/src/react/components/pages/editorPage/editorPage.tsx @@ -10,14 +10,14 @@ import { strings } from "../../../../common/strings"; import { AssetState, AssetType, EditorMode, IApplicationState, IAppSettings, IAsset, IAssetMetadata, IProject, IRegion, - ISize, ITag, + ISize, ITag, IAdditionalPageSettings, AppError, ErrorCode, } from "../../../../models/applicationState"; import { IToolbarItemRegistration, ToolbarItemFactory } from "../../../../providers/toolbar/toolbarItemFactory"; import IApplicationActions, * as applicationActions from "../../../../redux/actions/applicationActions"; import IProjectActions, * as projectActions from "../../../../redux/actions/projectActions"; import { ToolbarItemName } from "../../../../registerToolbar"; import { AssetService } from "../../../../services/assetService"; -import { AssetPreview, IAssetPreviewSettings } from "../../common/assetPreview/assetPreview"; +import { AssetPreview } from "../../common/assetPreview/assetPreview"; import { KeyboardBinding } from "../../common/keyboardBinding/keyboardBinding"; import { KeyEventType } from "../../common/keyboardManager/keyboardManager"; import { TagInput } from "../../common/tagInput/tagInput"; @@ -28,8 +28,9 @@ import "./editorPage.scss"; import EditorSideBar from "./editorSideBar"; import { EditorToolbar } from "./editorToolbar"; import Alert from "../../common/alert/alert"; -// tslint:disable-next-line:no-var-requires -const tagColors = require("../../common/tagColors.json"); +import Confirm from "../../common/confirm/confirm"; +import { ActiveLearningService } from "../../../../services/activeLearningService"; +import { toast } from "react-toastify"; /** * Properties for Editor Page @@ -50,8 +51,6 @@ export interface IEditorPageProps extends RouteComponentProps, React.Props { - public state: IEditorPageState = { - project: this.props.project, selectedTag: null, lockedTags: [], selectionMode: SelectionMode.RECT, assets: [], childAssets: [], editorMode: EditorMode.Rectangle, - additionalSettings: { videoSettings: (this.props.project) ? this.props.project.videoSettings : null }, + additionalSettings: { + videoSettings: (this.props.project) ? this.props.project.videoSettings : null, + activeLearningSettings: (this.props.project) ? this.props.project.activeLearningSettings : null, + }, thumbnailSize: this.props.appSettings.thumbnailSize || { width: 175, height: 155 }, isValid: true, showInvalidRegionWarning: false, }; + private activeLearningService: ActiveLearningService = null; private loadingProjectAssets: boolean = false; private toolbarItems: IToolbarItemRegistration[] = ToolbarItemFactory.getToolbarItems(); private canvas: RefObject = React.createRef(); + private renameTagConfirm: React.RefObject = React.createRef(); + private deleteTagConfirm: React.RefObject = React.createRef(); public async componentDidMount() { const projectId = this.props.match.params["projectId"]; @@ -129,9 +132,11 @@ export default class EditorPage extends React.Component project.id === projectId); await this.props.actions.loadProject(project); } + + this.activeLearningService = new ActiveLearningService(this.props.project.activeLearningSettings); } - public async componentDidUpdate() { + public async componentDidUpdate(prevProps: Readonly) { if (this.props.project && this.state.assets.length === 0) { await this.loadProjectAssets(); } @@ -139,12 +144,18 @@ export default class EditorPage extends React.Component
+ + this.canvas.current.applyTag(tag.name)); } + /** + * Open confirm dialog for tag renaming + */ + private confirmTagRenamed = (tagName: string, newTagName: string): void => { + this.renameTagConfirm.current.open(tagName, newTagName); + } + + /** + * Renames tag in assets and project, and saves files + * @param tagName Name of tag to be renamed + * @param newTagName New name of tag + */ + private onTagRenamed = async (tagName: string, newTagName: string): Promise => { + const assetUpdates = await this.props.actions.updateProjectTag(this.props.project, tagName, newTagName); + const selectedAsset = assetUpdates.find((am) => am.asset.id === this.state.selectedAsset.asset.id); + + if (selectedAsset) { + if (selectedAsset) { + this.setState({ selectedAsset }); + } + } + } + + /** + * Open Confirm dialog for tag deletion + */ + private confirmTagDeleted = (tagName: string): void => { + this.deleteTagConfirm.current.open(tagName); + } + + /** + * Removes tag from assets and projects and saves files + * @param tagName Name of tag to be deleted + */ + private onTagDeleted = async (tagName: string): Promise => { + const assetUpdates = await this.props.actions.deleteProjectTag(this.props.project, tagName); + const selectedAsset = assetUpdates.find((am) => am.asset.id === this.state.selectedAsset.asset.id); + + if (selectedAsset) { + this.setState({ selectedAsset }); + } + } + private onCtrlTagClicked = (tag: ITag): void => { const locked = this.state.lockedTags; this.setState({ @@ -419,21 +486,28 @@ export default class EditorPage extends React.Component { + // When active learning auto-detect is enabled + // run predictions when asset changes + if (this.props.project.activeLearningSettings.autoDetect && !this.state.selectedAsset.asset.predicted) { + await this.predictRegions(canvas); + } + } + private onSelectedRegionsChanged = (selectedRegions: IRegion[]) => { this.setState({ selectedRegions }); } - private onTagsChanged = (tags) => { + private onTagsChanged = async (tags) => { const project = { ...this.props.project, tags, }; - this.setState({ project }, async () => { - await this.props.actions.saveProject(project); - if (this.canvas.current) { - this.canvas.current.updateCanvasToolsRegions(); - } - }); + + await this.props.actions.saveProject(project); } private onLockedTagsChanged = (lockedTags: string[]) => { @@ -484,6 +558,41 @@ export default class EditorPage extends React.Component { + canvas = canvas || document.querySelector("canvas"); + if (!canvas) { + return; + } + + // Load the configured ML model + if (!this.activeLearningService.isModelLoaded()) { + let toastId: number = null; + try { + toastId = toast.info(strings.activeLearning.messages.loadingModel, { autoClose: false }); + await this.activeLearningService.ensureModelLoaded(); + } catch (e) { + toast.error(strings.activeLearning.messages.errorLoadModel); + return; + } finally { + toast.dismiss(toastId); + } + } + + // Predict and add regions to current asset + try { + const updatedAssetMetadata = await this.activeLearningService + .predictRegions(canvas, this.state.selectedAsset); + + await this.onAssetMetadataChanged(updatedAssetMetadata); + this.setState({ selectedAsset: updatedAssetMetadata }); + } catch (e) { + throw new AppError(ErrorCode.ActiveLearningPredictionError, "Error predicting regions"); } } @@ -523,7 +632,6 @@ export default class EditorPage extends React.Component region.tags.forEach((tag) => assetTags.add(tag))); - - const newTags: ITag[] = this.props.project.tags ? [...this.props.project.tags] : []; - let updateTags = false; - - assetTags.forEach((tag) => { - if (!this.props.project.tags || this.props.project.tags.length === 0 || - !this.props.project.tags.find((projectTag) => tag === projectTag.name)) { - newTags.push({ - name: tag, - color: tagColors[newTags.length % tagColors.length], - }); - updateTags = true; - } - }); - - if (updateTags) { - asset.asset.state = AssetState.Tagged; - const newProject = { ...this.props.project, tags: newTags }; - await this.props.actions.saveAssetMetadata(newProject, asset); - await this.props.actions.saveProject(newProject); - } - } - private loadProjectAssets = async (): Promise => { if (this.loadingProjectAssets || this.state.assets.length > 0) { return; @@ -598,4 +680,19 @@ export default class EditorPage extends React.Component { + const updatedAssets = [...this.state.assets]; + updatedAssets.forEach((asset) => { + const projectAsset = this.props.project.assets[asset.id]; + if (projectAsset) { + asset.state = projectAsset.state; + } + }); + + this.setState({ assets: updatedAssets }); + } } diff --git a/src/react/components/pages/export/exportForm.test.tsx b/src/react/components/pages/export/exportForm.test.tsx index 8dc7d8fbf2..0f7a791bac 100644 --- a/src/react/components/pages/export/exportForm.test.tsx +++ b/src/react/components/pages/export/exportForm.test.tsx @@ -52,6 +52,7 @@ describe("Export Form Component", () => { providerType: "vottJson", providerOptions: { assetState: ExportAssetState.Tagged, + includeImages: true, }, }, onSubmit: onSubmitHandler, diff --git a/src/react/components/pages/export/exportForm.tsx b/src/react/components/pages/export/exportForm.tsx index 7780ddbc7d..e97534e86b 100644 --- a/src/react/components/pages/export/exportForm.tsx +++ b/src/react/components/pages/export/exportForm.tsx @@ -1,6 +1,7 @@ import React from "react"; import _ from "lodash"; import Form, { Widget, FormValidation, IChangeEvent, ISubmitEvent } from "react-jsonschema-form"; +import { getDefaultFormState } from "react-jsonschema-form/lib/utils"; import { addLocValues, strings } from "../../../../common/strings"; import { IExportFormat, IExportProviderOptions } from "../../../../models/applicationState"; import { ExportProviderFactory } from "../../../../providers/export/exportProviderFactory"; @@ -115,7 +116,7 @@ export default class ExportForm extends React.ComponentProfileSettingsPage - ); - } -} diff --git a/src/react/components/pages/projectSettings/projectForm.test.tsx b/src/react/components/pages/projectSettings/projectForm.test.tsx index b031945109..12103c3bd9 100644 --- a/src/react/components/pages/projectSettings/projectForm.test.tsx +++ b/src/react/components/pages/projectSettings/projectForm.test.tsx @@ -15,8 +15,9 @@ describe("Project Form Component", () => { const appSettings = MockFactory.appSettings(); const connections = MockFactory.createTestConnections(); let wrapper: ReactWrapper = null; - let onSubmitHandler: jest.Mock = null; - let onCancelHandler: jest.Mock = null; + const onSubmitHandler = jest.fn(); + const onChangeHandler = jest.fn(); + const onCancelHandler = jest.fn(); function createComponent(props: IProjectFormProps) { return mount( @@ -33,13 +34,16 @@ describe("Project Form Component", () => { describe("Completed project", () => { beforeEach(() => { - onSubmitHandler = jest.fn(); - onCancelHandler = jest.fn(); + onChangeHandler.mockClear(); + onSubmitHandler.mockClear(); + onCancelHandler.mockClear(); + wrapper = createComponent({ project, connections, appSettings, onSubmit: onSubmitHandler, + onChange: onChangeHandler, onCancel: onCancelHandler, }); }); @@ -76,10 +80,14 @@ describe("Project Form Component", () => { const form = wrapper.find("form"); form.simulate("submit"); - expect(onSubmitHandler).toBeCalledWith({ + + const expectedProject = { ...project, name: newName, - }); + }; + + expect(onChangeHandler).toBeCalled(); + expect(onSubmitHandler).toBeCalledWith(expectedProject); }); it("starting project should update description upon submission", () => { @@ -92,10 +100,14 @@ describe("Project Form Component", () => { const form = wrapper.find("form"); form.simulate("submit"); - expect(onSubmitHandler).toBeCalledWith({ + + const expectedProject = { ...project, description: newDescription, - }); + }; + + expect(onChangeHandler).toBeCalledWith(expect.objectContaining(project)); + expect(onSubmitHandler).toBeCalledWith(expectedProject); }); it("starting project should update source connection ID upon submission", () => { @@ -109,11 +121,14 @@ describe("Project Form Component", () => { expect(wrapper.state().formData.sourceConnection).toEqual(newConnection); const form = wrapper.find("form"); form.simulate("submit"); - expect(onSubmitHandler).toBeCalledWith({ + + const expectedProject = { ...project, sourceConnection: connections[1], - }); + }; + expect(onChangeHandler).toBeCalledWith(expect.objectContaining(project)); + expect(onSubmitHandler).toBeCalledWith(expectedProject); }); it("starting project should update target connection ID upon submission", () => { @@ -125,13 +140,17 @@ describe("Project Form Component", () => { wrapper.find("select#root_targetConnection").simulate("change", { target: { value: newConnection.id } }); expect(wrapper.state().formData.targetConnection).toEqual(newConnection); wrapper.find("form").simulate("submit"); - expect(onSubmitHandler).toBeCalledWith({ + + const expectedProject = { ...project, targetConnection: connections[1], - }); + }; + + expect(onChangeHandler).toBeCalledWith(expect.objectContaining(project)); + expect(onSubmitHandler).toBeCalledWith(expectedProject); }); - it("starting project should call onChangeHandler on submission", () => { + it("starting project should call onSubmitHandler on submission", () => { const form = wrapper.find("form"); form.simulate("submit"); expect(onSubmitHandler).toBeCalledWith({ @@ -155,6 +174,7 @@ describe("Project Form Component", () => { const form = wrapper.find("form"); form.simulate("submit"); + expect(onChangeHandler).toBeCalledWith(expect.objectContaining(project)); expect(onSubmitHandler).toBeCalledWith( expect.objectContaining({ name: newName, @@ -187,6 +207,7 @@ describe("Project Form Component", () => { appSettings, connections: newConnections, onSubmit: onSubmitHandler, + onChange: onChangeHandler, onCancel: onCancelHandler, }); // Source Connection should have all connections @@ -202,13 +223,12 @@ describe("Project Form Component", () => { describe("Empty Project", () => { beforeEach(() => { - onSubmitHandler = jest.fn(); - onCancelHandler = jest.fn(); wrapper = createComponent({ project: null, appSettings, connections, onSubmit: onSubmitHandler, + onChange: onChangeHandler, onCancel: onCancelHandler, }); }); @@ -239,6 +259,7 @@ describe("Project Form Component", () => { appSettings, connections, onSubmit: onSubmitHandler, + onChange: onChangeHandler, onCancel: onCancelHandler, }); const newTagName = "My new tag"; diff --git a/src/react/components/pages/projectSettings/projectForm.tsx b/src/react/components/pages/projectSettings/projectForm.tsx index 7eaf7b26d1..0cfc8dad8e 100644 --- a/src/react/components/pages/projectSettings/projectForm.tsx +++ b/src/react/components/pages/projectSettings/projectForm.tsx @@ -1,5 +1,5 @@ import React from "react"; -import Form, { FormValidation, ISubmitEvent } from "react-jsonschema-form"; +import Form, { FormValidation, ISubmitEvent, IChangeEvent, Widget } from "react-jsonschema-form"; import { ITagsInputProps, TagEditorModal, TagsInput } from "vott-react"; import { addLocValues, strings } from "../../../../common/strings"; import { IConnection, IProject, ITag, IAppSettings } from "../../../../models/applicationState"; @@ -10,6 +10,7 @@ import CustomFieldTemplate from "../../common/customField/customFieldTemplate"; import { ISecurityTokenPickerProps, SecurityTokenPicker } from "../../common/securityTokenPicker/securityTokenPicker"; import "vott-react/dist/css/tagsInput.css"; import { IConnectionProviderPickerProps } from "../../common/connectionProviderPicker/connectionProviderPicker"; +import LocalFolderPicker from "../../common/localFolderPicker/localFolderPicker"; // tslint:disable-next-line:no-var-requires const formSchema = addLocValues(require("./projectForm.json")); @@ -28,6 +29,7 @@ export interface IProjectFormProps extends React.Props { connections: IConnection[]; appSettings: IAppSettings; onSubmit: (project: IProject) => void; + onChange?: (project: IProject) => void; onCancel?: () => void; } @@ -50,6 +52,10 @@ export interface IProjectFormState { * @description - Form for editing or creating VoTT projects */ export default class ProjectForm extends React.Component { + private widgets = { + localFolderPicker: (LocalFolderPicker as any) as Widget, + }; + private tagsInput: React.RefObject; private tagEditorModal: React.RefObject; @@ -94,9 +100,11 @@ export default class ProjectForm extends React.Component
@@ -184,6 +192,12 @@ export default class ProjectForm extends React.Component) => { + if (this.props.onChange) { + this.props.onChange(changeEvent.formData); + } + } + private onFormSubmit(args: ISubmitEvent) { const project: IProject = { ...args.formData, diff --git a/src/react/components/pages/projectSettings/projectSettingsPage.test.tsx b/src/react/components/pages/projectSettings/projectSettingsPage.test.tsx index 4490aaa35d..c5b3777e31 100644 --- a/src/react/components/pages/projectSettings/projectSettingsPage.test.tsx +++ b/src/react/components/pages/projectSettings/projectSettingsPage.test.tsx @@ -4,20 +4,21 @@ import { Provider } from "react-redux"; import { BrowserRouter as Router } from "react-router-dom"; import MockFactory from "../../../../common/mockFactory"; import createReduxStore from "../../../../redux/store/store"; -import ProjectSettingsPage, { IProjectSettingsPageProps } from "./projectSettingsPage"; +import ProjectSettingsPage, { IProjectSettingsPageProps, IProjectSettingsPageState } from "./projectSettingsPage"; jest.mock("../../../../services/projectService"); import ProjectService from "../../../../services/projectService"; -import { IAppSettings } from "../../../../models/applicationState"; +import { IAppSettings, IProject } from "../../../../models/applicationState"; import ProjectMetrics from "./projectMetrics"; +import ProjectForm, { IProjectFormProps } from "./projectForm"; jest.mock("./projectMetrics", () => () => { - return ( -
- Dummy Project Metrics -
- ); - }, + return ( +
+ Dummy Project Metrics +
+ ); +}, ); describe("Project settings page", () => { @@ -33,12 +34,29 @@ describe("Project settings page", () => { ); } + const localStorageMock = { + getItem: jest.fn(), + setItem: jest.fn(), + removeItem: jest.fn(), + }; + + beforeAll(() => { + Object.defineProperty(global, "_localStorage", { + value: localStorageMock, + writable: false, + }); + }); + beforeEach(() => { + localStorageMock.getItem.mockClear(); + localStorageMock.setItem.mockClear(); + localStorageMock.removeItem.mockClear(); + projectServiceMock = ProjectService as jest.Mocked; - projectServiceMock.prototype.load = jest.fn((project) => ({...project})); + projectServiceMock.prototype.load = jest.fn((project) => ({ ...project })); }); - it("Form submission calls save project action", (done) => { + it("Form submission calls save project action", async () => { const store = createReduxStore(MockFactory.initialState()); const props = MockFactory.projectSettingsProps(); const saveProjectSpy = jest.spyOn(props.projectActions, "saveProject"); @@ -47,14 +65,12 @@ describe("Project settings page", () => { const wrapper = createComponent(store, props); wrapper.find("form").simulate("submit"); + await MockFactory.flushUi(); - setImmediate(() => { - expect(saveProjectSpy).toBeCalled(); - done(); - }); + expect(saveProjectSpy).toBeCalled(); }); - it("Throws an error when a user tries to create a duplicate project", async (done) => { + it("Throws an error when a user tries to create a duplicate project", async () => { const project = MockFactory.createTestProject("1"); project.id = "25"; const initialStateOverride = { @@ -78,18 +94,16 @@ describe("Project settings page", () => { }, }); wrapper.find("form").simulate("submit"); - setImmediate(async () => { - // expect(saveProjectSpy).toBeCalled(); - expect(saveProjectSpy.mockRejectedValue).not.toBeNull(); - done(); - }); + await MockFactory.flushUi(); + + expect(saveProjectSpy.mockRejectedValue).not.toBeNull(); }); - it("calls save project when user creates a unique project", (done) => { + it("calls save project when user creates a unique project", async () => { const initialState = MockFactory.initialState(); // New Project should not have id or security token set by default - const project = {...initialState.recentProjects[0]}; + const project = { ...initialState.recentProjects[0] }; project.id = null; project.name = "Brand New Project"; project.securityToken = ""; @@ -106,20 +120,20 @@ describe("Project settings page", () => { const wrapper = createComponent(store, props); wrapper.find("form").simulate("submit"); - setImmediate(() => { - // New security token was created for new project - expect(saveAppSettingsSpy).toBeCalled(); - const appSettings = saveAppSettingsSpy.mock.calls[0][0] as IAppSettings; - expect(appSettings.securityTokens.length).toEqual(initialState.appSettings.securityTokens.length + 1); + await MockFactory.flushUi(); - // New project was saved with new security token - expect(saveProjectSpy).toBeCalledWith({ - ...project, - securityToken: `${project.name} Token`, - }); + // New security token was created for new project + expect(saveAppSettingsSpy).toBeCalled(); + const appSettings = saveAppSettingsSpy.mock.calls[0][0] as IAppSettings; + expect(appSettings.securityTokens.length).toEqual(initialState.appSettings.securityTokens.length + 1); - done(); + // New project was saved with new security token + expect(saveProjectSpy).toBeCalledWith({ + ...project, + securityToken: `${project.name} Token`, }); + + expect(localStorage.removeItem).toBeCalledWith("projectForm"); }); it("render ProjectMetrics", () => { @@ -146,4 +160,64 @@ describe("Project settings page", () => { expect(projectMetrics).toHaveLength(0); }); }); + + describe("Persisting project form", () => { + let wrapper: ReactWrapper = null; + + function initPersistProjectFormTest() { + const store = createReduxStore(MockFactory.initialState()); + const props = MockFactory.projectSettingsProps(); + props.match.url = "/projects/create"; + wrapper = createComponent(store, props); + } + + it("Loads partial project from local storage", () => { + const partialProject: IProject = { + ...{} as any, + name: "partial project", + description: "partial project description", + tags: [ + { name: "tag-1", color: "#ff0000" }, + { name: "tag-3", color: "#ffff00" }, + ], + }; + + localStorageMock.getItem.mockImplementationOnce(() => JSON.stringify(partialProject)); + + initPersistProjectFormTest(); + const projectSettingsPage = wrapper + .find(ProjectSettingsPage) + .childAt(0) as ReactWrapper; + + expect(localStorage.getItem).toBeCalledWith("projectForm"); + expect(projectSettingsPage.state().project).toEqual(partialProject); + }); + + it("Stores partial project in local storage", () => { + initPersistProjectFormTest(); + const partialProject: IProject = { + ...{} as any, + name: "partial project", + }; + + const projectForm = wrapper.find(ProjectForm) as ReactWrapper; + projectForm.props().onChange(partialProject); + + expect(localStorage.setItem).toBeCalledWith("projectForm", JSON.stringify(partialProject)); + }); + + it("Does NOT store empty project in local storage", () => { + initPersistProjectFormTest(); + const emptyProject: IProject = { + ...{} as any, + sourceConnection: {}, + targetConnection: {}, + exportFormat: {}, + }; + const projectForm = wrapper.find(ProjectForm) as ReactWrapper; + projectForm.props().onChange(emptyProject); + + expect(localStorage.setItem).not.toBeCalled(); + }); + }); }); diff --git a/src/react/components/pages/projectSettings/projectSettingsPage.tsx b/src/react/components/pages/projectSettings/projectSettingsPage.tsx index 0aeed1c81a..68bdf43c4b 100644 --- a/src/react/components/pages/projectSettings/projectSettingsPage.tsx +++ b/src/react/components/pages/projectSettings/projectSettingsPage.tsx @@ -27,6 +27,10 @@ export interface IProjectSettingsPageProps extends RouteComponentProps, React.Pr appSettings: IAppSettings; } +export interface IProjectSettingsPageState { + project: IProject; +} + function mapStateToProps(state: IApplicationState) { return { project: state.currentProject, @@ -43,24 +47,40 @@ function mapDispatchToProps(dispatch) { }; } +const projectFormTempKey = "projectForm"; + /** * @name - Project Settings Page * @description - Page for adding/editing/removing projects */ @connect(mapStateToProps, mapDispatchToProps) -export default class ProjectSettingsPage extends React.Component { - constructor(props, context) { - super(props, context); +export default class ProjectSettingsPage extends React.Component { + public state: IProjectSettingsPageState = { + project: this.props.project, + }; + public async componentDidMount() { const projectId = this.props.match.params["projectId"]; - if (!this.props.project && projectId) { - const project = this.props.recentProjects.find((project) => project.id === projectId); - this.props.applicationActions.ensureSecurityToken(project); - this.props.projectActions.loadProject(project); + // If we are creating a new project check to see if there is a partial + // project already created in local storage + if (this.props.match.url === "/projects/create") { + const projectJson = localStorage.getItem(projectFormTempKey); + if (projectJson) { + this.setState({ project: JSON.parse(projectJson) }); + } + } else if (!this.props.project && projectId) { + const projectToLoad = this.props.recentProjects.find((project) => project.id === projectId); + if (projectToLoad) { + await this.props.applicationActions.ensureSecurityToken(projectToLoad); + await this.props.projectActions.loadProject(projectToLoad); + } } + } - this.onFormSubmit = this.onFormSubmit.bind(this); - this.onFormCancel = this.onFormCancel.bind(this); + public componentDidUpdate(prevProps: Readonly) { + if (prevProps.project !== this.props.project) { + this.setState({ project: this.props.project }); + } } public render() { @@ -75,9 +95,10 @@ export default class ProjectSettingsPage extends React.Component
@@ -91,11 +112,23 @@ export default class ProjectSettingsPage extends React.Component { + if (this.isPartialProject(project)) { + localStorage.setItem(projectFormTempKey, JSON.stringify(project)); + } + } + private onFormSubmit = async (project: IProject) => { const isNew = !(!!project.id); await this.props.applicationActions.ensureSecurityToken(project); await this.props.projectActions.saveProject(project); + localStorage.removeItem(projectFormTempKey); toast.success(interpolate(strings.projectSettings.messages.saveSuccess, { project })); @@ -106,7 +139,23 @@ export default class ProjectSettingsPage extends React.Component { + localStorage.removeItem(projectFormTempKey); this.props.history.goBack(); } + + /** + * Checks whether a project is partially populated + */ + private isPartialProject = (project: IProject): boolean => { + return project && !(!!project.id) && + ( + !!project.name + || !!project.description + || (project.sourceConnection && Object.keys(project.sourceConnection).length > 0) + || (project.targetConnection && Object.keys(project.targetConnection).length > 0) + || (project.exportFormat && Object.keys(project.exportFormat).length > 0) + || (project.tags && project.tags.length > 0) + ); + } } diff --git a/src/react/components/shell/mainContentRouter.test.tsx b/src/react/components/shell/mainContentRouter.test.tsx index 876336c257..204b65d6b0 100644 --- a/src/react/components/shell/mainContentRouter.test.tsx +++ b/src/react/components/shell/mainContentRouter.test.tsx @@ -11,7 +11,6 @@ import MainContentRouter from "./mainContentRouter"; import HomePage, { IHomePageProps } from "./../pages/homepage/homePage"; import SettingsPage from "./../pages/appSettings/appSettingsPage"; import ConnectionsPage from "./../pages/connections/connectionsPage"; -import ProfilePage from "./../pages/profileSettingsPage"; import { IApplicationState } from "./../../../models/applicationState"; describe("Main Content Router", () => { @@ -43,7 +42,6 @@ describe("Main Content Router", () => { expect(pathMap["/"]).toBe(HomePage); expect(pathMap["/settings"]).toBe(SettingsPage); expect(pathMap["/connections"]).toBe(ConnectionsPage); - expect(pathMap["/profile"]).toBe(ProfilePage); }); it("renders a redirect when no route is matched", () => { diff --git a/src/react/components/shell/mainContentRouter.tsx b/src/react/components/shell/mainContentRouter.tsx index 4d6c6687ba..c8b8893c1e 100644 --- a/src/react/components/shell/mainContentRouter.tsx +++ b/src/react/components/shell/mainContentRouter.tsx @@ -1,13 +1,12 @@ import React from "react"; -import { Switch, Route, Redirect } from "react-router-dom"; +import { Switch, Route } from "react-router-dom"; import HomePage from "../pages/homepage/homePage"; -import ActiveLearningPage from "../pages/activeLearningPage"; +import ActiveLearningPage from "../pages/activeLearning/activeLearningPage"; import AppSettingsPage from "../pages/appSettings/appSettingsPage"; import ConnectionPage from "../pages/connections/connectionsPage"; import EditorPage from "../pages/editorPage/editorPage"; import ExportPage from "../pages/export/exportPage"; import ProjectSettingsPage from "../pages/projectSettings/projectSettingsPage"; -import ProfileSettingsPage from "../pages/profileSettingsPage"; /** * @name - Main Content Router @@ -19,7 +18,6 @@ export default function MainContentRouter() { - diff --git a/src/react/components/shell/sidebar.test.tsx b/src/react/components/shell/sidebar.test.tsx index 5beda94a6f..edd21cfdae 100644 --- a/src/react/components/shell/sidebar.test.tsx +++ b/src/react/components/shell/sidebar.test.tsx @@ -16,6 +16,6 @@ describe("Sidebar Component", () => { expect(wrapper).not.toBeNull(); const links = wrapper.find("ul li"); - expect(links.length).toEqual(6); + expect(links.length).toEqual(7); }); }); diff --git a/src/react/components/shell/sidebar.tsx b/src/react/components/shell/sidebar.tsx index 5b262d9096..ea6598bd49 100644 --- a/src/react/components/shell/sidebar.tsx +++ b/src/react/components/shell/sidebar.tsx @@ -39,7 +39,16 @@ export default function Sidebar({ project }) { - + + + +
  • + + + +
  • diff --git a/src/redux/actions/actionTypes.ts b/src/redux/actions/actionTypes.ts index 6f1ad9623c..2116460825 100644 --- a/src/redux/actions/actionTypes.ts +++ b/src/redux/actions/actionTypes.ts @@ -16,6 +16,8 @@ export enum ActionTypes { CLOSE_PROJECT_SUCCESS = "CLOSE_PROJECT_SUCCESS", LOAD_PROJECT_ASSETS_SUCCESS = "LOAD_PROJECT_ASSETS_SUCCESS", EXPORT_PROJECT_SUCCESS = "EXPORT_PROJECT_SUCCESS", + UPDATE_PROJECT_TAG_SUCCESS = "UPDATE_PROJECT_TAG_SUCCESS", + DELETE_PROJECT_TAG_SUCCESS = "DELETE_PROJECT_TAG_SUCCESS", // Connections LOAD_CONNECTION_SUCCESS = "LOAD_CONNECTION_SUCCESS", diff --git a/src/redux/actions/projectActions.test.ts b/src/redux/actions/projectActions.test.ts index ddf7b12eaa..c0f587bdcf 100644 --- a/src/redux/actions/projectActions.test.ts +++ b/src/redux/actions/projectActions.test.ts @@ -1,3 +1,4 @@ +import _ from "lodash"; import createMockStore, { MockStoreEnhanced } from "redux-mock-store"; import { ActionTypes } from "./actionTypes"; import * as projectActions from "./projectActions"; @@ -10,25 +11,30 @@ import ProjectService from "../../services/projectService"; jest.mock("../../services/assetService"); import { AssetService } from "../../services/assetService"; import { ExportProviderFactory } from "../../providers/export/exportProviderFactory"; -import { ExportAssetState, IExportProvider } from "../../providers/export/exportProvider"; -import { IApplicationState } from "../../models/applicationState"; +import { IExportProvider } from "../../providers/export/exportProvider"; +import { IApplicationState, IProject } from "../../models/applicationState"; import initialState from "../store/initialState"; import { appInfo } from "../../common/appInfo"; +import registerMixins from "../../registerMixins"; describe("Project Redux Actions", () => { let store: MockStoreEnhanced; let projectServiceMock: jest.Mocked; const appSettings = MockFactory.appSettings(); + beforeAll(registerMixins); + beforeEach(() => { const middleware = [thunk]; const mockState: IApplicationState = { ...initialState, appSettings, }; + store = createMockStore(middleware)(mockState); projectServiceMock = ProjectService as jest.Mocked; projectServiceMock.prototype.load = jest.fn((project) => Promise.resolve(project)); + projectServiceMock.prototype.save = jest.fn((project) => Promise.resolve(project)); }); it("Load Project action resolves a promise and dispatches redux action", async () => { @@ -81,39 +87,6 @@ describe("Project Redux Actions", () => { expect(result.version).toEqual(appInfo.version); }); - it("Save Project action on new project correctly add default export format", async () => { - projectServiceMock.prototype.save = jest.fn((project) => Promise.resolve(project)); - - const skeletonProject = MockFactory.createTestProject("TestProject"); - const project = { - ...skeletonProject, - exportFormat: null, - }; - - const result = await projectActions.saveProject(project)(store.dispatch, store.getState); - - expect(result.exportFormat).toEqual({ - providerType: "vottJson", - providerOptions: { - assetState: ExportAssetState.Visited, - }, - }); - }); - - it("Save Project action on new project correctly set tags to empty if none created", async () => { - projectServiceMock.prototype.save = jest.fn((project) => Promise.resolve(project)); - - const skeletonProject = MockFactory.createTestProject("TestProject"); - const project = { - ...skeletonProject, - tags: null, - }; - - const result = await projectActions.saveProject(project)(store.dispatch, store.getState); - - expect(result.tags).toEqual([]); - }); - it("Save Project action does not override existing export format", async () => { projectServiceMock.prototype.save = jest.fn((project) => Promise.resolve(project)); @@ -254,4 +227,81 @@ describe("Project Redux Actions", () => { expect(mockExportProvider.export).toHaveBeenCalled(); }); + + describe("Updating project tags", () => { + let project: IProject = null; + + beforeEach(() => { + project = MockFactory.createTestProject("TestProject"); + const middleware = [thunk]; + const mockState: IApplicationState = { + ...initialState, + currentProject: project, + appSettings, + }; + + store = createMockStore(middleware)(mockState); + }); + + it("Updates tags across all project assets when a tag is renamed", async () => { + const projectAssets = _.values(project.assets); + const updatedTag = project.tags[project.tags.length - 1]; + + const updatedAssets = [ + MockFactory.createTestAssetMetadata(projectAssets[0]), + MockFactory.createTestAssetMetadata(projectAssets[1]), + ]; + + const expectedTagName = `${updatedTag.name} - updated`; + + const assetServiceMock = AssetService as jest.Mocked; + assetServiceMock.prototype.renameTag = jest.fn(() => Promise.resolve(updatedAssets)); + + const actualUpdatedAssets = await projectActions.updateProjectTag( + project, + updatedTag.name, + expectedTagName, + )(store.dispatch, store.getState); + + const actions = store.getActions(); + + expect(actions.length).toEqual(5); + expect(actions[0].type).toEqual(ActionTypes.SAVE_ASSET_METADATA_SUCCESS); + expect(actions[1].type).toEqual(ActionTypes.SAVE_ASSET_METADATA_SUCCESS); + expect(actions[2].type).toEqual(ActionTypes.SAVE_PROJECT_SUCCESS); + expect(actions[3].type).toEqual(ActionTypes.LOAD_PROJECT_SUCCESS); + expect(actions[4].type).toEqual(ActionTypes.UPDATE_PROJECT_TAG_SUCCESS); + + expect(actualUpdatedAssets).toEqual(updatedAssets); + }); + + it("Deletes tags across all project assets when a tag is renamed", async () => { + const projectAssets = _.values(project.assets); + const deletedTag = project.tags[project.tags.length - 1]; + + const updatedAssets = [ + MockFactory.createTestAssetMetadata(projectAssets[0]), + MockFactory.createTestAssetMetadata(projectAssets[1]), + ]; + + const assetServiceMock = AssetService as jest.Mocked; + assetServiceMock.prototype.deleteTag = jest.fn(() => Promise.resolve(updatedAssets)); + + const actualUpdatedAssets = await projectActions.deleteProjectTag( + project, + deletedTag.name, + )(store.dispatch, store.getState); + + const actions = store.getActions(); + + expect(actions.length).toEqual(5); + expect(actions[0].type).toEqual(ActionTypes.SAVE_ASSET_METADATA_SUCCESS); + expect(actions[1].type).toEqual(ActionTypes.SAVE_ASSET_METADATA_SUCCESS); + expect(actions[2].type).toEqual(ActionTypes.SAVE_PROJECT_SUCCESS); + expect(actions[3].type).toEqual(ActionTypes.LOAD_PROJECT_SUCCESS); + expect(actions[4].type).toEqual(ActionTypes.DELETE_PROJECT_TAG_SUCCESS); + + expect(actualUpdatedAssets).toEqual(updatedAssets); + }); + }); }); diff --git a/src/redux/actions/projectActions.ts b/src/redux/actions/projectActions.ts index 99b465f04d..f15575d851 100644 --- a/src/redux/actions/projectActions.ts +++ b/src/redux/actions/projectActions.ts @@ -15,6 +15,8 @@ import { createAction, createPayloadAction, IPayloadAction } from "./actionCreat import { ExportAssetState, IExportResults } from "../../providers/export/exportProvider"; import { appInfo } from "../../common/appInfo"; import { strings } from "../../common/strings"; +import { IExportFormat } from "vott-react"; +import { IVottJsonExportProviderOptions } from "../../providers/export/vottJson"; /** * Actions to be performed in relation to projects @@ -28,6 +30,8 @@ export default interface IProjectActions { loadAssets(project: IProject): Promise; loadAssetMetadata(project: IProject, asset: IAsset): Promise; saveAssetMetadata(project: IProject, assetMetadata: IAssetMetadata): Promise; + updateProjectTag(project: IProject, oldTagName: string, newTagName: string): Promise; + deleteProjectTag(project: IProject, tagName): Promise; } /** @@ -76,21 +80,7 @@ export function saveProject(project: IProject) throw new AppError(ErrorCode.SecurityTokenNotFound, "Security Token Not Found"); } - const defaultExportFormat = { - providerType: "vottJson", - providerOptions: { - assetState: ExportAssetState.Visited, - }, - }; - - const newProject = { - ...project, - version: appInfo.version, - exportFormat: project.exportFormat || defaultExportFormat, - tags: project.tags || [], - }; - - const savedProject = await projectService.save(newProject, projectToken); + const savedProject = await projectService.save(project, projectToken); dispatch(saveProjectAction(savedProject)); // Reload project after save actions @@ -130,7 +120,7 @@ export function deleteProject(project: IProject) */ export function closeProject(): (dispatch: Dispatch) => void { return (dispatch: Dispatch): void => { - dispatch({type: ActionTypes.CLOSE_PROJECT_SUCCESS}); + dispatch({ type: ActionTypes.CLOSE_PROJECT_SUCCESS }); }; } @@ -159,7 +149,7 @@ export function loadAssetMetadata(project: IProject, asset: IAsset): (dispatch: const assetMetadata = await assetService.getAssetMetadata(asset); dispatch(loadAssetMetadataAction(assetMetadata)); - return {...assetMetadata}; + return { ...assetMetadata }; }; } @@ -171,14 +161,77 @@ export function loadAssetMetadata(project: IProject, asset: IAsset): (dispatch: export function saveAssetMetadata( project: IProject, assetMetadata: IAssetMetadata): (dispatch: Dispatch) => Promise { - const newAssetMetadata = {...assetMetadata, version: appInfo.version}; + const newAssetMetadata = { ...assetMetadata, version: appInfo.version }; return async (dispatch: Dispatch) => { const assetService = new AssetService(project); const savedMetadata = await assetService.save(newAssetMetadata); dispatch(saveAssetMetadataAction(savedMetadata)); - return {...savedMetadata}; + return { ...savedMetadata }; + }; +} + +/** + * Updates a project and all asset references from oldTagName to newTagName + * @param project The project to update tags + * @param oldTagName The old tag name + * @param newTagName The new tag name + */ +export function updateProjectTag(project: IProject, oldTagName: string, newTagName: string) + : (dispatch: Dispatch, getState: () => IApplicationState) => Promise { + return async (dispatch: Dispatch, getState: () => IApplicationState) => { + // Find tags to rename + const assetService = new AssetService(project); + const assetUpdates = await assetService.renameTag(oldTagName, newTagName); + + // Save updated assets + await assetUpdates.forEachAsync(async (assetMetadata) => { + await saveAssetMetadata(project, assetMetadata)(dispatch); + }); + + const currentProject = getState().currentProject; + const updatedProject = { + ...currentProject, + tags: project.tags.map((t) => (t.name === oldTagName) ? { ...t, name: newTagName } : t), + }; + + // Save updated project tags + await saveProject(updatedProject)(dispatch, getState); + dispatch(updateProjectTagAction(updatedProject)); + + return assetUpdates; + }; +} + +/** + * Updates a project and all asset references from oldTagName to newTagName + * @param project The project to delete tags + * @param tagName The tag to delete + */ +export function deleteProjectTag(project: IProject, tagName) + : (dispatch: Dispatch, getState: () => IApplicationState) => Promise { + return async (dispatch: Dispatch, getState: () => IApplicationState) => { + // Find tags to rename + const assetService = new AssetService(project); + const assetUpdates = await assetService.deleteTag(tagName); + + // Save updated assets + await assetUpdates.forEachAsync(async (assetMetadata) => { + await saveAssetMetadata(project, assetMetadata)(dispatch); + }); + + const currentProject = getState().currentProject; + const updatedProject = { + ...currentProject, + tags: project.tags.filter((t) => t.name !== tagName), + }; + + // Save updated project tags + await saveProject(updatedProject)(dispatch, getState); + dispatch(deleteProjectTagAction(updatedProject)); + + return assetUpdates; }; } @@ -262,6 +315,20 @@ export interface IExportProjectAction extends IPayloadAction { type: ActionTypes.EXPORT_PROJECT_SUCCESS; } +/** + * Update Project Tag action type + */ +export interface IUpdateProjectTagAction extends IPayloadAction { + type: ActionTypes.UPDATE_PROJECT_TAG_SUCCESS; +} + +/** + * Delete project tag action type + */ +export interface IDeleteProjectTagAction extends IPayloadAction { + type: ActionTypes.DELETE_PROJECT_TAG_SUCCESS; +} + /** * Instance of Load Project action */ @@ -298,3 +365,13 @@ export const saveAssetMetadataAction = */ export const exportProjectAction = createPayloadAction(ActionTypes.EXPORT_PROJECT_SUCCESS); +/** + * Instance of Update project tag action + */ +export const updateProjectTagAction = + createPayloadAction(ActionTypes.UPDATE_PROJECT_TAG_SUCCESS); +/** + * Instance of Delete project tag action + */ +export const deleteProjectTagAction = + createPayloadAction(ActionTypes.DELETE_PROJECT_TAG_SUCCESS); diff --git a/src/redux/reducers/currentProjectReducer.test.ts b/src/redux/reducers/currentProjectReducer.test.ts index 536e2f30d9..56c6f9802d 100644 --- a/src/redux/reducers/currentProjectReducer.test.ts +++ b/src/redux/reducers/currentProjectReducer.test.ts @@ -1,6 +1,6 @@ import _ from "lodash"; import { reducer } from "./currentProjectReducer"; -import { IProject, IAssetMetadata, AssetState } from "../../models/applicationState"; +import { IProject, IAssetMetadata, AssetState, ITag } from "../../models/applicationState"; import MockFactory from "../../common/mockFactory"; import { loadProjectAction, @@ -50,7 +50,7 @@ describe("Current Project Reducer", () => { expect(result).toEqual(currentProject); }); - it("Updating connection used by current project is updated in curren project", () => { + it("Updating connection used by current project is updated in current project", () => { const currentProject = MockFactory.createTestProject("1"); const state: IProject = currentProject; @@ -113,6 +113,29 @@ describe("Current Project Reducer", () => { expect(result.assets[testAssets[0].id]).toEqual(assetMetadata.asset); }); + it("Appends new tags to project when saving asset contains new tags", () => { + const state: IProject = MockFactory.createTestProject("TestProject"); + const testAssets = MockFactory.createTestAssets(); + + const expectedTag: ITag = { + name: "NEWTAG", + color: expect.any(String), + }; + + const assetMetadata = MockFactory.createTestAssetMetadata( + testAssets[0], + [MockFactory.createTestRegion("Region 1", [expectedTag.name])], + ); + + const action = saveAssetMetadataAction(assetMetadata); + const result = reducer(state, action); + expect(result).not.toBe(state); + expect(result.tags).toEqual([ + ...state.tags, + expectedTag, + ]); + }); + it("Unknown action performs a noop", () => { const state: IProject = MockFactory.createTestProject("TestProject"); const action = anyOtherAction(); diff --git a/src/redux/reducers/currentProjectReducer.ts b/src/redux/reducers/currentProjectReducer.ts index a674cac29f..16458ed387 100644 --- a/src/redux/reducers/currentProjectReducer.ts +++ b/src/redux/reducers/currentProjectReducer.ts @@ -1,7 +1,9 @@ import _ from "lodash"; import { ActionTypes } from "../actions/actionTypes"; -import { IProject } from "../../models/applicationState"; +import { IProject, ITag } from "../../models/applicationState"; import { AnyAction } from "../actions/actionCreators"; +// tslint:disable-next-line:no-var-requires +const tagColors = require("../../react/components/common/tagColors.json"); /** * Reducer for project. Actions handled: @@ -38,6 +40,31 @@ export const reducer = (state: IProject = null, action: AnyAction): IProject => const updatedAssets = { ...state.assets } || {}; updatedAssets[action.payload.asset.id] = { ...action.payload.asset }; + const assetTags = new Set(); + action.payload.regions.forEach((region) => region.tags.forEach((tag) => assetTags.add(tag))); + + const newTags: ITag[] = state.tags ? [...state.tags] : []; + let updateTags = false; + + assetTags.forEach((tag) => { + if (!state.tags || state.tags.length === 0 || + !state.tags.find((projectTag) => tag === projectTag.name)) { + newTags.push({ + name: tag, + color: tagColors[newTags.length % tagColors.length], + }); + updateTags = true; + } + }); + + if (updateTags) { + return { + ...state, + tags: newTags, + assets: updatedAssets, + }; + } + return { ...state, assets: updatedAssets, diff --git a/src/registerProviders.ts b/src/registerProviders.ts index 4259824fc3..e01209b0e0 100644 --- a/src/registerProviders.ts +++ b/src/registerProviders.ts @@ -1,7 +1,8 @@ import { ExportProviderFactory } from "./providers/export/exportProviderFactory"; -import { TFPascalVOCExportProvider } from "./providers/export/tensorFlowPascalVOC"; +import { PascalVOCExportProvider } from "./providers/export/pascalVOC"; import { TFRecordsExportProvider } from "./providers/export/tensorFlowRecords"; import { VottJsonExportProvider } from "./providers/export/vottJson"; +import { CsvExportProvider } from "./providers/export/csv"; import { AssetProviderFactory } from "./providers/storage/assetProviderFactory"; import { AzureBlobStorage } from "./providers/storage/azureBlobStorage"; import { BingImageSearch } from "./providers/storage/bingImageSearch"; @@ -11,6 +12,7 @@ import registerToolbar from "./registerToolbar"; import { strings } from "./common/strings"; import { HostProcessType } from "./common/hostProcess"; import { AzureCustomVisionProvider } from "./providers/export/azureCustomVision"; +import { CntkExportProvider } from "./providers/export/cntk"; /** * Registers storage, asset and export providers, as well as all toolbar items @@ -54,9 +56,9 @@ export default function registerProviders() { factory: (project, options) => new VottJsonExportProvider(project, options), }); ExportProviderFactory.register({ - name: "tensorFlowPascalVOC", - displayName: strings.export.providers.tfPascalVoc.displayName, - factory: (project, options) => new TFPascalVOCExportProvider(project, options), + name: "pascalVOC", + displayName: strings.export.providers.pascalVoc.displayName, + factory: (project, options) => new PascalVOCExportProvider(project, options), }); ExportProviderFactory.register({ name: "tensorFlowRecords", @@ -68,6 +70,16 @@ export default function registerProviders() { displayName: strings.export.providers.azureCV.displayName, factory: (project, options) => new AzureCustomVisionProvider(project, options), }); + ExportProviderFactory.register({ + name: "cntk", + displayName: strings.export.providers.cntk.displayName, + factory: (project, options) => new CntkExportProvider(project, options), + }); + ExportProviderFactory.register({ + name: "csv", + displayName: strings.export.providers.csv.displayName, + factory: (project, options) => new CsvExportProvider(project, options), + }); registerToolbar(); } diff --git a/src/registerToolbar.ts b/src/registerToolbar.ts index 51fdc3560c..231d8aaa31 100644 --- a/src/registerToolbar.ts +++ b/src/registerToolbar.ts @@ -17,6 +17,7 @@ export enum ToolbarItemName { NextAsset = "navigateNextAsset", SaveProject = "saveProject", ExportProject = "exportProject", + ActiveLearning = "activeLearning", } export enum ToolbarItemGroup { @@ -102,6 +103,15 @@ export default function registerToolbar() { accelerators: ["CmdOrCtrl+Delete", "CmdOrCtrl+Backspace"], }); + ToolbarItemFactory.register({ + name: ToolbarItemName.ActiveLearning, + tooltip: strings.editorPage.toolbar.activeLearning, + icon: "fas fa-graduation-cap", + group: ToolbarItemGroup.Canvas, + type: ToolbarItemType.Action, + accelerators: ["CmdOrCtrl+D", "CmdOrCtrl+d"], + }); + ToolbarItemFactory.register({ name: ToolbarItemName.PreviousAsset, tooltip: strings.editorPage.toolbar.previousAsset, diff --git a/src/services/activeLearningService.test.ts b/src/services/activeLearningService.test.ts new file mode 100644 index 0000000000..bf8d4e9460 --- /dev/null +++ b/src/services/activeLearningService.test.ts @@ -0,0 +1,120 @@ +import { ActiveLearningService } from "./activeLearningService"; +import { IActiveLearningSettings, ModelPathType, IAssetMetadata, AssetState } from "../models/applicationState"; +import MockFactory from "../common/mockFactory"; +import { appInfo } from "../common/appInfo"; +import { ObjectDetection } from "../providers/activeLearning/objectDetection"; + +describe("Active Learning Service", () => { + const objectDetectionMock = ObjectDetection as jest.Mocked; + const defaultSettings: IActiveLearningSettings = { + modelPathType: ModelPathType.Coco, + autoDetect: true, + predictTag: true, + }; + + let activeLearningService: ActiveLearningService = null; + + const electronMock = { + remote: { + app: { + getAppPath: jest.fn(), + }, + }, + }; + + beforeAll(() => { + window["require"] = jest.fn(() => electronMock); + }); + + beforeEach(() => { + activeLearningService = new ActiveLearningService(defaultSettings); + objectDetectionMock.prototype.load = jest.fn(() => Promise.resolve()); + objectDetectionMock.prototype.predictImage = jest.fn(() => Promise.resolve([])); + }); + + it("Predicts new regions to the asset metadata", async () => { + objectDetectionMock.prototype.predictImage = jest.fn(() => Promise.resolve(expectedRegions)); + + const expectedRegions = MockFactory.createTestRegions(2); + const canvas = MockFactory.mockCanvas()(); + const asset = MockFactory.createTestAsset("TestAsset", AssetState.Visited); + const assetMetadata: IAssetMetadata = { + asset: { + ...asset, + state: AssetState.Tagged, + }, + regions: [], + version: appInfo.version, + }; + + const updatedAssetMetadata = await activeLearningService.predictRegions(canvas, assetMetadata); + + expect(updatedAssetMetadata).toEqual({ + asset: { + ...assetMetadata.asset, + predicted: true, + }, + regions: expectedRegions, + version: appInfo.version, + }); + }); + + it("Predicts non matching regions to the asset metadata", async () => { + objectDetectionMock.prototype.predictImage = jest.fn(() => Promise.resolve(expectedRegions)); + + const uniqueRegion = MockFactory.createTestRegion("UniqueRegion", ["tag1", "tag2"]); + const expectedRegions = MockFactory.createTestRegions(4); + const canvas = MockFactory.mockCanvas()(); + const asset = MockFactory.createTestAsset("TestAsset", AssetState.Visited); + const assetMetadata: IAssetMetadata = { + asset: { + ...asset, + state: AssetState.Tagged, + }, + regions: [ + uniqueRegion, + expectedRegions[0], + expectedRegions[1], + ], + version: appInfo.version, + }; + + const updatedAssetMetadata = await activeLearningService.predictRegions(canvas, assetMetadata); + + expect(updatedAssetMetadata).toEqual({ + asset: { + ...assetMetadata.asset, + predicted: true, + }, + regions: [ + uniqueRegion, + ...expectedRegions, + ], + version: appInfo.version, + }); + }); + + it("ensures the underlying object detection model is only loaded 1 time", async () => { + const canvas = MockFactory.mockCanvas()(); + const assetMetadata: IAssetMetadata = { + asset: MockFactory.createTestAsset("TestAsset", AssetState.Visited), + regions: [], + version: appInfo.version, + }; + + await activeLearningService.predictRegions(canvas, assetMetadata); + await activeLearningService.predictRegions(canvas, assetMetadata); + await activeLearningService.predictRegions(canvas, assetMetadata); + await activeLearningService.predictRegions(canvas, assetMetadata); + expect(objectDetectionMock.prototype.load).toBeCalledTimes(1); + }); + + it("fails if constructor requirements aren't satisfied", () => { + expect(() => new ActiveLearningService(null)).toThrow(); + }); + + it("fails if method requirements aren't satisfied", () => { + const service = new ActiveLearningService(defaultSettings); + expect(service.predictRegions(null, null)).rejects.not.toBeNull(); + }); +}); diff --git a/src/services/activeLearningService.ts b/src/services/activeLearningService.ts new file mode 100644 index 0000000000..f607ea6df7 --- /dev/null +++ b/src/services/activeLearningService.ts @@ -0,0 +1,104 @@ +import { IAssetMetadata, ModelPathType, IActiveLearningSettings, AssetState } from "../models/applicationState"; +import { ObjectDetection } from "../providers/activeLearning/objectDetection"; +import Guard from "../common/guard"; +import { isElectron } from "../common/hostProcess"; +import { Env } from "../common/environment"; + +export class ActiveLearningService { + private objectDetection: ObjectDetection; + private modelLoaded: boolean = false; + + constructor(private settings: IActiveLearningSettings) { + Guard.null(settings); + this.objectDetection = new ObjectDetection(); + } + + public isModelLoaded() { + return this.modelLoaded; + } + + public async predictRegions(canvas: HTMLCanvasElement, assetMetadata: IAssetMetadata): Promise { + Guard.null(canvas); + Guard.null(assetMetadata); + + // If the canvas or asset are invalid return asset metadata + if (!(canvas.width && canvas.height && assetMetadata.asset && assetMetadata.asset.size)) { + return assetMetadata; + } + + await this.ensureModelLoaded(); + + const xRatio = assetMetadata.asset.size.width / canvas.width; + const yRatio = assetMetadata.asset.size.height / canvas.height; + const predictedRegions = await this.objectDetection.predictImage( + canvas, + this.settings.predictTag, + xRatio, + yRatio, + ); + + const updatedRegions = [...assetMetadata.regions]; + predictedRegions.forEach((prediction) => { + const matchingRegion = updatedRegions.find((region) => { + return region.boundingBox + && region.boundingBox.left === prediction.boundingBox.left + && region.boundingBox.top === prediction.boundingBox.top + && region.boundingBox.width === prediction.boundingBox.width + && region.boundingBox.height === prediction.boundingBox.height; + }); + + if (updatedRegions.length === 0 || !matchingRegion) { + updatedRegions.push(prediction); + } + }); + + return { + ...assetMetadata, + regions: updatedRegions, + asset: { + ...assetMetadata.asset, + state: updatedRegions.length > 0 ? AssetState.Tagged : AssetState.Visited, + predicted: true, + }, + } as IAssetMetadata; + } + + public async ensureModelLoaded(): Promise { + if (this.modelLoaded) { + return Promise.resolve(); + } + + await this.loadModel(); + this.modelLoaded = true; + } + + private async loadModel() { + let modelPath = ""; + if (this.settings.modelPathType === ModelPathType.Coco) { + if (isElectron()) { + const appPath = this.getAppPath(); + + if (Env.get() !== "production") { + modelPath = appPath + "/cocoSSDModel"; + } else { + modelPath = appPath + "/../../cocoSSDModel"; + } + } else { + modelPath = "https://vott.blob.core.windows.net/coco-ssd-model"; + } + } else if (this.settings.modelPathType === ModelPathType.File) { + if (isElectron()) { + modelPath = this.settings.modelPath; + } + } else { + modelPath = this.settings.modelUrl; + } + + await this.objectDetection.load(modelPath); + } + + private getAppPath = () => { + const remote = (window as any).require("electron").remote as Electron.Remote; + return remote.app.getAppPath(); + } +} diff --git a/src/services/assetService.test.ts b/src/services/assetService.test.ts index 90d07d15bd..58c7e67173 100644 --- a/src/services/assetService.test.ts +++ b/src/services/assetService.test.ts @@ -1,5 +1,5 @@ import { AssetService } from "./assetService"; -import { AssetType, IAssetMetadata, AssetState } from "../models/applicationState"; +import { AssetType, IAssetMetadata, AssetState, IAsset, IProject } from "../models/applicationState"; import MockFactory from "../common/mockFactory"; import { AssetProviderFactory, IAssetProvider } from "../providers/storage/assetProviderFactory"; import { StorageProviderFactory } from "../providers/storage/storageProviderFactory"; @@ -7,6 +7,8 @@ import { constants } from "../common/constants"; import { TFRecordsBuilder, FeatureType } from "../providers/export/tensorFlowRecords/tensorFlowBuilder"; import HtmlFileReader from "../common/htmlFileReader"; import { encodeFileURI } from "../common/utils"; +import _ from "lodash"; +import registerMixins from "../registerMixins"; describe("Asset Service", () => { describe("Static Methods", () => { @@ -323,4 +325,105 @@ describe("Asset Service", () => { expect(Math.floor(result.regions[1].points[1].y)).toEqual(800); }); }); + + describe("Tag Update functions", () => { + + function populateProjectAssets(project?: IProject, assetCount = 10) { + if (!project) { + project = MockFactory.createTestProject(); + } + const assets = MockFactory.createTestAssets(assetCount); + assets.forEach((asset) => { + asset.state = AssetState.Tagged; + }); + + project.assets = _.keyBy(assets, (asset) => asset.id); + return project; + } + + beforeAll(() => { + registerMixins(); + }); + + it("Deletes tag from assets", async () => { + const tag1 = "tag1"; + const tag2 = "tag2"; + const region = MockFactory.createTestRegion(undefined, [tag1, tag2]); + const asset: IAsset = { + ...MockFactory.createTestAsset("1"), + state: AssetState.Tagged, + }; + const assetMetadata = MockFactory.createTestAssetMetadata(asset, [region]); + AssetService.prototype.getAssetMetadata = jest.fn((asset: IAsset) => Promise.resolve(assetMetadata)); + + const expectedAssetMetadata: IAssetMetadata = { + ...MockFactory.createTestAssetMetadata( + asset, + [ + { + ...region, + tags: [tag2], + }, + ], + ), + }; + + const project = populateProjectAssets(); + const assetService = new AssetService(project); + const assetUpdates = await assetService.deleteTag(tag1); + + expect(assetUpdates).toHaveLength(1); + expect(assetUpdates[0]).toEqual(expectedAssetMetadata); + }); + + it("Deletes empty regions after deleting only tag from region", async () => { + const tag1 = "tag1"; + const region = MockFactory.createTestRegion(undefined, [tag1]); + const asset: IAsset = { + ...MockFactory.createTestAsset("1"), + state: AssetState.Tagged, + }; + const assetMetadata = MockFactory.createTestAssetMetadata(asset, [region]); + AssetService.prototype.getAssetMetadata = jest.fn((asset: IAsset) => Promise.resolve(assetMetadata)); + + const expectedAssetMetadata: IAssetMetadata = MockFactory.createTestAssetMetadata(asset, []); + const project = populateProjectAssets(); + const assetService = new AssetService(project); + const assetUpdates = await assetService.deleteTag(tag1); + + expect(assetUpdates).toHaveLength(1); + expect(assetUpdates[0]).toEqual(expectedAssetMetadata); + }); + + it("Updates renamed tag within all assets", async () => { + const tag1 = "tag1"; + const newTag = "tag2"; + const region = MockFactory.createTestRegion(undefined, [tag1]); + const asset: IAsset = { + ...MockFactory.createTestAsset("1"), + state: AssetState.Tagged, + }; + const assetMetadata = MockFactory.createTestAssetMetadata(asset, [region]); + AssetService.prototype.getAssetMetadata = jest.fn((asset: IAsset) => Promise.resolve(assetMetadata)); + + const expectedAssetMetadata: IAssetMetadata = { + ...MockFactory.createTestAssetMetadata( + asset, + [ + { + ...region, + tags: [newTag], + }, + ], + ), + }; + + const project = populateProjectAssets(); + const assetService = new AssetService(project); + const assetUpdates = await assetService.renameTag(tag1, newTag); + + expect(assetUpdates).toHaveLength(1); + expect(assetUpdates[0]).toEqual(expectedAssetMetadata); + }); + }); }); diff --git a/src/services/assetService.ts b/src/services/assetService.ts index 58335b606a..2ab0ffabd0 100644 --- a/src/services/assetService.ts +++ b/src/services/assetService.ts @@ -204,10 +204,73 @@ export class AssetService { } } + /** + * Delete a tag from asset metadata files + * @param tagName Name of tag to delete + */ + public async deleteTag(tagName: string): Promise { + const transformer = (tags) => tags.filter((t) => t !== tagName); + return await this.getUpdatedAssets(tagName, transformer); + } + + /** + * Rename a tag within asset metadata files + * @param tagName Name of tag to rename + */ + public async renameTag(tagName: string, newTagName: string): Promise { + const transformer = (tags) => tags.map((t) => (t === tagName) ? newTagName : t); + return await this.getUpdatedAssets(tagName, transformer); + } + + /** + * Update tags within asset metadata files + * @param tagName Name of tag to update within project + * @param transformer Function that accepts array of tags from a region and returns a modified array of tags + */ + private async getUpdatedAssets(tagName: string, transformer: (tags: string[]) => string[]) + : Promise { + // Loop over assets and update if necessary + const updates = await _.values(this.project.assets).mapAsync(async (asset) => { + const assetMetadata = await this.getAssetMetadata(asset); + const isUpdated = this.updateTagInAssetMetadata(assetMetadata, tagName, transformer); + + return isUpdated ? assetMetadata : null; + }); + + return updates.filter((assetMetadata) => !!assetMetadata); + } + + /** + * Update tag within asset metadata object + * @param assetMetadata Asset metadata to update + * @param tagName Name of tag being updated + * @param transformer Function that accepts array of tags from a region and returns a modified array of tags + * @returns Modified asset metadata object or null if object does not need to be modified + */ + private updateTagInAssetMetadata( + assetMetadata: IAssetMetadata, + tagName: string, + transformer: (tags: string[]) => string[]): boolean { + let foundTag = false; + + for (const region of assetMetadata.regions) { + if (region.tags.find((t) => t === tagName)) { + foundTag = true; + region.tags = transformer(region.tags); + } + } + if (foundTag) { + assetMetadata.regions = assetMetadata.regions.filter((region) => region.tags.length > 0); + assetMetadata.asset.state = (assetMetadata.regions.length) ? AssetState.Tagged : AssetState.Visited; + return true; + } + + return false; + } + private async getRegionsFromTFRecord(asset: IAsset): Promise { const objectArray = await this.getTFRecordMetadata(asset); const regions: IRegion[] = []; - const tags: string[] = []; // Add Regions from TFRecord in Regions for (let index = 0; index < objectArray.textArray.length; index++) { diff --git a/src/services/importService.ts b/src/services/importService.ts index 5f9440b613..80c5d25625 100644 --- a/src/services/importService.ts +++ b/src/services/importService.ts @@ -2,7 +2,7 @@ import shortid from "shortid"; import { IProject, ITag, IConnection, AppError, ErrorCode, IAssetMetadata, IRegion, RegionType, AssetState, IFileInfo, - IAsset, AssetType, + IAsset, AssetType, ModelPathType, } from "../models/applicationState"; import { IV1Project, IV1Region } from "../models/v1Models"; import packageJson from "../../package.json"; @@ -66,6 +66,7 @@ export default class ImportService implements IImportService { videoSettings: { frameExtractionRate: originalProject.framerate ? Number(originalProject.framerate) : 15, }, + activeLearningSettings: null, autoSave: true, }; } diff --git a/src/services/projectService.test.ts b/src/services/projectService.test.ts index f610e750a3..bec6f4fb71 100644 --- a/src/services/projectService.test.ts +++ b/src/services/projectService.test.ts @@ -2,11 +2,17 @@ import _ from "lodash"; import ProjectService, { IProjectService } from "./projectService"; import MockFactory from "../common/mockFactory"; import { StorageProviderFactory } from "../providers/storage/storageProviderFactory"; -import { IProject, IExportFormat, ISecurityToken, AssetState } from "../models/applicationState"; +import { + IProject, IExportFormat, ISecurityToken, + AssetState, IActiveLearningSettings, ModelPathType, +} from "../models/applicationState"; import { constants } from "../common/constants"; import { ExportProviderFactory } from "../providers/export/exportProviderFactory"; import { generateKey } from "../common/crypto"; -import { encryptProject } from "../common/utils"; +import { encryptProject, decryptProject } from "../common/utils"; +import { ExportAssetState } from "../providers/export/exportProvider"; +import { IVottJsonExportProviderOptions } from "../providers/export/vottJson"; +import { IPascalVOCExportProviderOptions } from "../providers/export/pascalVOC"; describe("Project Service", () => { let projectSerivce: IProjectService = null; @@ -76,6 +82,45 @@ describe("Project Service", () => { expect.any(String)); }); + it("sets default export settings when not defined", async () => { + testProject.exportFormat = null; + const result = await projectSerivce.save(testProject, securityToken); + + const vottJsonExportProviderOptions: IVottJsonExportProviderOptions = { + assetState: ExportAssetState.Visited, + includeImages: true, + }; + + const expectedExportFormat: IExportFormat = { + providerType: "vottJson", + providerOptions: vottJsonExportProviderOptions, + }; + + const decryptedProject = decryptProject(result, securityToken); + + expect(decryptedProject.exportFormat).toEqual(expectedExportFormat); + }); + + it("sets default active learning setting when not defined", async () => { + testProject.activeLearningSettings = null; + const result = await projectSerivce.save(testProject, securityToken); + + const activeLearningSettings: IActiveLearningSettings = { + autoDetect: false, + predictTag: true, + modelPathType: ModelPathType.Coco, + }; + + expect(result.activeLearningSettings).toEqual(activeLearningSettings); + }); + + it("initializes tags to empty array if not defined", async () => { + testProject.tags = null; + const result = await projectSerivce.save(testProject, securityToken); + + expect(result.tags).toEqual([]); + }); + it("Save calls configured export provider save when defined", async () => { testProject.exportFormat = { providerType: "azureCustomVision", @@ -157,4 +202,23 @@ describe("Project Service", () => { await projectSerivce.delete(testProject); expect(storageProviderMock.deleteFile.mock.calls).toHaveLength(assets.length + 1); }); + + it("Updates export settings to v2.1 supported values", async () => { + testProject = MockFactory.createTestProject("TestProject"); + testProject.version = "2.0.0"; + testProject.exportFormat = { + providerType: "tensorFlowPascalVOC", + providerOptions: { + assetState: ExportAssetState.All, + exportUnassigned: true, + testTrainSplit: 80, + } as IPascalVOCExportProviderOptions, + }; + + const encryptedProject = encryptProject(testProject, securityToken); + const decryptedProject = await projectSerivce.load(encryptedProject, securityToken); + + expect(decryptedProject.exportFormat.providerType).toEqual("pascalVOC"); + expect(decryptedProject.exportFormat.providerOptions).toEqual(testProject.exportFormat.providerOptions); + }); }); diff --git a/src/services/projectService.ts b/src/services/projectService.ts index 3b868cf27f..cf1c83a255 100644 --- a/src/services/projectService.ts +++ b/src/services/projectService.ts @@ -1,12 +1,17 @@ import _ from "lodash"; import shortid from "shortid"; import { StorageProviderFactory } from "../providers/storage/storageProviderFactory"; -import { IProject, ISecurityToken, AppError, ErrorCode, AssetState } from "../models/applicationState"; +import { + IProject, ISecurityToken, AppError, + ErrorCode, ModelPathType, IActiveLearningSettings, +} from "../models/applicationState"; import Guard from "../common/guard"; import { constants } from "../common/constants"; import { ExportProviderFactory } from "../providers/export/exportProviderFactory"; import { decryptProject, encryptProject } from "../common/utils"; import packageJson from "../../package.json"; +import { ExportAssetState } from "../providers/export/exportProvider"; +import { IExportFormat } from "vott-react"; /** * Functions required for a project service @@ -20,6 +25,20 @@ export interface IProjectService { isDuplicate(project: IProject, projectList: IProject[]): boolean; } +const defaultActiveLearningSettings: IActiveLearningSettings = { + autoDetect: false, + predictTag: true, + modelPathType: ModelPathType.Coco, +}; + +const defaultExportOptions: IExportFormat = { + providerType: "vottJson", + providerOptions: { + assetState: ExportAssetState.Visited, + includeImages: true, + }, +}; + /** * @name - Project Service * @description - Functions for dealing with projects @@ -35,7 +54,25 @@ export default class ProjectService implements IProjectService { try { const loadedProject = decryptProject(project, securityToken); - return Promise.resolve(loadedProject); + + // Ensure tags is always initialized to an array + if (!loadedProject.tags) { + loadedProject.tags = []; + } + + // Initialize active learning settings if they don't exist + if (!loadedProject.activeLearningSettings) { + loadedProject.activeLearningSettings = defaultActiveLearningSettings; + } + + // Initialize export settings if they don't exist + if (!loadedProject.exportFormat) { + loadedProject.exportFormat = defaultExportOptions; + } + + this.ensureBackwardsCompatibility(loadedProject); + + return Promise.resolve({ ...loadedProject }); } catch (e) { const error = new AppError(ErrorCode.ProjectInvalidSecurityToken, "Error decrypting project settings"); return Promise.reject(error); @@ -54,6 +91,21 @@ export default class ProjectService implements IProjectService { project.id = shortid.generate(); } + // Ensure tags is always initialized to an array + if (!project.tags) { + project.tags = []; + } + + // Initialize active learning settings if they don't exist + if (!project.activeLearningSettings) { + project.activeLearningSettings = defaultActiveLearningSettings; + } + + // Initialize export settings if they don't exist + if (!project.exportFormat) { + project.exportFormat = defaultExportOptions; + } + project.version = packageJson.version; const storageProvider = StorageProviderFactory.createFromConnection(project.targetConnection); @@ -113,4 +165,19 @@ export default class ProjectService implements IProjectService { project.exportFormat.providerOptions = await exportProvider.save(project.exportFormat); } + + /** + * Ensures backwards compatibility with project + * @param project The project to update + */ + private ensureBackwardsCompatibility(project: IProject) { + const projectVersion = project.version.toLowerCase(); + + if (projectVersion.startsWith("2.0.0")) { + // Required for backwards compatibility with v2.0.0 release + if (project.exportFormat.providerType === "tensorFlowPascalVOC") { + project.exportFormat.providerType = "pascalVOC"; + } + } + } } diff --git a/tsconfig.json b/tsconfig.json index 4bc1ec092d..962164b754 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,25 +1,29 @@ { - "compilerOptions": { - "target": "es6", - "allowJs": false, - "skipLibCheck": false, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": false, - "forceConsistentCasingInFileNames": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "experimentalDecorators": true, - "lib": [ - "es2015", - "dom" + "compilerOptions": { + "target": "es6", + "allowJs": false, + "skipLibCheck": false, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "experimentalDecorators": true, + "lib": [ + "es2015", + "dom" + ], + "typeRoots": [ + "./typings", + "./node_modules/@types" + ], + }, + "include": [ + "src" ] - }, - "include": [ - "src" - ] } diff --git a/typings.json b/typings.json index dd7ce80870..e69de29bb2 100644 --- a/typings.json +++ b/typings.json @@ -1,5 +0,0 @@ -{ - "globalDevDependencies": { - "react-jsonschema-form": "registry:dt/react-jsonschema-form#0.43.0+20170226152137" - } -} diff --git a/typings/globals/react-jsonschema-form/index.d.ts b/typings/globals/react-jsonschema-form/index.d.ts deleted file mode 100644 index 3d961e28ee..0000000000 --- a/typings/globals/react-jsonschema-form/index.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Generated by typings -// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/46d11bc6ab4a0a9b711b403662dceefb67ebb575/react-jsonschema-form/index.d.ts -declare module "react-jsonschema-form" { - import * as React from "react"; - - export interface FormProps { - schema: {}; - uiSchema?: {}; - formData?: any; - widgets?: {}; - fields?: {}; - noValidate?: boolean; - noHtml5Validate?: boolean; - showErrorList?: boolean; - validate?: (formData: any, errors: any) => any; - onChange?: (e: IChangeEvent) => any; - onError?: (e: any) => any; - onSubmit?: (e: any) => any; - liveValidate?: boolean; - safeRenderCompletion?: boolean; - } - - export interface IChangeEvent { - edit: boolean; - formData: any; - errors: any[]; - errorSchema: any; - idSchema: any; - status: string; - } - - export default class Form extends React.Component {} -} diff --git a/typings/globals/react-jsonschema-form/typings.json b/typings/globals/react-jsonschema-form/typings.json deleted file mode 100644 index 7a7a41ba2c..0000000000 --- a/typings/globals/react-jsonschema-form/typings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "resolution": "main", - "tree": { - "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/46d11bc6ab4a0a9b711b403662dceefb67ebb575/react-jsonschema-form/index.d.ts", - "raw": "registry:dt/react-jsonschema-form#0.43.0+20170226152137", - "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/46d11bc6ab4a0a9b711b403662dceefb67ebb575/react-jsonschema-form/index.d.ts" - } -} diff --git a/typings/index.d.ts b/typings/index.d.ts deleted file mode 100644 index bc2855ed1c..0000000000 --- a/typings/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/typings/react-jsonschema-form/index.d.ts b/typings/react-jsonschema-form/index.d.ts new file mode 100644 index 0000000000..44874259b7 --- /dev/null +++ b/typings/react-jsonschema-form/index.d.ts @@ -0,0 +1,3 @@ +declare module "react-jsonschema-form/lib/utils" { + export function getDefaultFormState(schema: any, formData: T): T; +}